From bc228ba1571ffea2c7a33835a88e1f0509d3378b Mon Sep 17 00:00:00 2001 From: rguenth Date: Thu, 17 Oct 2013 09:59:47 +0000 Subject: [PATCH] 2013-10-17 Richard Biener 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@203745 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 +++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/torture/pr58143-1.c | 51 +++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr58143-2.c | 34 ++++++++++++++ gcc/testsuite/gcc.dg/torture/pr58143-3.c | 18 ++++++++ gcc/tree-ssa-loop-im.c | 77 +++++++++++++++++++++++++++++++- 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr58143-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr58143-2.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr58143-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index de8bf8891a9..5a8fb7f2242 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2013-10-17 Richard Biener + + 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. + 2013-10-16 Michael Meissner PR target/57756 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8be60258613..dce8a58de8c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-10-17 Richard Biener + + PR tree-optimization/58143 + * gcc.dg/torture/pr58143-1.c: New testcase. + * gcc.dg/torture/pr58143-2.c: Likewise. + * gcc.dg/torture/pr58143-3.c: Likewise. + 2013-10-17 Marek Polacek PR c/58267 diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-1.c b/gcc/testsuite/gcc.dg/torture/pr58143-1.c new file mode 100644 index 00000000000..855515edb97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58143-1.c @@ -0,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; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-2.c b/gcc/testsuite/gcc.dg/torture/pr58143-2.c new file mode 100644 index 00000000000..dd0dae1efe0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58143-2.c @@ -0,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; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58143-3.c b/gcc/testsuite/gcc.dg/torture/pr58143-3.c new file mode 100644 index 00000000000..23ae9cd39ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58143-3.c @@ -0,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; +} diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 84f50cdb92d..15af428f51f 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -1117,6 +1117,67 @@ public: 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. */ @@ -1247,7 +1308,21 @@ move_computations_dom_walker::before_dom_children (basic_block bb) } } gsi_remove (&bsi, false); - gsi_insert_on_edge (e, stmt); + /* 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)) + && (!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); } } -- 2.11.4.GIT