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

commit r15-9607-gf685d317738524dc837dee94bb762f71ff30fb23
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Mon Apr 14 16:25:15 2025 -0400

    Always reflect lower bits from mask in subranges.
    
    During intersection, we expand the subranges to exclude the lower values
    from a bitmask with trailing zeros.  This leads to inconsistant evaluations
    and in this case of this PR, that lead to an infinite cycle.
    
    Always expand the lower subranges in set_range_from_bitmask instead.
    
            PR tree-optimization/119712
            gcc/
            * value-range.cc (range_bitmask::adjust_range): Delete.
            (irange::set_range_from_bitmask): Integrate adjust_range.
            (irange::update_bitmask): Do nothing if bitmask doesnt change.
            (irange:intersect_bitmask): Do not call adjust_range. Exit if there
            is no second bitmask.
            * value-range.h (adjust_range): Remove prototype.
    
            gcc/testsuite/
            * gcc.dg/pr119712.c: New.
            * gcc.dg/pr83072-2.c: Adjust.
            * gcc.dg/tree-ssa/phi-opt-value-5.c: Adjust.
            * gcc.dg/tree-ssa/vrp122.c: Adjust

Diff:
---
 gcc/testsuite/gcc.dg/pr119712.c                 | 27 +++++++++++
 gcc/testsuite/gcc.dg/pr83072-2.c                |  2 +-
 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c |  4 +-
 gcc/testsuite/gcc.dg/tree-ssa/vrp122.c          |  4 +-
 gcc/value-range.cc                              | 64 ++++++++++++-------------
 gcc/value-range.h                               |  1 -
 6 files changed, 61 insertions(+), 41 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/pr119712.c b/gcc/testsuite/gcc.dg/pr119712.c
new file mode 100644
index 000000000000..e845dd9ce55a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119712.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+int a, b, c, d, e, f;
+int main() {
+          f--;
+          goto q;
+j:
+          if (-1642776935 * c + 7 >= 0)
+            goto l;
+m:
+          if (4 * a - c - 21 >= 0)
+            goto i;
+          return 0;
+i:
+          if (d)
+            goto l;
+q:
+          c = 4 * c - 3;
+          if (c - f)
+             goto m;
+          goto j;
+l:
+          e = b + 1958960196 * c - 1016458303;
+          if (20 * e + 1 >= 0)
+              return 0;
+          goto j;
+}
diff --git a/gcc/testsuite/gcc.dg/pr83072-2.c b/gcc/testsuite/gcc.dg/pr83072-2.c
index dff6b50b717e..485e8041381e 100644
--- a/gcc/testsuite/gcc.dg/pr83072-2.c
+++ b/gcc/testsuite/gcc.dg/pr83072-2.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-evrp-details" } */
+/* { dg-options "-O2 -fdump-tree-evrp-details -fno-tree-forwprop" } */
 
 int f1(int a, int b, int c){
   if(c==0)__builtin_unreachable();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c 
b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c
index 12ba475b24e2..ed8ee3ab72dc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c
@@ -31,9 +31,7 @@ int fdiv1(int a, int b)
   return a != 0 ? c : 0;
 }
 
-/* fdiv1 requires until later than phiopt2 to be able to detect that
-   d is non-zero. to be able to remove the conditional.  */
-/* { dg-final { scan-tree-dump-times "goto" 2 "phiopt2" } } */
+/* { dg-final { scan-tree-dump-not "goto" "phiopt2" } } */
 /* { dg-final { scan-tree-dump-not "goto" "phiopt3" } } */
 /* { dg-final { scan-tree-dump-not "goto" "optimized" } } */
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c
index 5a4ca850beec..def2b892bd6b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp122.c
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-O2 -fdump-tree-evrp-details" }
+// { dg-options "-O2 -fdump-tree-ccp1-details" }
 
 void gg(void);
 int f(unsigned t)
@@ -16,4 +16,4 @@ int f(unsigned t)
   return 0;
 }
 
