@@ -689,25 +689,32 @@ static Value *foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal,
689689}
690690
691691// / We want to turn:
692- // / (select (icmp eq (and X, C1), 0), Y, (or Y, C2))
692+ // / (select (icmp eq (and X, C1), 0), Y, (BinOp Y, C2))
693693// / into:
694- // / (or (shl (and X, C1), C3), Y)
694+ // / IF C2 u>= C1
695+ // / (BinOp Y, (shl (and X, C1), C3))
696+ // / ELSE
697+ // / (BinOp Y, (lshr (and X, C1), C3))
695698// / iff:
699+ // / 0 on the RHS is the identity value (i.e add, xor, shl, etc...)
696700// / C1 and C2 are both powers of 2
697701// / where:
698- // / C3 = Log(C2) - Log(C1)
702+ // / IF C2 u>= C1
703+ // / C3 = Log(C2) - Log(C1)
704+ // / ELSE
705+ // / C3 = Log(C1) - Log(C2)
699706// /
700707// / This transform handles cases where:
701708// / 1. The icmp predicate is inverted
702709// / 2. The select operands are reversed
703710// / 3. The magnitude of C2 and C1 are flipped
704- static Value *foldSelectICmpAndOr (const ICmpInst *IC, Value *TrueVal,
711+ static Value *foldSelectICmpAndBinOp (const ICmpInst *IC, Value *TrueVal,
705712 Value *FalseVal,
706713 InstCombiner::BuilderTy &Builder) {
707714 // Only handle integer compares. Also, if this is a vector select, we need a
708715 // vector compare.
709716 if (!TrueVal->getType ()->isIntOrIntVectorTy () ||
710- TrueVal->getType ()->isVectorTy () != IC->getType ()->isVectorTy ())
717+ TrueVal->getType ()->isVectorTy () != IC->getType ()->isVectorTy ())
711718 return nullptr ;
712719
713720 Value *CmpLHS = IC->getOperand (0 );
@@ -735,21 +742,29 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
735742 NeedAnd = true ;
736743 }
737744
738- Value *Or, *Y, *V = CmpLHS;
745+ Value *Y, *V = CmpLHS;
746+ BinaryOperator *BinOp;
739747 const APInt *C2;
740748 bool NeedXor;
741- if (match (FalseVal, m_Or (m_Specific (TrueVal), m_Power2 (C2)))) {
749+ if (match (FalseVal, m_BinOp (m_Specific (TrueVal), m_Power2 (C2)))) {
742750 Y = TrueVal;
743- Or = FalseVal;
751+ BinOp = cast<BinaryOperator>( FalseVal) ;
744752 NeedXor = Pred == ICmpInst::ICMP_NE;
745- } else if (match (TrueVal, m_Or (m_Specific (FalseVal), m_Power2 (C2)))) {
753+ } else if (match (TrueVal, m_BinOp (m_Specific (FalseVal), m_Power2 (C2)))) {
746754 Y = FalseVal;
747- Or = TrueVal;
755+ BinOp = cast<BinaryOperator>( TrueVal) ;
748756 NeedXor = Pred == ICmpInst::ICMP_EQ;
749757 } else {
750758 return nullptr ;
751759 }
752760
761+ // Check that 0 on RHS is identity value for this binop.
762+ auto *IdentityC =
763+ ConstantExpr::getBinOpIdentity (BinOp->getOpcode (), BinOp->getType (),
764+ /* AllowRHSConstant*/ true );
765+ if (IdentityC == nullptr || !IdentityC->isNullValue ())
766+ return nullptr ;
767+
753768 unsigned C2Log = C2->logBase2 ();
754769
755770 bool NeedShift = C1Log != C2Log;
@@ -758,7 +773,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
758773
759774 // Make sure we don't create more instructions than we save.
760775 if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >
761- (IC->hasOneUse () + Or ->hasOneUse ()))
776+ (IC->hasOneUse () + BinOp ->hasOneUse ()))
762777 return nullptr ;
763778
764779 if (NeedAnd) {
@@ -779,7 +794,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
779794 if (NeedXor)
780795 V = Builder.CreateXor (V, *C2);
781796
782- return Builder.CreateOr (V , Y);
797+ return Builder.CreateBinOp (BinOp-> getOpcode () , Y, V );
783798}
784799
785800// / Canonicalize a set or clear of a masked set of constant bits to
@@ -1788,7 +1803,7 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
17881803 if (Instruction *V = foldSelectZeroOrOnes (ICI, TrueVal, FalseVal, Builder))
17891804 return V;
17901805
1791- if (Value *V = foldSelectICmpAndOr (ICI, TrueVal, FalseVal, Builder))
1806+ if (Value *V = foldSelectICmpAndBinOp (ICI, TrueVal, FalseVal, Builder))
17921807 return replaceInstUsesWith (SI, V);
17931808
17941809 if (Value *V = foldSelectICmpLshrAshr (ICI, TrueVal, FalseVal, Builder))
0 commit comments