diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index f33e04e804e3d..75a59c9553e18 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -3308,6 +3308,300 @@ void DependenceInfo::updateDirection(Dependence::DVEntry &Level, llvm_unreachable("constraint has unexpected kind"); } +namespace { + +/// The type of signed monotonicity of a SCEV expression. This property is +/// defined with respect to the outermost loop that DA is analyzing. Invariant +/// and MultiMonotonic mutually exclusive, and both imply NoSignedWrap. +/// +/// This is designed to classify the behavior of AddRec expressions, and does +/// not care about other SCEVs. For example, given the two loop invariants `A` +/// and `B`, `A + B` is treated as Invariant even if the addition may wrap. On +/// the other hand, if either `A` or `B` is an AddRec and we cannot prove the +/// addition doesn't wrap, the result is classified as Unknown. +enum class MonotonicityType { + Unknown, ///< The expression contains some non loop-invariant SCEVUnknown or + ///< arithmetic operation that has some AddRec as its subexpression + ///< and may cause signed wrap. + NoSignedWrap, ///< The expression doesn't contain any AddRecs that may wrap. + ///< This is a weaker property than Invariant or MultiMonotonic. + ///< Invariant and MultiMonotonic imply NoSignedWrap. + Invariant, ///< The expression is a loop-invariant. + MultiMonotonic, ///< The expression is monotonically increasing or decreasing + ///< with respect to each loop. This is exclusive of + ///< Invariant. That is, we say an SCEV is MultiMonotonic only + ///< if it contains at least one AddRec where its step + ///< reccurence value is non-zero. Monotonicity is checked + ///< independently for each loop. It is allowed to contain + ///< both increasing and decreasing AddRecs. +}; + +/// A visitor that checks the signed monotonicity of SCEVs. +struct SCEVSignedMonotonicityChecker + : public SCEVVisitor { + + /// \p Ptr is the pointer that the SCEV is associated with, if any. It may be + /// used for the inferrence. + static MonotonicityType checkMonotonicity(ScalarEvolution *SE, + const SCEV *Expr, + const Loop *OutermostLoop, + const Value *Ptr = nullptr); + + MonotonicityType visitAddRecExpr(const SCEVAddRecExpr *Expr); + MonotonicityType visitUnknown(const SCEVUnknown *Expr); + MonotonicityType visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr); + MonotonicityType visitSignExtendExpr(const SCEVSignExtendExpr *Expr); + + MonotonicityType visitAddExpr(const SCEVAddExpr *Expr) { + return visitNAryHelper(Expr); + } + MonotonicityType visitMulExpr(const SCEVMulExpr *Expr) { + return visitNAryHelper(Expr); + } + + MonotonicityType visitConstant(const SCEVConstant *) { + return MonotonicityType::Invariant; + } + MonotonicityType visitVScale(const SCEVVScale *) { + return MonotonicityType::Invariant; + } + + // TODO: Handle more cases. + MonotonicityType visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitTruncateExpr(const SCEVTruncateExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitUDivExpr(const SCEVUDivExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitSMaxExpr(const SCEVSMaxExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitUMaxExpr(const SCEVUMaxExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitSMinExpr(const SCEVSMinExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitUMinExpr(const SCEVUMinExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) { + return unknownMonotonicity(Expr); + } + MonotonicityType visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return unknownMonotonicity(Expr); + } + +private: + ScalarEvolution *SE; + const Loop *OutermostLoop; + bool NoWrapFromGEP = false; + + SCEVSignedMonotonicityChecker(ScalarEvolution *SE, const Loop *OutermostLoop, + const Value *Ptr); + + MonotonicityType visitNAryHelper(const SCEVNAryExpr *Expr); + MonotonicityType unknownMonotonicity(const SCEV *Expr); + bool isLoopInvariant(const SCEV *Expr) const; +}; + +} // anonymous namespace + +SCEVSignedMonotonicityChecker::SCEVSignedMonotonicityChecker( + ScalarEvolution *SE, const Loop *OutermostLoop, const Value *Ptr) + : SE(SE), OutermostLoop(OutermostLoop) { + if (Ptr) { + // Perform reasoning similar to LoopAccessAnalysis. If an AddRec would wrap + // and the GEP would have nusw, the wrapped memory location would become + // like as follows (in the mathmatical sense, assuming the step recurrence + // is positive): + // + // (previously accessed location) + (step recurrence) - 2^N + // + // where N is the size of the pointer index type. Since the value of step + // recurrence is less than 2^(N-1), the distance between the previously + // accessed location and the wrapped location will be greater than 2^(N-1), + // which is larger than half the pointer index type space. The size of + // allocated object must not exceed the largest signed integer that fits + // into the index type, so the GEP value would be poison and any memory + // access using it would be immediate UB when executed. + // + // TODO: We don't check if the result of the GEP is always used. Maybe we + // should check the reachability from the GEP to the target instruction. + // E.g., in the following case, no-wrap would not trigger immediate UB: + // + // entry: + // ... + // %gep = getelementptr inbounds i32, ptr %ptr, i32 %addrec + // br i1 %cond, label %store, label %sink + // + // store: + // store i32 42, ptr %ptr + // br label %sink + // + // sink: + // ... + // + auto *GEP = dyn_cast(Ptr); + if (GEP && GEP->hasNoUnsignedSignedWrap()) + NoWrapFromGEP = true; + } +} + +MonotonicityType SCEVSignedMonotonicityChecker::checkMonotonicity( + ScalarEvolution *SE, const SCEV *Expr, const Loop *OutermostLoop, + const Value *Ptr) { + SCEVSignedMonotonicityChecker Checker(SE, OutermostLoop, Ptr); + MonotonicityType MT = Checker.visit(Expr); + +#ifndef NDEBUG + switch (MT) { + case MonotonicityType::Unknown: + LLVM_DEBUG(dbgs() << "Monotonicity: Unknown expr: " << *Expr << "\n"); + break; + case MonotonicityType::NoSignedWrap: + LLVM_DEBUG(dbgs() << "Monotonicity: No signed wrap expr: " << *Expr + << "\n"); + break; + case MonotonicityType::Invariant: + LLVM_DEBUG(dbgs() << "Monotonicity: Invariant expr: " << *Expr << "\n"); + break; + case MonotonicityType::MultiMonotonic: + LLVM_DEBUG(dbgs() << "Monotonicity: Monotonic expr: " << *Expr << "\n"); + break; + } +#endif + return MT; +} + +MonotonicityType +SCEVSignedMonotonicityChecker::visitNAryHelper(const SCEVNAryExpr *Expr) { + assert((isa(Expr) || isa(Expr)) && + "Unexpected SCEV"); + + if (isLoopInvariant(Expr)) + return MonotonicityType::Invariant; + + MonotonicityType Result = MonotonicityType::Invariant; + for (const SCEV *Op : Expr->operands()) { + assert(Result != MonotonicityType::Unknown && "Unexpected state"); + switch (visit(Op)) { + case MonotonicityType::Unknown: + return unknownMonotonicity(Expr); + case MonotonicityType::NoSignedWrap: + Result = MonotonicityType::NoSignedWrap; + break; + case MonotonicityType::Invariant: + break; + case MonotonicityType::MultiMonotonic: { + switch (Result) { + case MonotonicityType::Unknown: + llvm_unreachable("should have been handled above"); + case MonotonicityType::NoSignedWrap: + break; + case MonotonicityType::Invariant: + if (!Expr->hasNoSignedWrap()) + return unknownMonotonicity(Expr); + Result = MonotonicityType::MultiMonotonic; + break; + case MonotonicityType::MultiMonotonic: + if (!Expr->hasNoSignedWrap()) + return unknownMonotonicity(Expr); + if (!isa(Expr)) + return unknownMonotonicity(Expr); + // Monotonic + Monotonic might be a loop invariant, e.g., the following + // SCEV: + // + // {0,+,1}<%loop> + {0,+,-1}<%loop> + // + // In that case, relax the property to NoSignedWrap. + Result = MonotonicityType::NoSignedWrap; + break; + } + } break; + } + } + return Result; +} + +MonotonicityType +SCEVSignedMonotonicityChecker::unknownMonotonicity(const SCEV *Expr) { + LLVM_DEBUG(dbgs() << "Failed to prove monotonicity for: " << *Expr << "\n"); + return MonotonicityType::Unknown; +} + +bool SCEVSignedMonotonicityChecker::isLoopInvariant(const SCEV *Expr) const { + return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop); +} + +MonotonicityType +SCEVSignedMonotonicityChecker::visitAddRecExpr(const SCEVAddRecExpr *Expr) { + if (!Expr->isAffine()) + return unknownMonotonicity(Expr); + + const SCEV *Start = Expr->getStart(); + const SCEV *Step = Expr->getStepRecurrence(*SE); + + MonotonicityType StartRes = visit(Start); + if (StartRes == MonotonicityType::Unknown) + return unknownMonotonicity(Expr); + + MonotonicityType StepRes = visit(Step); + if (StepRes != MonotonicityType::Invariant) + return unknownMonotonicity(Expr); + + // TODO: Enhance the inference here. + if (!Expr->hasNoSignedWrap() && !NoWrapFromGEP) { + if (!SE->isKnownNegative(Step)) + // If the coefficient can be positive value, ensure that the AddRec is + // monotonically increasing. + if (!SE->isKnownOnEveryIteration(ICmpInst::ICMP_SGE, Expr, Start)) + return unknownMonotonicity(Expr); + + if (!SE->isKnownPositive(Step)) + // If the coefficient can be positive value, ensure that the AddRec is + // monotonically decreasing. + if (!SE->isKnownOnEveryIteration(ICmpInst::ICMP_SLE, Expr, Start)) + return unknownMonotonicity(Expr); + } + + bool IsKnownNonZero = SE->isKnownNonZero(Step); + switch (StartRes) { + case MonotonicityType::Unknown: + llvm_unreachable("should have been handled above"); + case MonotonicityType::NoSignedWrap: + return MonotonicityType::NoSignedWrap; + case MonotonicityType::Invariant: + return IsKnownNonZero ? MonotonicityType::MultiMonotonic + : MonotonicityType::NoSignedWrap; + case MonotonicityType::MultiMonotonic: + // TODO: Should handle SCEV like `{{0,+,-1}<%loop>,+,1}<%loop>`? + return IsKnownNonZero ? MonotonicityType::MultiMonotonic + : MonotonicityType::NoSignedWrap; + } + llvm_unreachable("unhandled MonotonicityType"); +} + +MonotonicityType SCEVSignedMonotonicityChecker::visitZeroExtendExpr( + const SCEVZeroExtendExpr *Expr) { + return visit(Expr->getOperand()); +} + +MonotonicityType SCEVSignedMonotonicityChecker::visitSignExtendExpr( + const SCEVSignExtendExpr *Expr) { + return visit(Expr->getOperand()); +} + +MonotonicityType +SCEVSignedMonotonicityChecker::visitUnknown(const SCEVUnknown *Expr) { + if (!isLoopInvariant(Expr)) + return unknownMonotonicity(Expr); + return MonotonicityType::Invariant; +} + /// Check if we can delinearize the subscripts. If the SCEVs representing the /// source and destination array references are recurrences on a nested loop, /// this function flattens the nested recurrences into separate recurrences @@ -3500,12 +3794,37 @@ bool DependenceInfo::tryDelinearizeParametricSize( // to the dependency checks. if (!DisableDelinearizationChecks) for (size_t I = 1; I < Size; ++I) { + const Loop *OutermostLoop = + LI->getLoopFor(Src->getParent())->getOutermostLoop(); + + // TODO: In general, reasoning about monotonicity of a subscript from the + // base pointer would lead incorrect result. Probably we need to check + // the loops associated with this subscript are disjoint from those + // associated with the other subscripts. The validation would be + // something like: + // + // LoopsI = collectCommonLoops(SrcSubscripts[I]) + // LoopsOthers = collectCommonLoops(SrcSCEV - SrcSubscripts[I]) + // CanUsePtr = (LoopsI intersect LoopsOthers) is empty. + // + MonotonicityType SrcMonotonicity = + SCEVSignedMonotonicityChecker::checkMonotonicity( + SE, SrcSubscripts[I], OutermostLoop, SrcPtr); + if (SrcMonotonicity == MonotonicityType::Unknown) + return false; + if (!isKnownNonNegative(SrcSubscripts[I], SrcPtr)) return false; if (!isKnownLessThan(SrcSubscripts[I], Sizes[I - 1])) return false; + MonotonicityType DstMonotonicity = + SCEVSignedMonotonicityChecker::checkMonotonicity( + SE, DstSubscripts[I], OutermostLoop, DstPtr); + if (DstMonotonicity == MonotonicityType::Unknown) + return false; + if (!isKnownNonNegative(DstSubscripts[I], DstPtr)) return false; @@ -3679,11 +3998,23 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst, Pair[0].Src = SrcSCEV; Pair[0].Dst = DstSCEV; + const Loop *OutermostLoop = SrcLoop ? SrcLoop->getOutermostLoop() : nullptr; + if (SCEVSignedMonotonicityChecker::checkMonotonicity( + SE, SrcEv, OutermostLoop, SrcPtr) == MonotonicityType::Unknown) + return std::make_unique(Src, Dst, + SCEVUnionPredicate(Assume, *SE)); + if (SCEVSignedMonotonicityChecker::checkMonotonicity( + SE, DstEv, OutermostLoop, DstPtr) == MonotonicityType::Unknown) + return std::make_unique(Src, Dst, + SCEVUnionPredicate(Assume, *SE)); + if (Delinearize) { if (tryDelinearize(Src, Dst, Pair)) { LLVM_DEBUG(dbgs() << " delinearized\n"); Pairs = Pair.size(); } + // TODO: Check that the original offsets are monotonic when delinearization + // fails. } for (unsigned P = 0; P < Pairs; ++P) { diff --git a/llvm/test/Analysis/DependenceAnalysis/Banerjee.ll b/llvm/test/Analysis/DependenceAnalysis/Banerjee.ll index e0def901d1759..c96f0dfa1f5d5 100644 --- a/llvm/test/Analysis/DependenceAnalysis/Banerjee.ll +++ b/llvm/test/Analysis/DependenceAnalysis/Banerjee.ll @@ -28,7 +28,7 @@ define void @banerjee0(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; ; NORMALIZE-LABEL: 'banerjee0' ; NORMALIZE-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -42,7 +42,7 @@ define void @banerjee0(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; NORMALIZE-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; NORMALIZE-NEXT: da analyze - confused! ; NORMALIZE-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; NORMALIZE-NEXT: da analyze - none! +; NORMALIZE-NEXT: da analyze - confused! ; ; DELIN-LABEL: 'banerjee0' ; DELIN-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -56,7 +56,7 @@ define void @banerjee0(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; DELIN-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; DELIN-NEXT: da analyze - confused! ; DELIN-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; DELIN-NEXT: da analyze - none! +; DELIN-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -810,7 +810,7 @@ define void @banerjee9(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %1 = load i64, ptr %arrayidx7, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; ; NORMALIZE-LABEL: 'banerjee9' ; NORMALIZE-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -824,7 +824,7 @@ define void @banerjee9(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; NORMALIZE-NEXT: Src: %1 = load i64, ptr %arrayidx7, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; NORMALIZE-NEXT: da analyze - confused! ; NORMALIZE-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; NORMALIZE-NEXT: da analyze - none! +; NORMALIZE-NEXT: da analyze - confused! ; ; DELIN-LABEL: 'banerjee9' ; DELIN-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -838,7 +838,7 @@ define void @banerjee9(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; DELIN-NEXT: Src: %1 = load i64, ptr %arrayidx7, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; DELIN-NEXT: da analyze - confused! ; DELIN-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; DELIN-NEXT: da analyze - none! +; DELIN-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -896,7 +896,7 @@ define void @banerjee10(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %1 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; ; NORMALIZE-LABEL: 'banerjee10' ; NORMALIZE-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -910,7 +910,7 @@ define void @banerjee10(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; NORMALIZE-NEXT: Src: %1 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; NORMALIZE-NEXT: da analyze - confused! ; NORMALIZE-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; NORMALIZE-NEXT: da analyze - none! +; NORMALIZE-NEXT: da analyze - confused! ; ; DELIN-LABEL: 'banerjee10' ; DELIN-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -924,7 +924,7 @@ define void @banerjee10(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; DELIN-NEXT: Src: %1 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 ; DELIN-NEXT: da analyze - confused! ; DELIN-NEXT: Src: store i64 %1, ptr %B.addr.11, align 8 --> Dst: store i64 %1, ptr %B.addr.11, align 8 -; DELIN-NEXT: da analyze - none! +; DELIN-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -981,7 +981,7 @@ define void @banerjee11(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; ; NORMALIZE-LABEL: 'banerjee11' ; NORMALIZE-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -995,7 +995,7 @@ define void @banerjee11(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; NORMALIZE-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; NORMALIZE-NEXT: da analyze - confused! ; NORMALIZE-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; NORMALIZE-NEXT: da analyze - none! +; NORMALIZE-NEXT: da analyze - confused! ; ; DELIN-LABEL: 'banerjee11' ; DELIN-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -1009,7 +1009,7 @@ define void @banerjee11(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; DELIN-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; DELIN-NEXT: da analyze - confused! ; DELIN-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; DELIN-NEXT: da analyze - none! +; DELIN-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -1066,7 +1066,7 @@ define void @banerjee12(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; ; NORMALIZE-LABEL: 'banerjee12' ; NORMALIZE-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -1080,7 +1080,7 @@ define void @banerjee12(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; NORMALIZE-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; NORMALIZE-NEXT: da analyze - confused! ; NORMALIZE-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; NORMALIZE-NEXT: da analyze - none! +; NORMALIZE-NEXT: da analyze - confused! ; ; DELIN-LABEL: 'banerjee12' ; DELIN-NEXT: Src: store i64 0, ptr %arrayidx, align 8 --> Dst: store i64 0, ptr %arrayidx, align 8 @@ -1094,7 +1094,7 @@ define void @banerjee12(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { ; DELIN-NEXT: Src: %0 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 ; DELIN-NEXT: da analyze - confused! ; DELIN-NEXT: Src: store i64 %0, ptr %B.addr.11, align 8 --> Dst: store i64 %0, ptr %B.addr.11, align 8 -; DELIN-NEXT: da analyze - none! +; DELIN-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader diff --git a/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll b/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll index 81e461a5e092d..f51f1fa59f544 100644 --- a/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll +++ b/llvm/test/Analysis/DependenceAnalysis/BasePtrBug.ll @@ -18,11 +18,11 @@ define void @test1(ptr nocapture %A, ptr nocapture %B, i32 %N) #0 { ; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: %0 = load i32, ptr %gep.0, align 4 ; CHECK-NEXT: da analyze - none! ; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: %1 = load i32, ptr %gep.1, align 4 -; CHECK-NEXT: da analyze - input [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %0 = load i32, ptr %gep.0, align 4 --> Dst: store i32 %add, ptr %gep.B, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %1 = load i32, ptr %gep.1, align 4 --> Dst: %1 = load i32, ptr %gep.1, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %1 = load i32, ptr %gep.1, align 4 --> Dst: store i32 %add, ptr %gep.B, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %add, ptr %gep.B, align 4 --> Dst: store i32 %add, ptr %gep.B, align 4 diff --git a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll index 8f94a455d3724..174f105b666f3 100644 --- a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll +++ b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll @@ -646,11 +646,11 @@ exit: define void @coeff_may_negative(ptr %a, i32 %k) { ; CHECK-LABEL: 'coeff_may_negative' ; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.0, align 1 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.1, align 1 -; CHECK-NEXT: da analyze - output [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i8 42, ptr %idx.1, align 1 --> Dst: store i8 42, ptr %idx.1, align 1 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %loop @@ -685,11 +685,11 @@ exit: define void @coeff_positive(ptr %a, i32 %k) { ; CHECK-LABEL: 'coeff_positive' ; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.0, align 1 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i8 42, ptr %idx.0, align 1 --> Dst: store i8 42, ptr %idx.1, align 1 -; CHECK-NEXT: da analyze - output [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i8 42, ptr %idx.1, align 1 --> Dst: store i8 42, ptr %idx.1, align 1 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %loop diff --git a/llvm/test/Analysis/DependenceAnalysis/ExactRDIV.ll b/llvm/test/Analysis/DependenceAnalysis/ExactRDIV.ll index b5ece14121686..73c0c8b47d74f 100644 --- a/llvm/test/Analysis/DependenceAnalysis/ExactRDIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/ExactRDIV.ll @@ -508,7 +508,7 @@ define void @rdiv9(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -564,7 +564,7 @@ define void @rdiv10(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -619,7 +619,7 @@ define void @rdiv11(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -674,7 +674,7 @@ define void @rdiv12(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader diff --git a/llvm/test/Analysis/DependenceAnalysis/GCD.ll b/llvm/test/Analysis/DependenceAnalysis/GCD.ll index 03343e7a98211..93a2f07e7df21 100644 --- a/llvm/test/Analysis/DependenceAnalysis/GCD.ll +++ b/llvm/test/Analysis/DependenceAnalysis/GCD.ll @@ -25,7 +25,7 @@ define void @gcd0(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -84,7 +84,7 @@ define void @gcd1(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx8, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -144,7 +144,7 @@ define void @gcd2(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx8, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -204,7 +204,7 @@ define void @gcd3(ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx6, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -262,7 +262,7 @@ define void @gcd4(ptr %A, ptr %B, i64 %M, i64 %N) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx16, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -330,7 +330,7 @@ define void @gcd5(ptr %A, ptr %B, i64 %M, i64 %N) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx16, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -465,13 +465,13 @@ for.end12: ; preds = %for.end12.loopexit, define void @gcd7(i32 %n, ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-LABEL: 'gcd7' ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: store i32 %7, ptr %arrayidx6, align 4 -; CHECK-NEXT: da analyze - output [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: %11 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - flow [* *|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %11 = load i32, ptr %arrayidx12, align 4 --> Dst: %11 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - input [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %11 = load i32, ptr %arrayidx12, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %11, ptr %B.addr.12, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 @@ -640,13 +640,13 @@ for.end15: ; preds = %for.end15.loopexit, define void @gcd9(i32 %n, ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-LABEL: 'gcd9' ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: store i32 %7, ptr %arrayidx6, align 4 -; CHECK-NEXT: da analyze - output [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: %11 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - flow [* *|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %7, ptr %arrayidx6, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %11 = load i32, ptr %arrayidx12, align 4 --> Dst: %11 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - input [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %11 = load i32, ptr %arrayidx12, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %11, ptr %B.addr.12, align 4 --> Dst: store i32 %11, ptr %B.addr.12, align 4 diff --git a/llvm/test/Analysis/DependenceAnalysis/PR21585.ll b/llvm/test/Analysis/DependenceAnalysis/PR21585.ll index 0d59e107b9c35..c234c59db9f17 100644 --- a/llvm/test/Analysis/DependenceAnalysis/PR21585.ll +++ b/llvm/test/Analysis/DependenceAnalysis/PR21585.ll @@ -70,11 +70,11 @@ for.end: define void @i16_wrap(ptr %a) { ; CHECK-LABEL: 'i16_wrap' ; CHECK-NEXT: Src: %0 = load i64, ptr %idx, align 4 --> Dst: %0 = load i64, ptr %idx, align 4 -; CHECK-NEXT: da analyze - input [*]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %0 = load i64, ptr %idx, align 4 --> Dst: store i64 %1, ptr %idx, align 4 -; CHECK-NEXT: da analyze - anti [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i64 %1, ptr %idx, align 4 --> Dst: store i64 %1, ptr %idx, align 4 -; CHECK-NEXT: da analyze - output [*]! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.body diff --git a/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll b/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll index 8cb0e2ac770dc..e7449c6072846 100644 --- a/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll +++ b/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll @@ -448,7 +448,7 @@ define void @p4(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx5, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp sgt i64 %n, 0 @@ -501,7 +501,7 @@ define void @p5(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx5, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp sgt i64 %n, 0 @@ -729,9 +729,9 @@ define void @foo(ptr %s, i32 %size) nounwind uwtable ssp { ; CHECK-NEXT: Src: %1 = load i32, ptr %0, align 4 --> Dst: %1 = load i32, ptr %0, align 4 ; CHECK-NEXT: da analyze - none! ; CHECK-NEXT: Src: %1 = load i32, ptr %0, align 4 --> Dst: store i32 %1, ptr %i.02, align 4 -; CHECK-NEXT: da analyze - consistent anti [1]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %1, ptr %i.02, align 4 --> Dst: store i32 %1, ptr %i.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %idx.ext = zext i32 %size to i64 diff --git a/llvm/test/Analysis/DependenceAnalysis/Propagating.ll b/llvm/test/Analysis/DependenceAnalysis/Propagating.ll index 866f515baeafb..2cd393730096d 100644 --- a/llvm/test/Analysis/DependenceAnalysis/Propagating.ll +++ b/llvm/test/Analysis/DependenceAnalysis/Propagating.ll @@ -24,7 +24,7 @@ define void @prop0(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx8, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -81,7 +81,7 @@ define void @prop1(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx14, align 4 --> Dst: store i32 %0, ptr %B.addr.21, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.21, align 4 --> Dst: store i32 %0, ptr %B.addr.21, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -151,7 +151,7 @@ define void @prop2(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -208,7 +208,7 @@ define void @prop3(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx8, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -266,7 +266,7 @@ define void @prop4(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx10, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -325,7 +325,7 @@ define void @prop5(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx12, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -385,7 +385,7 @@ define void @prop6(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -445,7 +445,7 @@ define void @prop7(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx13, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -507,7 +507,7 @@ define void @prop8(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx9, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -565,7 +565,7 @@ define void @prop9(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx9, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.11, align 4 --> Dst: store i32 %0, ptr %B.addr.11, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader diff --git a/llvm/test/Analysis/DependenceAnalysis/Separability.ll b/llvm/test/Analysis/DependenceAnalysis/Separability.ll index 2ed9cca4d1fc0..3e886e65c5ab1 100644 --- a/llvm/test/Analysis/DependenceAnalysis/Separability.ll +++ b/llvm/test/Analysis/DependenceAnalysis/Separability.ll @@ -26,7 +26,7 @@ define void @sep0(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx15, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.31, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -108,7 +108,7 @@ define void @sep1(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx15, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.31, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -190,7 +190,7 @@ define void @sep2(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx19, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.31, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader @@ -272,7 +272,7 @@ define void @sep3(ptr %A, ptr %B, i32 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx20, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.31, align 4 --> Dst: store i32 %0, ptr %B.addr.31, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: br label %for.cond1.preheader diff --git a/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll b/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll index 44bd9b7727910..d6bd30ed9050f 100644 --- a/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/StrongSIV.ll @@ -122,7 +122,7 @@ define void @strong2(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -435,7 +435,7 @@ define void @strong9(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/SymbolicRDIV.ll b/llvm/test/Analysis/DependenceAnalysis/SymbolicRDIV.ll index 8b9aa257a7c57..ba4f2101df77e 100644 --- a/llvm/test/Analysis/DependenceAnalysis/SymbolicRDIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/SymbolicRDIV.ll @@ -25,7 +25,7 @@ define void @symbolicrdiv0(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx8, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 @@ -94,7 +94,7 @@ define void @symbolicrdiv1(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx9, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 @@ -165,7 +165,7 @@ define void @symbolicrdiv2(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 @@ -234,7 +234,7 @@ define void @symbolicrdiv3(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx6, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 @@ -301,7 +301,7 @@ define void @symbolicrdiv4(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 @@ -369,7 +369,7 @@ define void @symbolicrdiv5(ptr %A, ptr %B, i64 %n1, i64 %n2) nounwind uwtable ss ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp4 = icmp eq i64 %n1, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll b/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll index cdfaec76fa892..b2b021cf41681 100644 --- a/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/SymbolicSIV.ll @@ -23,7 +23,7 @@ define void @symbolicsiv0(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -75,7 +75,7 @@ define void @symbolicsiv1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx5, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -129,7 +129,7 @@ define void @symbolicsiv2(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx3, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -181,7 +181,7 @@ define void @symbolicsiv3(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx3, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -234,7 +234,7 @@ define void @symbolicsiv4(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx3, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -286,7 +286,7 @@ define void @symbolicsiv5(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx4, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -341,7 +341,7 @@ define void @weaktest(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -392,7 +392,7 @@ define void @symbolicsiv6(ptr %A, ptr %B, i64 %n, i64 %N, i64 %M) nounwind uwtab ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx7, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -448,7 +448,7 @@ define void @symbolicsiv7(ptr %A, ptr %B, i64 %n, i64 %N, i64 %M) nounwind uwtab ; CHECK-NEXT: Src: %1 = load i32, ptr %arrayidx6, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %1, ptr %B.addr.02, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll index cd044032e34f1..4884a34217a86 100644 --- a/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll @@ -24,7 +24,7 @@ define void @weakcrossing0(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -77,7 +77,7 @@ define void @weakcrossing1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -254,7 +254,7 @@ define void @weakcrossing5(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %1 = load i32, ptr %arrayidx2, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %1, ptr %B.addr.02, align 4 --> Dst: store i32 %1, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll index 71a5ed62b8e21..3c7ab6075964b 100644 --- a/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll @@ -100,7 +100,7 @@ define void @weakzerodst1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -318,7 +318,7 @@ define void @weakzerodst6(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll b/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll index 2ee1a37775f46..31fae73f0b652 100644 --- a/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll +++ b/llvm/test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll @@ -98,7 +98,7 @@ define void @weakzerosrc1(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 @@ -316,7 +316,7 @@ define void @weakzerosrc6(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx1, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %0, ptr %B.addr.02, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 -; CHECK-NEXT: da analyze - none! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i64 %n, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/monotonic.ll b/llvm/test/Analysis/DependenceAnalysis/monotonic.ll new file mode 100644 index 0000000000000..4d80772e5ed24 --- /dev/null +++ b/llvm/test/Analysis/DependenceAnalysis/monotonic.ll @@ -0,0 +1,379 @@ +; REQUIRES: asserts +; RUN: opt < %s -disable-output -passes="print" -debug-only=da 2>&1 | FileCheck %s + +; for (int i = 0; i < n; i++) +; a[i] = 0; +; +define void @single_loop_nsw(ptr %a, i64 %n) { +; CHECK-LABEL: 'single_loop_nsw' +; CHECK: Monotonicity: Monotonic expr: {0,+,1}<%loop> +; +entry: + %guard = icmp sgt i64 %n, 0 + br i1 %guard, label %loop, label %exit + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %idx = getelementptr inbounds i8, ptr %a, i64 %i + store i8 0, ptr %idx + %i.inc = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.inc, %n + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The purpose of the variable `begin` is to avoid violating the size limitation +; of the allocated object in LLVM IR, which would cause UB. +; +; for (unsigned long long i = begin; i < end; i++) +; a[i] = 0; +; +define void @single_loop_nuw(ptr %a, i64 %begin, i64 %end) { +; CHECK-LABEL: 'single_loop_nuw' +; CHECK: Failed to prove monotonicity for: {%begin,+,1}<%loop> +; CHECK: Monotonicity: Unknown expr: {%begin,+,1}<%loop> +; +entry: + %guard = icmp ult i64 %begin, %end + br i1 %guard, label %loop, label %exit + +loop: + %i = phi i64 [ %begin, %entry ], [ %i.inc, %loop ] + %idx = getelementptr i8, ptr %a, i64 %i + store i8 0, ptr %idx + %i.inc = add nuw i64 %i, 1 + %exitcond = icmp eq i64 %i.inc, %end + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; for (int i = 0; i < n; i++) +; for (int j = 0; j < m; j++) +; a[i + j] = 0; +; +define void @nested_loop_nsw0(ptr %a, i64 %n, i64 %m) { +; CHECK-LABEL: 'nested_loop_nsw0' +; CHECK: Monotonicity: Monotonic expr: {{\{}}{0,+,1}<%loop.i.header>,+,1}<%loop.j> +; +entry: + %guard.i = icmp sgt i64 %n, 0 + br i1 %guard.i, label %loop.i.header, label %exit + +loop.i.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ] + br label %loop.j.preheader + +loop.j.preheader: + %gurard.j = icmp sgt i64 %m, 0 + br i1 %gurard.j, label %loop.j, label %loop.i.latch + +loop.j: + %j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ] + %offset = add nsw i64 %i, %j + %idx = getelementptr inbounds i8, ptr %a, i64 %offset + store i8 0, ptr %idx + %j.inc = add nsw i64 %j, 1 + %exitcond.j = icmp eq i64 %j.inc, %m + br i1 %exitcond.j, label %loop.i.latch, label %loop.j + +loop.i.latch: + %i.inc = add nsw i64 %i, 1 + %exitcond.i = icmp eq i64 %i.inc, %n + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +} + +; for (int i = n - 1; i >= 0; i--) +; for (int j = 0; j < m; j++) +; a[i + j] = 0; +; +define void @nested_loop_nsw1(ptr %a, i64 %n, i64 %m) { +; CHECK-LABEL: 'nested_loop_nsw1' +; CHECK: Monotonicity: Monotonic expr: {{\{}}{(-1 + %n),+,-1}<%loop.i.header>,+,1}<%loop.j> +; +entry: + %guard.i = icmp sgt i64 %n, 0 + br i1 %guard.i, label %loop.i.header, label %exit + +loop.i.header: + %i = phi i64 [ %n, %entry ], [ %i.dec, %loop.i.latch ] + %i.dec = add nsw i64 %i, -1 + br label %loop.j.preheader + +loop.j.preheader: + %gurard.j = icmp sgt i64 %m, 0 + br i1 %gurard.j, label %loop.j, label %loop.i.latch + +loop.j: + %j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ] + %offset = add nsw i64 %i.dec, %j + %idx = getelementptr inbounds i8, ptr %a, i64 %offset + store i8 0, ptr %idx + %j.inc = add nsw i64 %j, 1 + %exitcond.j = icmp eq i64 %j.inc, %m + br i1 %exitcond.j, label %loop.i.latch, label %loop.j + +loop.i.latch: + %exitcond.i = icmp eq i64 %i.dec, 0 + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +} + +; for (int i = begin0; i < end0; i++) +; for (int j = begin1; j < end1; j++) { +; unsigned long long offset = (unsigned long long)i + (unsigned long long)j; +; a[offset] = 0; +; } +; +define void @nested_loop_nuw(ptr %a, i64 %begin0, i64 %end0, i64 %begin1, i64 %end1) { +; CHECK-LABEL: 'nested_loop_nuw' +; CHECK: Failed to prove monotonicity for: {{\{}}{(%begin0 + %begin1),+,1}<%loop.i.header>,+,1}<%loop.j> +; CHECK: Monotonicity: Unknown expr: {{\{}}{(%begin0 + %begin1),+,1}<%loop.i.header>,+,1}<%loop.j> +; +entry: + %guard.i.0 = icmp slt i64 0, %begin0 + %guard.i.1 = icmp slt i64 %begin0, %end0 + %guard.i.2 = icmp slt i64 0, %end0 + %and.i.0 = and i1 %guard.i.0, %guard.i.1 + %and.i.1 = and i1 %and.i.0, %guard.i.2 + br i1 %and.i.1, label %loop.i.header, label %exit + +loop.i.header: + %i = phi i64 [ %begin0, %entry ], [ %i.inc, %loop.i.latch ] + br label %loop.j.preheader + +loop.j.preheader: + %guard.j.0 = icmp slt i64 0, %begin1 + %guard.j.1 = icmp slt i64 %begin1, %end1 + %guard.j.2 = icmp slt i64 0, %end1 + %and.j.0 = and i1 %guard.j.0, %guard.j.1 + %and.j.1 = and i1 %and.j.0, %guard.j.2 + br i1 %and.j.1, label %loop.j, label %loop.i.latch + +loop.j: + %j = phi i64 [ %begin1, %loop.j.preheader ], [ %j.inc, %loop.j ] + %offset = add nuw i64 %i, %j + %idx = getelementptr i8, ptr %a, i64 %offset + store i8 0, ptr %idx + %j.inc = add nsw i64 %j, 1 + %exitcond.j = icmp eq i64 %j.inc, %end1 + br i1 %exitcond.j, label %loop.i.latch, label %loop.j + +loop.i.latch: + %i.inc = add nsw i64 %i, 1 + %exitcond.i = icmp eq i64 %i.inc, %end0 + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +} + +; `step` can be zero, so `step*j` can be either Invariant or Monotonic. This +; propagates to `i + step*j`. +; +; for (int i = 0; i < n; i++) +; for (int j = 0; j < m; j++) +; a[i + step*j] = 0; +; +define void @nested_loop_step(ptr %a, i64 %n, i64 %m, i64 %step) { +; CHECK-LABEL: 'nested_loop_step' +; CHECK: Monotonicity: No signed wrap expr: {{\{}}{0,+,1}<%loop.i.header>,+,%step}<%loop.j> +; +entry: + %guard.i = icmp sgt i64 %n, 0 + br i1 %guard.i, label %loop.i.header, label %exit + +loop.i.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ] + br label %loop.j.preheader + +loop.j.preheader: + %gurard.j = icmp sgt i64 %m, 0 + br i1 %gurard.j, label %loop.j, label %loop.i.latch + +loop.j: + %j = phi i64 [ 0, %loop.j.preheader ], [ %j.inc, %loop.j ] + %offset.j = phi i64 [ 0, %loop.j.preheader ], [ %offset.j.next, %loop.j ] + %offset = add nsw i64 %i, %offset.j + %idx = getelementptr inbounds i8, ptr %a, i64 %offset + store i8 0, ptr %idx + %j.inc = add nsw i64 %j, 1 + %offset.j.next = add nsw i64 %offset.j, %step + %exitcond.j = icmp eq i64 %j.inc, %m + br i1 %exitcond.j, label %loop.i.latch, label %loop.j + +loop.i.latch: + %i.inc = add nsw i64 %i, 1 + %exitcond.i = icmp eq i64 %i.inc, %n + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +} + +; `offset` can be loop-invariant since `step` can be zero. +; +; int8_t offset = start; +; for (int i = 0; i < 100; i++, offset += step) +; a[sext(offset)] = 0; +; +define void @sext_nsw(ptr %a, i8 %start, i8 %step) { +; CHECK-LABEL: 'sext_nsw' +; CHECK: Monotonicity: No signed wrap expr: {(sext i8 %start to i64),+,(sext i8 %step to i64)}<%loop> +; +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %offset = phi i8 [ %start, %entry ], [ %offset.next, %loop ] + %offset.sext = sext i8 %offset to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.sext + store i8 0, ptr %idx + %i.inc = add nsw i64 %i, 1 + %offset.next = add nsw i8 %offset, %step + %exitcond = icmp eq i64 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The addition for `%offset.next` can wrap, so we cannot prove monotonicity. +; +; int8_t offset = start; +; for (int i = 0; i < 100; i++, offset += step) +; a[sext(offset)] = 0; +; +define void @sext_may_wrap(ptr %a, i8 %start, i8 %step) { +; CHECK-LABEL: 'sext_may_wrap' +; CHECK: Failed to prove monotonicity for: {%start,+,%step}<%loop> +; CHECK: Monotonicity: Unknown expr: (sext i8 {%start,+,%step}<%loop> to i64) +; +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %offset = phi i8 [ %start, %entry ], [ %offset.next, %loop ] + %offset.sext = sext i8 %offset to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.sext + store i8 0, ptr %idx + %i.inc = add nsw i64 %i, 1 + %offset.next = add i8 %offset, %step + %exitcond = icmp eq i64 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; `offset` can be loop-invariant since `step` can be zero. +; +; int8_t offset = start; +; for (int i = 0; i < 100; i++, offset += step) +; a[zext(offset)] = 0; +; +define void @zext_nsw(ptr %a, i8 %start, i8 %step) { +; CHECK-LABEL: 'zext_nsw' +; CHECK: Monotonicity: No signed wrap expr: (zext i8 {%start,+,%step}<%loop> to i64) +; +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %offset = phi i8 [ %start, %entry ], [ %offset.next, %loop ] + %offset.zext = zext i8 %offset to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.zext + store i8 0, ptr %idx + %i.inc = add nsw i64 %i, 1 + %offset.next = add nsw i8 %offset, %step + %exitcond = icmp eq i64 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The addition for `%offset.next` can wrap, so we cannot prove monotonicity. +; +; int8_t offset = start; +; for (int i = 0; i < 100; i++, offset += step) +; a[zext(offset)] = 0; +; +define void @zext_may_wrap(ptr %a, i8 %start, i8 %step) { +; CHECK-LABEL: 'zext_may_wrap' +; CHECK: Failed to prove monotonicity for: {%start,+,%step}<%loop> +; CHECK: Monotonicity: Unknown expr: (zext i8 {%start,+,%step}<%loop> to i64) +; +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %offset = phi i8 [ %start, %entry ], [ %offset.next, %loop ] + %offset.zext = zext i8 %offset to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.zext + store i8 0, ptr %idx + %i.inc = add nsw i64 %i, 1 + %offset.next = add i8 %offset, %step + %exitcond = icmp eq i64 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The value of step reccurence is not invariant with respect to the outer most +; loop (the i-loop). +; +; offset_i = 0; +; for (int i = 0; i < 100; i++) { +; for (int j = 0; j < 100; j++) +; a[offset_i + j] = 0; +; offset_i += (i % 2 == 0) ? 0 : 3; +; } +; +define void @step_is_variant(ptr %a) { +; CHECK-LABEL: 'step_is_variant' +; CHECK: Failed to prove monotonicity for: %offset.i +; CHECK: Failed to prove monotonicity for: {%offset.i,+,1}<%loop.j> +; CHECK: Monotonicity: Unknown expr: {%offset.i,+,1}<%loop.j> +; +entry: + br label %loop.i.header + +loop.i.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ] + %offset.i = phi i64 [ 0, %entry ], [ %offset.i.next, %loop.i.latch ] + %step.i.0 = phi i64 [ 0, %entry ], [ %step.i.1, %loop.i.latch ] + %step.i.1 = phi i64 [ 3, %entry ], [ %step.i.0, %loop.i.latch ] + br label %loop.j + +loop.j: + %j = phi i64 [ 0, %loop.i.header ], [ %j.inc, %loop.j ] + %offset = add nsw i64 %offset.i, %j + %idx = getelementptr inbounds i8, ptr %a, i64 %offset + store i8 0, ptr %idx + %j.inc = add nsw i64 %j, 1 + %exitcond.j = icmp eq i64 %j.inc, 100 + br i1 %exitcond.j, label %loop.i.latch, label %loop.j + +loop.i.latch: + %i.inc = add nsw i64 %i, 1 + %offset.i.next = add nsw i64 %offset.i, %step.i.0 + %exitcond.i = icmp eq i64 %i.inc, 100 + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +}