aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2025-04-14 16:25:15 -0400
committerAndrew MacLeod <amacleod@redhat.com>2025-04-30 13:07:12 -0400
commitf685d317738524dc837dee94bb762f71ff30fb23 (patch)
treeaf600863b262b930a7b1691992ea49183127c0b9
parentc9d4d3ba15c55e108f5f9a28d2609a698634a5db (diff)
downloadgcc-f685d317738524dc837dee94bb762f71ff30fb23.zip
gcc-f685d317738524dc837dee94bb762f71ff30fb23.tar.gz
gcc-f685d317738524dc837dee94bb762f71ff30fb23.tar.bz2
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
-rw-r--r--gcc/testsuite/gcc.dg/pr119712.c27
-rw-r--r--gcc/testsuite/gcc.dg/pr83072-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-value-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp122.c4
-rw-r--r--gcc/value-range.cc64
-rw-r--r--gcc/value-range.h1
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 0000000..e845dd9
--- /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 dff6b50..485e804 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 12ba475..ed8ee3a 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 5a4ca85..def2b89 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 5136674..a770b41 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 b50cb89..f694298 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;