[PATCH] [PR18861] Fix for LoopUnroll pass was breaking LCSSA form while completely removing loop

Andrew Trick atrick at apple.com
Fri May 9 15:44:00 PDT 2014


Thanks for fixing this bug! And sorry for the review delay.

I'm concerned that this implementation only handles some cases. I know
this code is super confusing, and your fix is better than nothing. But
we should try to generalize a bit because the existing LCSSA update is
full of missing corner cases. Your fix is just working around one specific
case with a new analysis.

In general, the problem is that full unrolling may cause some basic blocks to bubble up in the loop tree. Now some of the original loop's blocks may be shallower in the loop nest than others. The -view-cfg of each of the unloop.ll functions will hopefully show you some interesting cases. You have to have at least four levels of loops to see the interesting cases. Note that the problem you are solving is not limited to the case when a block "exits the function".

Also when replacing uses:

+                if (OiPN != Ui && Ui->getParent() == BB)
+                  Ui->replaceUsesOfWith(Oi, OiPN);

We need to replace all uses that are not contained in the defining instruction's parent loop.

The only clean, robust way of handling this is to rerun LCSSA
formation as a utility on any block on a path to a new loop exit after
unrolling. Trying to reimplement LCSSA formation and take shortcuts is
not a good idea, because the problem of updating after unrolling seems
subject to the same corner cases as the general problem. Also,
"updateUnloop" is only supposed to update LoopInfo so we don't want to
mess with that unless necessary.

Currently, LoopUnroll does attempt to rerun LCSSA on the parent loop. So the real question is, why does this fail to catch some cases? The problem is that it only handles loop exits that end up in the parent loop. Now, we don't want to rerun LCSSA on the whole function, so what do we do? The answer is to find the shallowest loop one level deeper than the shallowest exit and rerun formLCSSARecursively on that loop.

i.e.

- Outer->L1->L2->L3
- Fully unroll L3.
- If we see an exit to L1, formLCSSA for L2
- If we see an exit to Outer, formLCSSA for L1

Loop unrolling can probably notice these exits when setting up
branches. Then walk up the loop tree from the current loop to find the
child of the exit.

http://reviews.llvm.org/D2976






More information about the llvm-commits mailing list