[llvm] [InstCombine] Preserve profile data with select instructions and binary operators (PR #158375)

Alan Zhao via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 12 15:11:07 PDT 2025


https://github.com/alanzhao1 updated https://github.com/llvm/llvm-project/pull/158375

>From 5ac86b7c827058d790d792bb8c0a03131312c340 Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Fri, 12 Sep 2025 15:04:03 -0700
Subject: [PATCH 1/4] [InstCombine] Preserve profile data with select
 instructions and binary operators

Tracking issue: #147390
---
 .../InstCombine/InstructionCombining.cpp      | 21 +++++++---
 .../InstCombine/preserve-profile.ll           | 40 +++++++++++++++++++
 2 files changed, 56 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/preserve-profile.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c2f045a2ab02e..4f4d533262006 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -144,6 +144,8 @@ static cl::opt<unsigned>
 MaxArraySize("instcombine-maxarray-size", cl::init(1024),
              cl::desc("Maximum array size considered when doing a combine"));
 
+extern cl::opt<bool> ProfcheckDisableMetadataFixes;      
+
 // FIXME: Remove this flag when it is no longer necessary to convert
 // llvm.dbg.declare to avoid inaccurate debug info. Setting this to false
 // increases variable availability at the cost of accuracy. Variables that
@@ -1372,6 +1374,7 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
   SimplifyQuery Q = SQ.getWithInstruction(&I);
 
   Value *Cond, *True = nullptr, *False = nullptr;
+  MDNode *ProfileData;
 
   // Special-case for add/negate combination. Replace the zero in the negation
   // with the trailing add operand:
@@ -1381,17 +1384,18 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
     // We need an 'add' and exactly 1 arm of the select to have been simplified.
     if (Opcode != Instruction::Add || (!True && !False) || (True && False))
       return nullptr;
-
-    Value *N;
+    Value *N, *SI = nullptr;
     if (True && match(FVal, m_Neg(m_Value(N)))) {
       Value *Sub = Builder.CreateSub(Z, N);
-      return Builder.CreateSelect(Cond, True, Sub, I.getName());
+      SI = Builder.CreateSelect(Cond, True, Sub, I.getName());
     }
     if (False && match(TVal, m_Neg(m_Value(N)))) {
       Value *Sub = Builder.CreateSub(Z, N);
-      return Builder.CreateSelect(Cond, Sub, False, I.getName());
+      SI = Builder.CreateSelect(Cond, Sub, False, I.getName());
     }
-    return nullptr;
+    if (!ProfcheckDisableMetadataFixes && !SI)
+      cast<SelectInst>(SI)->setMetadata(LLVMContext::MD_prof, ProfileData);
+    return SI;
   };
 
   if (LHSIsSelect && RHSIsSelect && A == D) {
@@ -1399,6 +1403,9 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
     Cond = A;
     True = simplifyBinOp(Opcode, B, E, FMF, Q);
     False = simplifyBinOp(Opcode, C, F, FMF, Q);
+    // Profile weights for both LHS and RHS should be the same because they have
+    // the same idempotent conditional.
+    ProfileData = cast<SelectInst>(LHS)->getMetadata(LLVMContext::MD_prof);
 
     if (LHS->hasOneUse() && RHS->hasOneUse()) {
       if (False && !True)
@@ -1408,6 +1415,7 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
     }
   } else if (LHSIsSelect && LHS->hasOneUse()) {
     // (A ? B : C) op Y -> A ? (B op Y) : (C op Y)
+    ProfileData = cast<SelectInst>(LHS)->getMetadata(LLVMContext::MD_prof);
     Cond = A;
     True = simplifyBinOp(Opcode, B, RHS, FMF, Q);
     False = simplifyBinOp(Opcode, C, RHS, FMF, Q);
@@ -1415,6 +1423,7 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
       return NewSel;
   } else if (RHSIsSelect && RHS->hasOneUse()) {
     // X op (D ? E : F) -> D ? (X op E) : (X op F)
+    ProfileData = cast<SelectInst>(RHS)->getMetadata(LLVMContext::MD_prof);
     Cond = D;
     True = simplifyBinOp(Opcode, LHS, E, FMF, Q);
     False = simplifyBinOp(Opcode, LHS, F, FMF, Q);
@@ -1427,6 +1436,8 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
 
   Value *SI = Builder.CreateSelect(Cond, True, False);
   SI->takeName(&I);
+  if (!ProfcheckDisableMetadataFixes)
+    cast<SelectInst>(SI)->setMetadata(LLVMContext::MD_prof, ProfileData);
   return SI;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/preserve-profile.ll b/llvm/test/Transforms/InstCombine/preserve-profile.ll
new file mode 100644
index 0000000000000..806cbc3e80c1a
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/preserve-profile.ll
@@ -0,0 +1,40 @@
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; CHECK: define i32 @LHSBin(i1 %C) !prof ![[PROF0:[0-9]]]
+; CHECK: %V = select i1 %C, i32 1010, i32 20, !prof ![[PROF1:[0-9]]]
+define i32 @LHSBin(i1 %C) !prof !0 {
+  %A = select i1 %C, i32 1000, i32 10, !prof !1
+  %V = add i32 %A, 10
+  ret i32 %V
+}
+
+; CHECK: define i32 @RHSBin(i1 %C) !prof ![[PROF0]]
+; CHECK: %V = select i1 %C, i32 1010, i32 20, !prof ![[PROF1]]
+define i32 @RHSBin(i1 %C) !prof !0 {
+  %A = select i1 %C, i32 1000, i32 10, !prof !1
+  %V = add i32 10, %A
+  ret i32 %V;
+}
+
+; CHECK: define i32 @BothBin(i1 %C) !prof ![[PROF0]]
+; CHECK: %V = select i1 %C, i32 2000, i32 20, !prof ![[PROF1]]
+define i32 @BothBin(i1 %C) !prof !0 {
+  %A = select i1 %C, i32 1000, i32 10, !prof !1
+  %B = select i1 %C, i32 1000, i32 10, !prof !1
+  %V = add i32 %A, %B
+  ret i32 %V;
+}
+
+; CHECK: define i32 @NegBin(i1 %C) !prof ![[PROF0:[0-9]]]
+; CHECK: %V = select i1 %C, i32 1010, i32 0, !prof ![[PROF1:[0-9]]]
+define i32 @NegBin(i1 %C) !prof !0 {
+  %A = select i1 %C, i32 1000, i32 -10, !prof !1
+  %V = add i32 %A, 10
+  ret i32 %V
+}
+
+
+; CHECK: ![[PROF0]] = !{!"function_entry_count", i64 1000}
+; CHECK: ![[PROF1]] = !{!"branch_weights", i32 2, i32 3}
+!0 = !{!"function_entry_count", i64 1000}
+!1 = !{!"branch_weights", i32 2, i32 3}
\ No newline at end of file

>From cad50aa28e159b8423f84fb56e886e0ff62c21af Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Fri, 12 Sep 2025 15:07:20 -0700
Subject: [PATCH 2/4] fix missing trailing newline

---
 llvm/test/Transforms/InstCombine/preserve-profile.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/InstCombine/preserve-profile.ll b/llvm/test/Transforms/InstCombine/preserve-profile.ll
index 806cbc3e80c1a..47254a88b1ed1 100644
--- a/llvm/test/Transforms/InstCombine/preserve-profile.ll
+++ b/llvm/test/Transforms/InstCombine/preserve-profile.ll
@@ -37,4 +37,4 @@ define i32 @NegBin(i1 %C) !prof !0 {
 ; CHECK: ![[PROF0]] = !{!"function_entry_count", i64 1000}
 ; CHECK: ![[PROF1]] = !{!"branch_weights", i32 2, i32 3}
 !0 = !{!"function_entry_count", i64 1000}
-!1 = !{!"branch_weights", i32 2, i32 3}
\ No newline at end of file
+!1 = !{!"branch_weights", i32 2, i32 3}

>From 938a4d48dabb409ea7ba63d2eded1f80b35bcf27 Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Fri, 12 Sep 2025 15:08:39 -0700
Subject: [PATCH 3/4] fix conditional

---
 llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 4f4d533262006..6a0ae3623151d 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -1393,7 +1393,7 @@ Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
       Value *Sub = Builder.CreateSub(Z, N);
       SI = Builder.CreateSelect(Cond, Sub, False, I.getName());
     }
-    if (!ProfcheckDisableMetadataFixes && !SI)
+    if (!ProfcheckDisableMetadataFixes && SI)
       cast<SelectInst>(SI)->setMetadata(LLVMContext::MD_prof, ProfileData);
     return SI;
   };

