This is an archive of the discontinued LLVM Phabricator instance.

[LoopSimplify] Simplify constant conditional branches to unconditional branches
AbandonedPublic

Authored by anna on Apr 21 2017, 8:13 AM.

Details

Summary

This is an enhancement to add support to loop-simplify to change constant
conditional branches (eg: `br i1 true, label L1, label L2) to unconditional
branches (br label L1).
This will remove blocks from the
loop in the process. We avoid cases where a loop is completely removed.

Added test cases shows various use cases for the transformation. The benefit
would be for these branches that are created after loop-unswitching, can be
cleaned up using loop-simplifycfg.

Event Timeline

anna created this revision.Apr 21 2017, 8:13 AM
anna updated this revision to Diff 96146.Apr 21 2017, 8:20 AM

Missed adding the test file, and removed some messages used while debugging.

efriedma added inline comments.
lib/Transforms/Scalar/LoopSimplifyCFG.cpp
97

This is pretty clearly false... for example, consider:

OldDest:
  br label %OldDest

OldDest is no longer a Loop in the LLVM sense because loops only exist in reachable code.

Or consider the case where OldDest == block; L is not a loop anymore because you deleted the backedge.

157

You're messing up updating dominfo in many ways besides this.

efriedma added inline comments.Apr 21 2017, 12:39 PM
lib/Transforms/Scalar/LoopSimplifyCFG.cpp
97

Err, the OldDest == block example doesn't precisely work because the other branch would be an exit. Better example:

block1:
  br label %block2

block2:
  bi i1 true, label %block2, label %block1

You're destroying the outer loop by deleting its backedge.

anna planned changes to this revision.Apr 21 2017, 1:45 PM

Based on Eli's comments, this definitely needs more thought.

lib/Transforms/Scalar/LoopSimplifyCFG.cpp
97

In the first example:

OldDest:
  br label %OldDest

I was under the impression we are only worried about making a loop become a non-loop by removing back edge (see line 70). From what I understood, we *are removing loops* if a loop that was originally unreachable, i.e. the selfLoop OldDest is now *effectively* unreachable. By effectively unreachable, I mean the edge that targets the OldDest is deleted (when it was originally unreachable - the branch existed, but it was never taken).

97

The outerloop example is very useful. Thank you! I think even changing the check in line 70, to consider getLoopFor for both target blocks would not be enough. Again, it would be making an llvm loop become a non-loop because it is not reachable. Will have to think about this more.

efriedma added inline comments.Apr 21 2017, 3:26 PM
lib/Transforms/Scalar/LoopSimplifyCFG.cpp
97

For the first example, folding the branch turns a loop into unreachable code. That unreachable code might look like a loop, but LoopInfo ignores any code which isn't reachable from the entry block, so you have to erase the Loop* for that loop.

anna abandoned this revision.Apr 21 2017, 3:40 PM

Thanks for the comments, Eli. As proven, the implicit assumption that loops won't be removed is not true. I had a chat with Chandler on IRC, and his suggestion was to merge the loop-deletion pass and loop-simplifyCFG (loop deletion is a form of simplifyCFG for loop).
Effectively, when we change branches to unconditional, we will be deleting loops in someway or another:

  1. a subloop becomes unreachable, i.e. a branch to the header is removed.
  2. a parent loop is a non-loop because it's backedge is removed.

Abandoning this revision, since this requires major rework from current state.