diff options
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 0a3837f..418302d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1896,7 +1896,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { {Sub, Builder.getFalse()}); Value *Ret = Builder.CreateSub( ConstantInt::get(A->getType(), A->getType()->getScalarSizeInBits()), - Ctlz, "", /*HasNUW*/ true, /*HasNSW*/ true); + Ctlz, "", /*HasNUW=*/true, /*HasNSW=*/true); return replaceInstUsesWith(I, Builder.CreateZExtOrTrunc(Ret, I.getType())); } @@ -2363,8 +2363,8 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) { OverflowingBinaryOperator *LHSSub = cast<OverflowingBinaryOperator>(Op0); bool HasNUW = I.hasNoUnsignedWrap() && LHSSub->hasNoUnsignedWrap(); bool HasNSW = HasNUW && I.hasNoSignedWrap() && LHSSub->hasNoSignedWrap(); - Value *Add = Builder.CreateAdd(Y, Op1, "", /* HasNUW */ HasNUW, - /* HasNSW */ HasNSW); + Value *Add = Builder.CreateAdd(Y, Op1, "", /*HasNUW=*/HasNUW, + /*HasNSW=*/HasNSW); BinaryOperator *Sub = BinaryOperator::CreateSub(X, Add); Sub->setHasNoUnsignedWrap(HasNUW); Sub->setHasNoSignedWrap(HasNSW); @@ -2835,6 +2835,51 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) { if (Instruction *Res = foldBinOpOfSelectAndCastOfSelectCondition(I)) return Res; + // (sub (sext (add nsw (X, Y)), sext (X))) --> (sext (Y)) + if (match(Op1, m_SExtLike(m_Value(X))) && + match(Op0, m_SExtLike(m_c_NSWAdd(m_Specific(X), m_Value(Y))))) { + Value *SExtY = Builder.CreateSExt(Y, I.getType()); + return replaceInstUsesWith(I, SExtY); + } + + // (sub[ nsw] (sext (add nsw (X, Y)), sext (add nsw (X, Z)))) --> + // --> (sub[ nsw] (sext (Y), sext (Z))) + { + Value *Z, *Add0, *Add1; + if (match(Op0, m_SExtLike(m_Value(Add0))) && + match(Op1, m_SExtLike(m_Value(Add1))) && + ((match(Add0, m_NSWAdd(m_Value(X), m_Value(Y))) && + match(Add1, m_c_NSWAdd(m_Specific(X), m_Value(Z)))) || + (match(Add0, m_NSWAdd(m_Value(Y), m_Value(X))) && + match(Add1, m_c_NSWAdd(m_Specific(X), m_Value(Z)))))) { + unsigned NumOfNewInstrs = 0; + // Non-constant Y, Z require new SExt. + NumOfNewInstrs += !isa<Constant>(Y) ? 1 : 0; + NumOfNewInstrs += !isa<Constant>(Z) ? 1 : 0; + // Check if we can trade some of the old instructions for the new ones. + unsigned NumOfDeadInstrs = 0; + if (Op0->hasOneUse()) { + // If Op0 (sext) has multiple uses, then we keep it + // and the add that it uses, otherwise, we can remove + // the sext and probably the add (depending on the number of its uses). + ++NumOfDeadInstrs; + NumOfDeadInstrs += Add0->hasOneUse() ? 1 : 0; + } + if (Op1->hasOneUse()) { + ++NumOfDeadInstrs; + NumOfDeadInstrs += Add1->hasOneUse() ? 1 : 0; + } + if (NumOfDeadInstrs >= NumOfNewInstrs) { + Value *SExtY = Builder.CreateSExt(Y, I.getType()); + Value *SExtZ = Builder.CreateSExt(Z, I.getType()); + Value *Sub = Builder.CreateSub(SExtY, SExtZ, "", + /*HasNUW=*/false, + /*HasNSW=*/I.hasNoSignedWrap()); + return replaceInstUsesWith(I, Sub); + } + } + } + return TryToNarrowDeduceFlags(); } |