>From 5d7169eba4c932f6bbc91eaed8922f8b7e23fdfc Mon Sep 17 00:00:00 2001
From: Alan Zhao <ayzhao at google.com>
Date: Fri, 12 Sep 2025 15:10:54 -0700
Subject: [PATCH 4/4] test fixes

---
 llvm/test/Transforms/InstCombine/preserve-profile.ll | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/preserve-profile.ll b/llvm/test/Transforms/InstCombine/preserve-profile.ll
index 47254a88b1ed1..f945efbb2103d 100644
--- a/llvm/test/Transforms/InstCombine/preserve-profile.ll
+++ b/llvm/test/Transforms/InstCombine/preserve-profile.ll
@@ -26,14 +26,13 @@ define i32 @BothBin(i1 %C) !prof !0 {
 }
 
 ; CHECK: define i32 @NegBin(i1 %C) !prof ![[PROF0:[0-9]]]
-; CHECK: %V = select i1 %C, i32 1010, i32 0, !prof ![[PROF1:[0-9]]]
+; CHECK: %V = select i1 %C, i32 1010, i32 0, !prof ![[PROF1]]
 define i32 @NegBin(i1 %C) !prof !0 {
   %A = select i1 %C, i32 1000, i32 -10, !prof !1
   %V = add i32 %A, 10
   ret i32 %V
 }
 
-
 ; CHECK: ![[PROF0]] = !{!"function_entry_count", i64 1000}
 ; CHECK: ![[PROF1]] = !{!"branch_weights", i32 2, i32 3}
 !0 = !{!"function_entry_count", i64 1000}



More information about the llvm-commits mailing list