diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index f85a3c9..0c34cf0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -121,21 +121,17 @@ static Value *foldMulSelectToNegate(BinaryOperator &I, // 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)); - } + m_Value(OtherOp)))) + return Builder.CreateSelectFMF(Cond, OtherOp, + Builder.CreateFNegFMF(OtherOp, &I), &I); // 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); - } + m_Value(OtherOp)))) + return Builder.CreateSelectFMF(Cond, Builder.CreateFNegFMF(OtherOp, &I), + OtherOp, &I); return nullptr; } @@ -590,11 +586,9 @@ Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) { // fabs(X) / fabs(Y) --> fabs(X / Y) if (match(Op0, m_FAbs(m_Value(X))) && match(Op1, m_FAbs(m_Value(Y))) && (Op0->hasOneUse() || Op1->hasOneUse())) { - IRBuilder<>::FastMathFlagGuard FMFGuard(Builder); - Builder.setFastMathFlags(I.getFastMathFlags()); - Value *XY = Builder.CreateBinOp(Opcode, X, Y); - Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, XY); - Fabs->takeName(&I); + Value *XY = Builder.CreateBinOpFMF(Opcode, X, Y, &I); + Value *Fabs = + Builder.CreateUnaryIntrinsic(Intrinsic::fabs, XY, &I, I.getName()); return replaceInstUsesWith(I, Fabs); } @@ -685,8 +679,6 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { match(Op0, m_AllowReassoc(m_BinOp(Op0BinOp)))) { // Everything in this scope folds I with Op0, intersecting their FMF. FastMathFlags FMF = I.getFastMathFlags() & Op0BinOp->getFastMathFlags(); - IRBuilder<>::FastMathFlagGuard FMFGuard(Builder); - Builder.setFastMathFlags(FMF); Constant *C1; if (match(Op0, m_OneUse(m_FDiv(m_Constant(C1), m_Value(X))))) { // (C1 / X) * C --> (C * C1) / X @@ -718,7 +710,7 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { // (X + C1) * C --> (X * C) + (C * C1) if (Constant *CC1 = ConstantFoldBinaryOpOperands(Instruction::FMul, C, C1, DL)) { - Value *XC = Builder.CreateFMul(X, C); + Value *XC = Builder.CreateFMulFMF(X, C, FMF); return BinaryOperator::CreateFAddFMF(XC, CC1, FMF); } } @@ -726,7 +718,7 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { // (C1 - X) * C --> (C * C1) - (X * C) if (Constant *CC1 = ConstantFoldBinaryOpOperands(Instruction::FMul, C, C1, DL)) { - Value *XC = Builder.CreateFMul(X, C); + Value *XC = Builder.CreateFMulFMF(X, C, FMF); return BinaryOperator::CreateFSubFMF(CC1, XC, FMF); } } @@ -740,9 +732,7 @@ Instruction *InstCombinerImpl::foldFMulReassoc(BinaryOperator &I) { FastMathFlags FMF = I.getFastMathFlags() & DivOp->getFastMathFlags(); if (FMF.allowReassoc()) { // Sink division: (X / Y) * Z --> (X * Z) / Y - IRBuilder<>::FastMathFlagGuard FMFGuard(Builder); - Builder.setFastMathFlags(FMF); - auto *NewFMul = Builder.CreateFMul(X, Z); + auto *NewFMul = Builder.CreateFMulFMF(X, Z, FMF); return BinaryOperator::CreateFDivFMF(NewFMul, Y, FMF); } } @@ -2066,14 +2056,18 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I, bool ShiftByX = false; // If V is not nullptr, it will be matched using m_Specific. - auto MatchShiftOrMulXC = [](Value *Op, Value *&V, APInt &C) -> bool { + auto MatchShiftOrMulXC = [](Value *Op, Value *&V, APInt &C, + bool &PreserveNSW) -> bool { const APInt *Tmp = nullptr; if ((!V && match(Op, m_Mul(m_Value(V), m_APInt(Tmp)))) || (V && match(Op, m_Mul(m_Specific(V), m_APInt(Tmp))))) C = *Tmp; else if ((!V && match(Op, m_Shl(m_Value(V), m_APInt(Tmp)))) || - (V && match(Op, m_Shl(m_Specific(V), m_APInt(Tmp))))) + (V && match(Op, m_Shl(m_Specific(V), m_APInt(Tmp))))) { C = APInt(Tmp->getBitWidth(), 1) << *Tmp; + // We cannot preserve NSW when shifting by BW - 1. + PreserveNSW = Tmp->ult(Tmp->getBitWidth() - 1); + } if (Tmp != nullptr) return true; @@ -2095,7 +2089,9 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I, return false; }; - if (MatchShiftOrMulXC(Op0, X, Y) && MatchShiftOrMulXC(Op1, X, Z)) { + bool Op0PreserveNSW = true, Op1PreserveNSW = true; + if (MatchShiftOrMulXC(Op0, X, Y, Op0PreserveNSW) && + MatchShiftOrMulXC(Op1, X, Z, Op1PreserveNSW)) { // pass } else if (MatchShiftCX(Op0, Y, X) && MatchShiftCX(Op1, Z, X)) { ShiftByX = true; @@ -2108,7 +2104,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I, OverflowingBinaryOperator *BO0 = cast<OverflowingBinaryOperator>(Op0); // TODO: We may be able to deduce more about nsw/nuw of BO0/BO1 based on Y >= // Z or Z >= Y. - bool BO0HasNSW = BO0->hasNoSignedWrap(); + bool BO0HasNSW = Op0PreserveNSW && BO0->hasNoSignedWrap(); bool BO0HasNUW = BO0->hasNoUnsignedWrap(); bool BO0NoWrap = IsSRem ? BO0HasNSW : BO0HasNUW; @@ -2131,7 +2127,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I, }; OverflowingBinaryOperator *BO1 = cast<OverflowingBinaryOperator>(Op1); - bool BO1HasNSW = BO1->hasNoSignedWrap(); + bool BO1HasNSW = Op1PreserveNSW && BO1->hasNoSignedWrap(); bool BO1HasNUW = BO1->hasNoUnsignedWrap(); bool BO1NoWrap = IsSRem ? BO1HasNSW : BO1HasNUW; // (rem (mul X, Y), (mul nuw/nsw X, Z)) |