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;