@@ -701,6 +701,45 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
701701 return Builder.CreateICmp (NewPred, Input, RangeEnd);
702702}
703703
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+
704743// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
705744// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
706745Value *InstCombinerImpl::foldAndOrOfICmpsOfAndWithPow2 (ICmpInst *LHS,
@@ -3240,6 +3279,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
32403279 ICmpInst::Predicate PredL = LHS->getPredicate (), PredR = RHS->getPredicate ();
32413280 Value *LHS0 = LHS->getOperand (0 ), *RHS0 = RHS->getOperand (0 );
32423281 Value *LHS1 = LHS->getOperand (1 ), *RHS1 = RHS->getOperand (1 );
3282+
32433283 const APInt *LHSC = nullptr , *RHSC = nullptr ;
32443284 match (LHS1, m_APInt (LHSC));
32453285 match (RHS1, m_APInt (RHSC));
@@ -3345,6 +3385,11 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
33453385 Constant::getAllOnesValue (LHS0->getType ()));
33463386 }
33473387
3388+ if (!IsLogical)
3389+ if (Value *V =
3390+ foldAndOrOfICmpsWithPow2AndWithZero (Builder, LHS, RHS, IsAnd, Q))
3391+ return V;
3392+
33483393 // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
33493394 if (!LHSC || !RHSC)
33503395 return nullptr ;
0 commit comments