Skip to content

Commit 54ec8bc

Browse files
committed
Recommit "[InstCombine] Expand foldSelectICmpAndOr -> foldSelectICmpAndBinOp to work for more binops" (3rd Try)
Fixed bug that assumed binop was commutative. Was re-reviewed by nikic and chapuni Differential Revision: https://reviews.llvm.org/D148414
1 parent a69f78b commit 54ec8bc

File tree

2 files changed

+133
-69
lines changed

2 files changed

+133
-69
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)