[llvm] [InstCombine]: Fold OR bit tests (PR #178366)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 27 21:21:57 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (arrowten)

<details>
<summary>Changes</summary>

Fold: OR of bit tests with shifted constants.
((X & (C0 << Y)) != 0) || ((X & (C1 << Y)) != 0) --> (X & ((C0 | C1) << Y)) != 0

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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+55) 
- (added) llvm/test/Transforms/InstCombine/fold-or-bit-tests.ll (+21) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index fb30a4545cffe..d2761c3e09e2f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -4422,6 +4422,61 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
     if (Instruction *Result = foldSelectInstWithICmp(SI, ICI))
       return Result;
 
+  // Fold: OR of bit tests with shifted constants.
+  //
+  // ((X & (C0 << Y)) != 0) || ((X & (C1 << Y)) != 0)
+  //   --> (X & ((C0 | C1) << Y)) != 0
+  auto *CondICmp = dyn_cast<ICmpInst>(CondVal);
+  auto *FalseICmp = dyn_cast<ICmpInst>(FalseVal);
+
+  if (CondICmp && FalseICmp && match(TrueVal, m_One()) &&
+      CondICmp->getPredicate() == ICmpInst::ICMP_NE &&
+      FalseICmp->getPredicate() == ICmpInst::ICMP_NE &&
+      match(CondICmp->getOperand(1), m_Zero()) &&
+      match(FalseICmp->getOperand(1), m_Zero())) {
+    Value *X, *Mask0, *Mask1;
+
+    if (match(CondICmp->getOperand(0), m_And(m_Value(X), m_Value(Mask0))) &&
+        match(FalseICmp->getOperand(0), m_And(m_Specific(X), m_Value(Mask1)))) {
+      auto Extract = [&](Value *V, Value *&Shift, const APInt *&Base) -> bool {
+        if (auto *T = dyn_cast<TruncInst>(V))
+          V = T->getOperand(0);
+
+        Value *LHS, *RHS;
+
+        if (!match(V, m_Shl(m_Value(LHS), m_Value(RHS))))
+          return false;
+
+        if (!match(LHS, m_APInt(Base)))
+          return false;
+
+        Shift = RHS;
+
+        return true;
+      };
+
+      Value *Shift0, *Shift1;
+      const APInt *Base0, *Base1;
+
+      if (Extract(Mask0, Shift0, Base0) &&
+          Extract(Mask1, Shift1, Base1) && (Shift0 == Shift1)) {
+        APInt NewBase = *Base0 | *Base1;
+        Value *NewShl = Builder.CreateShl(
+          ConstantInt::get(Shift0->getType(), NewBase), Shift0);
+        Value *NewMask = NewShl;
+
+        if (Mask0->getType() != NewShl->getType())
+          NewMask = Builder.CreateTrunc(NewShl, Mask0->getType());
+
+        Value *NewAnd = Builder.CreateAnd(X, NewMask);
+        Instruction *NewCmp = cast<Instruction>(Builder.CreateICmpNE(
+          NewAnd, ConstantInt::getNullValue(NewAnd->getType())));
+
+        return replaceInstUsesWith(SI, NewCmp);
+      }
+    }
+  }
+
   if (Value *V = foldSelectBitTest(SI, CondVal, TrueVal, FalseVal, Builder, SQ))
     return replaceInstUsesWith(SI, V);
 
diff --git a/llvm/test/Transforms/InstCombine/fold-or-bit-tests.ll b/llvm/test/Transforms/InstCombine/fold-or-bit-tests.ll
new file mode 100644
index 0000000000000..afea70e3a6df5
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fold-or-bit-tests.ll
@@ -0,0 +1,21 @@
+; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+
+define i1 @src(i64 %arg0, ptr %arg1) {
+; CHECK: %[[SH:.*]] = shl i32 5, %[[SHIFT:.*]]
+; CHECK: %[[TR:.*]] = trunc i32 %[[SH]] to i8
+; CHECK: %[[AND:.*]] = and i8 %{{.*}}, %[[TR]]
+; CHECK: icmp ne i8 %[[AND]], 0
+
+  %v0 = load i8, ptr %arg1, align 1
+  %v1 = trunc nuw nsw i64 %arg0 to i32
+  %v2 = shl nuw nsw i32 1, %v1
+  %v3 = trunc nuw nsw i32 %v2 to i8
+  %v4 = and i8 %v0, %v3
+  %v5 = shl nuw nsw i32 4, %v1
+  %v6 = trunc nuw nsw i32 %v5 to i8
+  %v7 = and i8 %v0, %v6
+  %v8 = icmp ne i8 %v4, 0
+  %v9 = icmp ne i8 %v7, 0
+  %v10 = select i1 %v8, i1 true, i1 %v9
+  ret i1 %v10
+}

``````````

</details>


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


More information about the llvm-commits mailing list