diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 54 | ||||
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 61 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyIndVar.cpp | 107 |
3 files changed, 5 insertions, 217 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 6366e3621ae..654a766b416 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -3831,7 +3831,7 @@ struct BinaryOp { /// Try to map \p V into a BinaryOp, and return \c None on failure. -static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) { +static Optional<BinaryOp> MatchBinaryOp(Value *V) { auto *Op = dyn_cast<Operator>(V); if (!Op) return None; @@ -3877,50 +3877,6 @@ static Optional<BinaryOp> MatchBinaryOp(Value *V, DominatorTree &DT) { } return BinaryOp(Op); - case Instruction::ExtractValue: { - auto *EVI = cast<ExtractValueInst>(Op); - if (EVI->getNumIndices() != 1 || EVI->getIndices()[0] != 0) - break; - - auto *CI = dyn_cast<CallInst>(EVI->getAggregateOperand()); - if (!CI) - break; - - if (auto *F = CI->getCalledFunction()) - switch (F->getIntrinsicID()) { - case Intrinsic::sadd_with_overflow: - case Intrinsic::uadd_with_overflow: { - if (!isOverflowIntrinsicNoWrap(cast<IntrinsicInst>(CI), DT)) - return BinaryOp(Instruction::Add, CI->getArgOperand(0), - CI->getArgOperand(1)); - - // Now that we know that all uses of the arithmetic-result component of - // CI are guarded by the overflow check, we can go ahead and pretend - // that the arithmetic is non-overflowing. - if (F->getIntrinsicID() == Intrinsic::sadd_with_overflow) - return BinaryOp(Instruction::Add, CI->getArgOperand(0), - CI->getArgOperand(1), /* IsNSW = */ true, - /* IsNUW = */ false); - else - return BinaryOp(Instruction::Add, CI->getArgOperand(0), - CI->getArgOperand(1), /* IsNSW = */ false, - /* IsNUW*/ true); - } - - case Intrinsic::ssub_with_overflow: - case Intrinsic::usub_with_overflow: - return BinaryOp(Instruction::Sub, CI->getArgOperand(0), - CI->getArgOperand(1)); - - case Intrinsic::smul_with_overflow: - case Intrinsic::umul_with_overflow: - return BinaryOp(Instruction::Mul, CI->getArgOperand(0), - CI->getArgOperand(1)); - default: - break; - } - } - default: break; } @@ -3997,7 +3953,7 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) { // If the increment doesn't overflow, then neither the addrec nor // the post-increment will overflow. - if (auto BO = MatchBinaryOp(BEValueV, DT)) { + if (auto BO = MatchBinaryOp(BEValueV)) { if (BO->Opcode == Instruction::Add && BO->LHS == PN) { if (BO->IsNUW) Flags = setFlags(Flags, SCEV::FlagNUW); @@ -4877,7 +4833,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { return getUnknown(V); Operator *U = cast<Operator>(V); - if (auto BO = MatchBinaryOp(U, DT)) { + if (auto BO = MatchBinaryOp(U)) { switch (BO->Opcode) { case Instruction::Add: { // The simple thing to do would be to just call getSCEV on both operands @@ -4918,7 +4874,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { else AddOps.push_back(getSCEV(BO->RHS)); - auto NewBO = MatchBinaryOp(BO->LHS, DT); + auto NewBO = MatchBinaryOp(BO->LHS); if (!NewBO || (NewBO->Opcode != Instruction::Add && NewBO->Opcode != Instruction::Sub)) { AddOps.push_back(getSCEV(BO->LHS)); @@ -4948,7 +4904,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { } MulOps.push_back(getSCEV(BO->RHS)); - auto NewBO = MatchBinaryOp(BO->LHS, DT); + auto NewBO = MatchBinaryOp(BO->LHS); if (!NewBO || NewBO->Opcode != Instruction::Mul) { MulOps.push_back(getSCEV(BO->LHS)); break; diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 6df22943ce1..6f8dc2c2937 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3253,67 +3253,6 @@ static OverflowResult computeOverflowForSignedAdd( return OverflowResult::MayOverflow; } -bool llvm::isOverflowIntrinsicNoWrap(IntrinsicInst *II, DominatorTree &DT) { -#ifndef NDEBUG - auto IID = II->getIntrinsicID(); - assert((IID == Intrinsic::sadd_with_overflow || - IID == Intrinsic::uadd_with_overflow || - IID == Intrinsic::ssub_with_overflow || - IID == Intrinsic::usub_with_overflow || - IID == Intrinsic::smul_with_overflow || - IID == Intrinsic::umul_with_overflow) && - "Not an overflow intrinsic!"); -#endif - - SmallVector<BranchInst *, 2> GuardingBranches; - SmallVector<ExtractValueInst *, 2> Results; - - for (User *U : II->users()) { - if (auto *EVI = dyn_cast<ExtractValueInst>(U)) { - assert(EVI->getNumIndices() == 1 && "Obvious from CI's type"); - - if (EVI->getIndices()[0] == 0) - Results.push_back(EVI); - else { - assert(EVI->getIndices()[0] == 1 && "Obvious from CI's type"); - - for (auto *U : EVI->users()) - if (auto *B = dyn_cast<BranchInst>(U)) { - assert(B->isConditional() && "How else is it using an i1?"); - GuardingBranches.push_back(B); - } - } - } else { - // We are using the aggregate directly in a way we don't want to analyze - // here (storing it to a global, say). - return false; - } - } - - auto AllUsesGuardedByBranch = [&](BranchInst *BI) { - BasicBlockEdge NoWrapEdge(BI->getParent(), BI->getSuccessor(1)); - if (!NoWrapEdge.isSingleEdge()) - return false; - - // Check if all users of the add are provably no-wrap. - for (auto *Result : Results) { - // If the extractvalue itself is not executed on overflow, the we don't - // need to check each use separately, since domination is transitive. - if (DT.dominates(NoWrapEdge, Result->getParent())) - continue; - - for (auto &RU : Result->uses()) - if (!DT.dominates(NoWrapEdge, RU)) - return false; - } - - return true; - }; - - return any_of(GuardingBranches, AllUsesGuardedByBranch); -} - - OverflowResult llvm::computeOverflowForSignedAdd(AddOperator *Add, const DataLayout &DL, AssumptionCache *AC, diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index e542d403c7e..c95f10e1b7b 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -71,7 +71,6 @@ 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, @@ -319,108 +318,6 @@ 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. @@ -438,10 +335,6 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst, } } - if (auto *CI = dyn_cast<CallInst>(UseInst)) - if (eliminateOverflowIntrinsic(CI)) - return true; - if (eliminateIdentitySCEV(UseInst, IVOperand)) return true; |