What was the resolution to this issue? Was the patch accepted?
I am also running into an issue with this. Basically, I have a fairly simple loop with control flow, and the loopSimplify pass is turning it into a nested loop in order to remove multiple backedges. This is making the loop more complicated, not simple, and is causing our backend to miss performance opportunities.
In particular, I have the following loop:
While (n)
{
If (c)
A
Else
B
}
Normally I would expect to rotate the loop termination test to the end of the loop, and then our backend would if-convert blocks A and B and then effectively software pipeline the entire loop.
However, because the loop has two backedges (from A and from B), the LoopSimplify pass will create a nested loop, which I awkwardly write in C as:
While (n)
{
While (n)
{
If (c)
A
Else
Goto L;
}
Break;
L:
B
}
Now, the original loop shape is obscured and the backend no longer sees this as an if-then-else if-conversion opportunity, and software pipelining does not occur.
I have not looked at the patch, but I'm also afraid that the patch may not handle this case, as the other examples I've seen in the discussion only have if-then's, not if-then-else's. Will the patch work on the example above?
If not, this issue may simply be an optimization ordering dilemma in balancing micro optimizations (presumably the reason block's A and B don't branch to a common block that then forms a single backedge is to save a branch instruction) vs clear loop shapes that enable optimizations downstream.
Couple of thoughts:
- how firm is the constraint that all loops must have a single backedge? I don't know how fundamental this assumption is made in LLVM code. This really causes some common loops to have a funky shape.
- can we delay whatever transformation is removing the common successor block of A and B, possibly until the backend after which we've had a chance to perform other important optimizations
- is there a tell-tale sign with the loop structure that would let us predict when to form nested loops vs adding a common loop latch? Or should we always add a common loop latch, and then like above, assume that the backend cleans up any unneeded branches.
- I could add a pass that would 'undo' the nested loop. On principle, I don't like doing that type of thing, because it's really just dodging the problem and would be problematic to determine when to undo.
I appreciate your thoughts.
Jon