Richard Biener via Gcc-patches <gcc-patches@gcc.gnu.org> writes: > The following makes sure to rewrite arithmetic with undefined behavior > on overflow to a well-defined variant when moving them to be always > executed as part of doing if-conversion for loop vectorization. > > Bootstrapped and tested on x86_64-unknown-linux-gnu. > > Any comments?
LGTM FWIW, although… > Thanks, > Richard. > > 2021-10-11 Richard Biener <rguent...@suse.de> > > PR tree-optimization/102659 > * tree-if-conv.c (need_to_rewrite_undefined): New flag. > (if_convertible_gimple_assign_stmt_p): Mark the loop for > rewrite when stmts with undefined behavior on integer > overflow appear. > (combine_blocks): Predicate also when we need to rewrite stmts. > (predicate_statements): Rewrite affected stmts to something > with well-defined behavior on overflow. > (tree_if_conversion): Initialize need_to_rewrite_undefined. > > * gcc.dg/torture/pr69760.c: Adjust the testcase. > * gcc.target/i386/avx2-vect-mask-store-move1.c: Expect to move > the conversions to unsigned as well. > --- > gcc/testsuite/gcc.dg/torture/pr69760.c | 3 +- > .../i386/avx2-vect-mask-store-move1.c | 2 +- > gcc/tree-if-conv.c | 28 ++++++++++++++++++- > 3 files changed, 29 insertions(+), 4 deletions(-) > > diff --git a/gcc/testsuite/gcc.dg/torture/pr69760.c > b/gcc/testsuite/gcc.dg/torture/pr69760.c > index 53733c7c6a4..47e01ae59bd 100644 > --- a/gcc/testsuite/gcc.dg/torture/pr69760.c > +++ b/gcc/testsuite/gcc.dg/torture/pr69760.c > @@ -1,11 +1,10 @@ > /* PR tree-optimization/69760 */ > /* { dg-do run { target { { *-*-linux* *-*-gnu* *-*-uclinux* } && mmap } } } > */ > -/* { dg-options "-O2" } */ > > #include <unistd.h> > #include <sys/mman.h> > > -__attribute__((noinline, noclone)) void > +__attribute__((noinline, noclone)) static void > test_func (double *a, int L, int m, int n, int N) > { > int i, k; > diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c > b/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c > index 989ba402e0e..6a47a09c835 100644 > --- a/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c > +++ b/gcc/testsuite/gcc.target/i386/avx2-vect-mask-store-move1.c > @@ -78,4 +78,4 @@ avx2_test (void) > abort (); > } > > -/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 6 "vect" } } > */ > +/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 10 "vect" } } > */ > diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c > index d7b7b309309..6a67acfeaae 100644 > --- a/gcc/tree-if-conv.c > +++ b/gcc/tree-if-conv.c > @@ -132,6 +132,11 @@ along with GCC; see the file COPYING3. If not see > predicate_statements for the kinds of predication we support. */ > static bool need_to_predicate; > > +/* True if we have to rewrite stmts that may invoke undefined behavior > + when a condition C was false so it doesn't if it is always executed. > + See predicate_statements for the kinds of predication we support. */ > +static bool need_to_rewrite_undefined; > + > /* Indicate if there are any complicated PHIs that need to be handled in > if-conversion. Complicated PHI has more than two arguments and can't > be degenerated to two arguments PHI. See more information in comment > @@ -1042,6 +1047,12 @@ if_convertible_gimple_assign_stmt_p (gimple *stmt, > fprintf (dump_file, "tree could trap...\n"); > return false; > } > + else if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) > + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)) > + && arith_code_with_undefined_signed_overflow > + (gimple_assign_rhs_code (stmt))) > + /* We have to rewrite stmts with undefined overflow. */ > + need_to_rewrite_undefined = true; > > /* When if-converting stores force versioning, likewise if we > ended up generating store data races. */ > @@ -2563,6 +2574,20 @@ predicate_statements (loop_p loop) > > gsi_replace (&gsi, new_stmt, true); > } > + else if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt))) > + && TYPE_OVERFLOW_UNDEFINED > + (TREE_TYPE (gimple_assign_lhs (stmt))) > + && arith_code_with_undefined_signed_overflow > + (gimple_assign_rhs_code (stmt))) > + { > + gsi_remove (&gsi, true); > + gsi_insert_seq_before (&gsi, rewrite_to_defined_overflow (stmt), > + GSI_SAME_STMT); > + if (gsi_end_p (gsi)) > + gsi = gsi_last_bb (gimple_bb (stmt)); > + else > + gsi_prev (&gsi); …perhaps there should be a GSI_* for this idiom. Thanks, Richard > + } > else if (gimple_vdef (stmt)) > { > tree lhs = gimple_assign_lhs (stmt); > @@ -2647,7 +2672,7 @@ combine_blocks (class loop *loop) > insert_gimplified_predicates (loop); > predicate_all_scalar_phis (loop); > > - if (need_to_predicate) > + if (need_to_predicate || need_to_rewrite_undefined) > predicate_statements (loop); > > /* Merge basic blocks. */ > @@ -3148,6 +3173,7 @@ tree_if_conversion (class loop *loop, vec<gimple *> > *preds) > rloop = NULL; > ifc_bbs = NULL; > need_to_predicate = false; > + need_to_rewrite_undefined = false; > any_complicated_phi = false; > > /* Apply more aggressive if-conversion when loop or its outer loop were