On Thu, 26 Sep 2024, Andrew Pinski wrote: > On Tue, Oct 15, 2013 at 6:57 AM Richard Biener <rguent...@suse.de> wrote: > > > > > > This is an alternate fix (see > > http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00234.html for the other > > one) for the various PRs that show that LIM exposes undefined > > signed overflow on paths where it wasn't executed before LIM > > ultimately leading to a miscompilation. > > > > For this fix we rewrite invariant stmts to use unsigned arithmetic > > when it is one of the operations that SCEV and niter analysis > > handles (thus not division or absolute). The other fix instead > > disables invariant motion for those expressions. > > > > Bootstrapped and tested on x86_64-unknown-linux-gnu. > > > > The issue is also present on the 4.8 branch, so either patch > > should be backported in the end. I will try to benchmark > > both tomorrow (unless somebody beats me on that). > > > > Any preference or other suggestions? > > > > Thanks, > > Richard. > > > > 2013-10-15 Richard Biener <rguent...@suse.de> > > > > PR tree-optimization/58143 > > * tree-ssa-loop-im.c (arith_code_with_undefined_signed_overflow): > > New function. > > (rewrite_to_defined_overflow): Likewise. > > (move_computations_dom_walker::before_dom): Rewrite stmts > > with undefined signed overflow that are not always executed > > into unsigned arithmetic. > > > > * gcc.dg/torture/pr58143-1.c: New testcase. > > * gcc.dg/torture/pr58143-2.c: Likewise. > > * gcc.dg/torture/pr58143-3.c: Likewise. > > > > Index: gcc/tree-ssa-loop-im.c > > =================================================================== > > *** gcc/tree-ssa-loop-im.c (revision 203600) > > --- gcc/tree-ssa-loop-im.c (working copy) > > *************** public: > > *** 1117,1122 **** > > --- 1117,1183 ---- > > unsigned int todo_; > > }; > > > > + /* Return true if CODE is an operation that when operating on signed > > + integer types involves undefined behavior on overflow and the > > + operation can be expressed with unsigned arithmetic. */ > > + > > + static bool > > + arith_code_with_undefined_signed_overflow (tree_code code) > > + { > > + switch (code) > > + { > > + case PLUS_EXPR: > > + case MINUS_EXPR: > > + case MULT_EXPR: > > + case NEGATE_EXPR: > > + case POINTER_PLUS_EXPR: > > + return true; > > + default: > > + return false; > > + } > > + } > > + > > + /* Rewrite STMT, an assignment with a signed integer or pointer arithmetic > > + operation that can be transformed to unsigned arithmetic by converting > > + its operand, carrying out the operation in the corresponding unsigned > > + type and converting the result back to the original type. > > + > > + Returns a sequence of statements that replace STMT and also contain > > + a modified form of STMT itself. */ > > + > > + static gimple_seq > > + rewrite_to_defined_overflow (gimple stmt) > > + { > > + if (dump_file && (dump_flags & TDF_DETAILS)) > > + { > > + fprintf (dump_file, "rewriting stmt with undefined signed " > > + "overflow "); > > + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); > > + } > > + > > + tree lhs = gimple_assign_lhs (stmt); > > + tree type = unsigned_type_for (TREE_TYPE (lhs)); > > + gimple_seq stmts = NULL; > > + for (unsigned i = 1; i < gimple_num_ops (stmt); ++i) > > + { > > + gimple_seq stmts2 = NULL; > > + gimple_set_op (stmt, i, > > + force_gimple_operand (fold_convert (type, > > + gimple_op (stmt, > > i)), > > + &stmts2, true, NULL_TREE)); > > + gimple_seq_add_seq (&stmts, stmts2); > > + } > > + gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt)); > > + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) > > + gimple_assign_set_rhs_code (stmt, PLUS_EXPR); > > + gimple_seq_add_stmt (&stmts, stmt); > > + gimple cvt = gimple_build_assign_with_ops > > + (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE); > > + gimple_seq_add_stmt (&stmts, cvt); > > + > > + return stmts; > > + } > > + > > /* Hoist the statements in basic block BB out of the loops prescribed by > > data stored in LIM_DATA structures associated with each statement. > > Callback > > for walk_dominator_tree. */ > > *************** move_computations_dom_walker::before_dom > > *** 1247,1253 **** > > } > > } > > gsi_remove (&bsi, false); > > ! gsi_insert_on_edge (e, stmt); > > } > > } > > > > --- 1308,1328 ---- > > } > > } > > gsi_remove (&bsi, false); > > ! /* In case this is a stmt that is not unconditionally executed > > ! when the target loop header is executed and the stmt may > > ! invoke undefined integer or pointer overflow rewrite it to > > ! unsigned arithmetic. */ > > ! if (is_gimple_assign (stmt) > > ! && 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)) > > I was trying to consolidate the checks into a single function which > checked before calling rewrite_to_defined_overflow and noticed that > this above check and the comment disagree. The comment talks about > pointers but pointers are not handled in the code.
Oops (arith_code_with_undefined_signed_overflow handles POINTER_PLUS_EXPR, misses POINTER_DIFF_EXPR now). I think I intended to handle pointers as well here. > If we do pointers also for rewrite_to_defined_overflow; > gcc.c-torture/execute/pr111422.c starts to fail at -O3 as the > workaround for the stack reuse issue is no longer working for some > reason. > Should we fix the comment and not call rewrite_to_defined_overflow for > pointers or is the fix to add the check for pointers and xfail > pr111422.c for -O3 and open a new bug? It would be good to fix the issue with stack-reuse since for example IVOPTs will happily rewrite pointer arith to unsigned and I suspect the extra casts might be the issue here. So I think yes, we want to fix the above. Richard. > Thanks, > Andrew > > > > ! && (!ALWAYS_EXECUTED_IN (bb) > > ! || !(ALWAYS_EXECUTED_IN (bb) == level > > ! || flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level)))) > > ! gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt)); > > ! else > > ! gsi_insert_on_edge (e, stmt); > > } > > } > > > > Index: gcc/testsuite/gcc.dg/torture/pr58143-1.c > > =================================================================== > > *** gcc/testsuite/gcc.dg/torture/pr58143-1.c (revision 0) > > --- gcc/testsuite/gcc.dg/torture/pr58143-1.c (working copy) > > *************** > > *** 0 **** > > --- 1,51 ---- > > + /* { dg-do run } */ > > + /* { dg-additional-options "-fstrict-overflow" } */ > > + > > + extern void abort (void); > > + > > + int a, b, c, d, e, f, g, h = 1, i; > > + > > + int foo (int p) > > + { > > + return p < 0 && a < - __INT_MAX__ - 1 - p ? 0 : 1; > > + } > > + > > + int *bar () > > + { > > + int j; > > + i = h ? 0 : 1 % h; > > + for (j = 0; j < 1; j++) > > + for (d = 0; d; d++) > > + for (e = 1; e;) > > + return 0; > > + return 0; > > + } > > + > > + int baz () > > + { > > + for (; b >= 0; b--) > > + for (c = 1; c >= 0; c--) > > + { > > + int *k = &c; > > + for (;;) > > + { > > + for (f = 0; f < 1; f++) > > + { > > + g = foo (*k); > > + bar (); > > + } > > + if (*k) > > + break; > > + return 0; > > + } > > + } > > + return 0; > > + } > > + > > + int main () > > + { > > + baz (); > > + if (b != 0) > > + abort (); > > + return 0; > > + } > > Index: gcc/testsuite/gcc.dg/torture/pr58143-2.c > > =================================================================== > > *** gcc/testsuite/gcc.dg/torture/pr58143-2.c (revision 0) > > --- gcc/testsuite/gcc.dg/torture/pr58143-2.c (working copy) > > *************** > > *** 0 **** > > --- 1,34 ---- > > + /* { dg-do run } */ > > + /* { dg-additional-options "-fstrict-overflow" } */ > > + > > + int a, b, d, e, f, *g, h, i; > > + volatile int c; > > + > > + char foo (unsigned char p) > > + { > > + return p + 1; > > + } > > + > > + int bar () > > + { > > + for (h = 0; h < 3; h = foo (h)) > > + { > > + c; > > + for (f = 0; f < 1; f++) > > + { > > + i = a && 0 < -__INT_MAX__ - h ? 0 : 1; > > + if (e) > > + for (; d;) > > + b = 0; > > + else > > + g = 0; > > + } > > + } > > + return 0; > > + } > > + > > + int main () > > + { > > + bar (); > > + return 0; > > + } > > Index: gcc/testsuite/gcc.dg/torture/pr58143-3.c > > =================================================================== > > *** gcc/testsuite/gcc.dg/torture/pr58143-3.c (revision 0) > > --- gcc/testsuite/gcc.dg/torture/pr58143-3.c (working copy) > > *************** > > *** 0 **** > > --- 1,18 ---- > > + /* { dg-do run } */ > > + /* { dg-additional-options "-fstrict-overflow" } */ > > + > > + int a, b, c, d, e; > > + > > + int > > + main () > > + { > > + for (b = 4; b > -30; b--) > > + for (; c;) > > + for (;;) > > + { > > + e = a > __INT_MAX__ - b; > > + if (d) > > + break; > > + } > > + return 0; > > + } > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)