[llvm] [DA] Remove monotonicity-related code and tests (PR #193697)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 23 02:00:40 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Ryotaro Kasuga (kasuga-fj)
<details>
<summary>Changes</summary>
The concept of monotonicity was introduced in #<!-- -->162280 to abstract the assumptions used in dependence tests. However, for the ZIV / SIV / RDIV tests, this concept is excessive and not meaningful. For the MIV tests, I believe such a concept is necessary, but since we have decided to disable the Banerjee MIV test for now (see #<!-- -->174733), monotonicity has effectively become a maintenance burden. Let's clean it for the time being and reintroduce it only when we truly need it.
Discussion: #<!-- -->176367
---
Patch is 54.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/193697.diff
7 Files Affected:
- (modified) llvm/lib/Analysis/DependenceAnalysis.cpp (-288)
- (removed) llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll (-209)
- (removed) llvm/test/Analysis/DependenceAnalysis/monotonicity-delinearize.ll (-59)
- (removed) llvm/test/Analysis/DependenceAnalysis/monotonicity-invariant.ll (-150)
- (removed) llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll (-141)
- (removed) llvm/test/Analysis/DependenceAnalysis/monotonicity-no-wrap-flags.ll (-571)
- (removed) llvm/test/Analysis/DependenceAnalysis/non-monotonic.ll (-77)
``````````diff
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 3191651dc5b8a..17b9fe580db39 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -150,18 +150,6 @@ static cl::opt<DependenceTestType> EnableDependenceTest(
clEnumValN(DependenceTestType::BanerjeeMIV, "banerjee-miv",
"Enable only Banerjee MIV test.")));
-// TODO: This flag is disabled by default because it is still under development.
-// Enable it or delete this flag when the feature is ready.
-static cl::opt<bool> EnableMonotonicityCheck(
- "da-enable-monotonicity-check", cl::init(false), cl::Hidden,
- cl::desc("Check if the subscripts are monotonic. If it's not, dependence "
- "is reported as unknown."));
-
-static cl::opt<bool> DumpMonotonicityReport(
- "da-dump-monotonicity-report", cl::init(false), cl::Hidden,
- cl::desc(
- "When printing analysis, dump the results of monotonicity checks."));
-
//===----------------------------------------------------------------------===//
// basics
@@ -213,168 +201,6 @@ void DependenceAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
namespace {
-/// The property of monotonicity of a SCEV. To define the monotonicity, assume
-/// a SCEV defined within N-nested loops. Let i_k denote the iteration number
-/// of the k-th loop. Then we can regard the SCEV as an N-ary function:
-///
-/// F(i_1, i_2, ..., i_N)
-///
-/// The domain of i_k is the closed range [0, BTC_k], where BTC_k is the
-/// backedge-taken count of the k-th loop.
-///
-/// A function F is said to be "monotonically increasing with respect to the
-/// k-th loop" if x <= y implies the following condition:
-///
-/// F(i_1, ..., i_{k-1}, x, i_{k+1}, ..., i_N) <=
-/// F(i_1, ..., i_{k-1}, y, i_{k+1}, ..., i_N)
-///
-/// where i_1, ..., i_{k-1}, i_{k+1}, ..., i_N, x, and y are elements of their
-/// respective domains.
-///
-/// Likewise F is "monotonically decreasing with respect to the k-th loop"
-/// if x <= y implies
-///
-/// F(i_1, ..., i_{k-1}, x, i_{k+1}, ..., i_N) >=
-/// F(i_1, ..., i_{k-1}, y, i_{k+1}, ..., i_N)
-///
-/// A function F that is monotonically increasing or decreasing with respect to
-/// the k-th loop is simply called "monotonic with respect to k-th loop".
-///
-/// A function F is said to be "multivariate monotonic" when it is monotonic
-/// with respect to all of the N loops.
-///
-/// Since integer comparison can be either signed or unsigned, we need to
-/// distinguish monotonicity in the signed sense from that in the unsigned
-/// sense. Note that the inequality "x <= y" merely indicates loop progression
-/// and is not affected by the difference between signed and unsigned order.
-///
-/// Currently we only consider monotonicity in a signed sense.
-enum class SCEVMonotonicityType {
- /// We don't know anything about the monotonicity of the SCEV.
- Unknown,
-
- /// The SCEV is loop-invariant with respect to the outermost loop. In other
- /// words, the function F corresponding to the SCEV is a constant function.
- Invariant,
-
- /// The function F corresponding to the SCEV is multivariate monotonic in a
- /// signed sense. Note that the multivariate monotonic function may also be a
- /// constant function. The order employed in the definition of monotonicity
- /// is not strict order.
- MultivariateSignedMonotonic,
-};
-
-struct SCEVMonotonicity {
- SCEVMonotonicity(SCEVMonotonicityType Type,
- const SCEV *FailurePoint = nullptr);
-
- SCEVMonotonicityType getType() const { return Type; }
-
- const SCEV *getFailurePoint() const { return FailurePoint; }
-
- bool isUnknown() const { return Type == SCEVMonotonicityType::Unknown; }
-
- void print(raw_ostream &OS, unsigned Depth) const;
-
-private:
- SCEVMonotonicityType Type;
-
- /// The subexpression that caused Unknown. Mainly for debugging purpose.
- const SCEV *FailurePoint;
-};
-
-/// Check the monotonicity of a SCEV. Since dependence tests (SIV, MIV, etc.)
-/// assume that subscript expressions are (multivariate) monotonic, we need to
-/// verify this property before applying those tests. Violating this assumption
-/// may cause them to produce incorrect results.
-struct SCEVMonotonicityChecker
- : public SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity> {
-
- SCEVMonotonicityChecker(ScalarEvolution *SE) : SE(SE) {}
-
- /// Check the monotonicity of \p Expr. \p Expr must be integer type. If \p
- /// OutermostLoop is not null, \p Expr must be defined in \p OutermostLoop or
- /// one of its nested loops.
- SCEVMonotonicity checkMonotonicity(const SCEV *Expr,
- const Loop *OutermostLoop);
-
-private:
- ScalarEvolution *SE;
-
- /// The outermost loop that DA is analyzing.
- const Loop *OutermostLoop;
-
- /// A helper to classify \p Expr as either Invariant or Unknown.
- SCEVMonotonicity invariantOrUnknown(const SCEV *Expr);
-
- /// Return true if \p Expr is loop-invariant with respect to the outermost
- /// loop.
- bool isLoopInvariant(const SCEV *Expr) const;
-
- /// A helper to create an Unknown SCEVMonotonicity.
- SCEVMonotonicity createUnknown(const SCEV *FailurePoint) {
- return SCEVMonotonicity(SCEVMonotonicityType::Unknown, FailurePoint);
- }
-
- SCEVMonotonicity visitAddRecExpr(const SCEVAddRecExpr *Expr);
-
- SCEVMonotonicity visitConstant(const SCEVConstant *) {
- return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
- }
- SCEVMonotonicity visitVScale(const SCEVVScale *) {
- return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
- }
-
- // TODO: Handle more cases.
- SCEVMonotonicity visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitAddExpr(const SCEVAddExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitMulExpr(const SCEVMulExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitPtrToAddrExpr(const SCEVPtrToAddrExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitPtrToIntExpr(const SCEVPtrToIntExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitTruncateExpr(const SCEVTruncateExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitUDivExpr(const SCEVUDivExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitSMaxExpr(const SCEVSMaxExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitUMaxExpr(const SCEVUMaxExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitSMinExpr(const SCEVSMinExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitUMinExpr(const SCEVUMinExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitUnknown(const SCEVUnknown *Expr) {
- return invariantOrUnknown(Expr);
- }
- SCEVMonotonicity visitCouldNotCompute(const SCEVCouldNotCompute *Expr) {
- return invariantOrUnknown(Expr);
- }
-
- friend struct SCEVVisitor<SCEVMonotonicityChecker, SCEVMonotonicity>;
-};
-
/// A wrapper class for std::optional<APInt> that provides arithmetic operators
/// with overflow checking in a signed sense. This allows us to omit inserting
/// an overflow check at every arithmetic operation, which simplifies the code
@@ -475,25 +301,6 @@ static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA,
bool NormalizeResults) {
auto *F = DA->getFunction();
- if (DumpMonotonicityReport) {
- SCEVMonotonicityChecker Checker(&SE);
- OS << "Monotonicity check:\n";
- for (Instruction &Inst : instructions(F)) {
- if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst))
- continue;
- Value *Ptr = getLoadStorePointerOperand(&Inst);
- const Loop *L = LI.getLoopFor(Inst.getParent());
- const Loop *OutermostLoop = L ? L->getOutermostLoop() : nullptr;
- const SCEV *PtrSCEV = SE.getSCEVAtScope(Ptr, L);
- const SCEV *AccessFn = SE.removePointerBase(PtrSCEV);
- SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
- OS.indent(2) << "Inst: " << Inst << "\n";
- OS.indent(4) << "Expr: " << *AccessFn << "\n";
- Mon.print(OS, 4);
- }
- OS << "\n";
- }
-
for (inst_iterator SrcI = inst_begin(F), SrcE = inst_end(F); SrcI != SrcE;
++SrcI) {
if (SrcI->mayReadOrWriteMemory()) {
@@ -678,83 +485,6 @@ bool FullDependence::inSameSDLoops(unsigned Level) const {
return Level > Levels;
}
-//===----------------------------------------------------------------------===//
-// SCEVMonotonicity
-
-SCEVMonotonicity::SCEVMonotonicity(SCEVMonotonicityType Type,
- const SCEV *FailurePoint)
- : Type(Type), FailurePoint(FailurePoint) {
- assert(
- ((Type == SCEVMonotonicityType::Unknown) == (FailurePoint != nullptr)) &&
- "FailurePoint must be provided iff Type is Unknown");
-}
-
-void SCEVMonotonicity::print(raw_ostream &OS, unsigned Depth) const {
- OS.indent(Depth) << "Monotonicity: ";
- switch (Type) {
- case SCEVMonotonicityType::Unknown:
- assert(FailurePoint && "FailurePoint must be provided for Unknown");
- OS << "Unknown\n";
- OS.indent(Depth) << "Reason: " << *FailurePoint << "\n";
- break;
- case SCEVMonotonicityType::Invariant:
- OS << "Invariant\n";
- break;
- case SCEVMonotonicityType::MultivariateSignedMonotonic:
- OS << "MultivariateSignedMonotonic\n";
- break;
- }
-}
-
-bool SCEVMonotonicityChecker::isLoopInvariant(const SCEV *Expr) const {
- return !OutermostLoop || SE->isLoopInvariant(Expr, OutermostLoop);
-}
-
-SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(const SCEV *Expr) {
- if (isLoopInvariant(Expr))
- return SCEVMonotonicity(SCEVMonotonicityType::Invariant);
- return createUnknown(Expr);
-}
-
-SCEVMonotonicity
-SCEVMonotonicityChecker::checkMonotonicity(const SCEV *Expr,
- const Loop *OutermostLoop) {
- assert((!OutermostLoop || OutermostLoop->isOutermost()) &&
- "OutermostLoop must be outermost");
- assert(Expr->getType()->isIntegerTy() && "Expr must be integer type");
- this->OutermostLoop = OutermostLoop;
- return visit(Expr);
-}
-
-/// We only care about an affine AddRec at the moment. For an affine AddRec,
-/// the monotonicity can be inferred from its nowrap property. For example, let
-/// X and Y be loop-invariant, and assume Y is non-negative. An AddRec
-/// {X,+.Y}<nsw> implies:
-///
-/// X <=s (X + Y) <=s ((X + Y) + Y) <=s ...
-///
-/// Thus, we can conclude that the AddRec is monotonically increasing with
-/// respect to the associated loop in a signed sense. The similar reasoning
-/// applies when Y is non-positive, leading to a monotonically decreasing
-/// AddRec.
-SCEVMonotonicity
-SCEVMonotonicityChecker::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
- if (!Expr->isAffine() || !Expr->hasNoSignedWrap())
- return createUnknown(Expr);
-
- const SCEV *Start = Expr->getStart();
- const SCEV *Step = Expr->getStepRecurrence(*SE);
-
- SCEVMonotonicity StartMon = visit(Start);
- if (StartMon.isUnknown())
- return StartMon;
-
- if (!isLoopInvariant(Step))
- return createUnknown(Expr);
-
- return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
-}
-
//===----------------------------------------------------------------------===//
// DependenceInfo methods
@@ -2751,21 +2481,12 @@ bool DependenceInfo::tryDelinearize(Instruction *Src, Instruction *Dst,
// resize Pair to contain as many pairs of subscripts as the delinearization
// has found, and then initialize the pairs following the delinearization.
Pair.resize(Size);
- SCEVMonotonicityChecker MonChecker(SE);
- const Loop *OutermostLoop = SrcLoop ? SrcLoop->getOutermostLoop() : nullptr;
for (int I = 0; I < Size; ++I) {
Pair[I].Src = SrcSubscripts[I];
Pair[I].Dst = DstSubscripts[I];
assert(Pair[I].Src->getType() == Pair[I].Dst->getType() &&
"Unexpected different types for the subscripts");
-
- if (EnableMonotonicityCheck) {
- if (MonChecker.checkMonotonicity(Pair[I].Src, OutermostLoop).isUnknown())
- return false;
- if (MonChecker.checkMonotonicity(Pair[I].Dst, OutermostLoop).isUnknown())
- return false;
- }
}
return true;
@@ -3024,15 +2745,6 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
SmallVector<Subscript, 2> Pair(Pairs);
Pair[0].Src = SrcEv;
Pair[0].Dst = DstEv;
-
- SCEVMonotonicityChecker MonChecker(SE);
- const Loop *OutermostLoop = SrcLoop ? SrcLoop->getOutermostLoop() : nullptr;
- if (EnableMonotonicityCheck)
- if (MonChecker.checkMonotonicity(Pair[0].Src, OutermostLoop).isUnknown() ||
- MonChecker.checkMonotonicity(Pair[0].Dst, OutermostLoop).isUnknown())
- return std::make_unique<Dependence>(Src, Dst,
- SCEVUnionPredicate(Assume, *SE));
-
if (Delinearize) {
if (tryDelinearize(Src, Dst, Pair)) {
LLVM_DEBUG(dbgs() << " delinearized\n");
diff --git a/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll b/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
deleted file mode 100644
index 90da99c32ac17..0000000000000
--- a/llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll
+++ /dev/null
@@ -1,209 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
-; RUN: opt < %s -disable-output -passes="print<da>" -da-dump-monotonicity-report \
-; RUN: -da-enable-monotonicity-check 2>&1 | FileCheck %s
-
-; 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)}<nsw><%loop>
-; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
-; 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 [0]!
-; CHECK-NEXT: Runtime Assumptions:
-; CHECK-NEXT: Compare predicate: (sext i8 %step to i64) ne) 0
-;
-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: (sext i8 {%start,+,%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 [ %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}<nuw><nsw><%loop>
-; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
-; 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}<nsw><%loop> to i64)
-; CHECK-NEXT: Monotonicity: Unknown
-; CHECK-NEXT: Reason: (zext i8 {-1,+,1}<nsw><%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
-}
-
-; In principle, we can prove that `zext(offset)` is monotonic since we know
-; that `offset` is non-negative.
-;
-; 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}<nsw><%loop> to i64)
-; CHECK-NEXT: Monotonicity: Unknown
-; CHECK-NEXT: Reason: (zext i8 {0,+,%step}<nsw><%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
-}
-
-; SCEV handles `i & 1` as an i1 addrec. Ensure that the monotonicity analysis
-; properly analyzes it.
-;
-; for (i = 0; i < 100; i++)
-; a[i & 1] = 0;
-;
-define void @offset_truncated_to_i1(ptr %a) {
-; CHECK-LABEL: 'offset_truncated_to_i1'
-; CHECK-NEXT: Monotonicity check:
-; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
-; CHECK-NEXT: Expr: (zext i1 {false,+,true}<%loop> to i64)
-; CHECK-NEXT: Monotonicity: Unknown
-; CHECK-NEXT: Reason: (zext i1 {false,+,true}<%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 ]
- %and = and i64 %i, 1
- %idx = getelementptr inbounds i8, ptr %a, i64 %and
- store i8 0, ptr %idx
- %i.inc = add nsw i64 %i, 1
- %exitcond = icmp eq i64 %i.inc, 100
- br i1 %exitcond, label %exit, label %loop
-
-exit:
- ret void
-}
diff --git a/llvm/test/Analysis/Depe...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/193697
More information about the llvm-commits
mailing list