Hi!
Here is the floating point division fold_range implementation,
as I wrote in the last mail, we could outline some of the common parts
into static methods with descriptive names and share them between
foperator_div and foperator_mult.
Bootstrapped/regtested on top of the earlier version of the multiplication
fold_range on x86_64-linux and i686-linux, regressions are
+FAIL: gcc.dg/pr95115.c execution test
+FAIL: libphobos.phobos/std/math/hardware.d execution test
+FAIL: libphobos.phobos_shared/std/math/hardware.d execution test
The first test is we have:
# RANGE [frange] double [] +-NAN
_3 = Inf / Inf;
if (_3 ord _3)
goto ; [INV]
else
goto ; [INV]
:
abort ();
:
before evrp, the range is correct, Inf / Inf is known NAN of unknown
sign. evrp correctly folds _3 ord _3 into false and the
_3 = Inf / Inf;
remains in the IL, but then comes dse1 and removes it as dead
statement. So, I think yet another example of the PR107608 problems
where DCE? removes dead statements which raise floating point exceptions.
And -fno-delete-dead-exceptions doesn't help.
2022-11-11 Jakub Jelinek
PR tree-optimization/107569
* range-op-float.cc (foperator_div): New class.
(floating_op_table::floating_op_table): Use foperator_div
for RDIV_EXPR.
--- gcc/range-op-float.cc.jj2022-11-10 12:31:57.987917289 +0100
+++ gcc/range-op-float.cc 2022-11-10 17:04:35.743056880 +0100
@@ -2027,6 +2027,183 @@ class foperator_mult : public range_oper
}
} fop_mult;
+class foperator_div : public range_operator_float
+{
+ void rv_fold (REAL_VALUE_TYPE , REAL_VALUE_TYPE , bool _nan,
+ tree type,
+ const REAL_VALUE_TYPE _lb,
+ const REAL_VALUE_TYPE _ub,
+ const REAL_VALUE_TYPE _lb,
+ const REAL_VALUE_TYPE _ub,
+ relation_kind) const final override
+ {
+// +-0.0 / +-0.0 or +-INF / +-INF is a known NAN.
+if ((real_iszero (_lb)
+&& real_iszero (_ub)
+&& real_iszero (_lb)
+&& real_iszero (_ub))
+ || (real_isinf (_lb)
+ && real_isinf (_ub, real_isneg (_lb))
+ && real_isinf (_lb)
+ && real_isinf (_ub, real_isneg (_lb
+ {
+ real_nan (, "", 0, TYPE_MODE (type));
+ ub = lb;
+ maybe_nan = true;
+ return;
+ }
+
+bool both_maybe_zero = false;
+bool both_maybe_inf = false;
+bool must_have_signbit_zero = false;
+bool must_have_signbit_nonzero = false;
+
+// If +-0.0 is in both ranges, it is a maybe NAN.
+if (real_compare (LE_EXPR, _lb, )
+ && real_compare (GE_EXPR, _ub, )
+ && real_compare (LE_EXPR, _lb, )
+ && real_compare (GE_EXPR, _ub, ))
+ {
+ both_maybe_zero = true;
+ maybe_nan = true;
+ }
+// If +-INF is in both ranges, it is a maybe NAN.
+else if ((real_isinf (_lb) || real_isinf (_ub))
+&& (real_isinf (_lb) || real_isinf (_ub)))
+ {
+ both_maybe_inf = true;
+ maybe_nan = true;
+ }
+else
+ maybe_nan = false;
+
+if (real_isneg (_lb) == real_isneg (_ub)
+ && real_isneg (_lb) == real_isneg (_ub))
+ {
+ if (real_isneg (_lb) == real_isneg (_ub))
+ must_have_signbit_zero = true;
+ else
+ must_have_signbit_nonzero = true;
+ }
+
+// If dividend must be zero, the range is just +-0
+// (including if the divisor is +-INF).
+// If divisor must be +-INF, the range is just +-0
+// (including if the dividend is zero).
+if ((real_iszero (_lb) && real_iszero (_ub))
+ || real_isinf (_lb, false)
+ || real_isinf (_ub, true))
+ {
+ ub = lb = dconst0;
+ // If all the boundary signs are the same, [+0.0, +0.0].
+ if (must_have_signbit_zero)
+ ;
+ // If divisor and dividend must have different signs,
+ // [-0.0, -0.0].
+ else if (must_have_signbit_nonzero)
+ ub = lb = real_value_negate ();
+ // Otherwise -> [-0.0, +0.0].
+ else
+ lb = real_value_negate ();
+ return;
+ }
+
+// If divisor must be zero, the range is just +-INF
+// (including if the dividend is +-INF).
+// If dividend must be +-INF, the range is just +-INF
+// (including if the dividend is zero).
+if ((real_iszero (_lb) && real_iszero (_ub))
+ || real_isinf (_lb, false)
+ || real_isinf (_ub, true))
+ {
+ // If all the boundary signs are the same, [+INF, +INF].
+ if (must_have_signbit_zero)
+ ub = lb = dconstinf;
+ // If divisor and dividend must have different signs,
+ // [-INF, -INF].
+ else if (must_have_signbit_nonzero)
+ ub = lb = dconstninf;
+ // Otherwise -> [-INF, +INF] (-INF or +INF).
+ else
+ {
+ lb = dconstninf;
+ ub = dconstinf;
+ }
+ return;
+ }
+
+// Otherwise if both operands may be zero, divisor could be
+//