Message ID | 20201020152039.336641-1-aldyh@redhat.com |
---|---|
State | New |
Headers | show |
Series | Saturate overflows return from SCEV in ranger. | expand |
On Tue, Oct 20, 2020 at 5:21 PM Aldy Hernandez via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > bounds_of_var_in_loop is returning an overflowed int, which is causing > us to create a range for which we can't compare the bounds causing > an ICE in verify_range. > > Overflowed bounds cause compare_values() to return -2, which we > don't handle in verify_range. > > We don't represent overflowed ranges in irange, so this patch just > saturates any overflowed end-points to MIN or MAX. I don't think TREE_OVERFLOW means what you think it means in the context of bounds_of_var_in_loop - look at its bottom which does /* Even for valid range info, sometimes overflow flag will leak in. As GIMPLE IL should have no constants with TREE_OVERFLOW set, we drop them. */ if (TREE_OVERFLOW_P (*min)) *min = drop_tree_overflow (*min); if (TREE_OVERFLOW_P (*max)) *max = drop_tree_overflow (*max); and the code explicitly checks for overflow, doing range adjustments accordingly. So not sure what you're trying to fix here. Every use of TREE_OVERFLOW in the GIMPLE parts of the ME are a sign of a bug. Richard. > Pushed. > > gcc/ChangeLog: > > PR 97501/tree-optimization > * gimple-range.cc (gimple_ranger::range_of_ssa_name_with_loop_info): > Saturate overflows returned from SCEV. > > gcc/testsuite/ChangeLog: > > * gcc.dg/pr97501.c: New test. > --- > gcc/gimple-range.cc | 4 ++-- > gcc/testsuite/gcc.dg/pr97501.c | 14 ++++++++++++++ > 2 files changed, 16 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/pr97501.c > > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc > index e4864ba60f6..ed9609be68e 100644 > --- a/gcc/gimple-range.cc > +++ b/gcc/gimple-range.cc > @@ -1146,9 +1146,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info (irange &r, tree name, > // ?? We could do better here. Since MIN/MAX can only be an > // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call > // the ranger and solve anything not an integer. > - if (TREE_CODE (min) != INTEGER_CST) > + if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) > min = vrp_val_min (type); > - if (TREE_CODE (max) != INTEGER_CST) > + if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) > max = vrp_val_max (type); > r.set (min, max); > } > diff --git a/gcc/testsuite/gcc.dg/pr97501.c b/gcc/testsuite/gcc.dg/pr97501.c > new file mode 100644 > index 00000000000..aedac83962d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr97501.c > @@ -0,0 +1,14 @@ > +// { dg-do compile } > +// { dg-options "-O2" } > + > +static int c = 0; > + > +int main() { > + int b = 0; > + if (c) { > + for (;; b--) > + do > + b++; > + while (b); > + } > +} > -- > 2.26.2 >
On 10/21/20 8:19 AM, Richard Biener wrote: > On Tue, Oct 20, 2020 at 5:21 PM Aldy Hernandez via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: >> >> bounds_of_var_in_loop is returning an overflowed int, which is causing >> us to create a range for which we can't compare the bounds causing >> an ICE in verify_range. >> >> Overflowed bounds cause compare_values() to return -2, which we >> don't handle in verify_range. >> >> We don't represent overflowed ranges in irange, so this patch just >> saturates any overflowed end-points to MIN or MAX. > > I don't think TREE_OVERFLOW means what you think it means in the > context of bounds_of_var_in_loop - look at its bottom which does > > /* Even for valid range info, sometimes overflow flag will leak in. > As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > drop them. */ > if (TREE_OVERFLOW_P (*min)) > *min = drop_tree_overflow (*min); > if (TREE_OVERFLOW_P (*max)) > *max = drop_tree_overflow (*max); Interesting. If these values "leaked" in. Should they have been fixed at the source, instead of after the fact? You mention below that every use of TREE_OVERFLOW in the ME is a bug, should we clean them up before arriving in gimple, or are there legitimate uses of it? > > and the code explicitly checks for overflow, doing range adjustments > accordingly. Well, not all overflows are adjusted: /* Like in PR19590, scev can return a constant function. */ if (is_gimple_min_invariant (chrec)) { *min = *max = chrec; return true; } Are these min/max not adjusted for overflow by design, or is this an oversight? If the latter, we could instead what I do below. What do you think? Thanks for the feedback. Aldy diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index b790d62d75f..c5520e0700b 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -1156,9 +1156,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info (irange &r, tree name, // ?? We could do better here. Since MIN/MAX can only be an // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call // the ranger and solve anything not an integer. - if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) + if (TREE_CODE (min) != INTEGER_CST) min = vrp_val_min (type); - if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) + if (TREE_CODE (max) != INTEGER_CST) max = vrp_val_max (type); r.set (min, max); } diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 67c88006f13..7778ceccf0a 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -1844,7 +1844,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, if (is_gimple_min_invariant (chrec)) { *min = *max = chrec; - return true; + goto fix_overflow; } if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) @@ -1964,6 +1964,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, else *min = init; + fix_overflow: /* Even for valid range info, sometimes overflow flag will leak in. As GIMPLE IL should have no constants with TREE_OVERFLOW set, we drop them. */
On Wed, Oct 21, 2020 at 9:30 AM Aldy Hernandez <aldyh@redhat.com> wrote: > > > > On 10/21/20 8:19 AM, Richard Biener wrote: > > On Tue, Oct 20, 2020 at 5:21 PM Aldy Hernandez via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > >> > >> bounds_of_var_in_loop is returning an overflowed int, which is causing > >> us to create a range for which we can't compare the bounds causing > >> an ICE in verify_range. > >> > >> Overflowed bounds cause compare_values() to return -2, which we > >> don't handle in verify_range. > >> > >> We don't represent overflowed ranges in irange, so this patch just > >> saturates any overflowed end-points to MIN or MAX. > > > > I don't think TREE_OVERFLOW means what you think it means in the > > context of bounds_of_var_in_loop - look at its bottom which does > > > > /* Even for valid range info, sometimes overflow flag will leak in. > > As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > > drop them. */ > > if (TREE_OVERFLOW_P (*min)) > > *min = drop_tree_overflow (*min); > > if (TREE_OVERFLOW_P (*max)) > > *max = drop_tree_overflow (*max); > > Interesting. > > If these values "leaked" in. Should they have been fixed at the source, > instead of after the fact? You mention below that every use of > TREE_OVERFLOW in the ME is a bug, should we clean them up before > arriving in gimple, or are there legitimate uses of it? There are no legitimate uses in GIMPLE. They are (ab-)used by GENERIC folding for propagating overflow (also used in FE diagnostics). Generally the better way is to use wide_ints overflow handling which also "sticks". > > > > and the code explicitly checks for overflow, doing range adjustments > > accordingly. > > Well, not all overflows are adjusted: > > /* Like in PR19590, scev can return a constant function. */ > if (is_gimple_min_invariant (chrec)) > { > *min = *max = chrec; > return true; > } > > Are these min/max not adjusted for overflow by design, or is this an > oversight? Ah, that's an oversight here. And yes, "fixing" it in scalar evolution analysis itself (dropping the flag there) would be best > > If the latter, we could instead what I do below. What do you think? Yeah, though *cough* goto ... (well, not so bad I guess) Thanks, Richard. > Thanks for the feedback. > Aldy > > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc > index b790d62d75f..c5520e0700b 100644 > --- a/gcc/gimple-range.cc > +++ b/gcc/gimple-range.cc > @@ -1156,9 +1156,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info > (irange &r, tree name, > // ?? We could do better here. Since MIN/MAX can only be an > // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call > // the ranger and solve anything not an integer. > - if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) > + if (TREE_CODE (min) != INTEGER_CST) > min = vrp_val_min (type); > - if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) > + if (TREE_CODE (max) != INTEGER_CST) > max = vrp_val_max (type); > r.set (min, max); > } > diff --git a/gcc/vr-values.c b/gcc/vr-values.c > index 67c88006f13..7778ceccf0a 100644 > --- a/gcc/vr-values.c > +++ b/gcc/vr-values.c > @@ -1844,7 +1844,7 @@ bounds_of_var_in_loop (tree *min, tree *max, > range_query *query, > if (is_gimple_min_invariant (chrec)) > { > *min = *max = chrec; > - return true; > + goto fix_overflow; > } > > if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) > @@ -1964,6 +1964,7 @@ bounds_of_var_in_loop (tree *min, tree *max, > range_query *query, > else > *min = init; > > + fix_overflow: > /* Even for valid range info, sometimes overflow flag will leak in. > As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > drop them. */ >
On 10/21/20 9:59 AM, Richard Biener wrote: >>> /* Even for valid range info, sometimes overflow flag will leak in. >>> As GIMPLE IL should have no constants with TREE_OVERFLOW set, we >>> drop them. */ >>> if (TREE_OVERFLOW_P (*min)) >>> *min = drop_tree_overflow (*min); >>> if (TREE_OVERFLOW_P (*max)) >>> *max = drop_tree_overflow (*max); >> >> Interesting. >> >> If these values "leaked" in. Should they have been fixed at the source, >> instead of after the fact? You mention below that every use of >> TREE_OVERFLOW in the ME is a bug, should we clean them up before >> arriving in gimple, or are there legitimate uses of it? > > There are no legitimate uses in GIMPLE. They are (ab-)used by > GENERIC folding for propagating overflow (also used in FE > diagnostics). Generally the better way is to use wide_ints overflow > handling which also "sticks". If there are no legitimate uses, perhaps we should drop them altogether as we go into GIMPLE?? I vaguely recall seeing them leak into value_range's. > >>> >>> and the code explicitly checks for overflow, doing range adjustments >>> accordingly. >> >> Well, not all overflows are adjusted: >> >> /* Like in PR19590, scev can return a constant function. */ >> if (is_gimple_min_invariant (chrec)) >> { >> *min = *max = chrec; >> return true; >> } >> >> Are these min/max not adjusted for overflow by design, or is this an >> oversight? > > Ah, that's an oversight here. And yes, "fixing" it in scalar evolution > analysis itself (dropping the flag there) would be best Excellent. I've pushed the patch below after testing it. Thanks again. Aldy Adjust overflow for invariants in bounds_of_var_in_loop. Invariants returned from SCEV can have TREE_OVERFLOW set. Clear the overflow as we do with the rest of the values returned from this function. gcc/ChangeLog: * gimple-range.cc (gimple_ranger::range_of_ssa_name_with_loop_info): Remove TREE_OVERFLOW special case. * vr-values.c (bounds_of_var_in_loop): Adjust overflow for invariants. diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index b790d62d75f..c5520e0700b 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -1156,9 +1156,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info (irange &r, tree name, // ?? We could do better here. Since MIN/MAX can only be an // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call // the ranger and solve anything not an integer. - if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) + if (TREE_CODE (min) != INTEGER_CST) min = vrp_val_min (type); - if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) + if (TREE_CODE (max) != INTEGER_CST) max = vrp_val_max (type); r.set (min, max); } diff --git a/gcc/vr-values.c b/gcc/vr-values.c index cc0ddca2bd3..7a0e70eab64 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -1844,7 +1844,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, if (is_gimple_min_invariant (chrec)) { *min = *max = chrec; - return true; + goto fix_overflow; } if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) @@ -1964,6 +1964,7 @@ bounds_of_var_in_loop (tree *min, tree *max, range_query *query, else *min = init; + fix_overflow: /* Even for valid range info, sometimes overflow flag will leak in. As GIMPLE IL should have no constants with TREE_OVERFLOW set, we drop them. */
On Wed, Oct 21, 2020 at 10:50 AM Aldy Hernandez <aldyh@redhat.com> wrote: > > > > On 10/21/20 9:59 AM, Richard Biener wrote: > > >>> /* Even for valid range info, sometimes overflow flag will leak in. > >>> As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > >>> drop them. */ > >>> if (TREE_OVERFLOW_P (*min)) > >>> *min = drop_tree_overflow (*min); > >>> if (TREE_OVERFLOW_P (*max)) > >>> *max = drop_tree_overflow (*max); > >> > >> Interesting. > >> > >> If these values "leaked" in. Should they have been fixed at the source, > >> instead of after the fact? You mention below that every use of > >> TREE_OVERFLOW in the ME is a bug, should we clean them up before > >> arriving in gimple, or are there legitimate uses of it? > > > > There are no legitimate uses in GIMPLE. They are (ab-)used by > > GENERIC folding for propagating overflow (also used in FE > > diagnostics). Generally the better way is to use wide_ints overflow > > handling which also "sticks". > > If there are no legitimate uses, perhaps we should drop them altogether > as we go into GIMPLE?? We do, but they tend to creep back in by infrastructure using the GENERIC folder. Some key places make sure to clear them (I've tracked down a lot of them). But I was never bave enough to assert they do not end up in IL operands ;) > I vaguely recall seeing them leak into > value_range's. > > > >>> > >>> and the code explicitly checks for overflow, doing range adjustments > >>> accordingly. > >> > >> Well, not all overflows are adjusted: > >> > >> /* Like in PR19590, scev can return a constant function. */ > >> if (is_gimple_min_invariant (chrec)) > >> { > >> *min = *max = chrec; > >> return true; > >> } > >> > >> Are these min/max not adjusted for overflow by design, or is this an > >> oversight? > > > > Ah, that's an oversight here. And yes, "fixing" it in scalar evolution > > analysis itself (dropping the flag there) would be best > > Excellent. I've pushed the patch below after testing it. > > Thanks again. > Aldy > > Adjust overflow for invariants in bounds_of_var_in_loop. > > Invariants returned from SCEV can have TREE_OVERFLOW set. Clear the > overflow as we do with the rest of the values returned from this > function. > > gcc/ChangeLog: > > * gimple-range.cc > (gimple_ranger::range_of_ssa_name_with_loop_info): > Remove TREE_OVERFLOW special case. > * vr-values.c (bounds_of_var_in_loop): Adjust overflow for > invariants. > > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc > index b790d62d75f..c5520e0700b 100644 > --- a/gcc/gimple-range.cc > +++ b/gcc/gimple-range.cc > @@ -1156,9 +1156,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info > (irange &r, tree name, > // ?? We could do better here. Since MIN/MAX can only be an > // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call > // the ranger and solve anything not an integer. > - if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) > + if (TREE_CODE (min) != INTEGER_CST) > min = vrp_val_min (type); > - if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) > + if (TREE_CODE (max) != INTEGER_CST) > max = vrp_val_max (type); > r.set (min, max); > } > diff --git a/gcc/vr-values.c b/gcc/vr-values.c > index cc0ddca2bd3..7a0e70eab64 100644 > --- a/gcc/vr-values.c > +++ b/gcc/vr-values.c > @@ -1844,7 +1844,7 @@ bounds_of_var_in_loop (tree *min, tree *max, > range_query *query, > if (is_gimple_min_invariant (chrec)) > { > *min = *max = chrec; > - return true; > + goto fix_overflow; > } > > if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) > @@ -1964,6 +1964,7 @@ bounds_of_var_in_loop (tree *min, tree *max, > range_query *query, > else > *min = init; > > + fix_overflow: > /* Even for valid range info, sometimes overflow flag will leak in. > As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > drop them. */ >
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index e4864ba60f6..ed9609be68e 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -1146,9 +1146,9 @@ gimple_ranger::range_of_ssa_name_with_loop_info (irange &r, tree name, // ?? We could do better here. Since MIN/MAX can only be an // SSA, SSA +- INTEGER_CST, or INTEGER_CST, we could easily call // the ranger and solve anything not an integer. - if (TREE_CODE (min) != INTEGER_CST) + if (TREE_CODE (min) != INTEGER_CST || TREE_OVERFLOW (min)) min = vrp_val_min (type); - if (TREE_CODE (max) != INTEGER_CST) + if (TREE_CODE (max) != INTEGER_CST || TREE_OVERFLOW (max)) max = vrp_val_max (type); r.set (min, max); } diff --git a/gcc/testsuite/gcc.dg/pr97501.c b/gcc/testsuite/gcc.dg/pr97501.c new file mode 100644 index 00000000000..aedac83962d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97501.c @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-O2" } + +static int c = 0; + +int main() { + int b = 0; + if (c) { + for (;; b--) + do + b++; + while (b); + } +}