public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-4502] range-op-float: Improve binary reverse operations
@ 2022-12-06  9:27 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-12-06  9:27 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a0ee2e522523b35ac810bd31c9769b9906f87953

commit r13-4502-ga0ee2e522523b35ac810bd31c9769b9906f87953
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Dec 6 10:26:09 2022 +0100

    range-op-float: Improve binary reverse operations
    
    On Mon, Dec 05, 2022 at 02:29:36PM +0100, Aldy Hernandez wrote:
    > > So like this for multiplication op1/2_range if it passes bootstrap/regtest?
    > > For division I'll need to go to a drawing board...
    >
    > Sure, looks good to me.
    
    Ulrich just filed PR107972, so in the light of that PR the following patch
    attempts to do that differently.
    
    As for testcase, I've tried both attached testcases, but unfortunately it
    seems that in neither of the cases we actually figure out that res range
    is finite (or for last function non-zero ordered).  So there is further
    work needed on that.
    
    2022-12-06  Jakub Jelinek  <jakub@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.

Diff:
---
 gcc/range-op-float.cc | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index ac57c8a61d0..c6c1137bafd 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -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 (frange &r, tree type,
 
 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, frange &r, tree type,
   // 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,

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-12-06  9:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-06  9:27 [gcc r13-4502] range-op-float: Improve binary reverse operations Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).