forked from OSchip/llvm-project
[InstCombine] add helper to foldXorOfICmps(); NFCI
Also, fix the old-style capitalization of the related functions and move them to the 'private' section of the class since they are just helpers of the visit* functions. As shown in the post-commit comments for D32143, we are missing folds for xor-of-icmps. llvm-svn: 303381
This commit is contained in:
parent
432b8dd8ad
commit
5e456b943a
|
@ -764,7 +764,7 @@ foldAndOrOfEqualityCmpsWithConstants(ICmpInst *LHS, ICmpInst *RHS,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fold (icmp)&(icmp) if possible.
|
/// Fold (icmp)&(icmp) if possible.
|
||||||
Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||||
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
|
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
|
||||||
|
|
||||||
// (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B)
|
// (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B)
|
||||||
|
@ -943,7 +943,7 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||||
|
|
||||||
/// Optimize (fcmp)&(fcmp). NOTE: Unlike the rest of instcombine, this returns
|
/// Optimize (fcmp)&(fcmp). NOTE: Unlike the rest of instcombine, this returns
|
||||||
/// a Value which should already be inserted into the function.
|
/// a Value which should already be inserted into the function.
|
||||||
Value *InstCombiner::FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
|
Value *InstCombiner::foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
|
||||||
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
|
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
|
||||||
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
|
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
|
||||||
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
|
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
|
||||||
|
@ -1126,8 +1126,8 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
|
||||||
ICmpInst *ICmp0 = dyn_cast<ICmpInst>(Cast0Src);
|
ICmpInst *ICmp0 = dyn_cast<ICmpInst>(Cast0Src);
|
||||||
ICmpInst *ICmp1 = dyn_cast<ICmpInst>(Cast1Src);
|
ICmpInst *ICmp1 = dyn_cast<ICmpInst>(Cast1Src);
|
||||||
if (ICmp0 && ICmp1) {
|
if (ICmp0 && ICmp1) {
|
||||||
Value *Res = LogicOpc == Instruction::And ? FoldAndOfICmps(ICmp0, ICmp1)
|
Value *Res = LogicOpc == Instruction::And ? foldAndOfICmps(ICmp0, ICmp1)
|
||||||
: FoldOrOfICmps(ICmp0, ICmp1, &I);
|
: foldOrOfICmps(ICmp0, ICmp1, &I);
|
||||||
if (Res)
|
if (Res)
|
||||||
return CastInst::Create(CastOpcode, Res, DestTy);
|
return CastInst::Create(CastOpcode, Res, DestTy);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1138,8 +1138,8 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
|
||||||
FCmpInst *FCmp0 = dyn_cast<FCmpInst>(Cast0Src);
|
FCmpInst *FCmp0 = dyn_cast<FCmpInst>(Cast0Src);
|
||||||
FCmpInst *FCmp1 = dyn_cast<FCmpInst>(Cast1Src);
|
FCmpInst *FCmp1 = dyn_cast<FCmpInst>(Cast1Src);
|
||||||
if (FCmp0 && FCmp1) {
|
if (FCmp0 && FCmp1) {
|
||||||
Value *Res = LogicOpc == Instruction::And ? FoldAndOfFCmps(FCmp0, FCmp1)
|
Value *Res = LogicOpc == Instruction::And ? foldAndOfFCmps(FCmp0, FCmp1)
|
||||||
: FoldOrOfFCmps(FCmp0, FCmp1);
|
: foldOrOfFCmps(FCmp0, FCmp1);
|
||||||
if (Res)
|
if (Res)
|
||||||
return CastInst::Create(CastOpcode, Res, DestTy);
|
return CastInst::Create(CastOpcode, Res, DestTy);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1425,7 +1425,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||||
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
|
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
|
||||||
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
|
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
|
||||||
if (LHS && RHS)
|
if (LHS && RHS)
|
||||||
if (Value *Res = FoldAndOfICmps(LHS, RHS))
|
if (Value *Res = foldAndOfICmps(LHS, RHS))
|
||||||
return replaceInstUsesWith(I, Res);
|
return replaceInstUsesWith(I, Res);
|
||||||
|
|
||||||
// TODO: Make this recursive; it's a little tricky because an arbitrary
|
// TODO: Make this recursive; it's a little tricky because an arbitrary
|
||||||
|
@ -1433,18 +1433,18 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||||
Value *X, *Y;
|
Value *X, *Y;
|
||||||
if (LHS && match(Op1, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
|
if (LHS && match(Op1, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
||||||
if (Value *Res = FoldAndOfICmps(LHS, Cmp))
|
if (Value *Res = foldAndOfICmps(LHS, Cmp))
|
||||||
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
|
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
||||||
if (Value *Res = FoldAndOfICmps(LHS, Cmp))
|
if (Value *Res = foldAndOfICmps(LHS, Cmp))
|
||||||
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
|
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
|
||||||
}
|
}
|
||||||
if (RHS && match(Op0, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
|
if (RHS && match(Op0, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
||||||
if (Value *Res = FoldAndOfICmps(Cmp, RHS))
|
if (Value *Res = foldAndOfICmps(Cmp, RHS))
|
||||||
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
|
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
||||||
if (Value *Res = FoldAndOfICmps(Cmp, RHS))
|
if (Value *Res = foldAndOfICmps(Cmp, RHS))
|
||||||
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
|
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1452,7 +1452,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
|
||||||
// If and'ing two fcmp, try combine them into one.
|
// If and'ing two fcmp, try combine them into one.
|
||||||
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
|
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
|
||||||
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
|
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
|
||||||
if (Value *Res = FoldAndOfFCmps(LHS, RHS))
|
if (Value *Res = foldAndOfFCmps(LHS, RHS))
|
||||||
return replaceInstUsesWith(I, Res);
|
return replaceInstUsesWith(I, Res);
|
||||||
|
|
||||||
if (Instruction *CastedAnd = foldCastedBitwiseLogic(I))
|
if (Instruction *CastedAnd = foldCastedBitwiseLogic(I))
|
||||||
|
@ -1589,7 +1589,7 @@ static Value *matchSelectFromAndOr(Value *A, Value *C, Value *B, Value *D,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fold (icmp)|(icmp) if possible.
|
/// Fold (icmp)|(icmp) if possible.
|
||||||
Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
|
Value *InstCombiner::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
|
||||||
Instruction *CxtI) {
|
Instruction *CxtI) {
|
||||||
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
|
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
|
||||||
|
|
||||||
|
@ -1846,7 +1846,7 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
|
||||||
|
|
||||||
/// Optimize (fcmp)|(fcmp). NOTE: Unlike the rest of instcombine, this returns
|
/// Optimize (fcmp)|(fcmp). NOTE: Unlike the rest of instcombine, this returns
|
||||||
/// a Value which should already be inserted into the function.
|
/// a Value which should already be inserted into the function.
|
||||||
Value *InstCombiner::FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
|
Value *InstCombiner::foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
|
||||||
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
|
Value *Op0LHS = LHS->getOperand(0), *Op0RHS = LHS->getOperand(1);
|
||||||
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
|
Value *Op1LHS = RHS->getOperand(0), *Op1RHS = RHS->getOperand(1);
|
||||||
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
|
FCmpInst::Predicate Op0CC = LHS->getPredicate(), Op1CC = RHS->getPredicate();
|
||||||
|
@ -2197,7 +2197,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||||
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
|
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
|
||||||
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
|
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
|
||||||
if (LHS && RHS)
|
if (LHS && RHS)
|
||||||
if (Value *Res = FoldOrOfICmps(LHS, RHS, &I))
|
if (Value *Res = foldOrOfICmps(LHS, RHS, &I))
|
||||||
return replaceInstUsesWith(I, Res);
|
return replaceInstUsesWith(I, Res);
|
||||||
|
|
||||||
// TODO: Make this recursive; it's a little tricky because an arbitrary
|
// TODO: Make this recursive; it's a little tricky because an arbitrary
|
||||||
|
@ -2205,18 +2205,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||||
Value *X, *Y;
|
Value *X, *Y;
|
||||||
if (LHS && match(Op1, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
if (LHS && match(Op1, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
||||||
if (Value *Res = FoldOrOfICmps(LHS, Cmp, &I))
|
if (Value *Res = foldOrOfICmps(LHS, Cmp, &I))
|
||||||
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
|
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
||||||
if (Value *Res = FoldOrOfICmps(LHS, Cmp, &I))
|
if (Value *Res = foldOrOfICmps(LHS, Cmp, &I))
|
||||||
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
|
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
|
||||||
}
|
}
|
||||||
if (RHS && match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
if (RHS && match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
if (auto *Cmp = dyn_cast<ICmpInst>(X))
|
||||||
if (Value *Res = FoldOrOfICmps(Cmp, RHS, &I))
|
if (Value *Res = foldOrOfICmps(Cmp, RHS, &I))
|
||||||
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
|
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
|
||||||
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
|
||||||
if (Value *Res = FoldOrOfICmps(Cmp, RHS, &I))
|
if (Value *Res = foldOrOfICmps(Cmp, RHS, &I))
|
||||||
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
|
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2224,7 +2224,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
|
||||||
// (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y)
|
// (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y)
|
||||||
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
|
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
|
||||||
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
|
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
|
||||||
if (Value *Res = FoldOrOfFCmps(LHS, RHS))
|
if (Value *Res = foldOrOfFCmps(LHS, RHS))
|
||||||
return replaceInstUsesWith(I, Res);
|
return replaceInstUsesWith(I, Res);
|
||||||
|
|
||||||
if (Instruction *CastedOr = foldCastedBitwiseLogic(I))
|
if (Instruction *CastedOr = foldCastedBitwiseLogic(I))
|
||||||
|
@ -2320,6 +2320,24 @@ static Instruction *foldXorToXor(BinaryOperator &I) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value *InstCombiner::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||||
|
if (PredicatesFoldable(LHS->getPredicate(), RHS->getPredicate())) {
|
||||||
|
if (LHS->getOperand(0) == RHS->getOperand(1) &&
|
||||||
|
LHS->getOperand(1) == RHS->getOperand(0))
|
||||||
|
LHS->swapOperands();
|
||||||
|
if (LHS->getOperand(0) == RHS->getOperand(0) &&
|
||||||
|
LHS->getOperand(1) == RHS->getOperand(1)) {
|
||||||
|
// (icmp1 A, B) ^ (icmp2 A, B) --> (icmp3 A, B)
|
||||||
|
Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
|
||||||
|
unsigned Code = getICmpCode(LHS) ^ getICmpCode(RHS);
|
||||||
|
bool isSigned = LHS->isSigned() || RHS->isSigned();
|
||||||
|
return getNewICmpValue(isSigned, Code, Op0, Op1, Builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
|
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
|
||||||
// here. We should standardize that construct where it is needed or choose some
|
// here. We should standardize that construct where it is needed or choose some
|
||||||
// other way to ensure that commutated variants of patterns are not missed.
|
// other way to ensure that commutated variants of patterns are not missed.
|
||||||
|
@ -2579,23 +2597,10 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
|
||||||
match(Op1, m_Not(m_Specific(A))))
|
match(Op1, m_Not(m_Specific(A))))
|
||||||
return BinaryOperator::CreateNot(Builder->CreateAnd(A, B));
|
return BinaryOperator::CreateNot(Builder->CreateAnd(A, B));
|
||||||
|
|
||||||
// (icmp1 A, B) ^ (icmp2 A, B) --> (icmp3 A, B)
|
if (auto *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
|
||||||
if (ICmpInst *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
|
if (auto *RHS = dyn_cast<ICmpInst>(I.getOperand(1)))
|
||||||
if (ICmpInst *LHS = dyn_cast<ICmpInst>(I.getOperand(0)))
|
if (Value *V = foldXorOfICmps(LHS, RHS))
|
||||||
if (PredicatesFoldable(LHS->getPredicate(), RHS->getPredicate())) {
|
return replaceInstUsesWith(I, V);
|
||||||
if (LHS->getOperand(0) == RHS->getOperand(1) &&
|
|
||||||
LHS->getOperand(1) == RHS->getOperand(0))
|
|
||||||
LHS->swapOperands();
|
|
||||||
if (LHS->getOperand(0) == RHS->getOperand(0) &&
|
|
||||||
LHS->getOperand(1) == RHS->getOperand(1)) {
|
|
||||||
Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
|
|
||||||
unsigned Code = getICmpCode(LHS) ^ getICmpCode(RHS);
|
|
||||||
bool isSigned = LHS->isSigned() || RHS->isSigned();
|
|
||||||
return replaceInstUsesWith(I,
|
|
||||||
getNewICmpValue(isSigned, Code, Op0, Op1,
|
|
||||||
Builder));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Instruction *CastedXor = foldCastedBitwiseLogic(I))
|
if (Instruction *CastedXor = foldCastedBitwiseLogic(I))
|
||||||
return CastedXor;
|
return CastedXor;
|
||||||
|
|
|
@ -275,11 +275,7 @@ public:
|
||||||
Instruction *visitSDiv(BinaryOperator &I);
|
Instruction *visitSDiv(BinaryOperator &I);
|
||||||
Instruction *visitFDiv(BinaryOperator &I);
|
Instruction *visitFDiv(BinaryOperator &I);
|
||||||
Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted);
|
Value *simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1, bool Inverted);
|
||||||
Value *FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS);
|
|
||||||
Value *FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
|
|
||||||
Instruction *visitAnd(BinaryOperator &I);
|
Instruction *visitAnd(BinaryOperator &I);
|
||||||
Value *FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction *CxtI);
|
|
||||||
Value *FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
|
|
||||||
Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
||||||
Value *B, Value *C);
|
Value *B, Value *C);
|
||||||
Instruction *FoldXorWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
Instruction *FoldXorWithConstants(BinaryOperator &I, Value *Op, Value *A,
|
||||||
|
@ -445,6 +441,12 @@ private:
|
||||||
Instruction::CastOps isEliminableCastPair(const CastInst *CI1,
|
Instruction::CastOps isEliminableCastPair(const CastInst *CI1,
|
||||||
const CastInst *CI2);
|
const CastInst *CI2);
|
||||||
|
|
||||||
|
Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS);
|
||||||
|
Value *foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
|
||||||
|
Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction *CxtI);
|
||||||
|
Value *foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
|
||||||
|
Value *foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// \brief Inserts an instruction \p New before instruction \p Old
|
/// \brief Inserts an instruction \p New before instruction \p Old
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue