This is an archive of the discontinued LLVM Phabricator instance.

[LoopDeletion] Also consider loops with subloops for deletion.
ClosedPublic

Authored by fhahn on Dec 22 2020, 10:28 AM.

Details

Summary

Currently, LoopDeletion does skip loops that have sub-loops, but this
means we currently fail to remove some no-op loops.

One example are inner loops with live-out values. Those cannot be
removed by itself. But the containing loop may itself be a no-op and the
whole loop-nest can be deleted.

The legality checks do not seem to rely on analyzing inner-loops only
for correctness.

With LoopDeletion being a LoopPass, the change means that we now
unfortunately need to do some extra work in parent loops, by checking
some conditions we already checked. But there appears to be no
noticeable compile time impact:
http://llvm-compile-time-tracker.com/compare.php?from=02d11f3cda2ab5b8bf4fc02639fd1f4b8c45963e&to=843201e9cf3b6871e18c52aede5897a22994c36c&stat=instructions

This changes patch leads to ~10 more loops being deleted on
MultiSource, SPEC2000, SPEC2006 with -O3 & LTO

This patch is also required (together with a few others) to eliminate a
no-op loop in omnetpp as discussed on llvm-dev 'LoopDeletion / removal of
empty loops.' (http://lists.llvm.org/pipermail/llvm-dev/2020-December/147462.html)

This change becomes relevant after removing potentially infinite loops
is made possible in 'must-progress' loops (D86844).

Note that I added a function call with side-effects to an outer loop in
llvm/test/Transforms/LoopDeletion/update-scev.ll to preserve the
original spirit of the test.

Diff Detail

Event Timeline

fhahn created this revision.Dec 22 2020, 10:28 AM
fhahn requested review of this revision.Dec 22 2020, 10:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 22 2020, 10:28 AM

LGTM

Reading through the code, I had a couple of separate thoughts. If you're interested, feel free to follow up on these. If not, feel free to disregard.

  1. It's not clear to my why the unreachable loop case requires an exit block. That seems like an overly strict check for the transformation.
  1. I was surprised we didn't break the backedge of loops with exit count == 0. This isn't strictly loop deletion, but it sure seems analogous. We seem to rely on simplifycfg for this today which seems likely to cause pass ordering problems.
  1. Extending the invariant case to handle multiple exits where all but one are trivially dead might be useful. (IndVarSimplify likes to produce exactly that form. Again, we rely on simplifycfg for cleanup before loop deletion and thus pass ordering is an issue.)
reames accepted this revision.Dec 22 2020, 12:37 PM
This revision is now accepted and ready to land.Dec 22 2020, 12:37 PM
This revision was landed with ongoing or failed builds.Jan 6 2021, 6:52 AM
This revision was automatically updated to reflect the committed changes.
fhahn added a comment.Jan 6 2021, 6:55 AM

LGTM

Reading through the code, I had a couple of separate thoughts. If you're interested, feel free to follow up on these. If not, feel free to disregard.

  1. It's not clear to my why the unreachable loop case requires an exit block. That seems like an overly strict check for the transformation.
  1. I was surprised we didn't break the backedge of loops with exit count == 0. This isn't strictly loop deletion, but it sure seems analogous. We seem to rely on simplifycfg for this today which seems likely to cause pass ordering problems.
  1. Extending the invariant case to handle multiple exits where all but one are trivially dead might be useful. (IndVarSimplify likes to produce exactly that form. Again, we rely on simplifycfg for cleanup before loop deletion and thus pass ordering is an issue.)

Thank you very much for taking a loop Philip!

Thanks for also sharing the additional thoughts, I'll try to look into them when I have a bit more time. IIUC 2) is already fixed by D93906.