diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/pr111845.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr111845.c | 47 | ||||
-rw-r--r-- | gcc/tree-ssa-math-opts.cc | 48 |
3 files changed, 94 insertions, 17 deletions
diff --git a/gcc/testsuite/gcc.dg/pr111845.c b/gcc/testsuite/gcc.dg/pr111845.c new file mode 100644 index 0000000..1bcb4f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr111845.c @@ -0,0 +1,16 @@ +/* PR tree-optimization/111845 */ +/* { dg-do compile } */ +/* { dg-options "-O2 --param tree-reassoc-width=2" } */ + +int a, b; +unsigned int c, d, e; + +void +foo (int x) +{ + b += d; + c += b < d; + b += e = a < x; + c += b; + c += b < e; +} diff --git a/gcc/testsuite/gcc.target/i386/pr111845.c b/gcc/testsuite/gcc.target/i386/pr111845.c new file mode 100644 index 0000000..d52110a --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr111845.c @@ -0,0 +1,47 @@ +/* PR tree-optimization/111845 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -g -masm=att" } */ +/* { dg-final { scan-assembler-times "\tadcq\t" 8 { target lp64 } } } */ +/* { dg-final { scan-assembler-times "\tadcl\t" 8 { target ia32 } } } */ + +unsigned long l, m; + +__attribute__((noipa)) void +foo (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int a, int b) +{ + unsigned long c, d; + unsigned long e = __builtin_add_overflow (x, y, &c); + unsigned long f = __builtin_add_overflow (c, a < b, &d); + m = ((h + i) + e) + f; + l = d; +} + +__attribute__((noipa)) void +bar (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int a, int b) +{ + unsigned long c, d; + unsigned long e = __builtin_add_overflow (x, y, &c); + unsigned long f = __builtin_add_overflow (c, a < b, &d); + m = (h + (i + e)) + f; + l = d; +} + +__attribute__((noipa)) void +baz (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int a, int b) +{ + unsigned long c, d; + unsigned long e = __builtin_add_overflow (x, y, &c); + unsigned long f = __builtin_add_overflow (c, a < b, &d); + m = h + (i + (e + f)); + l = d; +} + +__attribute__((noipa)) void +qux (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int a, int b) +{ + unsigned long c, d; + unsigned long e = __builtin_add_overflow (x, y, &c); + unsigned long f = __builtin_add_overflow (c, a < b, &d); + m = h + ((i + e) + f); + l = d; +} diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 51c14d6..363f316 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -4581,6 +4581,7 @@ match_uaddc_usubc (gimple_stmt_iterator *gsi, gimple *stmt, tree_code code) if (!INTEGRAL_TYPE_P (type) || !TYPE_UNSIGNED (type)) return false; + auto_vec<gimple *, 2> temp_stmts; if (code != BIT_IOR_EXPR && code != BIT_XOR_EXPR) { /* If overflow flag is ignored on the MSB limb, we can end up with @@ -4615,26 +4616,29 @@ match_uaddc_usubc (gimple_stmt_iterator *gsi, gimple *stmt, tree_code code) rhs[0] = gimple_assign_rhs1 (g); tree &r = rhs[2] ? rhs[3] : rhs[2]; r = r2; + temp_stmts.quick_push (g); } else break; } - while (TREE_CODE (rhs[1]) == SSA_NAME && !rhs[3]) - { - gimple *g = SSA_NAME_DEF_STMT (rhs[1]); - if (has_single_use (rhs[1]) - && is_gimple_assign (g) - && gimple_assign_rhs_code (g) == PLUS_EXPR) - { - rhs[1] = gimple_assign_rhs1 (g); - if (rhs[2]) - rhs[3] = gimple_assign_rhs2 (g); - else - rhs[2] = gimple_assign_rhs2 (g); - } - else - break; - } + for (int i = 1; i <= 2; ++i) + while (rhs[i] && TREE_CODE (rhs[i]) == SSA_NAME && !rhs[3]) + { + gimple *g = SSA_NAME_DEF_STMT (rhs[i]); + if (has_single_use (rhs[i]) + && is_gimple_assign (g) + && gimple_assign_rhs_code (g) == PLUS_EXPR) + { + rhs[i] = gimple_assign_rhs1 (g); + if (rhs[2]) + rhs[3] = gimple_assign_rhs2 (g); + else + rhs[2] = gimple_assign_rhs2 (g); + temp_stmts.quick_push (g); + } + else + break; + } /* If there are just 3 addends or one minuend and two subtrahends, check for UADDC or USUBC being pattern recognized earlier. Say r = op1 + op2 + ovf1 + ovf2; where the (ovf1 + ovf2) part @@ -5039,7 +5043,17 @@ match_uaddc_usubc (gimple_stmt_iterator *gsi, gimple *stmt, tree_code code) g = gimple_build_assign (ilhs, IMAGPART_EXPR, build1 (IMAGPART_EXPR, TREE_TYPE (ilhs), nlhs)); if (rhs[2]) - gsi_insert_before (gsi, g, GSI_SAME_STMT); + { + gsi_insert_before (gsi, g, GSI_SAME_STMT); + /* Remove some further statements which can't be kept in the IL because + they can use SSA_NAMEs whose setter is going to be removed too. */ + while (temp_stmts.length ()) + { + g = temp_stmts.pop (); + gsi2 = gsi_for_stmt (g); + gsi_remove (&gsi2, true); + } + } else gsi_replace (gsi, g, true); /* Remove some statements which can't be kept in the IL because they |