[llvm] [InstCombine] Fold icmp eq/ne X, select(icmp pred X, P, C1, C2) to set membership (PR #226756)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 27 01:40:52 PDT 2026


================
@@ -8105,6 +8105,69 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
     }
   }
 
+  // Fold icmp eq/ne X, select(icmp pred X, P, C1, C2)
+  // When the select condition is based on X and C1/C2 are constants,
+  // we can fold this to a simple set membership test.
+  // Example: X == select(X >s 0, 2, 0) -> (X == 2) | (X == 0)
+  // This is valid when C1 satisfies the select condition (C1 >s 0) and
+  // C2 does not satisfy it (C2 <=s 0).
+  if (I.isEquality()) {
+    // Try both operand orderings for the commutative icmp eq/ne
+    for (int Swap = 0; Swap < 2; ++Swap) {
+      Value *X = Swap ? Op1 : Op0;
+      Value *Sel = Swap ? Op0 : Op1;
+
+      Value *SelCond, *TrueVal, *FalseVal;
+      if (!match(Sel, m_Select(m_Value(SelCond), m_Value(TrueVal),
+                               m_Value(FalseVal))))
+        continue;
+
+      Value *CondLHS, *CondRHS;
+      CmpPredicate CondPred;
+      if (!match(SelCond, m_ICmp(CondPred, m_Value(CondLHS), m_Value(CondRHS))))
+        continue;
+
+      // Check if the select condition compares X with something
+      const APInt *C1, *C2, *P;
+      if (CondLHS == X && match(CondRHS, m_APInt(P))) {
+        // icmp pred X, P
+      } else if (CondRHS == X && match(CondLHS, m_APInt(P))) {
+        // icmp pred P, X -> swap to icmp swapped_pred X, P
+        CondPred = ICmpInst::getSwappedPredicate(CondPred);
+      } else {
+        continue;
+      }
+
+      if (!match(TrueVal, m_APInt(C1)) || !match(FalseVal, m_APInt(C2)) ||
+          !Sel->hasOneUse())
+        continue;
+
+      // Check: C1 must satisfy (C1 pred P) - true branch is taken when
+      // condition holds
+      // Check: C2 must NOT satisfy (C2 pred P) - false branch is taken
+      // when condition doesn't hold
+      bool C1SatisfiesCond = ICmpInst::compare(*C1, *P, CondPred);
+      bool C2SatisfiesCond = ICmpInst::compare(*C2, *P, CondPred);
+
+      if (C1SatisfiesCond && !C2SatisfiesCond) {
+        // Valid: X == select(cond, C1, C2) -> (X == C1) | (X == C2)
+        //        X != select(cond, C1, C2) -> (X != C1) & (X != C2)
+        Type *Ty = X->getType();
+        Constant *ConstC1 = ConstantInt::get(Ty, *C1);
+        Constant *ConstC2 = ConstantInt::get(Ty, *C2);
+        if (Pred == ICmpInst::ICMP_EQ) {
+          Value *Cmp1 = Builder.CreateICmpEQ(X, ConstC1);
+          Value *Cmp2 = Builder.CreateICmpEQ(X, ConstC2);
----------------
andjo403 wrote:

```suggestion
          Value *Cmp1 = Builder.CreateICmpEQ(X, Sel->getTrueValue());
          Value *Cmp2 = Builder.CreateICmpEQ(X, Sel->getFalseValue());
```

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


More information about the llvm-commits mailing list