[llvm] [profcheck][InstCombine] Preserve weights for xor statements (PR #175678)
Alan Zhao via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 12 15:50:27 PST 2026
https://github.com/alanzhao1 created https://github.com/llvm/llvm-project/pull/175678
When simplifying an xor statement with logical boolean operands, we may be able to preserve branch weight data if the simplified instruction's conditional was the first operand of one of the two logical boolean inputs.
Tracking issue: #147390
>From 2f7618daf1ecb8c7dfde96d04707de04b21adb6b Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Mon, 12 Jan 2026 15:30:43 -0800
Subject: [PATCH] [profcheck][InstCombine] Preserve weights for xor statements
When simplifying an xor statement with logical boolean operands, we may
be able to preserve branch weight data if the simplified instruction's
conditional was the first operand of one of the two logical boolean
inputs.
Tracking issue: #147390
---
.../InstCombine/InstCombineAndOrXor.cpp | 9 +++--
.../test/Transforms/InstCombine/xor-and-or.ll | 36 ++++++++++++-------
2 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b4961105c72c2..9450b288bf8a3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -5478,15 +5478,20 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
match(&I, m_c_Xor(m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B))),
m_OneUse(m_LogicalOr(m_Value(C), m_Value(D)))))) {
bool NeedFreeze = isa<SelectInst>(Op0) && isa<SelectInst>(Op1) && B == D;
- if (B == C || B == D)
+ Instruction *MDFrom = cast<Instruction>(Op0);
+ if (B == C || B == D) {
std::swap(A, B);
+ MDFrom = B == C ? cast<Instruction>(Op1) : nullptr;
+ }
if (A == C)
std::swap(C, D);
if (A == D) {
if (NeedFreeze)
A = Builder.CreateFreeze(A);
Value *NotB = Builder.CreateNot(B);
- return SelectInst::Create(A, NotB, C);
+ return MDFrom == nullptr || ProfcheckDisableMetadataFixes
+ ? createSelectInstWithUnknownProfile(A, NotB, C)
+ : SelectInst::Create(A, NotB, C, "", nullptr, MDFrom);
}
}
diff --git a/llvm/test/Transforms/InstCombine/xor-and-or.ll b/llvm/test/Transforms/InstCombine/xor-and-or.ll
index c380e2748f89b..2e0a2094bd800 100644
--- a/llvm/test/Transforms/InstCombine/xor-and-or.ll
+++ b/llvm/test/Transforms/InstCombine/xor-and-or.ll
@@ -1,4 +1,4 @@
-; 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=instcombine -S | FileCheck %s
define i1 @xor_logic_and_logic_or1(i1 %c, i1 %x, i1 %y) {
@@ -13,39 +13,39 @@ define i1 @xor_logic_and_logic_or1(i1 %c, i1 %x, i1 %y) {
ret i1 %r
}
-define i1 @xor_logic_and_logic_or2(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or2(i1 %c, i1 %x, i1 %y) !prof !0 {
; CHECK-LABEL: @xor_logic_and_logic_or2(
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]], !prof [[PROF1:![0-9]+]]
; CHECK-NEXT: ret i1 [[R]]
;
- %o = select i1 %y, i1 true, i1 %c
- %a = select i1 %c, i1 %x, i1 false
+ %o = select i1 %y, i1 true, i1 %c, !prof !1
+ %a = select i1 %c, i1 %x, i1 false, !prof !2
%r = xor i1 %a, %o
ret i1 %r
}
-define i1 @xor_logic_and_logic_or2_commuted(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or2_commuted(i1 %c, i1 %x, i1 %y) !prof !0 {
; CHECK-LABEL: @xor_logic_and_logic_or2_commuted(
; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i1 [[TMP1]], i1 [[Y:%.*]], !prof [[PROF2:![0-9]+]]
; CHECK-NEXT: ret i1 [[R]]
;
- %o = select i1 %y, i1 true, i1 %c
- %a = select i1 %c, i1 %x, i1 false
+ %o = select i1 %y, i1 true, i1 %c, !prof !1
+ %a = select i1 %c, i1 %x, i1 false, !prof !2
%r = xor i1 %o, %a
ret i1 %r
}
-define i1 @xor_logic_and_logic_or3(i1 %c, i1 %x, i1 %y) {
+define i1 @xor_logic_and_logic_or3(i1 %c, i1 %x, i1 %y) !prof !0 {
; CHECK-LABEL: @xor_logic_and_logic_or3(
; CHECK-NEXT: [[TMP1:%.*]] = freeze i1 [[C:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[X:%.*]], true
-; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 [[Y:%.*]]
+; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i1 [[TMP2]], i1 [[Y:%.*]], !prof [[PROF3:![0-9]+]]
; CHECK-NEXT: ret i1 [[R]]
;
- %o = select i1 %y, i1 true, i1 %c
- %a = select i1 %x, i1 %c, i1 false
+ %o = select i1 %y, i1 true, i1 %c, !prof !1
+ %a = select i1 %x, i1 %c, i1 false, !prof !2
%r = xor i1 %a, %o
ret i1 %r
}
@@ -254,3 +254,13 @@ define i1 @xor_and_or_negative_oneuse(i1 %c, i1 %x, i1 %y) {
}
declare void @use(i1)
+
+!0 = !{!"function_entry_count", i64 1000}
+!1 = !{!"branch_weights", i32 2, i32 3}
+!2 = !{!"branch_weights", i32 5, i32 7}
+;.
+; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i64 1000}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 5, i32 7}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 2, i32 3}
+; CHECK: [[PROF3]] = !{!"unknown", !"instcombine"}
+;.
More information about the llvm-commits
mailing list