-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[SimplfyCFG] Set MD_prof
for select
used for certain conditional simplifications
#154426
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
[SimplfyCFG] Set MD_prof
for select
used for certain conditional simplifications
#154426
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Mircea Trofin (mtrofin) ChangesThere’s a pattern where a branch is conditioned on a Issue #147390 Full diff: https://github.com/llvm/llvm-project/pull/154426.diff 3 Files Affected:
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 055e8cadaab76..bd25f14ec85d0 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -203,6 +203,8 @@ static cl::opt<unsigned> MaxJumpThreadingLiveBlocks(
cl::desc("Limit number of blocks a define in a threaded block is allowed "
"to be live in"));
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;
+
STATISTIC(NumBitMaps, "Number of switch instructions turned into bitmaps");
STATISTIC(NumLinearMaps,
"Number of switch instructions turned into linear mapping");
@@ -4772,6 +4774,14 @@ static bool SimplifyCondBranchToCondBranch(BranchInst *PBI, BranchInst *BI,
fitWeights(NewWeights);
setBranchWeights(PBI, NewWeights[0], NewWeights[1], /*IsExpected=*/false);
+ // Cond may be a select instruction with the first operand set to "true".
+ if (!ProfcheckDisableMetadataFixes)
+ if (auto *SI = dyn_cast<SelectInst>(Cond)) {
+ assert(isa<ConstantInt>(SI->getTrueValue()) &&
+ (dyn_cast<ConstantInt>(SI->getTrueValue())->isOne()));
+ setBranchWeights(SI, NewWeights[0], NewWeights[1],
+ /*IsExpected=*/false);
+ }
}
// OtherDest may have phi nodes. If so, add an entry from PBI's
diff --git a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
index 2f5fb4f33013d..b51398dd6222d 100644
--- a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
+++ b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
@@ -1,12 +1,12 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
define void @test(ptr %P, ptr %Q, i1 %A, i1 %B) {
; CHECK-LABEL: @test(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true
-; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[A_NOT]], i1 true, i1 [[B:%.*]]
-; CHECK-NEXT: br i1 [[BRMERGE]], label [[B:%.*]], label [[COMMON_RET:%.*]]
+; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[A_NOT]], i1 true, i1 [[B:%.*]], !prof [[PROF0:![0-9]+]]
+; CHECK-NEXT: br i1 [[BRMERGE]], label [[B:%.*]], label [[COMMON_RET:%.*]], !prof [[PROF0]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: b:
@@ -15,9 +15,9 @@ define void @test(ptr %P, ptr %Q, i1 %A, i1 %B) {
;
entry:
- br i1 %A, label %a, label %b
+ br i1 %A, label %a, label %b, !prof !0
a:
- br i1 %B, label %b, label %c
+ br i1 %B, label %b, label %c, !prof !1
b:
store i32 123, ptr %P
ret void
@@ -146,3 +146,11 @@ Succ:
}
declare void @dummy()
+
+!0 = !{!"branch_weights", i32 3, i32 7}
+!1 = !{!"branch_weights", i32 11, i32 4}
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind ssp memory(read) uwtable }
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 138, i32 12}
+;.
diff --git a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
index 0f78e236b4248..7d1153d5c0a0e 100644
--- a/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
+++ b/llvm/test/Transforms/SimplifyCFG/preserve-branchweights.ll
@@ -268,8 +268,8 @@ define void @test7(i1 %a, i1 %b) {
; CHECK-LABEL: @test7(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C:%.*]] = or i1 [[B:%.*]], false
-; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[C]]
-; CHECK-NEXT: br i1 [[BRMERGE]], label [[Y:%.*]], label [[Z:%.*]], !prof [[PROF6:![0-9]+]]
+; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[C]], !prof [[PROF6:![0-9]+]]
+; CHECK-NEXT: br i1 [[BRMERGE]], label [[Y:%.*]], label [[Z:%.*]], !prof [[PROF6]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
; CHECK: Y:
@@ -557,9 +557,9 @@ return:
define i32 @SimplifyCondBranchToCondBranch(i1 %cmpa, i1 %cmpb) {
; CHECK-LABEL: @SimplifyCondBranchToCondBranch(
; CHECK-NEXT: block1:
-; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA:%.*]], i1 true, i1 [[CMPB:%.*]]
-; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA]], i32 0, i32 2, !prof [[PROF13:![0-9]+]]
-; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF14:![0-9]+]]
+; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA:%.*]], i1 true, i1 [[CMPB:%.*]], !prof [[PROF13:![0-9]+]]
+; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA]], i32 0, i32 2, !prof [[PROF14:![0-9]+]]
+; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF13]]
; CHECK-NEXT: ret i32 [[OUTVAL]]
;
block1:
@@ -584,9 +584,9 @@ define i32 @SimplifyCondBranchToCondBranchSwap(i1 %cmpa, i1 %cmpb) {
; CHECK-NEXT: block1:
; CHECK-NEXT: [[CMPA_NOT:%.*]] = xor i1 [[CMPA:%.*]], true
; CHECK-NEXT: [[CMPB_NOT:%.*]] = xor i1 [[CMPB:%.*]], true
-; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA_NOT]], i1 true, i1 [[CMPB_NOT]]
-; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof [[PROF15:![0-9]+]]
-; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF16:![0-9]+]]
+; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA_NOT]], i1 true, i1 [[CMPB_NOT]], !prof [[PROF15:![0-9]+]]
+; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof [[PROF16:![0-9]+]]
+; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF15]]
; CHECK-NEXT: ret i32 [[OUTVAL]]
;
block1:
@@ -609,9 +609,9 @@ define i32 @SimplifyCondBranchToCondBranchSwapMissingWeight(i1 %cmpa, i1 %cmpb)
; CHECK-NEXT: block1:
; CHECK-NEXT: [[CMPA_NOT:%.*]] = xor i1 [[CMPA:%.*]], true
; CHECK-NEXT: [[CMPB_NOT:%.*]] = xor i1 [[CMPB:%.*]], true
-; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA_NOT]], i1 true, i1 [[CMPB_NOT]]
-; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof [[PROF17:![0-9]+]]
-; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF18:![0-9]+]]
+; CHECK-NEXT: [[BRMERGE:%.*]] = select i1 [[CMPA_NOT]], i1 true, i1 [[CMPB_NOT]], !prof [[PROF17:![0-9]+]]
+; CHECK-NEXT: [[DOTMUX:%.*]] = select i1 [[CMPA_NOT]], i32 0, i32 2, !prof [[PROF18:![0-9]+]]
+; CHECK-NEXT: [[OUTVAL:%.*]] = select i1 [[BRMERGE]], i32 [[DOTMUX]], i32 1, !prof [[PROF17]]
; CHECK-NEXT: ret i32 [[OUTVAL]]
;
block1:
@@ -1114,12 +1114,12 @@ exit:
; CHECK: [[PROF10]] = !{!"branch_weights", i32 8, i32 33}
; CHECK: [[PROF11]] = !{!"branch_weights", i32 112017436, i32 -735157296}
; CHECK: [[PROF12]] = !{!"branch_weights", i32 3, i32 5}
-; CHECK: [[PROF13]] = !{!"branch_weights", i32 22, i32 12}
-; CHECK: [[PROF14]] = !{!"branch_weights", i32 34, i32 21}
-; CHECK: [[PROF15]] = !{!"branch_weights", i32 33, i32 14}
-; CHECK: [[PROF16]] = !{!"branch_weights", i32 47, i32 8}
-; CHECK: [[PROF17]] = !{!"branch_weights", i32 6, i32 2}
-; CHECK: [[PROF18]] = !{!"branch_weights", i32 8, i32 2}
+; CHECK: [[PROF13]] = !{!"branch_weights", i32 34, i32 21}
+; CHECK: [[PROF14]] = !{!"branch_weights", i32 22, i32 12}
+; CHECK: [[PROF15]] = !{!"branch_weights", i32 47, i32 8}
+; CHECK: [[PROF16]] = !{!"branch_weights", i32 33, i32 14}
+; CHECK: [[PROF17]] = !{!"branch_weights", i32 8, i32 2}
+; CHECK: [[PROF18]] = !{!"branch_weights", i32 6, i32 2}
; CHECK: [[PROF19]] = !{!"branch_weights", i32 99, i32 1}
; CHECK: [[PROF20]] = !{!"branch_weights", i32 1, i32 99}
; CHECK: [[PROF21]] = !{!"branch_weights", i32 199, i32 1}
|
af93acd
to
37e4c28
Compare
if (!ProfcheckDisableMetadataFixes) | ||
if (auto *SI = dyn_cast<SelectInst>(PBI->getCondition())) | ||
if (!MDWeights.empty()) { | ||
assert(isSelectInRoleOfConjunctionOrDisjunction(SI)); |
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.
Note: I preferred assert
-ing here (and below) because the expectation is the condition comes from createLogicalOp
and the only reason we get a select
is because of how or
or and
get lowered there.
961489a
to
386761d
Compare
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.
I'm not sure on this one. The thing is that the canonical form here is a plain and/or, and the only reason we use select is to prevent poison-propagation issues. Improvements to frontend information (e.g. if you slap noundef on the relevant arguments) or analysis may end up converting the select to and/or, in which case we won't be able to preserve the prof metadata. Cases where better analysis has adverse effects are always awkward.
Do you have an example where duplicating this information on the select ends up being useful? After all, these weights are already on the branch over the select.
The approach is defensive rather than example-driven, because at large scale, places where profile information starts deteriorating are hard to identify, and it's also hard to know there's a problem - hence the approach of "if an instruction can have MD_profile, and it's known, let's capture it, otherwise mark it as Not sure what you mean by "better analysis has adverse effects"? |
386761d
to
4fea73e
Compare
4fea73e
to
34f5a42
Compare
34f5a42
to
5427cb6
Compare
c61eb49
to
9d2d78e
Compare
fitWeights(NewWeights); | ||
|
||
SmallVector<uint32_t, 8> MDWeights(NewWeights.begin(), NewWeights.end()); | ||
append_range(MDWeights, NewWeights); |
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.
Why this change?
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.
I need MDWeights
in the newly introduced code.
5427cb6
to
1f876ac
Compare
9d2d78e
to
7b84436
Compare
1f876ac
to
80e4431
Compare
If you add noundef to the parameters for the condition, then we'll generate and/or instead of select, which can't carry !prof metadata. |
That's OK, the |
a9fc269
to
a8bb3f0
Compare
@nikic am I OK to push? Thanks! |
a8bb3f0
to
a80b9ee
Compare
There’s a pattern where a branch is conditioned on a conjunction or disjunction that ends up being modeled as a
select
where the first operand is set totrue
or the second tofalse
. If the branch has known branch weights, they can be copied to theselect
. This is worth doing in case later theselect
gets transformed to something else (i.e. if we know the profile, we should propagate it).Issue #147390