diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index da86a8d2cc9c0..534316cace498 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -121,6 +121,135 @@ static cl::opt MIVMaxLevelThreshold( cl::desc("Maximum depth allowed for the recursive algorithm used to " "explore MIV direction vectors.")); +static cl::opt DumpMonotonicityReport( + "da-dump-monotonicity-report", cl::init(false), cl::Hidden, + cl::desc("When printing analysis, dump a report of monotonicity checks.")); + +namespace { + +/// The type of signed monotonicity of a SCEV expression. This property is +/// defined with respect to the outermost loop that DA is analyzing. +/// +/// 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 SignedMonotonicityType { + Unknown, ///< The expression contains some non loop-invariant SCEVUnknown or + ///< arithmetic operation that has some AddRec as its subexpression + ///< and may cause signed wrap. + Invariant, ///< The expression is a loop-invariant. + MultiMonotonic, ///< The expression is monotonically increasing or decreasing + ///< with respect to each loop. Monotonicity is checked + ///< independently for each loop. It is allowed to contain + ///< both increasing and decreasing AddRecs. For example, + ///< `{{0,+,1}<%L0>,+,-1}<%L1>` is classified as + ///< MultiMonotonic if it doesn't wrap. + ///< Currently we don't check whether the expression is + ///< "strictly" increasing or decreasing. An AddRec whose step + ///< reccurence can be zero, like {0,+,%mayzero}, would + ///< classified as MultiMonotonic. +}; + +struct SignedMonotonicity { + explicit SignedMonotonicity(SignedMonotonicityType Type, + const SCEV *FailurePoint = nullptr); + + SignedMonotonicityType getType() const { return Type; } + + const SCEV *getFailurePoint() const { return FailurePoint; } + + void print(raw_ostream &OS, unsigned Depth) const; + +private: + SignedMonotonicityType Type; + + /// The subexpression that caused Unknown. + const SCEV *FailurePoint; +}; + +/// 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. + SCEVSignedMonotonicityChecker(ScalarEvolution *SE, const Loop *L, + const Value *Ptr = nullptr); + + SignedMonotonicity visitAddRecExpr(const SCEVAddRecExpr *Expr); + SignedMonotonicity visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr); + SignedMonotonicity visitSignExtendExpr(const SCEVSignExtendExpr *Expr); + + SignedMonotonicity visitConstant(const SCEVConstant *) { + return SignedMonotonicity(SignedMonotonicityType::Invariant); + } + SignedMonotonicity visitVScale(const SCEVVScale *) { + return SignedMonotonicity(SignedMonotonicityType::Invariant); + } + + // TODO: Handle more cases. + SignedMonotonicity visitAddExpr(const SCEVAddExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitMulExpr(const SCEVMulExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitTruncateExpr(const SCEVTruncateExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitUDivExpr(const SCEVUDivExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitSMaxExpr(const SCEVSMaxExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitUMaxExpr(const SCEVUMaxExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitSMinExpr(const SCEVSMinExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitUMinExpr(const SCEVUMinExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity + visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitUnknown(const SCEVUnknown *Expr) { + return checkInvarianceOnly(Expr); + } + SignedMonotonicity visitCouldNotCompute(const SCEVCouldNotCompute *Expr) { + return checkInvarianceOnly(Expr); + } + +private: + ScalarEvolution *SE; + const Loop *OutermostLoop; + bool NoWrapFromGEP = false; + + /// A helper to classify \p Expr as either Invariant or Unknown. + SignedMonotonicity checkInvarianceOnly(const SCEV *Expr); + + /// Return true if \p Expr is loop-invariant with respect to the outermost + /// loop. + bool isLoopInvariant(const SCEV *Expr) const; +}; + +} // anonymous namespace + +static SignedMonotonicity checkSignedMonotonicity(ScalarEvolution *SE, + const SCEV *Expr, + const Loop *L, + const Value *Ptr) { + return SCEVSignedMonotonicityChecker(SE, L, Ptr).visit(Expr); +} + //===----------------------------------------------------------------------===// // basics @@ -175,8 +304,27 @@ void DependenceAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { // Calls depends() on every possible pair and prints out the result. // Ignores all other instructions. static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, - ScalarEvolution &SE, bool NormalizeResults) { + ScalarEvolution &SE, LoopInfo &LI, + bool NormalizeResults) { auto *F = DA->getFunction(); + + if (DumpMonotonicityReport) { + OS << "Monotonicity check:\n"; + for (Instruction &Inst : instructions(F)) { + if (!isa(Inst) && !isa(Inst)) + continue; + Value *Ptr = getLoadStorePointerOperand(&Inst); + const Loop *L = LI.getLoopFor(Inst.getParent()); + const SCEV *PtrSCEV = SE.getSCEVAtScope(Ptr, L); + const SCEV *AccessFn = SE.removePointerBase(PtrSCEV); + SignedMonotonicity SM = checkSignedMonotonicity(&SE, AccessFn, L, Ptr); + OS.indent(2) << "Inst: " << Inst << "\n"; + OS.indent(4) << "Expr: " << *AccessFn << "\n"; + SM.print(OS, 4); + } + OS << "\n"; + } + for (inst_iterator SrcI = inst_begin(F), SrcE = inst_end(F); SrcI != SrcE; ++SrcI) { if (SrcI->mayReadOrWriteMemory()) { @@ -228,7 +376,8 @@ static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA, void DependenceAnalysisWrapperPass::print(raw_ostream &OS, const Module *) const { dumpExampleDependence( - OS, info.get(), getAnalysis().getSE(), false); + OS, info.get(), getAnalysis().getSE(), + getAnalysis().getLoopInfo(), false); } PreservedAnalyses @@ -237,7 +386,7 @@ DependenceAnalysisPrinterPass::run(Function &F, FunctionAnalysisManager &FAM) { << "':\n"; dumpExampleDependence(OS, &FAM.getResult(F), FAM.getResult(F), - NormalizeResults); + FAM.getResult(F), NormalizeResults); return PreservedAnalyses::all(); } @@ -3308,6 +3457,148 @@ void DependenceInfo::updateDirection(Dependence::DVEntry &Level, llvm_unreachable("constraint has unexpected kind"); } +SignedMonotonicity::SignedMonotonicity(SignedMonotonicityType Type, + const SCEV *FailurePoint) + : Type(Type), FailurePoint(FailurePoint) { + assert((Type != SignedMonotonicityType::Unknown || FailurePoint) && + "Failure point must be provided iff Unknown type"); +} + +void SignedMonotonicity::print(raw_ostream &OS, unsigned Depth) const { + OS.indent(Depth) << "Monotonicity: "; + switch (Type) { + case SignedMonotonicityType::Unknown: + OS << "Unknown\n"; + if (FailurePoint) + OS.indent(Depth) << "Reason: " << *FailurePoint << "\n"; + break; + case SignedMonotonicityType::Invariant: + OS << "Invariant\n"; + break; + case SignedMonotonicityType::MultiMonotonic: + OS << "MultiMonotonic\n"; + break; + } +} + +SCEVSignedMonotonicityChecker::SCEVSignedMonotonicityChecker( + ScalarEvolution *SE, const Loop *L, const Value *Ptr) + : SE(SE), OutermostLoop(L ? L->getOutermostLoop() : nullptr), + NoWrapFromGEP(false) { + 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: The monotonicity check ensures that the given SCEV does not wrap + // in "any" iteration. Thus, inference from nusw should be valid only if + // the GEP is executed and its result is used in every iteration of the + // loop. + auto *GEP = dyn_cast(Ptr); + if (GEP && GEP->hasNoUnsignedSignedWrap()) + NoWrapFromGEP = true; + } +} + +SignedMonotonicity +SCEVSignedMonotonicityChecker::checkInvarianceOnly(const SCEV *Expr) { + if (isLoopInvariant(Expr)) + return SignedMonotonicity(SignedMonotonicityType::Invariant); + return SignedMonotonicity(SignedMonotonicityType::Unknown, Expr); +} + +bool SCEVSignedMonotonicityChecker::isLoopInvariant(const SCEV *Expr) const { + return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop); +} + +SignedMonotonicity +SCEVSignedMonotonicityChecker::visitAddRecExpr(const SCEVAddRecExpr *Expr) { + if (!Expr->isAffine()) + return SignedMonotonicity(SignedMonotonicityType::Unknown, Expr); + + const SCEV *Start = Expr->getStart(); + const SCEV *Step = Expr->getStepRecurrence(*SE); + + SignedMonotonicity StartRes = visit(Start); + if (StartRes.getType() == SignedMonotonicityType::Unknown) + return StartRes; + + SignedMonotonicity StepRes = visit(Step); + if (StepRes.getType() != SignedMonotonicityType::Invariant) + return SignedMonotonicity(SignedMonotonicityType::Unknown, 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 SignedMonotonicity(SignedMonotonicityType::Unknown, 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 SignedMonotonicity(SignedMonotonicityType::Unknown, Expr); + } + + switch (StartRes.getType()) { + case SignedMonotonicityType::Unknown: + llvm_unreachable("should have been handled above"); + case SignedMonotonicityType::Invariant: + case SignedMonotonicityType::MultiMonotonic: + // TODO: Should handle SCEV like `{{0,+,-1}<%loop>,+,1}<%loop>`? + // TODO: Should we prove here that the Step is non-zero? + return SignedMonotonicity(SignedMonotonicityType::MultiMonotonic); + } + llvm_unreachable("unhandled MonotonicityType"); +} + +SignedMonotonicity SCEVSignedMonotonicityChecker::visitZeroExtendExpr( + const SCEVZeroExtendExpr *Expr) { + const SCEV *Op = Expr->getOperand(); + SignedMonotonicity OpRes = visit(Op); + switch (OpRes.getType()) { + case SignedMonotonicityType::Unknown: + case SignedMonotonicityType::Invariant: + return OpRes; + + // If the operand can be Monotonic, check if it is preserved after ZExt. If + // the value can cross zero, it's no longer monotonic. For example, consider + // `(zext i8 {-1,+,1}<%loop> to i32)`. The values of the operand {-1,+,1} + // are: + // + // -1, 0, 1, 2, ... + // + // However, those of the zero-extened expression are: + // + // 255, 0, 1, 2, ... + // + // which is not monotonic. + case SignedMonotonicityType::MultiMonotonic: + if (SE->isKnownNonNegative(Op) || SE->isKnownNonPositive(Op)) + return OpRes; + return SignedMonotonicity(SignedMonotonicityType::Unknown, Expr); + } + llvm_unreachable("unhandled MonotonicityType"); +} + +SignedMonotonicity SCEVSignedMonotonicityChecker::visitSignExtendExpr( + const SCEVSignExtendExpr *Expr) { + return visit(Expr->getOperand()); +} + /// 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 @@ -3701,13 +3992,29 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst, Pair[0].Src = SrcSCEV; Pair[0].Dst = DstSCEV; + bool Delinearized = false; if (Delinearize) { if (tryDelinearize(Src, Dst, Pair)) { LLVM_DEBUG(dbgs() << " delinearized\n"); Pairs = Pair.size(); + Delinearized = true; } } + // If delinearization was not done, check the monotonicity of the original + // offsets. + if (!Delinearized) { + const Loop *OutermostLoop = SrcLoop ? SrcLoop->getOutermostLoop() : nullptr; + if (checkSignedMonotonicity(SE, SrcEv, OutermostLoop, SrcPtr).getType() == + SignedMonotonicityType::Unknown) + return std::make_unique(Src, Dst, + SCEVUnionPredicate(Assume, *SE)); + if (checkSignedMonotonicity(SE, DstEv, OutermostLoop, DstPtr).getType() == + SignedMonotonicityType::Unknown) + return std::make_unique(Src, Dst, + SCEVUnionPredicate(Assume, *SE)); + } + for (unsigned P = 0; P < Pairs; ++P) { Pair[P].Loops.resize(MaxLevels + 1); Pair[P].GroupLoops.resize(MaxLevels + 1); diff --git a/llvm/test/Analysis/DependenceAnalysis/AA.ll b/llvm/test/Analysis/DependenceAnalysis/AA.ll index 173744a07ef96..b03f82ed1b084 100644 --- a/llvm/test/Analysis/DependenceAnalysis/AA.ll +++ b/llvm/test/Analysis/DependenceAnalysis/AA.ll @@ -128,11 +128,11 @@ define void @test_tbaa_diff(ptr %A, ptr %B) { define void @tbaa_loop(i32 %I, i32 %J, ptr nocapture %A, ptr nocapture readonly %B) { ; CHECK-LABEL: 'tbaa_loop' ; CHECK-NEXT: Src: %0 = load i16, ptr %arrayidx.us, align 4, !tbaa !0 --> Dst: %0 = load i16, ptr %arrayidx.us, align 4, !tbaa !0 -; CHECK-NEXT: da analyze - input [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %0 = load i16, ptr %arrayidx.us, align 4, !tbaa !0 --> Dst: store i32 %add.us.lcssa, ptr %arrayidx6.us, align 4, !tbaa !4 ; CHECK-NEXT: da analyze - none! ; CHECK-NEXT: Src: store i32 %add.us.lcssa, ptr %arrayidx6.us, align 4, !tbaa !4 --> Dst: store i32 %add.us.lcssa, ptr %arrayidx6.us, align 4, !tbaa !4 -; CHECK-NEXT: da analyze - output [*]! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp = icmp ne i32 %J, 0 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..eb05b7dd3e9a8 100644 --- a/llvm/test/Analysis/DependenceAnalysis/DADelin.ll +++ b/llvm/test/Analysis/DependenceAnalysis/DADelin.ll @@ -547,9 +547,9 @@ define double @test_sizes(i16 %h, i16 %N, ptr nocapture %array) { ; CHECK-NEXT: Src: %2 = load i16, ptr %arrayidx, align 4 --> Dst: %2 = load i16, ptr %arrayidx, align 4 ; CHECK-NEXT: da analyze - consistent input [0 S]! ; CHECK-NEXT: Src: %2 = load i16, ptr %arrayidx, align 4 --> Dst: store i16 %add6, ptr %arrayidx8, align 4 -; CHECK-NEXT: da analyze - anti [* *|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i16 %add6, ptr %arrayidx8, align 4 --> Dst: store i16 %add6, ptr %arrayidx8, align 4 -; CHECK-NEXT: da analyze - output [* *]! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp28 = icmp sgt i16 %N, 1 @@ -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..98026629ce4e4 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 @@ -556,13 +556,13 @@ for.end15: ; preds = %for.end15.loopexit, define void @gcd8(i32 %n, ptr %A, ptr %B) nounwind uwtable ssp { ; CHECK-LABEL: 'gcd8' ; CHECK-NEXT: Src: store i32 %i.06, ptr %arrayidx, align 4 --> Dst: store i32 %i.06, ptr %arrayidx, align 4 -; CHECK-NEXT: da analyze - output [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %i.06, ptr %arrayidx, align 4 --> Dst: %5 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - flow [* *|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %i.06, ptr %arrayidx, align 4 --> Dst: store i32 %5, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %5 = load i32, ptr %arrayidx12, align 4 --> Dst: %5 = load i32, ptr %arrayidx12, align 4 -; CHECK-NEXT: da analyze - input [* *]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %5 = load i32, ptr %arrayidx12, align 4 --> Dst: store i32 %5, ptr %B.addr.12, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %5, ptr %B.addr.12, align 4 --> Dst: store i32 %5, 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..fe7a6135e23b5 100644 --- a/llvm/test/Analysis/DependenceAnalysis/PR21585.ll +++ b/llvm/test/Analysis/DependenceAnalysis/PR21585.ll @@ -47,7 +47,7 @@ define void @t(ptr noalias %a, i32 %n) nounwind { ; CHECK-NEXT: Src: %0 = load i32, ptr @g, align 4 --> Dst: store i32 %0, ptr %arrayidx, align 4 ; CHECK-NEXT: da analyze - none! ; CHECK-NEXT: Src: store i32 %0, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %arrayidx, align 4 -; CHECK-NEXT: da analyze - output [*]! +; CHECK-NEXT: da analyze - confused! ; entry: %cmp1 = icmp eq i32 %n, 0 @@ -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/PR31848.ll b/llvm/test/Analysis/DependenceAnalysis/PR31848.ll index 8ee1224a18ad1..db64d2cab2fed 100644 --- a/llvm/test/Analysis/DependenceAnalysis/PR31848.ll +++ b/llvm/test/Analysis/DependenceAnalysis/PR31848.ll @@ -8,7 +8,7 @@ define void @barney(ptr nocapture %arg, i32 %arg1) { ; CHECK-LABEL: 'barney' ; CHECK-NEXT: Src: store i32 7, ptr %getelementptr, align 4 --> Dst: store i32 7, ptr %getelementptr, align 4 -; CHECK-NEXT: da analyze - output [* * * *]! +; CHECK-NEXT: da analyze - confused! ; bb: %icmp = icmp sgt i32 %arg1, 0 diff --git a/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll b/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll index 8cb0e2ac770dc..3fac79957dfab 100644 --- a/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll +++ b/llvm/test/Analysis/DependenceAnalysis/Preliminary.ll @@ -438,17 +438,17 @@ for.end26: ; preds = %for.end26.loopexit, define void @p4(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-LABEL: 'p4' ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: store i32 %conv2, ptr %arrayidx, align 4 -; CHECK-NEXT: da analyze - output [*]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx5, align 4 -; CHECK-NEXT: da analyze - flow [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx5, align 4 --> Dst: %0 = load i32, ptr %arrayidx5, align 4 -; CHECK-NEXT: da analyze - input [*]! +; CHECK-NEXT: da analyze - confused! ; 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 @@ -491,17 +491,17 @@ for.end: ; preds = %for.end.loopexit, % define void @p5(ptr %A, ptr %B, i64 %n) nounwind uwtable ssp { ; CHECK-LABEL: 'p5' ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: store i32 %conv2, ptr %arrayidx, align 4 -; CHECK-NEXT: da analyze - output [*]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: %0 = load i32, ptr %arrayidx5, align 4 -; CHECK-NEXT: da analyze - flow [*|<]! +; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: store i32 %conv2, ptr %arrayidx, align 4 --> Dst: store i32 %0, ptr %B.addr.02, align 4 ; CHECK-NEXT: da analyze - confused! ; CHECK-NEXT: Src: %0 = load i32, ptr %arrayidx5, align 4 --> Dst: %0 = load i32, ptr %arrayidx5, align 4 -; CHECK-NEXT: da analyze - input [*]! +; CHECK-NEXT: da analyze - confused! ; 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..290aafe24c82d --- /dev/null +++ b/llvm/test/Analysis/DependenceAnalysis/monotonic.ll @@ -0,0 +1,603 @@ +; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5 +; RUN: opt < %s -disable-output -passes="print" -da-dump-monotonicity-report 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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {0,+,1}<%loop> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - none! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {%begin,+,1}<%loop> +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: {%begin,+,1}<%loop> +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<%loop.i.header>,+,1}<%loop.j> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - output [* *]! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {{\{\{}}(-1 + %n),+,-1}<%loop.i.header>,+,1}<%loop.j> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - output [* *]! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {{\{\{}}(%begin0 + %begin1),+,1}<%loop.i.header>,+,1}<%loop.j> +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: {(%begin0 + %begin1),+,1}<%loop.i.header> +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +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 +} + +; FIXME?: What if `step` is zero? +; +; 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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<%loop.i.header>,+,%step}<%loop.j> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - output [* *]! +; +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 +} + +; FIXME?: What if `step` is 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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {(sext i8 %start to i64),+,(sext i8 %step to i64)}<%loop> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - none! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: (sext i8 {%start,+,%step}<%loop> to i64) +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: {%start,+,%step}<%loop> +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +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 +} + +; for (int8_t i = 0; i < 100; i++) +; a[zext(offset)] = 0; +; +define void @zext_pos(ptr %a) { +; CHECK-LABEL: 'zext_pos' +; CHECK-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {0,+,1}<%loop> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - none! +; +entry: + br label %loop + +loop: + %i = phi i8 [ 0, %entry ], [ %i.inc, %loop ] + %offset.zext = zext nneg i8 %i to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.zext + store i8 0, ptr %idx + %i.inc = add nsw i8 %i, 1 + %exitcond = icmp eq i8 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; The zero-extened value of `offset` is no longer monotonic. In fact, the +; values of `offset` in each iteration are: +; +; iteration | 0 | 1 | 2 | ... +; -------------|-----|---|---|--------- +; offset | -1 | 0 | 1 | ... +; zext(offset) | 255 | 0 | 1 | ... +; +; +; for (int8_t i = -1; i < 100; i++) +; a[zext(offset)] = 0; +; +define void @zext_cross_zero(ptr %a) { +; CHECK-LABEL: 'zext_cross_zero' +; CHECK-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: (zext i8 {-1,+,1}<%loop> to i64) +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: (zext i8 {-1,+,1}<%loop> to i64) +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +entry: + br label %loop + +loop: + %i = phi i8 [ -1, %entry ], [ %i.inc, %loop ] + %offset.zext = zext nneg i8 %i to i64 + %idx = getelementptr i8, ptr %a, i64 %offset.zext + store i8 0, ptr %idx + %i.inc = add nsw i8 %i, 1 + %exitcond = icmp eq i8 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; `offset` can be loop-invariant since `step` can be zero. +; FIXME: The result should be NoSignedWrap? +; +; int8_t offset = 0; +; for (int i = 0; i < 100; i++, offset += step) +; a[zext(offset)] = 0; +; +define void @zext_nneg_nsw(ptr %a, i8 %step) { +; CHECK-LABEL: 'zext_nneg_nsw' +; CHECK-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: (zext i8 {0,+,%step}<%loop> to i64) +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: (zext i8 {0,+,%step}<%loop> to i64) +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop ] + %offset = phi i8 [ 0, %entry ], [ %offset.next, %loop ] + %offset.zext = zext nneg 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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: (zext i8 {%start,+,%step}<%loop> to i64) +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: {%start,+,%step}<%loop> +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +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-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {%offset.i,+,1}<%loop.j> +; CHECK-NEXT: Monotonicity: Unknown +; CHECK-NEXT: Reason: %offset.i +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - confused! +; +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 +} + +; for (unsigned long long i = 0; i < 100; i++) +; if (i % 4 == 0) +; a[i * (1ull << 62)] = 0; +; +; FIXME: This is not monotonic, the store always writes to `a[0]`. The +; reasoning based on `nusw` on GEP is incorrect. +define void @conditional_store0(ptr %a) { +; CHECK-LABEL: 'conditional_store0' +; CHECK-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {0,+,4611686018427387904}<%loop.header> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - none! +; +entry: + %step = shl i64 1, 62 + br label %loop.header + +loop.header: + %i = phi i64 [ 0, %entry ], [ %i.inc, %loop.latch ] + %offset = phi i64 [ 0, %entry ], [ %offset.next, %loop.latch ] + %mod4 = and i64 %i, 3 + %cond = icmp eq i64 %mod4, 0 + br i1 %cond, label %if.then, label %loop.latch + +if.then: + %idx = getelementptr inbounds i8, ptr %a, i64 %offset + store i8 0, ptr %idx + br label %loop.latch + +loop.latch: + %i.inc = add nsw i64 %i, 1 + %offset.next = add i64 %offset, %step + %exitcond = icmp eq i64 %i.inc, 100 + br i1 %exitcond, label %exit, label %loop.header + +exit: + ret void +} + +; for (unsigned long long i = 0; i < 100; i++) +; if (i % 4 == 0) +; for (unsigned long long j = 0; j < 100; j++) +; a[i * (1ull << 62) + j] = 0; +; +; FIXME: This is not monotonic. When the j-loop is executed, `i * (1ull << 62)` +; is always 0, so the array access here is effectively `a[j]`. The reasoning +; based on `nusw` on GEP is incorrect. +define void @conditional_store1(ptr %a) { +; CHECK-LABEL: 'conditional_store1' +; CHECK-NEXT: Monotonicity check: +; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: Expr: {{\{\{}}0,+,4611686018427387904}<%loop.i.header>,+,1}<%loop.j> +; CHECK-NEXT: Monotonicity: MultiMonotonic +; CHECK-EMPTY: +; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1 +; CHECK-NEXT: da analyze - none! +; +entry: + %step = shl i64 1, 62 + 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 ] + %mod4 = and i64 %i, 3 + %cond = icmp eq i64 %mod4, 0 + br i1 %cond, label %loop.j, label %loop.i.latch + +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 i64 %offset.i, %step + %exitcond.i = icmp eq i64 %i.inc, 100 + br i1 %exitcond.i, label %exit, label %loop.i.header + +exit: + ret void +}