@@ -701,6 +701,45 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
701
701
return Builder.CreateICmp (NewPred, Input, RangeEnd);
702
702
}
703
703
704
+ // (or (icmp eq X, 0), (icmp eq X, Pow2OrZero))
705
+ // -> (icmp eq (and X, Pow2OrZero), X)
706
+ // (and (icmp ne X, 0), (icmp ne X, Pow2OrZero))
707
+ // -> (icmp ne (and X, Pow2OrZero), X)
708
+ static Value *
709
+ foldAndOrOfICmpsWithPow2AndWithZero (InstCombiner::BuilderTy &Builder,
710
+ ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
711
+ const SimplifyQuery &Q) {
712
+ CmpInst::Predicate Pred = IsAnd ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
713
+ // Make sure we have right compares for our op.
714
+ if (LHS->getPredicate () != Pred || RHS->getPredicate () != Pred)
715
+ return nullptr ;
716
+
717
+ // Make it so we can match LHS against the (icmp eq/ne X, 0) just for
718
+ // simplicity.
719
+ if (match (RHS->getOperand (1 ), m_Zero ()))
720
+ std::swap (LHS, RHS);
721
+
722
+ Value *Pow2, *Op;
723
+ // Match the desired pattern:
724
+ // LHS: (icmp eq/ne X, 0)
725
+ // RHS: (icmp eq/ne X, Pow2OrZero)
726
+ // Skip if Pow2OrZero is 1. Either way it gets folded to (icmp ugt X, 1) but
727
+ // this form ends up slightly less canonical.
728
+ // We could potentially be more sophisticated than requiring LHS/RHS
729
+ // be one-use. We don't create additional instructions if only one
730
+ // of them is one-use. So cases where one is one-use and the other
731
+ // is two-use might be profitable.
732
+ if (!match (LHS, m_OneUse (m_ICmp (Pred, m_Value (Op), m_Zero ()))) ||
733
+ !match (RHS, m_OneUse (m_c_ICmp (Pred, m_Specific (Op), m_Value (Pow2)))) ||
734
+ match (Pow2, m_One ()) ||
735
+ !isKnownToBeAPowerOfTwo (Pow2, Q.DL , /* OrZero=*/ true , /* Depth=*/ 0 , Q.AC ,
736
+ Q.CxtI , Q.DT ))
737
+ return nullptr ;
738
+
739
+ Value *And = Builder.CreateAnd (Op, Pow2);
740
+ return Builder.CreateICmp (Pred, And, Op);
741
+ }
742
+
704
743
// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
705
744
// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
706
745
Value *InstCombinerImpl::foldAndOrOfICmpsOfAndWithPow2 (ICmpInst *LHS,
@@ -3240,6 +3279,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
3240
3279
ICmpInst::Predicate PredL = LHS->getPredicate (), PredR = RHS->getPredicate ();
3241
3280
Value *LHS0 = LHS->getOperand (0 ), *RHS0 = RHS->getOperand (0 );
3242
3281
Value *LHS1 = LHS->getOperand (1 ), *RHS1 = RHS->getOperand (1 );
3282
+
3243
3283
const APInt *LHSC = nullptr , *RHSC = nullptr ;
3244
3284
match (LHS1, m_APInt (LHSC));
3245
3285
match (RHS1, m_APInt (RHSC));
@@ -3345,6 +3385,11 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
3345
3385
Constant::getAllOnesValue (LHS0->getType ()));
3346
3386
}
3347
3387
3388
+ if (!IsLogical)
3389
+ if (Value *V =
3390
+ foldAndOrOfICmpsWithPow2AndWithZero (Builder, LHS, RHS, IsAnd, Q))
3391
+ return V;
3392
+
3348
3393
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
3349
3394
if (!LHSC || !RHSC)
3350
3395
return nullptr ;
0 commit comments