diff options
Diffstat (limited to 'contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp')
-rw-r--r-- | contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 230 |
1 files changed, 151 insertions, 79 deletions
diff --git a/contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index ddd8775..6b1d3dc 100644 --- a/contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/contrib/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -25,7 +25,6 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -71,14 +70,12 @@ namespace { bool eliminateIdentitySCEV(Instruction *UseInst, Instruction *IVOperand); + bool eliminateOverflowIntrinsic(CallInst *CI); bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand); void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand); void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand, bool IsSigned); bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand); - - Instruction *splitOverflowIntrinsic(Instruction *IVUser, - const DominatorTree *DT); }; } @@ -183,9 +180,8 @@ void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) { DeadInsts.emplace_back(ICmp); DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n'); } else if (isa<PHINode>(IVOperand) && - SE->isLoopInvariantPredicate(Pred, S, X, ICmpLoop, - InvariantPredicate, InvariantLHS, - InvariantRHS)) { + SE->isLoopInvariantPredicate(Pred, S, X, L, InvariantPredicate, + InvariantLHS, InvariantRHS)) { // Rewrite the comparison to a loop invariant comparison if it can be done // cheaply, where cheaply means "we don't need to emit any new @@ -201,9 +197,48 @@ void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) { NewRHS = ICmp->getOperand(S == InvariantRHS ? IVOperIdx : (1 - IVOperIdx)); - for (Value *Incoming : cast<PHINode>(IVOperand)->incoming_values()) { - if (NewLHS && NewRHS) - break; + auto *PN = cast<PHINode>(IVOperand); + for (unsigned i = 0, e = PN->getNumIncomingValues(); + i != e && (!NewLHS || !NewRHS); + ++i) { + + // If this is a value incoming from the backedge, then it cannot be a loop + // invariant value (since we know that IVOperand is an induction variable). + if (L->contains(PN->getIncomingBlock(i))) + continue; + + // NB! This following assert does not fundamentally have to be true, but + // it is true today given how SCEV analyzes induction variables. + // Specifically, today SCEV will *not* recognize %iv as an induction + // variable in the following case: + // + // define void @f(i32 %k) { + // entry: + // br i1 undef, label %r, label %l + // + // l: + // %k.inc.l = add i32 %k, 1 + // br label %loop + // + // r: + // %k.inc.r = add i32 %k, 1 + // br label %loop + // + // loop: + // %iv = phi i32 [ %k.inc.l, %l ], [ %k.inc.r, %r ], [ %iv.inc, %loop ] + // %iv.inc = add i32 %iv, 1 + // br label %loop + // } + // + // but if it starts to, at some point, then the assertion below will have + // to be changed to a runtime check. + + Value *Incoming = PN->getIncomingValue(i); + +#ifndef NDEBUG + if (auto *I = dyn_cast<Instruction>(Incoming)) + assert(DT->dominates(I, ICmp) && "Should be a unique loop dominating value!"); +#endif const SCEV *IncomingS = SE->getSCEV(Incoming); @@ -280,6 +315,108 @@ void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem, DeadInsts.emplace_back(Rem); } +bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) { + auto *F = CI->getCalledFunction(); + if (!F) + return false; + + typedef const SCEV *(ScalarEvolution::*OperationFunctionTy)( + const SCEV *, const SCEV *, SCEV::NoWrapFlags); + typedef const SCEV *(ScalarEvolution::*ExtensionFunctionTy)( + const SCEV *, Type *); + + OperationFunctionTy Operation; + ExtensionFunctionTy Extension; + + Instruction::BinaryOps RawOp; + + // We always have exactly one of nsw or nuw. If NoSignedOverflow is false, we + // have nuw. + bool NoSignedOverflow; + + switch (F->getIntrinsicID()) { + default: + return false; + + case Intrinsic::sadd_with_overflow: + Operation = &ScalarEvolution::getAddExpr; + Extension = &ScalarEvolution::getSignExtendExpr; + RawOp = Instruction::Add; + NoSignedOverflow = true; + break; + + case Intrinsic::uadd_with_overflow: + Operation = &ScalarEvolution::getAddExpr; + Extension = &ScalarEvolution::getZeroExtendExpr; + RawOp = Instruction::Add; + NoSignedOverflow = false; + break; + + case Intrinsic::ssub_with_overflow: + Operation = &ScalarEvolution::getMinusSCEV; + Extension = &ScalarEvolution::getSignExtendExpr; + RawOp = Instruction::Sub; + NoSignedOverflow = true; + break; + + case Intrinsic::usub_with_overflow: + Operation = &ScalarEvolution::getMinusSCEV; + Extension = &ScalarEvolution::getZeroExtendExpr; + RawOp = Instruction::Sub; + NoSignedOverflow = false; + break; + } + + const SCEV *LHS = SE->getSCEV(CI->getArgOperand(0)); + const SCEV *RHS = SE->getSCEV(CI->getArgOperand(1)); + + auto *NarrowTy = cast<IntegerType>(LHS->getType()); + auto *WideTy = + IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2); + + const SCEV *A = + (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap), WideTy); + const SCEV *B = + (SE->*Operation)((SE->*Extension)(LHS, WideTy), + (SE->*Extension)(RHS, WideTy), SCEV::FlagAnyWrap); + + if (A != B) + return false; + + // Proved no overflow, nuke the overflow check and, if possible, the overflow + // intrinsic as well. + + BinaryOperator *NewResult = BinaryOperator::Create( + RawOp, CI->getArgOperand(0), CI->getArgOperand(1), "", CI); + + if (NoSignedOverflow) + NewResult->setHasNoSignedWrap(true); + else + NewResult->setHasNoUnsignedWrap(true); + + SmallVector<ExtractValueInst *, 4> ToDelete; + + for (auto *U : CI->users()) { + if (auto *EVI = dyn_cast<ExtractValueInst>(U)) { + if (EVI->getIndices()[0] == 1) + EVI->replaceAllUsesWith(ConstantInt::getFalse(CI->getContext())); + else { + assert(EVI->getIndices()[0] == 0 && "Only two possibilities!"); + EVI->replaceAllUsesWith(NewResult); + } + ToDelete.push_back(EVI); + } + } + + for (auto *EVI : ToDelete) + EVI->eraseFromParent(); + + if (CI->use_empty()) + CI->eraseFromParent(); + + return true; +} + /// Eliminate an operation that consumes a simple IV and has no observable /// side-effect given the range of IV values. IVOperand is guaranteed SCEVable, /// but UseInst may not be. @@ -297,6 +434,10 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst, } } + if (auto *CI = dyn_cast<CallInst>(UseInst)) + if (eliminateOverflowIntrinsic(CI)) + return true; + if (eliminateIdentitySCEV(UseInst, IVOperand)) return true; @@ -408,69 +549,6 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO, return Changed; } -/// \brief Split sadd.with.overflow into add + sadd.with.overflow to allow -/// analysis and optimization. -/// -/// \return A new value representing the non-overflowing add if possible, -/// otherwise return the original value. -Instruction *SimplifyIndvar::splitOverflowIntrinsic(Instruction *IVUser, - const DominatorTree *DT) { - IntrinsicInst *II = dyn_cast<IntrinsicInst>(IVUser); - if (!II || II->getIntrinsicID() != Intrinsic::sadd_with_overflow) - return IVUser; - - // Find a branch guarded by the overflow check. - BranchInst *Branch = nullptr; - Instruction *AddVal = nullptr; - for (User *U : II->users()) { - if (ExtractValueInst *ExtractInst = dyn_cast<ExtractValueInst>(U)) { - if (ExtractInst->getNumIndices() != 1) - continue; - if (ExtractInst->getIndices()[0] == 0) - AddVal = ExtractInst; - else if (ExtractInst->getIndices()[0] == 1 && ExtractInst->hasOneUse()) - Branch = dyn_cast<BranchInst>(ExtractInst->user_back()); - } - } - if (!AddVal || !Branch) - return IVUser; - - BasicBlock *ContinueBB = Branch->getSuccessor(1); - if (std::next(pred_begin(ContinueBB)) != pred_end(ContinueBB)) - return IVUser; - - // Check if all users of the add are provably NSW. - bool AllNSW = true; - for (Use &U : AddVal->uses()) { - if (Instruction *UseInst = dyn_cast<Instruction>(U.getUser())) { - BasicBlock *UseBB = UseInst->getParent(); - if (PHINode *PHI = dyn_cast<PHINode>(UseInst)) - UseBB = PHI->getIncomingBlock(U); - if (!DT->dominates(ContinueBB, UseBB)) { - AllNSW = false; - break; - } - } - } - if (!AllNSW) - return IVUser; - - // Go for it... - IRBuilder<> Builder(IVUser); - Instruction *AddInst = dyn_cast<Instruction>( - Builder.CreateNSWAdd(II->getOperand(0), II->getOperand(1))); - - // The caller expects the new add to have the same form as the intrinsic. The - // IV operand position must be the same. - assert((AddInst->getOpcode() == Instruction::Add && - AddInst->getOperand(0) == II->getOperand(0)) && - "Bad add instruction created from overflow intrinsic."); - - AddVal->replaceAllUsesWith(AddInst); - DeadInsts.emplace_back(AddVal); - return AddInst; -} - /// Add all uses of Def to the current IV's worklist. static void pushIVUsers( Instruction *Def, @@ -545,12 +623,6 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) { // Bypass back edges to avoid extra work. if (UseInst == CurrIV) continue; - if (V && V->shouldSplitOverflowInstrinsics()) { - UseInst = splitOverflowIntrinsic(UseInst, V->getDomTree()); - if (!UseInst) - continue; - } - Instruction *IVOperand = UseOper.second; for (unsigned N = 0; IVOperand; ++N) { assert(N <= Simplified.size() && "runaway iteration"); |