forked from OSchip/llvm-project
[InstCombine] fold fneg disguised as select+fmul (PR43497)
Extends rL373230 and solves the motivating bug (although in a narrow way): https://bugs.llvm.org/show_bug.cgi?id=43497 llvm-svn: 373851
This commit is contained in:
parent
25ba49824d
commit
aab8b3ab9c
|
@ -124,6 +124,50 @@ static Constant *getLogBase2(Type *Ty, Constant *C) {
|
|||
return ConstantVector::get(Elts);
|
||||
}
|
||||
|
||||
// TODO: This is a specific form of a much more general pattern.
|
||||
// We could detect a select with any binop identity constant, or we
|
||||
// could use SimplifyBinOp to see if either arm of the select reduces.
|
||||
// But that needs to be done carefully and/or while removing potential
|
||||
// reverse canonicalizations as in InstCombiner::foldSelectIntoOp().
|
||||
static Value *foldMulSelectToNegate(BinaryOperator &I,
|
||||
InstCombiner::BuilderTy &Builder) {
|
||||
Value *Cond, *OtherOp;
|
||||
|
||||
// mul (select Cond, 1, -1), OtherOp --> select Cond, OtherOp, -OtherOp
|
||||
// mul OtherOp, (select Cond, 1, -1) --> select Cond, OtherOp, -OtherOp
|
||||
if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes())),
|
||||
m_Value(OtherOp))))
|
||||
return Builder.CreateSelect(Cond, OtherOp, Builder.CreateNeg(OtherOp));
|
||||
|
||||
// mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp
|
||||
// mul OtherOp, (select Cond, -1, 1) --> select Cond, -OtherOp, OtherOp
|
||||
if (match(&I, m_c_Mul(m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One())),
|
||||
m_Value(OtherOp))))
|
||||
return Builder.CreateSelect(Cond, Builder.CreateNeg(OtherOp), OtherOp);
|
||||
|
||||
// fmul (select Cond, 1.0, -1.0), OtherOp --> select Cond, OtherOp, -OtherOp
|
||||
// fmul OtherOp, (select Cond, 1.0, -1.0) --> select Cond, OtherOp, -OtherOp
|
||||
if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(1.0),
|
||||
m_SpecificFP(-1.0))),
|
||||
m_Value(OtherOp)))) {
|
||||
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
|
||||
Builder.setFastMathFlags(I.getFastMathFlags());
|
||||
return Builder.CreateSelect(Cond, OtherOp, Builder.CreateFNeg(OtherOp));
|
||||
}
|
||||
|
||||
// fmul (select Cond, -1.0, 1.0), OtherOp --> select Cond, -OtherOp, OtherOp
|
||||
// fmul OtherOp, (select Cond, -1.0, 1.0) --> select Cond, -OtherOp, OtherOp
|
||||
if (match(&I, m_c_FMul(m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(-1.0),
|
||||
m_SpecificFP(1.0))),
|
||||
m_Value(OtherOp)))) {
|
||||
IRBuilder<>::FastMathFlagGuard FMFGuard(Builder);
|
||||
Builder.setFastMathFlags(I.getFastMathFlags());
|
||||
return Builder.CreateSelect(Cond, Builder.CreateFNeg(OtherOp), OtherOp);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
if (Value *V = SimplifyMulInst(I.getOperand(0), I.getOperand(1),
|
||||
SQ.getWithInstruction(&I)))
|
||||
|
@ -213,24 +257,8 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
|||
if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
|
||||
return FoldedMul;
|
||||
|
||||
// TODO: This is a specific form of a much more general pattern.
|
||||
// We could detect a select with any binop identity constant, or we
|
||||
// could use SimplifyBinOp to see if either arm of the select reduces.
|
||||
// But that needs to be done carefully and/or while removing potential
|
||||
// reverse canonicalizations as in InstCombiner::foldSelectIntoOp().
|
||||
// mul (select Cond, 1, -1), Op1 --> select Cond, Op1, -Op1
|
||||
// mul (select Cond, -1, 1), Op1 --> select Cond, -Op1, Op1
|
||||
// mul Op0, (select Cond, 1, -1) --> select Cond, Op0, -Op0
|
||||
// mul Op0, (select Cond, -1, 1) --> select Cond, -Op0, Op0
|
||||
Value *Cond;
|
||||
if (match(Op0, m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes()))))
|
||||
return SelectInst::Create(Cond, Op1, Builder.CreateNeg(Op1));
|
||||
if (match(Op0, m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One()))))
|
||||
return SelectInst::Create(Cond, Builder.CreateNeg(Op1), Op1);
|
||||
if (match(Op1, m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes()))))
|
||||
return SelectInst::Create(Cond, Op0, Builder.CreateNeg(Op0));
|
||||
if (match(Op1, m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One()))))
|
||||
return SelectInst::Create(Cond, Builder.CreateNeg(Op0), Op0);
|
||||
if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
|
||||
return replaceInstUsesWith(I, FoldedMul);
|
||||
|
||||
// Simplify mul instructions with a constant RHS.
|
||||
if (isa<Constant>(Op1)) {
|
||||
|
@ -377,6 +405,9 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
|||
if (Instruction *FoldedMul = foldBinOpIntoSelectOrPhi(I))
|
||||
return FoldedMul;
|
||||
|
||||
if (Value *FoldedMul = foldMulSelectToNegate(I, Builder))
|
||||
return replaceInstUsesWith(I, FoldedMul);
|
||||
|
||||
// X * -1.0 --> -X
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
if (match(Op1, m_SpecificFP(-1.0)))
|
||||
|
|
|
@ -994,9 +994,9 @@ define double @fmul_negated_constant_expression(double %x) {
|
|||
|
||||
define float @negate_if_true(float %x, i1 %cond) {
|
||||
; CHECK-LABEL: @negate_if_true(
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float 1.000000e+00
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul float [[SEL]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fsub float -0.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[COND:%.*]], float [[TMP1]], float [[X]]
|
||||
; CHECK-NEXT: ret float [[TMP2]]
|
||||
;
|
||||
%sel = select i1 %cond, float -1.0, float 1.0
|
||||
%r = fmul float %sel, %x
|
||||
|
@ -1005,9 +1005,9 @@ define float @negate_if_true(float %x, i1 %cond) {
|
|||
|
||||
define float @negate_if_false(float %x, i1 %cond) {
|
||||
; CHECK-LABEL: @negate_if_false(
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float 1.000000e+00, float -1.000000e+00
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul arcp float [[SEL]], [[X:%.*]]
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fsub arcp float -0.000000e+00, [[X:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = select arcp i1 [[COND:%.*]], float [[X]], float [[TMP1]]
|
||||
; CHECK-NEXT: ret float [[TMP2]]
|
||||
;
|
||||
%sel = select i1 %cond, float 1.0, float -1.0
|
||||
%r = fmul arcp float %sel, %x
|
||||
|
@ -1017,9 +1017,9 @@ define float @negate_if_false(float %x, i1 %cond) {
|
|||
define <2 x double> @negate_if_true_commute(<2 x double> %px, i1 %cond) {
|
||||
; CHECK-LABEL: @negate_if_true_commute(
|
||||
; CHECK-NEXT: [[X:%.*]] = fdiv <2 x double> <double 4.200000e+01, double 4.200000e+01>, [[PX:%.*]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], <2 x double> <double -1.000000e+00, double -1.000000e+00>, <2 x double> <double 1.000000e+00, double 1.000000e+00>
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul ninf <2 x double> [[X]], [[SEL]]
|
||||
; CHECK-NEXT: ret <2 x double> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fsub ninf <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[X]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = select ninf i1 [[COND:%.*]], <2 x double> [[TMP1]], <2 x double> [[X]]
|
||||
; CHECK-NEXT: ret <2 x double> [[TMP2]]
|
||||
;
|
||||
%x = fdiv <2 x double> <double 42.0, double 42.0>, %px ; thwart complexity-based canonicalization
|
||||
%sel = select i1 %cond, <2 x double> <double -1.0, double -1.0>, <2 x double> <double 1.0, double 1.0>
|
||||
|
@ -1030,9 +1030,9 @@ define <2 x double> @negate_if_true_commute(<2 x double> %px, i1 %cond) {
|
|||
define <2 x double> @negate_if_false_commute(<2 x double> %px, <2 x i1> %cond) {
|
||||
; CHECK-LABEL: @negate_if_false_commute(
|
||||
; CHECK-NEXT: [[X:%.*]] = fdiv <2 x double> <double 4.200000e+01, double 5.100000e+00>, [[PX:%.*]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[COND:%.*]], <2 x double> <double 1.000000e+00, double 1.000000e+00>, <2 x double> <double -1.000000e+00, double -1.000000e+00>
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul <2 x double> [[X]], [[SEL]]
|
||||
; CHECK-NEXT: ret <2 x double> [[R]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fsub <2 x double> <double -0.000000e+00, double -0.000000e+00>, [[X]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[COND:%.*]], <2 x double> [[X]], <2 x double> [[TMP1]]
|
||||
; CHECK-NEXT: ret <2 x double> [[TMP2]]
|
||||
;
|
||||
%x = fdiv <2 x double> <double 42.0, double 5.1>, %px ; thwart complexity-based canonicalization
|
||||
%sel = select <2 x i1> %cond, <2 x double> <double 1.0, double 1.0>, <2 x double> <double -1.0, double -1.0>
|
||||
|
@ -1040,6 +1040,8 @@ define <2 x double> @negate_if_false_commute(<2 x double> %px, <2 x i1> %cond) {
|
|||
ret <2 x double> %r
|
||||
}
|
||||
|
||||
; Negative test
|
||||
|
||||
define float @negate_if_true_extra_use(float %x, i1 %cond) {
|
||||
; CHECK-LABEL: @negate_if_true_extra_use(
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float -1.000000e+00, float 1.000000e+00
|
||||
|
@ -1053,6 +1055,8 @@ define float @negate_if_true_extra_use(float %x, i1 %cond) {
|
|||
ret float %r
|
||||
}
|
||||
|
||||
; Negative test
|
||||
|
||||
define <2 x double> @negate_if_true_wrong_constant(<2 x double> %px, i1 %cond) {
|
||||
; CHECK-LABEL: @negate_if_true_wrong_constant(
|
||||
; CHECK-NEXT: [[X:%.*]] = fdiv <2 x double> <double 4.200000e+01, double 4.200000e+01>, [[PX:%.*]]
|
||||
|
|
Loading…
Reference in New Issue