On Mon, Dec 05, 2022 at 09:54:09PM +0100, Jakub Jelinek via Gcc-patches wrote: > On Mon, Dec 05, 2022 at 03:43:16PM -0500, Andrew MacLeod wrote: > > Id actually prefer to avoid passing the tree code around... we're trying to > > avoid that sort of thing even though Aldy temporarily introduced them to > > range-ops. Hes suppose to remove that next stage 1 :-P Ideally anything > > "special" is locally contained to the specific routine. > > Would a bool divide_op2 argument be better (perhaps defaulted to false)? > Inlining float_binary_op_range_finish by hand doesn't seem to be a good > idea, if it needs to be changed, it would need to be changed in multiple > places...
In patch form on top of PR107975 patch. 2022-12-05 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/107972 * range-op-float.cc (frange_drop_infs): New function. (float_binary_op_range_finish): Add DIV_OP2 argument. If DIV_OP2 is false and lhs is finite or if DIV_OP2 is true and lhs is non-zero and not NAN, r must be finite too. (foperator_div::op2_range): Pass true to DIV_OP2 of float_binary_op_range_finish. --- gcc/range-op-float.cc.jj 2022-12-05 11:17:34.900573272 +0100 +++ gcc/range-op-float.cc 2022-12-05 16:13:54.414845672 +0100 @@ -330,6 +330,18 @@ frange_drop_ninf (frange &r, tree type) r.intersect (tmp); } +// Crop R to [MIN, MAX] where MAX is the maximum representable number +// for TYPE and MIN the minimum representable number for TYPE. + +static inline void +frange_drop_infs (frange &r, tree type) +{ + REAL_VALUE_TYPE max = real_max_representable (type); + REAL_VALUE_TYPE min = real_min_representable (type); + frange tmp (type, min, max); + r.intersect (tmp); +} + // If zero is in R, make sure both -0.0 and +0.0 are in the range. static inline void @@ -1883,7 +1895,7 @@ foperator_unordered_equal::op1_range (fr static bool float_binary_op_range_finish (bool ret, frange &r, tree type, - const frange &lhs) + const frange &lhs, bool div_op2 = false) { if (!ret) return false; @@ -1904,7 +1916,20 @@ float_binary_op_range_finish (bool ret, // If lhs isn't NAN, then neither operand could be NAN, // even if the reverse operation does introduce a maybe_nan. if (!lhs.maybe_isnan ()) - r.clear_nan (); + { + r.clear_nan (); + if (div_op2 + ? !(real_compare (LE_EXPR, &lhs.lower_bound (), &dconst0) + && real_compare (GE_EXPR, &lhs.upper_bound (), &dconst0)) + : !(real_isinf (&lhs.lower_bound ()) + || real_isinf (&lhs.upper_bound ()))) + // For reverse + or - or * or op1 of /, if result is finite, then + // r must be finite too, as X + INF or X - INF or X * INF or + // INF / X is always +-INF or NAN. For op2 of /, if result is + // non-zero and not NAN, r must be finite, as X / INF is always + // 0 or NAN. + frange_drop_infs (r, type); + } // If lhs is a maybe or known NAN, the operand could be // NAN. else @@ -2330,7 +2355,7 @@ public: if (!ret) return ret; if (lhs.known_isnan () || op1.known_isnan () || op1.undefined_p ()) - return float_binary_op_range_finish (ret, r, type, lhs); + return float_binary_op_range_finish (ret, r, type, lhs, true); const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound (); const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound (); const REAL_VALUE_TYPE &op1_lb = op1.lower_bound (); @@ -2347,7 +2372,7 @@ public: zero_to_inf_range (lb, ub, signbit_known); r.set (type, lb, ub); } - return float_binary_op_range_finish (ret, r, type, lhs); + return float_binary_op_range_finish (ret, r, type, lhs, true); } private: void rv_fold (REAL_VALUE_TYPE &lb, REAL_VALUE_TYPE &ub, bool &maybe_nan, Jakub