This is an archive of the discontinued LLVM Phabricator instance.

[IndVarSimplify] Rewrite loop exit values with their initial values from loop preheader
ClosedPublic

Authored by chenli on Oct 22 2015, 12:06 AM.

Details

Summary

This patch adds support to check if a loop has loop invariant conditions which lead to loop exits. If so, we know that if the exit path is taken, it is at the first loop iteration. If there is an induction variable used in that exit path whose value has not been updated, it will keep its initial value passing from loop preheader. We can therefore rewrite the exit value with
its initial value. This will help remove phis created by LCSSA and enable other optimizations like loop unswitch.

Diff Detail

Event Timeline

chenli retitled this revision from to [IndVarSimplify] Rewrite loop exit values with their initial values from loop preheader.
chenli updated this object.
chenli added a reviewer: sanjoy.
chenli added a subscriber: llvm-commits.
sanjoy requested changes to this revision.Oct 22 2015, 12:52 AM
sanjoy edited edge metadata.
sanjoy added inline comments.
lib/Transforms/Scalar/IndVarSimplify.cpp
137

I'm not sure that RewriteLoopExitValuesWithoutBECount is the best name for this function. The transform is only incidentally being done over a loop for which we have no backedge count.

How about RewriteFirstIterationLoopExitValues, since we're really using the fact that the exit, if taken, will only be taken in the first ever loop iteration?

715

I think "updated" is misleading when talking about SSA. Why not keep the comment brief and simple, something like:

/// Check to see if this loop has exits conditional on loop invariant values.  If so, we know that if the exit path is taken, it is taken on the first iteration.  This lets us predict the value of well behaved induction variables.
718

I'm not sure if "As a side effect, the phi node generated by LCSSA is
/// no longer needed." is accurate -- can't LCSSA phis have multiple incoming values?

[edit] See longer discussion below.

727

Nit: spacing.

I'll suggest just running the diff through clang-format before submitting.

734

Use auto * here.

735

I think this is misleading -- can't LCSSA phis have multiple incoming values? I'm thinking of cases like these:

for (...) {
  t = ...;
  if (..) goto x;
  ..
  if (..) goto x;
}
...
x:
  print(t)

t dominates x so in "normal" code you won't need a PHI, but if you do want to insert a PHI for t then you'll need a phi [x, x]. Actually I'm not even sure if an "LCSSA PHI" is a well defined concept.

In any case, I don't think there is any need to special case LCSSA PHI's here. You could special case single entry PHIs if you really wanted to, but I doubt that restriction will make your change any simpler.

742

This is mostly stylistic, but prefer using auto * on the LHS of a dyn_cast; since the type is obvious.

752

What if Cond is a LoadInst loading from an i1 *?

758

How do you know that the 0th incoming value to PN is an induction PHI node?

770

I don't quite follow the logic of when InductionPHI->getBasicBlockIndex(LoopPreheader) can be -1. The preheader is the only block outside the loop branching into the header, and an induction variable (which will be a PHI node on the loop header) should have to have one incoming value for the "first" iteration which will have to be the value incoming from the preheader.

If you see failures without this check, I suspect this is because, as I mentioned in the previous comment, PN->getIncomingValue(0) need not be an induction PHI node.

This revision now requires changes to proceed.Oct 22 2015, 12:52 AM
chenli added inline comments.Oct 22 2015, 1:20 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
735

You are correct. For some reason I thought LCSSA PHIs were always single entry PHIs so I used the check to filter non LCSSA PHIs. I will fix it.

752

I think I'll just use Loop::isLoopInvariant(const Value *V) instead.

758

This is basically because of the previous assumption that we only have single entry PHI here. So if there is an induction PHI node, it should be 0th. The later

InductionPHI->getBasicBlockIndex(LoopPreheader) != -1

is used to filter non-induction PHI node.
The name InductionPHI is confusing because it's not necessary an indication PHI if it fails the check.
I will refactor the code to make it cleaner.

sanjoy added inline comments.Oct 22 2015, 2:07 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
758

In any case, we don't really care about the PHI being an induction variable (i.e. a integer that increases / decreases by some amount every iteration) -- whatever the value incoming from the preheader -> header edge is will be the exit value of the PHI. So perhaps it makes sense to not call the value InductionPHI?

chenli added inline comments.Oct 22 2015, 11:16 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
758

Yes, I will definitely pick a better name :)

chenli edited edge metadata.

Update patch w.r.t Sanjoy's request.

Mostly minor stylistic comments inline.

lib/Transforms/Scalar/IndVarSimplify.cpp
715

Now that we're not longer special casing induction variable, please change this comment to be something like "lets us predict values of PHI nodes that live on the loop header".

