[Instcombine] Code refactors for foldSelectOpOp; NFC
Reuse the code about find common operator. Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D139075
This commit is contained in:
parent
d0650d1089
commit
683b9fc7bd
|
@ -314,47 +314,68 @@ Instruction *InstCombinerImpl::foldSelectOpOp(SelectInst &SI, Instruction *TI,
|
||||||
TI->getType());
|
TI->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cond ? -X : -Y --> -(Cond ? X : Y)
|
Value *OtherOpT, *OtherOpF;
|
||||||
Value *X, *Y;
|
bool MatchIsOpZero;
|
||||||
if (match(TI, m_FNeg(m_Value(X))) && match(FI, m_FNeg(m_Value(Y))) &&
|
auto getCommonOp = [&](Instruction *TI, Instruction *FI,
|
||||||
(TI->hasOneUse() || FI->hasOneUse())) {
|
bool Commute) -> Value * {
|
||||||
// Intersect FMF from the fneg instructions and union those with the select.
|
Value *CommonOp = nullptr;
|
||||||
FastMathFlags FMF = TI->getFastMathFlags();
|
if (TI->getOperand(0) == FI->getOperand(0)) {
|
||||||
FMF &= FI->getFastMathFlags();
|
CommonOp = TI->getOperand(0);
|
||||||
FMF |= SI.getFastMathFlags();
|
OtherOpT = TI->getOperand(1);
|
||||||
Value *NewSel = Builder.CreateSelect(Cond, X, Y, SI.getName() + ".v", &SI);
|
OtherOpF = FI->getOperand(1);
|
||||||
if (auto *NewSelI = dyn_cast<Instruction>(NewSel))
|
MatchIsOpZero = true;
|
||||||
NewSelI->setFastMathFlags(FMF);
|
} else if (TI->getOperand(1) == FI->getOperand(1)) {
|
||||||
Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewSel);
|
CommonOp = TI->getOperand(1);
|
||||||
NewFNeg->setFastMathFlags(FMF);
|
OtherOpT = TI->getOperand(0);
|
||||||
return NewFNeg;
|
OtherOpF = FI->getOperand(0);
|
||||||
}
|
MatchIsOpZero = false;
|
||||||
|
} else if (!Commute) {
|
||||||
|
return nullptr;
|
||||||
|
} else if (TI->getOperand(0) == FI->getOperand(1)) {
|
||||||
|
CommonOp = TI->getOperand(0);
|
||||||
|
OtherOpT = TI->getOperand(1);
|
||||||
|
OtherOpF = FI->getOperand(0);
|
||||||
|
MatchIsOpZero = true;
|
||||||
|
} else if (TI->getOperand(1) == FI->getOperand(0)) {
|
||||||
|
CommonOp = TI->getOperand(1);
|
||||||
|
OtherOpT = TI->getOperand(0);
|
||||||
|
OtherOpF = FI->getOperand(1);
|
||||||
|
MatchIsOpZero = true;
|
||||||
|
}
|
||||||
|
return CommonOp;
|
||||||
|
};
|
||||||
|
|
||||||
// Min/max intrinsic with a common operand can have the common operand pulled
|
if (TI->hasOneUse() || FI->hasOneUse()) {
|
||||||
// after the select. This is the same transform as below for binops, but
|
// Cond ? -X : -Y --> -(Cond ? X : Y)
|
||||||
// specialized for intrinsic matching and without the restrictive uses clause.
|
Value *X, *Y;
|
||||||
auto *TII = dyn_cast<IntrinsicInst>(TI);
|
if (match(TI, m_FNeg(m_Value(X))) && match(FI, m_FNeg(m_Value(Y)))) {
|
||||||
auto *FII = dyn_cast<IntrinsicInst>(FI);
|
// Intersect FMF from the fneg instructions and union those with the
|
||||||
if (TII && FII && TII->getIntrinsicID() == FII->getIntrinsicID() &&
|
// select.
|
||||||
(TII->hasOneUse() || FII->hasOneUse())) {
|
FastMathFlags FMF = TI->getFastMathFlags();
|
||||||
Value *T0, *T1, *F0, *F1;
|
FMF &= FI->getFastMathFlags();
|
||||||
if (match(TII, m_MaxOrMin(m_Value(T0), m_Value(T1))) &&
|
FMF |= SI.getFastMathFlags();
|
||||||
match(FII, m_MaxOrMin(m_Value(F0), m_Value(F1)))) {
|
Value *NewSel =
|
||||||
if (T0 == F0) {
|
Builder.CreateSelect(Cond, X, Y, SI.getName() + ".v", &SI);
|
||||||
Value *NewSel = Builder.CreateSelect(Cond, T1, F1, "minmaxop", &SI);
|
if (auto *NewSelI = dyn_cast<Instruction>(NewSel))
|
||||||
return CallInst::Create(TII->getCalledFunction(), {NewSel, T0});
|
NewSelI->setFastMathFlags(FMF);
|
||||||
}
|
Instruction *NewFNeg = UnaryOperator::CreateFNeg(NewSel);
|
||||||
if (T0 == F1) {
|
NewFNeg->setFastMathFlags(FMF);
|
||||||
Value *NewSel = Builder.CreateSelect(Cond, T1, F0, "minmaxop", &SI);
|
return NewFNeg;
|
||||||
return CallInst::Create(TII->getCalledFunction(), {NewSel, T0});
|
}
|
||||||
}
|
|
||||||
if (T1 == F0) {
|
// Min/max intrinsic with a common operand can have the common operand
|
||||||
Value *NewSel = Builder.CreateSelect(Cond, T0, F1, "minmaxop", &SI);
|
// pulled after the select. This is the same transform as below for binops,
|
||||||
return CallInst::Create(TII->getCalledFunction(), {NewSel, T1});
|
// but specialized for intrinsic matching and without the restrictive uses
|
||||||
}
|
// clause.
|
||||||
if (T1 == F1) {
|
auto *TII = dyn_cast<IntrinsicInst>(TI);
|
||||||
Value *NewSel = Builder.CreateSelect(Cond, T0, F0, "minmaxop", &SI);
|
auto *FII = dyn_cast<IntrinsicInst>(FI);
|
||||||
return CallInst::Create(TII->getCalledFunction(), {NewSel, T1});
|
if (TII && FII && TII->getIntrinsicID() == FII->getIntrinsicID()) {
|
||||||
|
if (match(TII, m_MaxOrMin(m_Value(), m_Value()))) {
|
||||||
|
if (Value *MatchOp = getCommonOp(TI, FI, true)) {
|
||||||
|
Value *NewSel =
|
||||||
|
Builder.CreateSelect(Cond, OtherOpT, OtherOpF, "minmaxop", &SI);
|
||||||
|
return CallInst::Create(TII->getCalledFunction(), {NewSel, MatchOp});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,33 +391,9 @@ Instruction *InstCombinerImpl::foldSelectOpOp(SelectInst &SI, Instruction *TI,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Figure out if the operations have any operands in common.
|
// Figure out if the operations have any operands in common.
|
||||||
Value *MatchOp, *OtherOpT, *OtherOpF;
|
Value *MatchOp = getCommonOp(TI, FI, TI->isCommutative());
|
||||||
bool MatchIsOpZero;
|
if (!MatchOp)
|
||||||
if (TI->getOperand(0) == FI->getOperand(0)) {
|
|
||||||
MatchOp = TI->getOperand(0);
|
|
||||||
OtherOpT = TI->getOperand(1);
|
|
||||||
OtherOpF = FI->getOperand(1);
|
|
||||||
MatchIsOpZero = true;
|
|
||||||
} else if (TI->getOperand(1) == FI->getOperand(1)) {
|
|
||||||
MatchOp = TI->getOperand(1);
|
|
||||||
OtherOpT = TI->getOperand(0);
|
|
||||||
OtherOpF = FI->getOperand(0);
|
|
||||||
MatchIsOpZero = false;
|
|
||||||
} else if (!TI->isCommutative()) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (TI->getOperand(0) == FI->getOperand(1)) {
|
|
||||||
MatchOp = TI->getOperand(0);
|
|
||||||
OtherOpT = TI->getOperand(1);
|
|
||||||
OtherOpF = FI->getOperand(0);
|
|
||||||
MatchIsOpZero = true;
|
|
||||||
} else if (TI->getOperand(1) == FI->getOperand(0)) {
|
|
||||||
MatchOp = TI->getOperand(1);
|
|
||||||
OtherOpT = TI->getOperand(0);
|
|
||||||
OtherOpF = FI->getOperand(1);
|
|
||||||
MatchIsOpZero = true;
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the select condition is a vector, the operands of the original select's
|
// If the select condition is a vector, the operands of the original select's
|
||||||
// operands also must be vectors. This may not be the case for getelementptr
|
// operands also must be vectors. This may not be the case for getelementptr
|
||||||
|
|
Loading…
Reference in New Issue