Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Show First 20 Lines • Show All 1,692 Lines • ▼ Show 20 Lines | ConstantRange R = ConstantRange::makeExactICmpRegion(CPred, *CmpC) | ||||
.binaryOp(BO->getOpcode(), *BinOpC); | .binaryOp(BO->getOpcode(), *BinOpC); | ||||
if (R == *C) { | if (R == *C) { | ||||
BO->dropPoisonGeneratingFlags(); | BO->dropPoisonGeneratingFlags(); | ||||
return BO; | return BO; | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
/// canonicalize all variants of strong order compare to (a > b) - (a < b) | |||||
static Instruction * | |||||
canonicalizeStrongOrderCmp(ICmpInst *ICI, Value *TrueVal, Value *FalseVal, | |||||
InstCombiner::BuilderTy &Builder) { | |||||
if (!isa<Constant>(TrueVal)) | |||||
return nullptr; | |||||
Type *Ty = TrueVal->getType(); | |||||
ICmpInst::Predicate Pred = ICI->getPredicate(); | |||||
Value *CmpLHS = ICI->getOperand(0); | |||||
Value *CmpRHS = ICI->getOperand(1); | |||||
Value *ICI2; | |||||
ICmpInst::Predicate Pred2; | |||||
Constant *InnerTC, *InnerFC; | |||||
auto SwapICmp = [&Builder, CmpLHS, CmpRHS](ICmpInst::Predicate Pred) { | |||||
return Builder.CreateICmp(ICmpInst::getSwappedPredicate(Pred), CmpLHS, | |||||
CmpRHS); | |||||
}; | |||||
if (FalseVal->hasOneUse() && | |||||
match(FalseVal, m_Select(m_Value(ICI2), m_ImmConstant(InnerTC), | |||||
m_ImmConstant(InnerFC))) && | |||||
match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS)))) { | |||||
if (Pred == ICmpInst::ICMP_EQ && match(TrueVal, m_Zero()) && | |||||
ICI->hasOneUse()) { | |||||
// A == B ? 0 : (A < B ? -1 : 1) --> (a > b) - (a < b) | |||||
if (match(InnerTC, m_AllOnes()) && match(InnerFC, m_One()) && | |||||
(Pred2 == ICmpInst::ICMP_SLT || Pred2 == ICmpInst::ICMP_ULT)) { | |||||
Value *ZExt = Builder.CreateZExt(SwapICmp(Pred2), Ty); | |||||
Value *SExt = Builder.CreateSExt(ICI2, Ty); | |||||
return BinaryOperator::CreateAdd(ZExt, SExt); | |||||
} | |||||
// A == B ? 0 : (A > B ? 1 : -1) --> (a > b) - (a < b) | |||||
if (match(InnerTC, m_One()) && match(InnerFC, m_AllOnes()) && | |||||
(Pred2 == ICmpInst::ICMP_SGT || Pred2 == ICmpInst::ICMP_UGT)) { | |||||
Value *ZExt = Builder.CreateZExt(ICI2, Ty); | |||||
Value *SExt = Builder.CreateSExt(SwapICmp(Pred2), Ty); | |||||
return BinaryOperator::CreateAdd(ZExt, SExt); | |||||
} | |||||
} | |||||
} | |||||
if (match(TrueVal, m_AllOnes()) && match(FalseVal, m_ZExt(m_Value(ICI2))) && | |||||
match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS))) && | |||||
(Pred2 != ICmpInst::ICMP_NE || | |||||
(FalseVal->hasOneUse() && ICI2->hasOneUse()))) { | |||||
// A < B ? -1 : zext (A > B) --> (a > b) - (a < b) | |||||
// A < B ? -1 : zext (A != B) --> (a > b) - (a < b) | |||||
if ((Pred == ICmpInst::ICMP_SLT && | |||||
(Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_SGT)) || | |||||
(Pred == ICmpInst::ICMP_ULT && | |||||
(Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_UGT))) { | |||||
Value *ZExt = FalseVal; | |||||
if (Pred2 == ICmpInst::ICMP_NE) | |||||
ZExt = Builder.CreateZExt(SwapICmp(Pred), Ty); | |||||
Value *SExt = Builder.CreateSExt(ICI, Ty); | |||||
return BinaryOperator::CreateAdd(ZExt, SExt); | |||||
} | |||||
} | |||||
if (match(TrueVal, m_One()) && match(FalseVal, m_SExt(m_Value(ICI2))) && | |||||
match(ICI2, m_ICmp(Pred2, m_Specific(CmpLHS), m_Specific(CmpRHS))) && | |||||
(Pred2 != ICmpInst::ICMP_NE || | |||||
(FalseVal->hasOneUse() && ICI2->hasOneUse()))) { | |||||
// A > B ? 1 : sext (A < B) --> (a > b) - (a < b) | |||||
// A > B ? 1 : sext (A != B) --> (a > b) - (a < b) | |||||
if ((Pred == ICmpInst::ICMP_SGT && | |||||
(Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_SLT)) || | |||||
(Pred == ICmpInst::ICMP_UGT && | |||||
(Pred2 == ICmpInst::ICMP_NE || Pred2 == ICmpInst::ICMP_ULT))) { | |||||
Value *ZExt = Builder.CreateZExt(ICI, Ty); | |||||
Value *SExt = FalseVal; | |||||
if (Pred2 == ICmpInst::ICMP_NE) | |||||
SExt = Builder.CreateSExt(SwapICmp(Pred), Ty); | |||||
return BinaryOperator::CreateAdd(ZExt, SExt); | |||||
} | |||||
} | |||||
return nullptr; | |||||
} | |||||
/// Visit a SelectInst that has an ICmpInst as its first operand. | /// Visit a SelectInst that has an ICmpInst as its first operand. | ||||
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, | Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI, | ||||
ICmpInst *ICI) { | ICmpInst *ICI) { | ||||
if (Instruction *NewSel = foldSelectValueEquivalence(SI, *ICI)) | if (Instruction *NewSel = foldSelectValueEquivalence(SI, *ICI)) | ||||
return NewSel; | return NewSel; | ||||
if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this)) | if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this)) | ||||
return NewSPF; | return NewSPF; | ||||
Show All 26 Lines | if (CmpLHS == TrueVal && Pred == ICmpInst::ICMP_EQ) { | ||||
Changed = true; | Changed = true; | ||||
} else if (CmpLHS == FalseVal && Pred == ICmpInst::ICMP_NE) { | } else if (CmpLHS == FalseVal && Pred == ICmpInst::ICMP_NE) { | ||||
// Transform (X != C) ? Y : X -> (X != C) ? Y : C | // Transform (X != C) ? Y : X -> (X != C) ? Y : C | ||||
SI.setOperand(2, CmpRHS); | SI.setOperand(2, CmpRHS); | ||||
Changed = true; | Changed = true; | ||||
} | } | ||||
} | } | ||||
if (Instruction *V = | |||||
canonicalizeStrongOrderCmp(ICI, TrueVal, FalseVal, Builder)) | |||||
return V; | |||||
// Canonicalize a signbit condition to use zero constant by swapping: | // Canonicalize a signbit condition to use zero constant by swapping: | ||||
// (CmpLHS > -1) ? TV : FV --> (CmpLHS < 0) ? FV : TV | // (CmpLHS > -1) ? TV : FV --> (CmpLHS < 0) ? FV : TV | ||||
// To avoid conflicts (infinite loops) with other canonicalizations, this is | // To avoid conflicts (infinite loops) with other canonicalizations, this is | ||||
// not applied with any constant select arm. | // not applied with any constant select arm. | ||||
if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes()) && | if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes()) && | ||||
!match(TrueVal, m_Constant()) && !match(FalseVal, m_Constant()) && | !match(TrueVal, m_Constant()) && !match(FalseVal, m_Constant()) && | ||||
ICI->hasOneUse()) { | ICI->hasOneUse()) { | ||||
InstCombiner::BuilderTy::InsertPointGuard Guard(Builder); | InstCombiner::BuilderTy::InsertPointGuard Guard(Builder); | ||||
▲ Show 20 Lines • Show All 1,844 Lines • Show Last 20 Lines |