This is an archive of the discontinued LLVM Phabricator instance.

[SimplifyCFG] Speculatively flatten CFG based on profiling metadata (try 2)
AbandonedPublic

Authored by reames on Feb 23 2016, 3:00 PM.

Details

Reviewers
sanjoy
Summary

Note: This is a corrected version of an approach previously reviewed in http://reviews.llvm.org/D13070, landed, and reverted due to a problem with control dependence and nsw flags.

The main change in this patch over the previous approach is to explicitly check for possible control dependent flags in the BB we're considering flattening which might influence the condition of the second branch. I believe this is sufficient to prevent the problematic case, but it does end up making the transform less powerful.

I also had to add a bit of logic to the implies reasoning to handle the simpler test cases I want to introduce. This logic could arguable by separated, but I kept it together to show the motivation.

  • Original Review Comments --

If we have a series of branches which are all unlikely to fail, we can possibly combine them into a single check on the fastpath combined with a bit of dispatch logic on the slowpath. We don't want to do this unconditionally since it requires speculating instructions past a branch, but if the profiling metadata on the branch indicates profitability, this can reduce the number of checks needed along the fast path.

The canonical example this is trying to handle is removing the second bounds check implied by the Java code: a[i] + a[i+1]. Note that it can currently only do so for really simple conditions and the values of a[i] can't be used anywhere except in the addition. (i.e. the load has to have been sunk already and not prevent speculation.)

Diff Detail

Event Timeline

reames updated this revision to Diff 48852.Feb 23 2016, 3:00 PM
reames retitled this revision from to [SimplifyCFG] Speculatively flatten CFG based on profiling metadata (try 2).
reames updated this object.
reames added a reviewer: sanjoy.
reames added a subscriber: llvm-commits.
sanjoy requested changes to this revision.Feb 23 2016, 5:04 PM
sanjoy edited edge metadata.
sanjoy added inline comments.
lib/Transforms/Utils/SimplifyCFG.cpp
2708

Nit: should be IsRarelyUntaken.

2734

Minor: might do this check before the check on isSafeToSpeculativelyExecute, since it will be a cheaper way out, if it fails.

2741

Spelling nit: "computation"

2759

I'd say this is a little risky. I think you're okay now since isImpliedCondition only looks at overflow flags, but if it is changed to consider, e.g., the exact flag on udiv or inbounds on getelementptr at some time in the future, this might subtly break.

I'd rather split out a helper routine, GetCombinedCond that takes two predicates, P and Q and a location, Loc, and returns a predicate that is equivalent to P && Q at Loc, if it can be cheaply computed. Predicates like 5 u< L and 6 u< L can be combined into 6 u< L; and predicates like I u< L and (I +nuw 1) u< L can be combined into (I +nuw 1) u< L if you can prove that the nuw holds at Loc, etc.

This revision now requires changes to proceed.Feb 23 2016, 5:04 PM

Responding only to the material design comment for the moment. Will address nits once the design question is resolved.

lib/Transforms/Utils/SimplifyCFG.cpp
2759

To be clear, I'm not proposing that we *just* check nsw/nuw. As you point out, that would be utterly unsound. Assuming I extend the logic to include exact and inbounds (which I had completely forgotten about), what do you think of the approach? (If I've forgotten other cases, please suggest them.)

I'm a bit leery of introducing the separate predicate. I think that unless we're really careful here, we could end up duplicating a lot of code. Now, having said that, I'll give it a bit more thought tomorrow and see what I think after writing some prototype code.

It is probably worthwhile to have a more general transformation to reduce control dependence height by using logical/bitwise and|or operation:

br (cond1) fail1
check2:
br (cond2) fail2
label:

..

if cond2's computation can be safely control speculated, it becomes
br ( (cond1 == 0) & (cond2 == 0)) label;
dispatch:
br (cond1) fail1
br fail1
label:

Note that (cond1 == 0 & cond2 == 0) can be simplified in many cases (e.g, in the example test cases).

lib/Transforms/Utils/SimplifyCFG.cpp
2689

Should these two conditions swapped in this example or change > to < ?

2708

How about IsLikelyTaken?

2721

nit: similar.

sanjoy added inline comments.Feb 26 2016, 2:07 PM
lib/Transforms/Utils/SimplifyCFG.cpp
2759

I don't think we'll duplicate much code here, GetCombinedCond will just be a helper to simplify X && Y into something cheaper. X implies Y (without exploiting invalid no-wrap) will then just be one case where it X && Y can be simplified to X. It should also be a more natural extension point -- for instance, if we want to combine 0 < I < 20 and 10 < I < 50, neither implies the other but their logical-and can be expressed as 10 < I < 20.

reames abandoned this revision.Sep 24 2016, 11:41 AM