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.
This commit is contained in:
Richard Biener 2024-04-03 14:53:30 +02:00
parent fe385c2199
commit e152177b36
2 changed files with 38 additions and 2 deletions

View file

@ -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;
}

View file

@ -653,8 +653,26 @@ split_loop (class loop *loop1)
gimple_seq stmts2; gimple_seq stmts2;
border = force_gimple_operand (border, &stmts2, true, NULL_TREE); border = force_gimple_operand (border, &stmts2, true, NULL_TREE);
if (stmts2) 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, tree cond = fold_build2 (guard_code, boolean_type_node,
guard_init, border); guard_init, border);
if (!initial_true) if (!initial_true)