-// { dg-final { scan-tree-dump "Global Exported: g_.* MASK 0x1 VALUE 0x0" 
"evrp" } }
+// { dg-final { scan-tree-dump "Global Exported: g_.*MASK.*0 VALUE 0x0" "ccp1" 
} }
diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index 5136674b361a..a770b41b474a 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -2251,37 +2251,9 @@ irange::invert ()
     verify_range ();
 }
 
-// Remove trailing ranges that this bitmask indicates can't exist.
-
-void
-irange_bitmask::adjust_range (irange &r) const
-{
-  if (unknown_p () || r.undefined_p ())
-    return;
-
-  int_range_max range;
-  tree type = r.type ();
-  int prec = TYPE_PRECISION (type);
-  // If there are trailing zeros, create a range representing those bits.
-  gcc_checking_assert (m_mask != 0);
-  int z = wi::ctz (m_mask);
-  if (z)
-    {
-      wide_int ub = (wi::one (prec) << z) - 1;
-      range = int_range<5> (type, wi::zero (prec), ub);
-      // Then remove the specific value these bits contain from the range.
-      wide_int value = m_value & ub;
-      range.intersect (int_range<2> (type, value, value, VR_ANTI_RANGE));
-      // Inverting produces a list of ranges which can be valid.
-      range.invert ();
-      // And finally select R from only those valid values.
-      r.intersect (range);
-      return;
-    }
-}
-
-// If the mask can be trivially converted to a range, do so and
-// return TRUE.
+// If the mask can be trivially converted to a range, do so.
+// Otherwise attempt to remove the lower bits from the range.
+// Return true if the range changed in any way.
 
 bool
 irange::set_range_from_bitmask ()
@@ -2326,7 +2298,28 @@ irange::set_range_from_bitmask ()
       set_zero (type ());
       return true;
     }
-  return false;
+
+  // If the mask doesn't have any trailing zero, return.
+  int z = wi::ctz (m_bitmask.mask ());
+  if (!z)
+    return false;
+
+  // Remove trailing ranges that this bitmask indicates can't exist.
+  int_range_max mask_range;
+  int prec = TYPE_PRECISION (type ());
+  wide_int ub = (wi::one (prec) << z) - 1;
+  mask_range = int_range<2> (type (), wi::zero (prec), ub);
+
+  // Then remove the specific value these bits contain from the range.
+  wide_int value = m_bitmask.value () & ub;
+  mask_range.intersect (int_range<2> (type (), value, value, VR_ANTI_RANGE));
+
+  // Inverting produces a list of ranges which can be valid.
+  mask_range.invert ();
+
+  // And finally select R from only those valid values.
+  intersect (mask_range);
+  return true;
 }
 
 void
@@ -2334,6 +2327,10 @@ irange::update_bitmask (const irange_bitmask &bm)
 {
   gcc_checking_assert (!undefined_p ());
 
+  // If masks are the same, there is no change.
+  if (m_bitmask == bm)
+    return;
+
   // Drop VARYINGs with known bits to a plain range.
   if (m_kind == VR_VARYING && !bm.unknown_p ())
     m_kind = VR_RANGE;
@@ -2408,7 +2405,7 @@ irange::intersect_bitmask (const irange &r)
 {
   gcc_checking_assert (!undefined_p () && !r.undefined_p ());
 
-  if (m_bitmask == r.m_bitmask)
+  if (r.m_bitmask.unknown_p () || m_bitmask == r.m_bitmask)
     return false;
 
   irange_bitmask bm = get_bitmask ();
@@ -2427,7 +2424,6 @@ irange::intersect_bitmask (const irange &r)
 
   if (!set_range_from_bitmask ())
     normalize_kind ();
-  m_bitmask.adjust_range (*this);
   if (flag_checking)
     verify_range ();
   return true;
diff --git a/gcc/value-range.h b/gcc/value-range.h
index b50cb8963407..f6942989a6f3 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -149,7 +149,6 @@ public:
   void dump (FILE *) const;
 
   bool member_p (const wide_int &val) const;
-  void adjust_range (irange &r) const;
 
   // Convenience functions for nonzero bitmask compatibility.
   wide_int get_nonzero_bits () const;

Reply via email to