This is an archive of the discontinued LLVM Phabricator instance.

[SimplifyCFG] use profile metadata to refine merging branch conditions
ClosedPublic

Authored by spatel on Mar 18 2021, 2:22 PM.

Details

Summary

This is one step towards solving:
https://llvm.org/PR49336

In that example, we disregard the recommended usage of builtin_expect, so an expensive (unpredictable) branch is folded into another branch that is guarding it.
Here, we read the profile metadata to see if the 1st (predecessor) condition is likely to cause execution to bypass the 2nd (successor) condition before merging conditions by using logic ops.

Part of this patch is moving the Likely/Unlikely variables to make them visible to SimplifyCFG. We could do that as a preliminary step (if I got that right).

Diff Detail

Event Timeline

spatel created this revision.Mar 18 2021, 2:22 PM
spatel requested review of this revision.Mar 18 2021, 2:22 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 18 2021, 2:22 PM

Yep, please do split off the prep patch.
I think there is some other place that duplicates those constants, maybe in clang?
I will look over this in detail later..

spatel updated this revision to Diff 331847.Mar 19 2021, 6:05 AM

Updated:
Rebased on top of D98945 (move the branch prob options),

Can prof metadata and MD_unpredictable be mixed together?
What should we do here in presence of MD_unpredictable?

llvm/lib/Transforms/Utils/SimplifyCFG.cpp
2844–2846

... and check that it wouldn't be an obviously unprofitable thing to do as per the prof metadata.

2862–2863

And now that i actually start reviewing this, i see what was irking me.
While it seems like we should be using the weights from LowerExpectIntrinsic,
why is that the right threshold for profile-driven weights?

There's TLI->getPredictableBranchThreshold(),
shouldn't we use that?

Because the LikelyBranchWeight/UnlikelyBranchWeight appears to only be used in
CodeGenFunction.cpp and LowerExpectIntrinsic.cpp, none of the transforms use them,
unlike TLI->getPredictableBranchThreshold(). Which to me looks like
that they are LowerExpectIntrinsic's implementation detail
that is unintentionally overexposed.

Can prof metadata and MD_unpredictable be mixed together?
What should we do here in presence of MD_unpredictable?

They can be mixed, but I don't see any precedence for dealing with them simultaneously. So we get to decide here :) -- or in a follow-up standalone patch to make it more definitive
In theory, either of these metadata could be attached manually by a programmer or from actual training data / profile-guided optimization (PGO).
I'm leaning towards having unpredictable be the winner in that case because branch weights are good, but they can't really tell us how a given target will behave since we can't model even basic branch history hardware here. So we have to defer to whoever/whatever said a branch was unpredictable as true/correct.

llvm/lib/Transforms/Utils/SimplifyCFG.cpp
2862–2863

Yes, I thought about that too, and I don't have a good reason for using likely/unlikely. I think we will want to move the threshold API to TTI (rather than TLI) if we go with that setting, so we're not making an optimizer pass depend on TLI unnecessarily.

lebedev.ri added inline comments.Mar 21 2021, 12:17 PM
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
2862–2863

I'll revert D98945 along with fixing rG08196e0b2e1f8aaa8a854585335c17ba479114df in a moment.

Can prof metadata and MD_unpredictable be mixed together?
What should we do here in presence of MD_unpredictable?

They can be mixed, but I don't see any precedence for dealing with them simultaneously. So we get to decide here :) -- or in a follow-up standalone patch to make it more definitive
In theory, either of these metadata could be attached manually by a programmer or from actual training data / profile-guided optimization (PGO).
I'm leaning towards having unpredictable be the winner in that case because branch weights are good, but they can't really tell us how a given target will behave since we can't model even basic branch history hardware here. So we have to defer to whoever/whatever said a branch was unpredictable as true/correct.

I also believe unpredictable should win.

lebedev.ri requested changes to this revision.Mar 22 2021, 7:41 AM
This revision now requires changes to proceed.Mar 22 2021, 7:41 AM
spatel updated this revision to Diff 332406.Mar 22 2021, 1:05 PM

Patch updated:
Use TTI query to decide when a branch is predictable.
I changed the TLI query to TTI as a preliminary commit and adjusted the test metadata to match.

spatel marked 3 inline comments as done.Mar 22 2021, 1:07 PM

I think we should add the unpredictable override as a follow-up, so I have not added that yet, but if the consensus is to add it here, I can do that.

lebedev.ri accepted this revision.Mar 22 2021, 1:18 PM

LGTM, thanks.

I think we should add the unpredictable override as a follow-up, so I have not added that yet, but if the consensus is to add it here, I can do that.

I think that's fine, but as before that we should probably document that in LangRef

llvm/lib/Transforms/Utils/SimplifyCFG.cpp
2857
This revision is now accepted and ready to land.Mar 22 2021, 1:18 PM
This revision was landed with ongoing or failed builds.Mar 22 2021, 1:49 PM
This revision was automatically updated to reflect the committed changes.
lebedev.ri added inline comments.Mar 22 2021, 2:55 PM
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
3009–3012

FoldBranchToCommonDest() might be called from outside of SimplifyCFG (it is called from loopsimplify), without passing-in TTI, i guess.

Oh, I see it's already reverted. Thank you!

spatel added inline comments.Mar 23 2021, 4:55 AM
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
3009–3012

Yep, that was it. I was able to deduce a test for it without going through the stage2 failure.
I'll add a test for -loop-simplify and try again.

This does raise a question: is it intentional that a pass is ignoring the metadata? Does that mean we may lose the information despite making a change for SimplifyCFG?