720

I think this is a false promise :) There are restrictions around other
cases, e.g. (using a terrible LLVM and C mashup):

 for (init; cond; incr) {
  ..
  if (c) {
   ..
   br merge;
  } else {
   ..
   br merge;
  }
 merge:
  %val = phi [ 0, %if ], [ 1, %else ]
  if (loop_invariant_cond)
    br exit
  ...
}

exit:
  %lcssa = phi [ %val ]

You cannot predict the value of %val here.

I'd just remove this NOTE for now.

733

I'd suggest doing one of the following

  • rename i to something more descriptive (like incomingValIdx)

OR

  • extract out the loop body to a lambda called ProcessIncomingValue or something like that.
751

Super minor: do we actually need a line break here?

754

I'd remove the Currently -- this optimization is fundamentally intended to work with PHI nodes.

760

I think (if the exit value is in a joint block of the oop then it will not be qualified) bit is somewhat redundant.

I'd just say "If ExitVal is a PHI on the loop header, then we know its value along this exit because the exit can only be taken on the first iteration" and leave it at that. No point in discussing the invalid cases.

763

Add an assert here ExitVal lives on the loop header.

2132

This may be a good place to state that RewriteFirstIterationLoopExitValues does not depend on us being able to compute the trip count of L, and therefore can get cases that RewriteLoopExitValues does not. You can also put this "factoid" in the declaration of RewriteFirstIterationLoopExitValues

sanjoy requested changes to this revision.Oct 23 2015, 10:50 PM
sanjoy edited edge metadata.

(Nothing new, just to move the review out of my "blocked on you" queue).

This revision now requires changes to proceed.Oct 23 2015, 10:50 PM
chenli updated this revision to Diff 38501.Oct 26 2015, 9:51 PM
chenli edited edge metadata.

Update patch w.r.t Sanjoy's comments.

sanjoy requested changes to this revision.Oct 26 2015, 11:16 PM
sanjoy edited edge metadata.
sanjoy added inline comments.
lib/Transforms/Scalar/IndVarSimplify.cpp
729

I know I suggested this, but LLVM style is IncomingValIdx.

732

Do you not need to check that PN->getIncomingBlock(incomingValIdx) is inside the loop?

736

Note: this transform is also valid for unconditional branches (since br label %foo is equivalent to br true label %foo label %foo).

Actually, thinking about it, I think we can pretty much assert(BI->isConditional()) (IOW you don't need the check since BI->getCondition() will have the same assert it in). (Please verify this) I think you cannot have an unconditional branch from a block B in the loop to a loop exit since then B will not be connected to the header (i.e. there won't be a path from B to the loop header) and hence B won't be part of the loop leading to a contradiction.

759

I'd put an assert(LoopPreaheader) here.

This revision now requires changes to proceed.Oct 26 2015, 11:16 PM
chenli added inline comments.Oct 26 2015, 11:25 PM
lib/Transforms/Scalar/IndVarSimplify.cpp
736

I think you can not have an unconditional branch in B or B will be the loop exit. I will remove the check and run some test through the test cases.

chenli edited edge metadata.
chenli marked 2 inline comments as done.

Update patch w.r.t Sanjoy's comments.

sanjoy accepted this revision.Oct 27 2015, 12:48 AM
sanjoy edited edge metadata.

lgtm with comments addressed

lib/Transforms/Scalar/IndVarSimplify.cpp
743

Minor: remove the braces { form the else if.

747

]I'd change this to isLoopInvariant for now -- make LoopInvariant may hoist arithmetic etc. over control flow and this could be a regression e.g. in cases like

for ( ... )
  if (rare_condition) {
    int x = loop_invariant * 3;
    if (x == 42) then exit;
  }

hoisting loop_invariant * 3 to the loop preheader will be a net regression.

Sorry for not bringing this up earlier.

Also, note that both isLoopInvariant and makeLoopInvariant take a Value so you don't need to manually cast to an Instruction.

This revision is now accepted and ready to land.Oct 27 2015, 12:48 AM
chenli added inline comments.Oct 27 2015, 10:51 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
747

By regression, do you mean by register pressure?

sanjoy added inline comments.Oct 27 2015, 11:07 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
747

Register pressure also, but I was trying to say you'll just compute values that you don't need to compute (e.g. in the above example if rare_condition is always false at runtime then the multiplication in the loop preheader was useless).

chenli added inline comments.Oct 27 2015, 11:09 AM
lib/Transforms/Scalar/IndVarSimplify.cpp
747

Makes sense. I will modify and submit. Thanks!

chenli closed this revision.Oct 27 2015, 9:47 PM