-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Throws Prediction + HotColdSplitting #75382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@swift-ci Please test compiler performance |
@swift-ci Please benchmark |
4dfd362
to
51baeaf
Compare
@swift-ci Please benchmark |
Benchmark results with StaticBranchPrediction disabled: Performance (x86_64): -O
Code size: -OPerformance (x86_64): -Osize
Code size: -OsizePerformance (x86_64): -Onone
Code size: -swiftlibs |
@swift-ci Please benchmark |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation of the llvm's LowerExpectIntrinsics pass states the following.
// These default values are chosen to represent an extremely skewed outcome for
// a condition, but they leave some room for interpretation by later passes.
//
// If the documentation for __builtin_expect() was made explicit that it should
// only be used in extreme cases, we could make this ratio higher. As it stands,
// programmers may be using __builtin_expect() / llvm.expect to annotate that a
// branch is likely or unlikely to be taken.
// WARNING: these values are internal implementation detail of the pass.
// They should not be exposed to the outside of the pass, front-end codegen
// should emit @llvm.expect intrinsics instead of using these weights directly.
And then use the values 1 and 2000 as the branch weights.
Maybe, we should follow that recommendation and use the llvm.expect
intrinsic to be guarded against potential llvm changes in the interpretation of the branch weights.
Looks like if you ignore the ones with noise (marked with Performance (x86_64): -O
Code size: -OPerformance (x86_64): -Osize
Code size: -OsizePerformance (x86_64): -Onone
Code size: -swiftlibs |
@aschwaighofer I think we don't need to worry about a change to how the I think for this PR, we should prefer |
Is anyone using swift PGO? how would we “see” if llvm’s interpretation change hopefully nobody uses exceptions on the expected path — ie in which desired situation would profiling tell us otherwise — why should we design for this undesirable edge case. |
e5a48d8
to
8b569c4
Compare
@swift-ci test |
8b569c4
to
a4c7df4
Compare
@swift-ci test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you planning of hooking up PGO to set the new ProfileCounter arguments of the try_apply
?
An alternative approach could be to use either the profile counters or llvm.expect in IRGen depending on whether a ProfileCounter (eventually by PGO) is set or EnableThrowsPrediction
is on.
But I am nitpicking.
This lgtm.
I think we have some regression tests, but if not, we can add them to see, e.g., if
I plan to evaluate these new performance flags to see how it affects "ordinary" code. So in this PR everything's off by default. I think it's reasonable to expect no one is using |
@aschwaighofer yup that's the goal! This is a first step in that process. |
a4c7df4
to
cafabc0
Compare
@swift-ci smoke test |
Some calls to throwing functions aren't represented with `try_apply` in SIL, so we generate llvm.expect's when throw prediction is enabled.
cafabc0
to
baf87b4
Compare
@swift-ci smoke test |
baf87b4
to
11e8bb8
Compare
@swift-ci smoke test |
I'm not sure what criterion you used here to decide that some of these results are noise and others aren't. The wins here are very good, but it would be good to understand why it's a 10% regression on some benchmarks, including some fairly weighty ones like |
@rjmccall I plan to run the benchmarks with more samples on a local machine to see what really is noise or not. The |
It's reasonable to statically assume that errors are not typically thrown by functions. By making this assumption, we can annotate blocks of code dealing with errors as cold in LLVM. This aids in block layout among other things.