@@ -689,25 +689,32 @@ static Value *foldSelectICmpLshrAshr(const ICmpInst *IC, Value *TrueVal,
689
689
}
690
690
691
691
// / 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))
693
693
// / 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))
695
698
// / iff:
699
+ // / 0 on the RHS is the identity value (i.e add, xor, shl, etc...)
696
700
// / C1 and C2 are both powers of 2
697
701
// / 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)
699
706
// /
700
707
// / This transform handles cases where:
701
708
// / 1. The icmp predicate is inverted
702
709
// / 2. The select operands are reversed
703
710
// / 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,
705
712
Value *FalseVal,
706
713
InstCombiner::BuilderTy &Builder) {
707
714
// Only handle integer compares. Also, if this is a vector select, we need a
708
715
// vector compare.
709
716
if (!TrueVal->getType ()->isIntOrIntVectorTy () ||
710
- TrueVal->getType ()->isVectorTy () != IC->getType ()->isVectorTy ())
717
+ TrueVal->getType ()->isVectorTy () != IC->getType ()->isVectorTy ())
711
718
return nullptr ;
712
719
713
720
Value *CmpLHS = IC->getOperand (0 );
@@ -735,21 +742,29 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
735
742
NeedAnd = true ;
736
743
}
737
744
738
- Value *Or, *Y, *V = CmpLHS;
745
+ Value *Y, *V = CmpLHS;
746
+ BinaryOperator *BinOp;
739
747
const APInt *C2;
740
748
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)))) {
742
750
Y = TrueVal;
743
- Or = FalseVal;
751
+ BinOp = cast<BinaryOperator>( FalseVal) ;
744
752
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)))) {
746
754
Y = FalseVal;
747
- Or = TrueVal;
755
+ BinOp = cast<BinaryOperator>( TrueVal) ;
748
756
NeedXor = Pred == ICmpInst::ICMP_EQ;
749
757
} else {
750
758
return nullptr ;
751
759
}
752
760
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
+
753
768
unsigned C2Log = C2->logBase2 ();
754
769
755
770
bool NeedShift = C1Log != C2Log;
@@ -758,7 +773,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
758
773
759
774
// Make sure we don't create more instructions than we save.
760
775
if ((NeedShift + NeedXor + NeedZExtTrunc + NeedAnd) >
761
- (IC->hasOneUse () + Or ->hasOneUse ()))
776
+ (IC->hasOneUse () + BinOp ->hasOneUse ()))
762
777
return nullptr ;
763
778
764
779
if (NeedAnd) {
@@ -779,7 +794,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal,
779
794
if (NeedXor)
780
795
V = Builder.CreateXor (V, *C2);
781
796
782
- return Builder.CreateOr (V , Y);
797
+ return Builder.CreateBinOp (BinOp-> getOpcode () , Y, V );
783
798
}
784
799
785
800
// / Canonicalize a set or clear of a masked set of constant bits to
@@ -1788,7 +1803,7 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
1788
1803
if (Instruction *V = foldSelectZeroOrOnes (ICI, TrueVal, FalseVal, Builder))
1789
1804
return V;
1790
1805
1791
- if (Value *V = foldSelectICmpAndOr (ICI, TrueVal, FalseVal, Builder))
1806
+ if (Value *V = foldSelectICmpAndBinOp (ICI, TrueVal, FalseVal, Builder))
1792
1807
return replaceInstUsesWith (SI, V);
1793
1808
1794
1809
if (Value *V = foldSelectICmpLshrAshr (ICI, TrueVal, FalseVal, Builder))
0 commit comments