[llvm] [profcheck][InstCombine] Preserve branch weights in logical identities (PR #165810)
Alan Zhao via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 30 18:25:22 PDT 2025
https://github.com/alanzhao1 updated https://github.com/llvm/llvm-project/pull/165810
>From d2e9a891857af3a7e4b563a721ef9b5cac39a1c0 Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Thu, 30 Oct 2025 17:13:39 -0700
Subject: [PATCH 1/2] [profcheck][InstCombine] Preserve branch weights in
logical identities
For the simplification
```
(C && A) || (!C && B) --> sel C, A, B
```
(and related), if `C` (or (`!C`)) is the condition in the select
instruction representing the logical and, we can preserve that logical
and's branch weights when emitting the new instruction. Otherwise, the
profile data is unknown.
If `C` is the condition of both logical ands, then we just take the
branch weights of the first logical and (though in practice they should
be equal.)
Furthermore, `select-safe-transforms.ii` now passes under the profcheck
configuration, so we remove it from the failing tests.
Tracking issue: #147390
---
.../InstCombine/InstCombineSelect.cpp | 29 +++++++++++
.../InstCombine/select-safe-transforms.ll | 52 ++++++++++---------
llvm/utils/profcheck-xfail.txt | 1 -
3 files changed, 57 insertions(+), 25 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index f5130da818746..fb7de01bf254d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3599,6 +3599,21 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
m_Not(m_Specific(SelCond->getTrueValue())));
if (MayNeedFreeze)
C = Builder.CreateFreeze(C);
+ if (!ProfcheckDisableMetadataFixes) {
+ Value *C2, *A2, *B2;
+ if (match(CondVal, m_LogicalAnd(m_Specific(C2), m_Value(A2))) &&
+ SelCond) {
+ return SelectInst::Create(C, A, B, "", nullptr, SelCond);
+ } else if (match(FalseVal,
+ m_LogicalAnd(m_Not(m_Value(C2)), m_Value(B2))) &&
+ SelFVal) {
+ SelectInst *NewSI = SelectInst::Create(C, A, B, "", nullptr, SelFVal);
+ NewSI->swapProfMetadata();
+ return NewSI;
+ } else {
+ return createSelectInstWithUnknownProfile(C, A, B);
+ }
+ }
return SelectInst::Create(C, A, B);
}
@@ -3615,6 +3630,20 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
m_Not(m_Specific(SelFVal->getTrueValue())));
if (MayNeedFreeze)
C = Builder.CreateFreeze(C);
+ if (!ProfcheckDisableMetadataFixes) {
+ Value *C2, *A2, *B2;
+ if (match(CondVal, m_LogicalAnd(m_Not(m_Value(C2)), m_Value(B2))) &&
+ SelCond) {
+ SelectInst *NewSI = SelectInst::Create(C, B, A, "", nullptr, SelCond);
+ NewSI->swapProfMetadata();
+ return NewSI;
+ } else if (match(FalseVal, m_LogicalAnd(m_Specific(C2), m_Value(A2))) &&
+ SelFVal) {
+ return SelectInst::Create(C, B, A, "", nullptr, SelFVal);
+ } else {
+ return createSelectInstWithUnknownProfile(C, B, A);
+ }
+ }
return SelectInst::Create(C, B, A);
}
}
diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
index 3d97048f43127..4299b63870294 100644
--- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
+++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
@@ -256,27 +256,27 @@ define <2 x i1> @not_logical_or2(i1 %b, <2 x i32> %a) {
ret <2 x i1> %and
}
-define i1 @bools_logical_commute0(i1 %a, i1 %b, i1 %c) {
+define i1 @bools_logical_commute0(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools_logical_commute0(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF2]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
- %and1 = select i1 %not, i1 %a, i1 false
- %and2 = select i1 %c, i1 %b, i1 false
- %or = select i1 %and1, i1 true, i1 %and2
+ %and1 = select i1 %not, i1 %a, i1 false, !prof!1
+ %and2 = select i1 %c, i1 %b, i1 false, !prof !2
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !3
ret i1 %or
}
-define i1 @bools_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
+define i1 @bools_logical_commute0_and1(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools_logical_commute0_and1(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF1]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %not, %a
- %and2 = select i1 %c, i1 %b, i1 false
- %or = select i1 %and1, i1 true, i1 %and2
+ %and2 = select i1 %c, i1 %b, i1 false, !prof !1
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !2
ret i1 %or
}
@@ -292,15 +292,15 @@ define i1 @bools_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
+define i1 @bools_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools_logical_commute0_and1_and2(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF3:![0-9]+]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %not, %a
%and2 = and i1 %c, %b
- %or = select i1 %and1, i1 true, i1 %and2
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !1
ret i1 %or
}
@@ -457,27 +457,27 @@ define i1 @bools_logical_commute3_and1_and2(i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools2_logical_commute0(i1 %a, i1 %b, i1 %c) {
+define i1 @bools2_logical_commute0(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools2_logical_commute0(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF4:![0-9]+]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
- %and1 = select i1 %c, i1 %a, i1 false
- %and2 = select i1 %not, i1 %b, i1 false
- %or = select i1 %and1, i1 true, i1 %and2
+ %and1 = select i1 %c, i1 %a, i1 false, !prof !1
+ %and2 = select i1 %not, i1 %b, i1 false, !prof !2
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !3
ret i1 %or
}
-define i1 @bools2_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
+define i1 @bools2_logical_commute0_and1(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools2_logical_commute0_and1(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %c, %a
- %and2 = select i1 %not, i1 %b, i1 false
- %or = select i1 %and1, i1 true, i1 %and2
+ %and2 = select i1 %not, i1 %b, i1 false, !prof !1
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !2
ret i1 %or
}
@@ -493,15 +493,15 @@ define i1 @bools2_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
+define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) !prof !0 {
; CHECK-LABEL: @bools2_logical_commute0_and1_and2(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF3]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %c, %a
%and2 = and i1 %not, %b
- %or = select i1 %and1, i1 true, i1 %and2
+ %or = select i1 %and1, i1 true, i1 %and2, !prof !1
ret i1 %or
}
@@ -799,8 +799,12 @@ define <2 x i1> @not_logical_and2(i1 %b, <2 x i32> %a) {
!0 = !{!"function_entry_count", i64 1000}
!1 = !{!"branch_weights", i32 2, i32 3}
+!2 = !{!"branch_weights", i32 5, i32 7}
+!3 = !{!"branch_weights", i32 11, i32 17}
;.
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
; CHECK: [[PROF1]] = !{!"branch_weights", i32 2, i32 3}
; CHECK: [[PROF2]] = !{!"branch_weights", i32 3, i32 2}
+; CHECK: [[PROF3]] = !{!"unknown", !"instcombine"}
+; CHECK: [[PROF4]] = !{!"branch_weights", i32 7, i32 5}
;.
diff --git a/llvm/utils/profcheck-xfail.txt b/llvm/utils/profcheck-xfail.txt
index aef7c0987fda7..b6589ce454394 100644
--- a/llvm/utils/profcheck-xfail.txt
+++ b/llvm/utils/profcheck-xfail.txt
@@ -913,7 +913,6 @@ Transforms/InstCombine/select_frexp.ll
Transforms/InstCombine/select.ll
Transforms/InstCombine/select-min-max.ll
Transforms/InstCombine/select-of-symmetric-selects.ll
-Transforms/InstCombine/select-safe-transforms.ll
Transforms/InstCombine/select-select.ll
Transforms/InstCombine/select-with-extreme-eq-cond.ll
Transforms/InstCombine/shift.ll
>From 3a8ee93ff5f9d747cfed00beec17dc998aa951c8 Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Thu, 30 Oct 2025 18:25:04 -0700
Subject: [PATCH 2/2] initialize variables to nullptr to silence a warning
---
.../InstCombine/InstCombineSelect.cpp | 10 ++--
.../InstCombine/select-safe-transforms.ll | 52 +++++++++----------
2 files changed, 30 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index fb7de01bf254d..51e5b4d2bb347 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3600,11 +3600,12 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
if (MayNeedFreeze)
C = Builder.CreateFreeze(C);
if (!ProfcheckDisableMetadataFixes) {
- Value *C2, *A2, *B2;
+ Value *C2 = nullptr, *A2 = nullptr, *B2 = nullptr;
if (match(CondVal, m_LogicalAnd(m_Specific(C2), m_Value(A2))) &&
SelCond) {
return SelectInst::Create(C, A, B, "", nullptr, SelCond);
- } else if (match(FalseVal,
+ } else if (C2 = A2 = B2 = nullptr;
+ match(FalseVal,
m_LogicalAnd(m_Not(m_Value(C2)), m_Value(B2))) &&
SelFVal) {
SelectInst *NewSI = SelectInst::Create(C, A, B, "", nullptr, SelFVal);
@@ -3631,13 +3632,14 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
if (MayNeedFreeze)
C = Builder.CreateFreeze(C);
if (!ProfcheckDisableMetadataFixes) {
- Value *C2, *A2, *B2;
+ Value *C2 = nullptr, *A2 = nullptr, *B2 = nullptr;
if (match(CondVal, m_LogicalAnd(m_Not(m_Value(C2)), m_Value(B2))) &&
SelCond) {
SelectInst *NewSI = SelectInst::Create(C, B, A, "", nullptr, SelCond);
NewSI->swapProfMetadata();
return NewSI;
- } else if (match(FalseVal, m_LogicalAnd(m_Specific(C2), m_Value(A2))) &&
+ } else if (C2 = B2 = A2 = nullptr;
+ match(FalseVal, m_LogicalAnd(m_Specific(C2), m_Value(A2))) &&
SelFVal) {
return SelectInst::Create(C, B, A, "", nullptr, SelFVal);
} else {
diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
index 4299b63870294..3d97048f43127 100644
--- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
+++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll
@@ -256,27 +256,27 @@ define <2 x i1> @not_logical_or2(i1 %b, <2 x i32> %a) {
ret <2 x i1> %and
}
-define i1 @bools_logical_commute0(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools_logical_commute0(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools_logical_commute0(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF2]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
- %and1 = select i1 %not, i1 %a, i1 false, !prof!1
- %and2 = select i1 %c, i1 %b, i1 false, !prof !2
- %or = select i1 %and1, i1 true, i1 %and2, !prof !3
+ %and1 = select i1 %not, i1 %a, i1 false
+ %and2 = select i1 %c, i1 %b, i1 false
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
-define i1 @bools_logical_commute0_and1(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools_logical_commute0_and1(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF1]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %not, %a
- %and2 = select i1 %c, i1 %b, i1 false, !prof !1
- %or = select i1 %and1, i1 true, i1 %and2, !prof !2
+ %and2 = select i1 %c, i1 %b, i1 false
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
@@ -292,15 +292,15 @@ define i1 @bools_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools_logical_commute0_and1_and2(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]], !prof [[PROF3:![0-9]+]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %not, %a
%and2 = and i1 %c, %b
- %or = select i1 %and1, i1 true, i1 %and2, !prof !1
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
@@ -457,27 +457,27 @@ define i1 @bools_logical_commute3_and1_and2(i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools2_logical_commute0(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools2_logical_commute0(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools2_logical_commute0(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF4:![0-9]+]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
- %and1 = select i1 %c, i1 %a, i1 false, !prof !1
- %and2 = select i1 %not, i1 %b, i1 false, !prof !2
- %or = select i1 %and1, i1 true, i1 %and2, !prof !3
+ %and1 = select i1 %c, i1 %a, i1 false
+ %and2 = select i1 %not, i1 %b, i1 false
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
-define i1 @bools2_logical_commute0_and1(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools2_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools2_logical_commute0_and1(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF2]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %c, %a
- %and2 = select i1 %not, i1 %b, i1 false, !prof !1
- %or = select i1 %and1, i1 true, i1 %and2, !prof !2
+ %and2 = select i1 %not, i1 %b, i1 false
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
@@ -493,15 +493,15 @@ define i1 @bools2_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
ret i1 %or
}
-define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) !prof !0 {
+define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
; CHECK-LABEL: @bools2_logical_commute0_and1_and2(
-; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]], !prof [[PROF3]]
+; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
; CHECK-NEXT: ret i1 [[OR]]
;
%not = xor i1 %c, -1
%and1 = and i1 %c, %a
%and2 = and i1 %not, %b
- %or = select i1 %and1, i1 true, i1 %and2, !prof !1
+ %or = select i1 %and1, i1 true, i1 %and2
ret i1 %or
}
@@ -799,12 +799,8 @@ define <2 x i1> @not_logical_and2(i1 %b, <2 x i32> %a) {
!0 = !{!"function_entry_count", i64 1000}
!1 = !{!"branch_weights", i32 2, i32 3}
-!2 = !{!"branch_weights", i32 5, i32 7}
-!3 = !{!"branch_weights", i32 11, i32 17}
;.
; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
; CHECK: [[PROF1]] = !{!"branch_weights", i32 2, i32 3}
; CHECK: [[PROF2]] = !{!"branch_weights", i32 3, i32 2}
-; CHECK: [[PROF3]] = !{!"unknown", !"instcombine"}
-; CHECK: [[PROF4]] = !{!"branch_weights", i32 7, i32 5}
;.
More information about the llvm-commits
mailing list