aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-04-03 14:53:30 +0200
committerRichard Biener <rguenther@suse.de>2024-04-04 09:00:06 +0200
commite152177b362143465e2b9d721ea632cae3f13445 (patch)
tree961dfefa1e24808b7ce3a1b81a4cdcc28dfb91f9 /gcc
parentfe385c219994f6d5c1ffe00bcaf5a62c3d18caaf (diff)
downloadgcc-e152177b362143465e2b9d721ea632cae3f13445.zip
gcc-e152177b362143465e2b9d721ea632cae3f13445.tar.gz
gcc-e152177b362143465e2b9d721ea632cae3f13445.tar.bz2
tree-optimization/114551 - loop splitting and undefined overflow
When loop splitting hoists a guard computation it needs to make sure that can be safely evaluated at this place when it was previously only conditionally evaluated. The following fixes this for the case of undefined overflow. PR tree-optimization/114551 * tree-ssa-loop-split.cc (split_loop): If the guard is only conditionally evaluated rewrite computations with possibly undefined overflow to unsigned arithmetic. * gcc.dg/torture/pr114551.c: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr114551.c18
-rw-r--r--gcc/tree-ssa-loop-split.cc22
2 files changed, 38 insertions, 2 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr114551.c b/gcc/testsuite/gcc.dg/torture/pr114551.c
new file mode 100644
index 0000000..13c15fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr114551.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+int a, b[4], c, d, e, f;
+int main()
+{
+ a--;
+ for (f = 3; f >= 0; f--)
+ {
+ for (e = 0; e < 4; e++)
+ c = 0;
+ for (; c < 4; c++)
+ {
+ d = f && a > 0 && f > (2147483647 - a) ? 0 : b[f];
+ continue;
+ }
+ }
+ return 0;
+}
diff --git a/gcc/tree-ssa-loop-split.cc b/gcc/tree-ssa-loop-split.cc
index c0bb1b7..a770ea3 100644
--- a/gcc/tree-ssa-loop-split.cc
+++ b/gcc/tree-ssa-loop-split.cc
@@ -653,8 +653,26 @@ split_loop (class loop *loop1)
gimple_seq stmts2;
border = force_gimple_operand (border, &stmts2, true, NULL_TREE);
if (stmts2)
- gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop1),
- stmts2);
+ {
+ /* When the split condition is not always evaluated make sure
+ to rewrite it to defined overflow. */
+ if (!dominated_by_p (CDI_DOMINATORS, exit1->src, bbs[i]))
+ {
+ gimple_stmt_iterator gsi;
+ gsi = gsi_start (stmts2);
+ while (!gsi_end_p (gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (is_gimple_assign (stmt)
+ && arith_code_with_undefined_signed_overflow
+ (gimple_assign_rhs_code (stmt)))
+ rewrite_to_defined_overflow (&gsi);
+ gsi_next (&gsi);
+ }
+ }
+ gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop1),
+ stmts2);
+ }
tree cond = fold_build2 (guard_code, boolean_type_node,
guard_init, border);
if (!initial_true)