Strange loop unrolling problem

I am having a strange problem with loop unrolling. Attached is
a small example that demonstrates what happens.

There is a for-loop with a known trip count, and some control
flow inside the loop. If the condition of the control flow only
depends on the loop index and loop invariant variables, the loop
is not unrolled. However, if the condition involves potentially
loop variant variables, the loop does get unrolled.

The volatile variable assignments are there just to keep loop
body from disappearing completely. In the real case this
is derived from, the loop body contains some inline assembly.

The code within #ifdef MODIFY_V2 in the attached C code is in
fact dead code, as the condition of the if statement is never
true. However, including this dead code in the compilation
causes unrolling to take place.

Am I missing something or should I file a bug? I tried looking
around at LoopUnroll.cpp and UnrollLoop.cpp, but did not find
an immediate cause for this. From the debug output it looks like
instcombine is doing different things in the two cases.

unroll.c (380 Bytes)

Makefile (199 Bytes)

Pertti Kellomäki wrote:

I am having a strange problem with loop unrolling.

Forgot to mention that this happens both with 2.5 and svn trunk.

A short while ago I wrote about the strange loop unrolling
behavior we encountered. The problem was that with -O3,
the following loop does not get unrolled if the ifdef'ed
dead code is not present.

Hi,

Any ideas which pass does the lifting of the `then' branch?

if optimizing with "opt -std-compile-opts" shows this problem
then you can find the problematic pass using the following
method:
(1) run "opt -std-compile-opts -debug-pass=Arguments" to find
out which passes opt is running.
(2) run opt with that list of passes rather than -std-compile-opts.
(3) drop passes from the end of the list as long as the problematic
transform is still happening. At some point the problem will
disappear when you drop a pass. Then that pass is presumably
doing the transform. A more sophisticated version of this is
to do bisection on the list of passes.

Ciao,

Duncan.

Duncan Sands wrote:

if optimizing with "opt -std-compile-opts" shows this problem
then you can find the problematic pass using the following
method:
(1) run "opt -std-compile-opts -debug-pass=Arguments" to find
out which passes opt is running.
(2) run opt with that list of passes rather than -std-compile-opts.
(3) drop passes from the end of the list as long as the problematic
transform is still happening.

Thanks. It seems that it is -jump-threading doing the transformation.
Eliminating it or moving it past -loop-unroll makes the loop unroll.

This fixes our immediate problem, since we are running opt from
a script, so we can shuffle the passes around. I wonder if it is
worth filing a PR for LLVM?

Hi Pertti,

This is a major problem of the jump threading pass. I've fixed it in r70820, thanks for bringing this up!

-Chris