diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Transforms/InstCombine/InstCombineAddSub.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r-- | lib/Transforms/InstCombine/InstCombineAddSub.cpp | 321 |
1 files changed, 136 insertions, 185 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 83054588a9aa..6e196bfdbd25 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -186,8 +186,6 @@ namespace { Value *simplifyFAdd(AddendVect& V, unsigned InstrQuota); - Value *performFactorization(Instruction *I); - /// Convert given addend to a Value Value *createAddendVal(const FAddend &A, bool& NeedNeg); @@ -197,7 +195,6 @@ namespace { Value *createFSub(Value *Opnd0, Value *Opnd1); Value *createFAdd(Value *Opnd0, Value *Opnd1); Value *createFMul(Value *Opnd0, Value *Opnd1); - Value *createFDiv(Value *Opnd0, Value *Opnd1); Value *createFNeg(Value *V); Value *createNaryFAdd(const AddendVect& Opnds, unsigned InstrQuota); void createInstPostProc(Instruction *NewInst, bool NoNumber = false); @@ -427,89 +424,6 @@ unsigned FAddend::drillAddendDownOneStep return BreakNum; } -// Try to perform following optimization on the input instruction I. Return the -// simplified expression if was successful; otherwise, return 0. -// -// Instruction "I" is Simplified into -// ------------------------------------------------------- -// (x * y) +/- (x * z) x * (y +/- z) -// (y / x) +/- (z / x) (y +/- z) / x -Value *FAddCombine::performFactorization(Instruction *I) { - assert((I->getOpcode() == Instruction::FAdd || - I->getOpcode() == Instruction::FSub) && "Expect add/sub"); - - Instruction *I0 = dyn_cast<Instruction>(I->getOperand(0)); - Instruction *I1 = dyn_cast<Instruction>(I->getOperand(1)); - - if (!I0 || !I1 || I0->getOpcode() != I1->getOpcode()) - return nullptr; - - bool isMpy = false; - if (I0->getOpcode() == Instruction::FMul) - isMpy = true; - else if (I0->getOpcode() != Instruction::FDiv) - return nullptr; - - Value *Opnd0_0 = I0->getOperand(0); - Value *Opnd0_1 = I0->getOperand(1); - Value *Opnd1_0 = I1->getOperand(0); - Value *Opnd1_1 = I1->getOperand(1); - - // Input Instr I Factor AddSub0 AddSub1 - // ---------------------------------------------- - // (x*y) +/- (x*z) x y z - // (y/x) +/- (z/x) x y z - Value *Factor = nullptr; - Value *AddSub0 = nullptr, *AddSub1 = nullptr; - - if (isMpy) { - if (Opnd0_0 == Opnd1_0 || Opnd0_0 == Opnd1_1) - Factor = Opnd0_0; - else if (Opnd0_1 == Opnd1_0 || Opnd0_1 == Opnd1_1) - Factor = Opnd0_1; - - if (Factor) { - AddSub0 = (Factor == Opnd0_0) ? Opnd0_1 : Opnd0_0; - AddSub1 = (Factor == Opnd1_0) ? Opnd1_1 : Opnd1_0; - } - } else if (Opnd0_1 == Opnd1_1) { - Factor = Opnd0_1; - AddSub0 = Opnd0_0; - AddSub1 = Opnd1_0; - } - - if (!Factor) - return nullptr; - - FastMathFlags Flags; - Flags.setFast(); - if (I0) Flags &= I->getFastMathFlags(); - if (I1) Flags &= I->getFastMathFlags(); - - // Create expression "NewAddSub = AddSub0 +/- AddsSub1" - Value *NewAddSub = (I->getOpcode() == Instruction::FAdd) ? - createFAdd(AddSub0, AddSub1) : - createFSub(AddSub0, AddSub1); - if (ConstantFP *CFP = dyn_cast<ConstantFP>(NewAddSub)) { - const APFloat &F = CFP->getValueAPF(); - if (!F.isNormal()) - return nullptr; - } else if (Instruction *II = dyn_cast<Instruction>(NewAddSub)) - II->setFastMathFlags(Flags); - - if (isMpy) { - Value *RI = createFMul(Factor, NewAddSub); - if (Instruction *II = dyn_cast<Instruction>(RI)) - II->setFastMathFlags(Flags); - return RI; - } - - Value *RI = createFDiv(NewAddSub, Factor); - if (Instruction *II = dyn_cast<Instruction>(RI)) - II->setFastMathFlags(Flags); - return RI; -} - Value *FAddCombine::simplify(Instruction *I) { assert(I->hasAllowReassoc() && I->hasNoSignedZeros() && "Expected 'reassoc'+'nsz' instruction"); @@ -594,8 +508,7 @@ Value *FAddCombine::simplify(Instruction *I) { return R; } - // step 6: Try factorization as the last resort, - return performFactorization(I); + return nullptr; } Value *FAddCombine::simplifyFAdd(AddendVect& Addends, unsigned InstrQuota) { @@ -772,13 +685,6 @@ Value *FAddCombine::createFMul(Value *Opnd0, Value *Opnd1) { return V; } -Value *FAddCombine::createFDiv(Value *Opnd0, Value *Opnd1) { - Value *V = Builder.CreateFDiv(Opnd0, Opnd1); - if (Instruction *I = dyn_cast<Instruction>(V)) - createInstPostProc(I); - return V; -} - void FAddCombine::createInstPostProc(Instruction *NewInstr, bool NoNumber) { NewInstr->setDebugLoc(Instr->getDebugLoc()); @@ -1135,7 +1041,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { if (SimplifyAssociativeOrCommutative(I)) return &I; - if (Instruction *X = foldShuffledBinop(I)) + if (Instruction *X = foldVectorBinop(I)) return X; // (A*B)+(A*C) -> A*(B+C) etc @@ -1285,77 +1191,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } - // Check for (add (sext x), y), see if we can merge this into an - // integer add followed by a sext. - if (SExtInst *LHSConv = dyn_cast<SExtInst>(LHS)) { - // (add (sext x), cst) --> (sext (add x, cst')) - if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) { - if (LHSConv->hasOneUse()) { - Constant *CI = - ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType()); - if (ConstantExpr::getSExt(CI, Ty) == RHSC && - willNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) { - // Insert the new, smaller add. - Value *NewAdd = - Builder.CreateNSWAdd(LHSConv->getOperand(0), CI, "addconv"); - return new SExtInst(NewAdd, Ty); - } - } - } - - // (add (sext x), (sext y)) --> (sext (add int x, y)) - if (SExtInst *RHSConv = dyn_cast<SExtInst>(RHS)) { - // Only do this if x/y have the same type, if at least one of them has a - // single use (so we don't increase the number of sexts), and if the - // integer add will not overflow. - if (LHSConv->getOperand(0)->getType() == - RHSConv->getOperand(0)->getType() && - (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && - willNotOverflowSignedAdd(LHSConv->getOperand(0), - RHSConv->getOperand(0), I)) { - // Insert the new integer add. - Value *NewAdd = Builder.CreateNSWAdd(LHSConv->getOperand(0), - RHSConv->getOperand(0), "addconv"); - return new SExtInst(NewAdd, Ty); - } - } - } - - // Check for (add (zext x), y), see if we can merge this into an - // integer add followed by a zext. - if (auto *LHSConv = dyn_cast<ZExtInst>(LHS)) { - // (add (zext x), cst) --> (zext (add x, cst')) - if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) { - if (LHSConv->hasOneUse()) { - Constant *CI = - ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType()); - if (ConstantExpr::getZExt(CI, Ty) == RHSC && - willNotOverflowUnsignedAdd(LHSConv->getOperand(0), CI, I)) { - // Insert the new, smaller add. - Value *NewAdd = - Builder.CreateNUWAdd(LHSConv->getOperand(0), CI, "addconv"); - return new ZExtInst(NewAdd, Ty); - } - } - } - - // (add (zext x), (zext y)) --> (zext (add int x, y)) - if (auto *RHSConv = dyn_cast<ZExtInst>(RHS)) { - // Only do this if x/y have the same type, if at least one of them has a - // single use (so we don't increase the number of zexts), and if the - // integer add will not overflow. - if (LHSConv->getOperand(0)->getType() == - RHSConv->getOperand(0)->getType() && - (LHSConv->hasOneUse() || RHSConv->hasOneUse()) && - willNotOverflowUnsignedAdd(LHSConv->getOperand(0), - RHSConv->getOperand(0), I)) { - // Insert the new integer add. - Value *NewAdd = Builder.CreateNUWAdd( - LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv"); - return new ZExtInst(NewAdd, Ty); - } - } - } + if (Instruction *Ext = narrowMathIfNoOverflow(I)) + return Ext; // (add (xor A, B) (and A, B)) --> (or A, B) // (add (and A, B) (xor A, B)) --> (or A, B) @@ -1391,6 +1228,45 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { return Changed ? &I : nullptr; } +/// Factor a common operand out of fadd/fsub of fmul/fdiv. +static Instruction *factorizeFAddFSub(BinaryOperator &I, + InstCombiner::BuilderTy &Builder) { + assert((I.getOpcode() == Instruction::FAdd || + I.getOpcode() == Instruction::FSub) && "Expecting fadd/fsub"); + assert(I.hasAllowReassoc() && I.hasNoSignedZeros() && + "FP factorization requires FMF"); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + Value *X, *Y, *Z; + bool IsFMul; + if ((match(Op0, m_OneUse(m_FMul(m_Value(X), m_Value(Z)))) && + match(Op1, m_OneUse(m_c_FMul(m_Value(Y), m_Specific(Z))))) || + (match(Op0, m_OneUse(m_FMul(m_Value(Z), m_Value(X)))) && + match(Op1, m_OneUse(m_c_FMul(m_Value(Y), m_Specific(Z)))))) + IsFMul = true; + else if (match(Op0, m_OneUse(m_FDiv(m_Value(X), m_Value(Z)))) && + match(Op1, m_OneUse(m_FDiv(m_Value(Y), m_Specific(Z))))) + IsFMul = false; + else + return nullptr; + + // (X * Z) + (Y * Z) --> (X + Y) * Z + // (X * Z) - (Y * Z) --> (X - Y) * Z + // (X / Z) + (Y / Z) --> (X + Y) / Z + // (X / Z) - (Y / Z) --> (X - Y) / Z + bool IsFAdd = I.getOpcode() == Instruction::FAdd; + Value *XY = IsFAdd ? Builder.CreateFAddFMF(X, Y, &I) + : Builder.CreateFSubFMF(X, Y, &I); + + // Bail out if we just created a denormal constant. + // TODO: This is copied from a previous implementation. Is it necessary? + const APFloat *C; + if (match(XY, m_APFloat(C)) && !C->isNormal()) + return nullptr; + + return IsFMul ? BinaryOperator::CreateFMulFMF(XY, Z, &I) + : BinaryOperator::CreateFDivFMF(XY, Z, &I); +} + Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { if (Value *V = SimplifyFAddInst(I.getOperand(0), I.getOperand(1), I.getFastMathFlags(), @@ -1400,7 +1276,7 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { if (SimplifyAssociativeOrCommutative(I)) return &I; - if (Instruction *X = foldShuffledBinop(I)) + if (Instruction *X = foldVectorBinop(I)) return X; if (Instruction *FoldedFAdd = foldBinOpIntoSelectOrPhi(I)) @@ -1478,6 +1354,8 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { return replaceInstUsesWith(I, V); if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { + if (Instruction *F = factorizeFAddFSub(I, Builder)) + return F; if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } @@ -1577,7 +1455,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { SQ.getWithInstruction(&I))) return replaceInstUsesWith(I, V); - if (Instruction *X = foldShuffledBinop(I)) + if (Instruction *X = foldVectorBinop(I)) return X; // (A*B)-(A*C) -> A*(B-C) etc @@ -1771,19 +1649,51 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { // X - A*-B -> X + A*B // X - -A*B -> X + A*B Value *A, *B; - Constant *CI; if (match(Op1, m_c_Mul(m_Value(A), m_Neg(m_Value(B))))) return BinaryOperator::CreateAdd(Op0, Builder.CreateMul(A, B)); - // X - A*CI -> X + A*-CI + // X - A*C -> X + A*-C // No need to handle commuted multiply because multiply handling will // ensure constant will be move to the right hand side. - if (match(Op1, m_Mul(m_Value(A), m_Constant(CI)))) { - Value *NewMul = Builder.CreateMul(A, ConstantExpr::getNeg(CI)); + if (match(Op1, m_Mul(m_Value(A), m_Constant(C))) && !isa<ConstantExpr>(C)) { + Value *NewMul = Builder.CreateMul(A, ConstantExpr::getNeg(C)); return BinaryOperator::CreateAdd(Op0, NewMul); } } + { + // ~A - Min/Max(~A, O) -> Max/Min(A, ~O) - A + // ~A - Min/Max(O, ~A) -> Max/Min(A, ~O) - A + // Min/Max(~A, O) - ~A -> A - Max/Min(A, ~O) + // Min/Max(O, ~A) - ~A -> A - Max/Min(A, ~O) + // So long as O here is freely invertible, this will be neutral or a win. + Value *LHS, *RHS, *A; + Value *NotA = Op0, *MinMax = Op1; + SelectPatternFlavor SPF = matchSelectPattern(MinMax, LHS, RHS).Flavor; + if (!SelectPatternResult::isMinOrMax(SPF)) { + NotA = Op1; + MinMax = Op0; + SPF = matchSelectPattern(MinMax, LHS, RHS).Flavor; + } + if (SelectPatternResult::isMinOrMax(SPF) && + match(NotA, m_Not(m_Value(A))) && (NotA == LHS || NotA == RHS)) { + if (NotA == LHS) + std::swap(LHS, RHS); + // LHS is now O above and expected to have at least 2 uses (the min/max) + // NotA is epected to have 2 uses from the min/max and 1 from the sub. + if (IsFreeToInvert(LHS, !LHS->hasNUsesOrMore(3)) && + !NotA->hasNUsesOrMore(4)) { + // Note: We don't generate the inverse max/min, just create the not of + // it and let other folds do the rest. + Value *Not = Builder.CreateNot(MinMax); + if (NotA == Op0) + return BinaryOperator::CreateSub(Not, A); + else + return BinaryOperator::CreateSub(A, Not); + } + } + } + // Optimize pointer differences into the same array into a size. Consider: // &A[10] - &A[0]: we should compile this to "10". Value *LHSOp, *RHSOp; @@ -1819,6 +1729,9 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return SelectInst::Create(Cmp, Neg, A); } + if (Instruction *Ext = narrowMathIfNoOverflow(I)) + return Ext; + bool Changed = false; if (!I.hasNoSignedWrap() && willNotOverflowSignedSub(Op0, Op1, I)) { Changed = true; @@ -1838,7 +1751,7 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { SQ.getWithInstruction(&I))) return replaceInstUsesWith(I, V); - if (Instruction *X = foldShuffledBinop(I)) + if (Instruction *X = foldVectorBinop(I)) return X; // Subtraction from -0.0 is the canonical form of fneg. @@ -1847,13 +1760,27 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { if (I.hasNoSignedZeros() && match(Op0, m_PosZeroFP())) return BinaryOperator::CreateFNegFMF(Op1, &I); + Value *X, *Y; + Constant *C; + + // Fold negation into constant operand. This is limited with one-use because + // fneg is assumed better for analysis and cheaper in codegen than fmul/fdiv. + // -(X * C) --> X * (-C) + if (match(&I, m_FNeg(m_OneUse(m_FMul(m_Value(X), m_Constant(C)))))) + return BinaryOperator::CreateFMulFMF(X, ConstantExpr::getFNeg(C), &I); + // -(X / C) --> X / (-C) + if (match(&I, m_FNeg(m_OneUse(m_FDiv(m_Value(X), m_Constant(C)))))) + return BinaryOperator::CreateFDivFMF(X, ConstantExpr::getFNeg(C), &I); + // -(C / X) --> (-C) / X + if (match(&I, m_FNeg(m_OneUse(m_FDiv(m_Constant(C), m_Value(X)))))) + return BinaryOperator::CreateFDivFMF(ConstantExpr::getFNeg(C), X, &I); + // If Op0 is not -0.0 or we can ignore -0.0: Z - (X - Y) --> Z + (Y - X) // Canonicalize to fadd to make analysis easier. // This can also help codegen because fadd is commutative. // Note that if this fsub was really an fneg, the fadd with -0.0 will get // killed later. We still limit that particular transform with 'hasOneUse' // because an fneg is assumed better/cheaper than a generic fsub. - Value *X, *Y; if (I.hasNoSignedZeros() || CannotBeNegativeZero(Op0, SQ.TLI)) { if (match(Op1, m_OneUse(m_FSub(m_Value(X), m_Value(Y))))) { Value *NewSub = Builder.CreateFSubFMF(Y, X, &I); @@ -1869,7 +1796,6 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { // X - C --> X + (-C) // But don't transform constant expressions because there's an inverse fold // for X + (-Y) --> X - Y. - Constant *C; if (match(Op1, m_Constant(C)) && !isa<ConstantExpr>(Op1)) return BinaryOperator::CreateFAddFMF(Op0, ConstantExpr::getFNeg(C), &I); @@ -1879,21 +1805,46 @@ Instruction *InstCombiner::visitFSub(BinaryOperator &I) { // Similar to above, but look through a cast of the negated value: // X - (fptrunc(-Y)) --> X + fptrunc(Y) - if (match(Op1, m_OneUse(m_FPTrunc(m_FNeg(m_Value(Y)))))) { - Value *TruncY = Builder.CreateFPTrunc(Y, I.getType()); - return BinaryOperator::CreateFAddFMF(Op0, TruncY, &I); - } + Type *Ty = I.getType(); + if (match(Op1, m_OneUse(m_FPTrunc(m_FNeg(m_Value(Y)))))) + return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPTrunc(Y, Ty), &I); + // X - (fpext(-Y)) --> X + fpext(Y) - if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y)))))) { - Value *ExtY = Builder.CreateFPExt(Y, I.getType()); - return BinaryOperator::CreateFAddFMF(Op0, ExtY, &I); - } + if (match(Op1, m_OneUse(m_FPExt(m_FNeg(m_Value(Y)))))) + return BinaryOperator::CreateFAddFMF(Op0, Builder.CreateFPExt(Y, Ty), &I); - // Handle specials cases for FSub with selects feeding the operation + // Handle special cases for FSub with selects feeding the operation if (Value *V = SimplifySelectsFeedingBinaryOp(I, Op0, Op1)) return replaceInstUsesWith(I, V); if (I.hasAllowReassoc() && I.hasNoSignedZeros()) { + // (Y - X) - Y --> -X + if (match(Op0, m_FSub(m_Specific(Op1), m_Value(X)))) + return BinaryOperator::CreateFNegFMF(X, &I); + + // Y - (X + Y) --> -X + // Y - (Y + X) --> -X + if (match(Op1, m_c_FAdd(m_Specific(Op0), m_Value(X)))) + return BinaryOperator::CreateFNegFMF(X, &I); + + // (X * C) - X --> X * (C - 1.0) + if (match(Op0, m_FMul(m_Specific(Op1), m_Constant(C)))) { + Constant *CSubOne = ConstantExpr::getFSub(C, ConstantFP::get(Ty, 1.0)); + return BinaryOperator::CreateFMulFMF(Op1, CSubOne, &I); + } + // X - (X * C) --> X * (1.0 - C) + if (match(Op1, m_FMul(m_Specific(Op0), m_Constant(C)))) { + Constant *OneSubC = ConstantExpr::getFSub(ConstantFP::get(Ty, 1.0), C); + return BinaryOperator::CreateFMulFMF(Op0, OneSubC, &I); + } + + if (Instruction *F = factorizeFAddFSub(I, Builder)) + return F; + + // TODO: This performs reassociative folds for FP ops. Some fraction of the + // functionality has been subsumed by simple pattern matching here and in + // InstSimplify. We should let a dedicated reassociation pass handle more + // complex pattern matching and remove this from InstCombine. if (Value *V = FAddCombine(Builder).simplify(&I)) return replaceInstUsesWith(I, V); } |