This is an archive of the discontinued LLVM Phabricator instance.

[LoopPredication] Add profitability check based on BPI
ClosedPublic

Authored by anna on Mar 19 2018, 6:23 PM.

Details

Summary

LoopPredication is not profitable when the loop is known to always exit
through some block other than the latch block.
A coarse grained latch check can cause loop predication to predicate the
loop, making the guard invariant out of the loop and always
unconditionally deoptimize. However, the guard may never fail within the
loop because dynamically, it always exits earlier through some other block and never through
the latch block.
We teach LP about this using BranchProfileInfo pass.

This methodology was chosen instead of adding metadata to prevent loop
predication: https://reviews.llvm.org/D44535

Diff Detail

Repository
rL LLVM

Event Timeline

anna created this revision.Mar 19 2018, 6:23 PM
skatkov added inline comments.Mar 20 2018, 1:19 AM
lib/Transforms/Scalar/LoopPredication.cpp
740 ↗(On Diff #139065)

I'm not against lambda, but don't you think that this big code would be better to put in the separate method of LoopPredication?

765 ↗(On Diff #139065)

Don't you want to introduce some delta? Usually branch probability is something is better to compare with some delta.

anna added inline comments.Mar 20 2018, 6:07 AM
lib/Transforms/Scalar/LoopPredication.cpp
740 ↗(On Diff #139065)

agreed. Will do.

765 ↗(On Diff #139065)

Agreed. The delta would need to be cl::opt argument as well.

anna updated this revision to Diff 139134.Mar 20 2018, 8:51 AM

seperated out logic into a function, instead of lambda. Added a threshold for the BPI check.

anna updated this revision to Diff 139243.Mar 20 2018, 7:30 PM

fixed a bug in internal testing with Loop predication pass initialization - we need to register
the BPI pass dependency.

skatkov added inline comments.Mar 21 2018, 12:23 AM
lib/Transforms/Scalar/LoopPredication.cpp
212 ↗(On Diff #139243)

I think it is better to add some comment here, what the value of this option actually means.

722 ↗(On Diff #139243)

BasicBlock has an utility function getExitEdges.
I propose to use it instead of iteration over ExitingLoops.
This way, your loop will be simplified a lot I guess.

I would also consider inserting an assert that latch is an exiting block.
By definition latch should not require to be an exiting block. But the logic below expects it as I understand...
As I understand the latch is an exiting block due to it is a loop pass and loop is in canonical form. So it is ok but I would still consider inserting an assert... Or alternatively I would find an edge from latch to exit block in an array returned from getExitEdges (this will imply an assert and gives you an input to get probability).

746 ↗(On Diff #139243)

It is not a big deal and compiler should do it instead of you but you can hoist LatchExitProbability * ProbabilityThreshold to pre-header :)

skatkov added inline comments.Mar 21 2018, 12:25 AM
lib/Transforms/Scalar/LoopPredication.cpp
746 ↗(On Diff #139243)

Also please consider renaming of the option ProbabilityThreshold. To me threshold is actually "LatchExitProbability * ProbabilityThreshold". However I might be wrong.

skatkov added inline comments.Mar 21 2018, 12:29 AM
lib/Transforms/Scalar/LoopPredication.cpp
722 ↗(On Diff #139243)

I'm sorry, not a BasicBlock but Loop of course.

anna added inline comments.Mar 21 2018, 5:06 AM
lib/Transforms/Scalar/LoopPredication.cpp
722 ↗(On Diff #139243)

BasicBlock has an utility function getExitEdges.

Yes, that's useful (the one in LoopInfo). Thanks! I haven't seen that function being used anywhere in the code, so it may not be well tested. However, the functionality is exactly what I want and it simplifies the logic below. I'll still extract the LatchExitProbability the way I've done right now, without going through the array.

I would also consider inserting an assert that latch is an exiting block.

Yup, Latch is an exiting block at this point because Loop Predication requires that form. I'll add an assert here.

746 ↗(On Diff #139243)

Maybe something like loop-pred-latch-probability-scale?

anna updated this revision to Diff 139289.Mar 21 2018, 7:18 AM

use getExitEdges instead of getting exiting blocks.

anna marked 3 inline comments as done.Mar 21 2018, 7:18 AM
skatkov added inline comments.Mar 21 2018, 8:40 PM
lib/Transforms/Scalar/LoopPredication.cpp
726 ↗(On Diff #139289)

you do not need ExitingBlocks more.

736 ↗(On Diff #139289)

Please consider re-ordering the lines in this piece of code (it is a bit difficult to read it).

I would suggest to move all code related to getting edge probability below to computation of LatchProbabilityThreshold (to me it is connected parts). Additionally you will have an earlier bail out due to more than one exit and you do not need to do anything for latch in this case.

And separate by new line the code related to LatchProbabilityThreshold and getting ExitEdges.

748 ↗(On Diff #139289)

You still need to skip latch exiting basic block.

skatkov added inline comments.Mar 21 2018, 8:54 PM
lib/Transforms/Scalar/LoopPredication.cpp
747 ↗(On Diff #139289)

Just a side comment... Instead of "for loop" you can consider "any_of" usage in this case. However I do not know whether it looks better :) So it is up to you.

anna marked 2 inline comments as done.Mar 22 2018, 4:21 AM
anna added inline comments.
lib/Transforms/Scalar/LoopPredication.cpp
726 ↗(On Diff #139289)

stale line will remove.

736 ↗(On Diff #139289)

ok.

747 ↗(On Diff #139289)

since there's an extra computation of probability here, I'm not sure if any_of is better :)

748 ↗(On Diff #139289)

you don't need to skip it. The check at line 750 will never be true for latch exit basic block (exitingblock probability > latchExitingBlockProbability). I intentionally ignored checking for latch exiting basic block, it saves us a check for every exiting edge...

skatkov added inline comments.Mar 22 2018, 4:26 AM
lib/Transforms/Scalar/LoopPredication.cpp
748 ↗(On Diff #139289)

That is true until someone will not set LatchExitProbabilityScale to 0.5.

anna marked 2 inline comments as done.Mar 22 2018, 4:31 AM
anna added inline comments.
lib/Transforms/Scalar/LoopPredication.cpp
748 ↗(On Diff #139289)

hmm.. that changes the whole point of the profitability check. It inverts it. Thanks for pointing that out. We need to strengthen against such use cases...
if LatchExitProbabilityScale < 1, we set it to 1.

anna updated this revision to Diff 139428.Mar 22 2018, 4:49 AM

Address Serguei's comments.

skatkov accepted this revision.Mar 22 2018, 5:00 AM

LGTM with some comments.

lib/Transforms/Scalar/LoopPredication.cpp
215 ↗(On Diff #139428)

cl::opt has a way to add a description for the option: cl::desc("")
I would suggest always to provide a description which is printed in help message.
The notice about >=1 and ignoring the value <1 can be also added to desc.

726 ↗(On Diff #139428)

new line?

750 ↗(On Diff #139428)

DEBUG(dbgs() with message that we ignore user settings?
It is not a good idea to update the value of opt. I would suggest to use local variable for that.

This revision is now accepted and ready to land.Mar 22 2018, 5:00 AM
anna marked 3 inline comments as done.Mar 22 2018, 7:57 AM
This revision was automatically updated to reflect the committed changes.