[llvm] [InstCombine] Keep branch weights when folding a shift through a select (PR #227987)

Alok Kumar Sharma via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 1 02:37:38 PDT 2026


https://github.com/alokkrsharma updated https://github.com/llvm/llvm-project/pull/227987

>From 8c641f74c51f6c5b16c066c547f2e5055e049af9 Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma at amd.com>
Date: Thu, 1 Oct 2026 12:43:59 +0530
Subject: [PATCH 1/2] [InstCombine] Keep branch weights when folding a shift
 through a select

Pulling a binop out of a select and through a constant shift rebuilds
the select, and the new one was losing the original branch weights. Copy
!prof so the weights stay attached to the same condition.
---
 .../InstCombine/InstCombineShifts.cpp         | 10 ++++--
 .../pull-conditional-binop-through-shift.ll   | 33 +++++++++++++++++++
 2 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 97964cebb50b8..07c66045ae8b9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -994,7 +994,10 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1,
 
       Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, C1);
       Value *NewOp = Builder.CreateBinOp(TBO->getOpcode(), NewShift, NewRHS);
-      return SelectInst::Create(Cond, NewOp, NewShift);
+      auto *NewSel = SelectInst::Create(Cond, NewOp, NewShift);
+      if (auto *SI = dyn_cast<SelectInst>(Op0))
+        NewSel->copyMetadata(*SI, {LLVMContext::MD_prof});
+      return NewSel;
     }
   }
 
@@ -1011,7 +1014,10 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1,
 
       Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, C1);
       Value *NewOp = Builder.CreateBinOp(FBO->getOpcode(), NewShift, NewRHS);
-      return SelectInst::Create(Cond, NewShift, NewOp);
+      auto *NewSel = SelectInst::Create(Cond, NewShift, NewOp);
+      if (auto *SI = dyn_cast<SelectInst>(Op0))
+        NewSel->copyMetadata(*SI, {LLVMContext::MD_prof});
+      return NewSel;
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll b/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
index 5d8becae50023..cc3180fba8a35 100644
--- a/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
+++ b/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
@@ -306,3 +306,36 @@ define i32 @add_nosignbit_select_ashr(i32 %x, i1 %cond) {
   %r = ashr i32 %t1, 8
   ret i32 %r
 }
+
+; Branch weights stay on the new select, and stay attached to the same
+; condition arms. The binop may be on either arm.
+
+define i32 @and_select_shl_prof(i32 %x, i1 %cond) {
+; CHECK-LABEL: @and_select_shl_prof(
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -16777216
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]], !prof [[PROF0:![0-9]+]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %t0 = and i32 %x, 4294901760 ; 0xFFFF0000
+  %t1 = select i1 %cond, i32 %t0, i32 %x, !prof !0
+  %r = shl i32 %t1, 8
+  ret i32 %r
+}
+
+define i32 @and_select_shl_prof_binop_on_false(i32 %x, i1 %cond) {
+; CHECK-LABEL: @and_select_shl_prof_binop_on_false(
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -16777216
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]], !prof [[PROF0]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %t0 = and i32 %x, 4294901760 ; 0xFFFF0000
+  %t1 = select i1 %cond, i32 %x, i32 %t0, !prof !0
+  %r = shl i32 %t1, 8
+  ret i32 %r
+}
+
+!0 = !{!"branch_weights", i32 1, i32 99}
+
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 99}

>From c68b995d2efa8d255f8f45cda3724e223d6cce5b Mon Sep 17 00:00:00 2001
From: Alok Kumar Sharma <AlokKumar.Sharma at amd.com>
Date: Thu, 1 Oct 2026 14:30:31 +0530
Subject: [PATCH 2/2] Review comments.

---
 .../InstCombine/InstCombineShifts.cpp         | 12 +++-----
 .../pull-conditional-binop-through-shift.ll   | 28 +++++++++++++++++++
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 07c66045ae8b9..025470f067730 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -994,10 +994,8 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1,
 
       Value *NewShift = Builder.CreateBinOp(I.getOpcode(), FalseVal, C1);
       Value *NewOp = Builder.CreateBinOp(TBO->getOpcode(), NewShift, NewRHS);
-      auto *NewSel = SelectInst::Create(Cond, NewOp, NewShift);
-      if (auto *SI = dyn_cast<SelectInst>(Op0))
-        NewSel->copyMetadata(*SI, {LLVMContext::MD_prof});
-      return NewSel;
+      return SelectInst::Create(Cond, NewOp, NewShift, "", nullptr,
+                                cast<SelectInst>(Op0));
     }
   }
 
@@ -1014,10 +1012,8 @@ Instruction *InstCombinerImpl::FoldShiftByConstant(Value *Op0, Constant *C1,
 
       Value *NewShift = Builder.CreateBinOp(I.getOpcode(), TrueVal, C1);
       Value *NewOp = Builder.CreateBinOp(FBO->getOpcode(), NewShift, NewRHS);
-      auto *NewSel = SelectInst::Create(Cond, NewShift, NewOp);
-      if (auto *SI = dyn_cast<SelectInst>(Op0))
-        NewSel->copyMetadata(*SI, {LLVMContext::MD_prof});
-      return NewSel;
+      return SelectInst::Create(Cond, NewShift, NewOp, "", nullptr,
+                                cast<SelectInst>(Op0));
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll b/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
index cc3180fba8a35..36bc7bbb1c601 100644
--- a/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
+++ b/llvm/test/Transforms/InstCombine/pull-conditional-binop-through-shift.ll
@@ -336,6 +336,34 @@ define i32 @and_select_shl_prof_binop_on_false(i32 %x, i1 %cond) {
   ret i32 %r
 }
 
+define i32 @and_select_shl_unpredictable(i32 %x, i1 %cond) {
+; CHECK-LABEL: @and_select_shl_unpredictable(
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -16777216
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]], !unpredictable [[UNPREDICTABLE:![0-9]+]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %t0 = and i32 %x, 4294901760 ; 0xFFFF0000
+  %t1 = select i1 %cond, i32 %t0, i32 %x, !unpredictable !1
+  %r = shl i32 %t1, 8
+  ret i32 %r
+}
+
+define i32 @and_select_shl_unpredictable_binop_on_false(i32 %x, i1 %cond) {
+; CHECK-LABEL: @and_select_shl_unpredictable_binop_on_false(
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 8
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -16777216
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]], !unpredictable [[UNPREDICTABLE]]
+; CHECK-NEXT:    ret i32 [[R]]
+;
+  %t0 = and i32 %x, 4294901760 ; 0xFFFF0000
+  %t1 = select i1 %cond, i32 %x, i32 %t0, !unpredictable !1
+  %r = shl i32 %t1, 8
+  ret i32 %r
+}
+
 !0 = !{!"branch_weights", i32 1, i32 99}
+!1 = !{}
 
 ; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 99}
+; CHECK: [[UNPREDICTABLE]] = !{}



More information about the llvm-commits mailing list