This is an archive of the discontinued LLVM Phabricator instance.

[LICM] Ignore exits provably not taken on first iteration when computing must execute
ClosedPublic

Authored by reames on Mar 8 2018, 9:36 PM.

Details

Summary

It is common to have conditional exits within a loop which are known not to be taken on some iterations, but not necessarily all. This patches extends our reasoning around guaranteed to execute (used when establishing whether it's safe to dereference a location from the preheader) to handle the case where an exit is known not to be taken on the first iteration and the instruction of interest *is* known to be taken on the first iteration.

This case comes up in two major ways:

  1. If we have a range check which we've been unable to eliminate, we frequently know that it doesn't fail on the first iteration.
  2. Pass ordering. We may have a check which will be eliminated through some sequence of other passes, but depending on the exact pass sequence we might never actually do so or we might miss other optimizations from passes run before the check is finally eliminated.

The initial version (here) is implemented via InstSimplify. At the moment, it catches a few cases, but misses a lot too. I added test cases for missing cases in InstSimplify which I'll follow up on separately. Longer term, we should probably wire SCEV through to here to get much smarted loop aware simplification of the first iteration predicate.

Diff Detail

Repository
rL LLVM

Event Timeline

reames created this revision.Mar 8 2018, 9:36 PM
anna added inline comments.Mar 9 2018, 9:15 AM
lib/Transforms/Utils/LoopUtils.cpp
1535 ↗(On Diff #137695)

I think we do have SCEV logic to handle this case, but it maybe much weaker than InstSimplify. What we need is something along these lines but getMin instead of getExact for a given exiting block.

/// Return the number of times this loop exit may fall through to the back
   /// edge, or SCEVCouldNotCompute. The loop is guaranteed not to exit via
   /// this block before this number of iterations, but may exit via another
   /// block.
   const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const;

For every ExitBlock that Inst does not dominate, get the exiting block which is its single Predecessor (bail out if more than one). Then we just call this SCEV routine. Right now, since it only returns the "exact" count, we maybe usually returning CouldNotCompute.

1544 ↗(On Diff #137695)

ExitBlock->getModule()

1548 ↗(On Diff #137695)

Could you pls add what these nullptrs are? These are args that make up SimplifyQuery.

1585 ↗(On Diff #137695)

dominates the latch and *all* exits that might be taken on first iteration.

reames added inline comments.Mar 9 2018, 3:22 PM
lib/Transforms/Utils/LoopUtils.cpp
1535 ↗(On Diff #137695)

Seemly like my comment was unclear. I agree SCEV has lots of useful handling here. I don't think the conservatism you sketch is a problem in practice. The main issue is we simply don't pass a pointer to SCEV in from LICM at the moment. :)

reames updated this revision to Diff 137852.Mar 9 2018, 3:28 PM

address Anna's comments

mkazantsev added inline comments.Mar 11 2018, 10:33 PM
lib/Transforms/Utils/LoopUtils.cpp
1594 ↗(On Diff #137852)

I don't think that at this point we have a guarantee that the loop has a single latch. Should we not check it?

reames added inline comments.Mar 14 2018, 11:09 AM
lib/Transforms/Utils/LoopUtils.cpp
1594 ↗(On Diff #137852)

Good catch, will fix!

reames updated this revision to Diff 138464.Mar 14 2018, 3:20 PM

address Max's comment. I didn't manage to actual test the multiple latch case through LICM though, see attempt and comment.

anna accepted this revision.Mar 15 2018, 6:14 AM

LGTM. Could you add a test to scalar-promote.ll as well? I think now we should be able to promote stores that are guaranteed to execute on first iteration (because the check the store is conditional on, does not exit the loop on first iteration).

test/Transforms/LICM/hoist-mustexec.ll
220 ↗(On Diff #138464)

hmm, loop-simplify is pretty aggressive with insertUniqueBackedgeBlock. Interesting to know..

This revision is now accepted and ready to land.Mar 15 2018, 6:14 AM
This revision was automatically updated to reflect the committed changes.