[llvm] Fold select i cmp and bin op (PR #219676)

via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 29 05:13:01 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Andreas Jonson (andjo403)

<details>
<summary>Changes</summary>

avoids regression seen in https://github.com/llvm/llvm-project/pull/184182/changes#diff-47b908b9c27dfb9833310855fd957b4c8f43302b1d72983086e345a95a5b1dd5R1655

when the created shl shifts out all but one bit the and with one is not needed.

proof: https://alive2.llvm.org/ce/z/MQYp6f



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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+4) 
- (modified) llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll (+26) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 090abfaea28ec..f785ea182a389 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -928,6 +928,10 @@ static Value *foldSelectICmpAndBinOp(Value *CondVal, Value *TrueVal,
   bool NeedZExtTrunc = Y->getType()->getScalarSizeInBits() !=
                        V->getType()->getScalarSizeInBits();
 
+  // the demanded bits for the created shl make the and redundant
+  if (AndMask.isOne() && C2->isSignBitSet())
+    CreateAnd = false;
+
   // Make sure we don't create more instructions than we save.
   if ((NeedShift + NeedXor + NeedZExtTrunc + CreateAnd) >
       (CondVal->hasOneUse() + BinOp->hasOneUse()))
diff --git a/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll b/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll
index 771fad66e961e..5240a837bf014 100644
--- a/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll
+++ b/llvm/test/Transforms/InstCombine/select-with-bitwise-ops.ll
@@ -1765,6 +1765,32 @@ define i8 @select_trunc_or_2(i8 %x, i8 %y) {
   ret i8 %select
 }
 
+define i16 @select_trunc_or_signbit(i8 %x, i16 %y) {
+; CHECK-LABEL: @select_trunc_or_signbit(
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[X:%.*]] to i16
+; CHECK-NEXT:    [[TMP2:%.*]] = shl i16 [[TMP1]], 15
+; CHECK-NEXT:    [[SELECT:%.*]] = or i16 [[Y:%.*]], [[TMP2]]
+; CHECK-NEXT:    ret i16 [[SELECT]]
+;
+  %trunc = trunc i8 %x to i1
+  %or = or i16 %y, -32768
+  %select = select i1 %trunc, i16 %or, i16 %y
+  ret i16 %select
+}
+
+define i16 @neg_select_trunc_or_not_signbit(i8 %x, i16 %y) {
+; CHECK-LABEL: @neg_select_trunc_or_not_signbit(
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i8 [[X:%.*]] to i1
+; CHECK-NEXT:    [[OR:%.*]] = or i16 [[Y:%.*]], 16384
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[TRUNC]], i16 [[OR]], i16 [[Y]]
+; CHECK-NEXT:    ret i16 [[SELECT]]
+;
+  %trunc = trunc i8 %x to i1
+  %or = or i16 %y, 16384
+  %select = select i1 %trunc, i16 %or, i16 %y
+  ret i16 %select
+}
+
 define i8 @select_not_trunc_or_2(i8 %x, i8 %y) {
 ; CHECK-LABEL: @select_not_trunc_or_2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = shl i8 [[X:%.*]], 1

``````````

</details>


https://github.com/llvm/llvm-project/pull/219676


More information about the llvm-commits mailing list