Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

alanzhao1
Copy link
Contributor

Tracking issue: #147390

@alanzhao1 alanzhao1 requested a review from mtrofin September 12, 2025 22:07
@alanzhao1 alanzhao1 requested a review from nikic as a code owner September 12, 2025 22:07
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Sep 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 12, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Alan Zhao (alanzhao1)

Changes

Tracking issue: #147390


Full diff: https://github.com/llvm/llvm-project/pull/158375.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+16-5)
  • (added) llvm/test/Transforms/InstCombine/preserve-profile.ll (+40)
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..47254a88b1ed1
--- /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}

Copy link

github-actions bot commented Sep 12, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

};

if (LHSIsSelect && RHSIsSelect && A == D) {
// (A ? B : C) op (A ? E : F) -> A ? (B op E) : (C op F)
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
Copy link
Member

@mtrofin mtrofin Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there something we could assert? like maybe that the fraction is the same... albeit that's float point comparison, ugh... ok, how about a ORE message about what the 2 were, or LLVM_DEBUG, just so we can easily introspect if we ever need to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an assertion that left and right profiles should be equal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are 2 cases where the pointers won't be the same:

  1. the branch weights are e.g. 2, 4 and 1, 2. So same probability, different expression
  2. the metadata was added as unique, and then you'd have 2 different objects, content-wise identical

IDK, may be safer to LLVM_DEBUG. The assert may get someone on a wild goose chase in the cases above. Or add a comment above it that we don't expect those cases to happen, but if they do, safe to replace the assert w a LLVM_DEBUG or something of the sort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no IR validity constraint that branch weight metadata has to "make sense", so you also can't assert that here.

Copy link
Member

@mtrofin mtrofin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm - ptal my note about asserting on metadata equality

@@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused, should be dropped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants