aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/pr111845.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr111845.c47
-rw-r--r--gcc/tree-ssa-math-opts.cc48
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