https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69224
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot
gnu.org
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
Ok, so the issue is that discover_iteration_bound_by_body_walk adds one to the
upper bound derived for s->x[j] (5) because
/* Exit terminates loop at given iteration, while non-exits produce
undefined
effect on the next iteration. */
and after unrolling to 6 iterations we do
Latch of last iteration was marked by __builtin_unreachable ().
Forced statement unreachable: _25 = s_7(D)->x[_24];
Forced statement unreachable: _22 = s_7(D)->x[j_2];
so figure both reads have undefined behavior in iteration 6. But we never
try to force stmts unreachable in earlier iterations - s->x[j + 1] is
already undefined in iteration 5 which would end up removing that iteration
completely. remove_exits_and_undefined_stmts only has links to stmts in
the original loop body (which will become the last iteration), so marking
stmts unreachable would need to be done during
gimple_duplicate_loop_to_header_edge itself to catch this case.
Or avoid the + 1 in discover_iteration_bound_by_body_walk for unconditionally
executed "bounds".
So the following untested patch fixes the issue by unrolling one iteration
less.
Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c (revision 233661)
+++ gcc/tree-ssa-loop-niter.c (working copy)
@@ -3171,9 +3171,12 @@ discover_iteration_bound_by_body_walk (s
{
widest_int bound = elt->bound;
- /* Exit terminates loop at given iteration, while non-exits produce
undefined
- effect on the next iteration. */
- if (!elt->is_exit)
+ /* Exit terminates loop at given iteration, while non-exits produce
+ undefined effect on the next iteration. Unless they are always
+ executed. */
+ if (!elt->is_exit
+ && ! dominated_by_p (CDI_DOMINATORS, loop->latch,
+ gimple_bb (elt->stmt)))
{
bound += 1;
/* If an overflow occurred, ignore the result. */
@@ -3203,7 +3206,9 @@ discover_iteration_bound_by_body_walk (s
for (elt = loop->bounds; elt; elt = elt->next)
{
widest_int bound = elt->bound;
- if (!elt->is_exit)
+ if (!elt->is_exit
+ && ! dominated_by_p (CDI_DOMINATORS, loop->latch,
+ gimple_bb (elt->stmt)))
{
bound += 1;
/* If an overflow occurred, ignore the result. */