https://gcc.gnu.org/g:2a9fbe1920779b65eb817db7ce0c60096b0cea9e

commit r14-10877-g2a9fbe1920779b65eb817db7ce0c60096b0cea9e
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Thu Oct 31 14:07:00 2024 -0400

    Update bitwise_or op_range.
    
    If the LHS of a bitwise OR is positive, then so are both operands when
    using op1_range or op2_range.
    
            gcc/
            * range-op.cc (operator_bitwise_or::op1_range): If LHS is signed
            positive, so are both operands.
    
            gcc/testsuite
            * g++.dg/cpp23/attr-assume-opt.C (f2b): Alternate flow test.

Diff:
---
 gcc/range-op.cc                              | 13 ++++++++++
 gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C | 37 +++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 4ccb86ef0ba8..d1a1cd736876 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3738,6 +3738,19 @@ operator_bitwise_or::op1_range (irange &r, tree type,
       r.set_zero (type);
       return true;
     }
+
+  //   if (A < 0 && B < 0)
+  // Sometimes gets translated to
+  //   _1 = A | B
+  //   if (_1 < 0))
+  // It is useful for ranger to recognize a positive LHS means the RHS
+  // operands are also positive when dealing with the ELSE range..
+  if (TYPE_SIGN (type) == SIGNED && wi::ge_p (lhs.lower_bound (), 0, SIGNED))
+    {
+      unsigned prec = TYPE_PRECISION (type);
+      r.set (type, wi::zero (prec), wi::max_value (prec, SIGNED));
+      return true;
+    }
   r.set_varying (type);
   return true;
 }
diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C 
b/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C
index 88d5e78dbbae..e61ba7a27e0f 100644
--- a/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C
+++ b/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C
@@ -38,5 +38,40 @@ f3 (int x, int y, int z)
   return 1;
 }
 
+// This is the same as f2, except there is more complicated flow and 
+// required a range-op update to bitwise or.
+
+void barn(int x);
+// assume (x+12 == 14 && y >= 0 && y + 10 < 13 && z + 4 >= 4 && z - 2 < 18)
+// in different order and form with function calls to cause branches.
+bool assume_func (int x, int y, int z)
+{
+  if (z - 2 >= 18)
+    return false;
+  if (x+12 != 14)
+    return false;
+  barn (x);
+  if (y < 0)
+    return false;
+  if (z + 4 < 4)
+    return false;
+  barn (y);
+  if (y + 10 >= 13)
+    return false;
+  barn (z);
+  return true;
+}
+
+int
+f2b (int x, int y, int z)
+{
+  [[assume (assume_func (x, y, z))]];
+  unsigned q = x + y + z;
+  if (q*2 > 46)
+    return 0;
+  return 1;
+}
+
+
 /* { dg-final { scan-tree-dump-times "return 0" 0 "vrp2" } } */
-/* { dg-final { scan-tree-dump-times "return 1" 3 "vrp2" } } */
+/* { dg-final { scan-tree-dump-times "return 1" 4 "vrp2" } } */

Reply via email to