- Before this patch, loop metadata (if exists) will override the metadata of each predecessor; if the predecessor block already has loop metadata, the orignal loop metadata won't be preserved abd cause missed loop transformations (see 'test case2' in llvm/test/Transforms/SimplifyCFG/preserve-llvm-loop-metadata.ll).
Two alternative options are considered but they won't work well:To illustrate how inner-loop metadata might be dropped:
1.CFG Before
# BB is while.cond.exit, Partially forwards 'attached with loop metdata md2.
# BB->pred' to 'BB->succ'Pred is for.body, in other words, only do forwarding for predecessors of BB that are not loop latches.attached with loop metadata md1.
entry
|
v
---> while.cond -------------> while.end
| |
| v
| while.body
| |
| v
| for.body <---- (md1)
| | |______|
| v
| while.cond.exit (md2)
| |
|_______|
CFG After
In this case, 'BB' might be partially duplicated (e.g., the PHI instructions) into 'BB->succ' for non-loop-latch pred, and meanwhile still preserved for loop-latch pred. 'BB->succ' has more predecesors.
2. Proceed with deleting 'BB' when loop metadata of BB and Pred could be concatenated correctly (e.g. loop properties doesn't conflict, and the concatenation won't changing loop transformation result due to pass ordering, etc).
# while.cond1 is the merge of while.cond.exit and while.cond above.
1) Firstly, multiple transformations in the same metadata are ambigious -> the transformation result depend on execution order of different loop passes. Say 'BB' and 'BB->pred' are outer and inner loop respectively# for.body is attached with md2, concatenating them correctly for different scenarios is trickyand md1 is dropped.
2) In a subset of cases when concat is correct,# If LoopSimplify runs later (as a part of loop pass), it could create
a) if the inner-most loop of 'BB' and inner-most loop of Pred are the same loop, LoopSimplify (scheduled before each LoopPass by pass managers) will ensure there is only exactly one loop latch. So it's better to let LoopSimplify simplify the CFG.# dedicated exits for inner-loop (essentially adding `while.cond.exit` basck),
b) If 'BB' is from an outer loop and 'Pred' is from an inner loop, then 'BB' is an exit block of the inner-loop with predecessors that are out of the inner-loop. As a result, LoopSimplify will create dedicated exits for the inner loop, which has the same effect of adding 'BB' back. By then it's ambiguious how to undo the concatenation of loop metadata# but won't it won't see 'md1' nor restore it for the inner-loop.
In practice, the SimplifyCFG pass could run many times in an optimizer pipeline. When SimplifyCFG run after all loops passes complete, loops might have been simplified away (e.g. completely unrolled). In these cases, this function could still kick in and simplify trival 'BB' away. entry
|
v
---> while.cond1 -------------> while.end
| |
| v
| while.body
| |
| v
| for.body <---- (md2)
|_______| |______|