Skip to content

Commit 9e341b3

Browse files
authored
[DA] Properly pass outermost loop to monotonicity checker (#166928)
This patch fixes the unexpected result in monotonicity check for `@step_is_variant` in `monotonicity-no-wrap-flags.ll`. Currently, the SCEV is considered non-monotonic if it contains an expression which is neither loop-invariant nor an affine addrec. In `@step_is_variant`, the `offset_i` satisfies this condition, but `offset_i + j` was classified as monotonic. The root cause is that a non-outermost loop was passed to monotonicity checker instead of the outermost one. This patch ensures that the correct outermost loop is passed.
1 parent cce1055 commit 9e341b3

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,10 @@ static void dumpExampleDependence(raw_ostream &OS, DependenceInfo *DA,
407407
continue;
408408
Value *Ptr = getLoadStorePointerOperand(&Inst);
409409
const Loop *L = LI.getLoopFor(Inst.getParent());
410+
const Loop *OutermostLoop = L ? L->getOutermostLoop() : nullptr;
410411
const SCEV *PtrSCEV = SE.getSCEVAtScope(Ptr, L);
411412
const SCEV *AccessFn = SE.removePointerBase(PtrSCEV);
412-
SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, L);
413+
SCEVMonotonicity Mon = Checker.checkMonotonicity(AccessFn, OutermostLoop);
413414
OS.indent(2) << "Inst: " << Inst << "\n";
414415
OS.indent(4) << "Expr: " << *AccessFn << "\n";
415416
Mon.print(OS, 4);
@@ -945,6 +946,8 @@ SCEVMonotonicity SCEVMonotonicityChecker::invariantOrUnknown(const SCEV *Expr) {
945946
SCEVMonotonicity
946947
SCEVMonotonicityChecker::checkMonotonicity(const SCEV *Expr,
947948
const Loop *OutermostLoop) {
949+
assert((!OutermostLoop || OutermostLoop->isOutermost()) &&
950+
"OutermostLoop must be outermost");
948951
assert(Expr->getType()->isIntegerTy() && "Expr must be integer type");
949952
this->OutermostLoop = OutermostLoop;
950953
return visit(Expr);

llvm/test/Analysis/DependenceAnalysis/monotonicity-no-wrap-flags.ll

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,8 @@ exit:
298298
}
299299

300300
; The value of step reccurence is not invariant with respect to the outer most
301-
; loop (the i-loop).
301+
; loop (the i-loop). It is theoretically multivariate monotonic by definition,
302+
; but we cannot handle non-affine addrec for now.
302303
;
303304
; offset_i = 0;
304305
; for (int i = 0; i < 100; i++) {
@@ -312,7 +313,8 @@ define void @step_is_variant(ptr %a) {
312313
; CHECK-NEXT: Monotonicity check:
313314
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
314315
; CHECK-NEXT: Expr: {%offset.i,+,1}<nuw><nsw><%loop.j>
315-
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
316+
; CHECK-NEXT: Monotonicity: Unknown
317+
; CHECK-NEXT: Reason: %offset.i
316318
; CHECK-EMPTY:
317319
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
318320
; CHECK-NEXT: da analyze - confused!
@@ -346,6 +348,56 @@ exit:
346348
ret void
347349
}
348350

351+
; The value of step reccurence is not invariant with respect to the outer most
352+
; loop (the i-loop). Actually, `offset_i` is not monotonic.
353+
;
354+
; offset_i = 0;
355+
; for (int i = 0; i < 100; i++) {
356+
; for (int j = 0; j < 100; j++)
357+
; a[offset_i + j] = 0;
358+
; offset_i += (i % 2 == 0) ? -1 : 3;
359+
; }
360+
;
361+
define void @step_is_variant2(ptr %a) {
362+
; CHECK-LABEL: 'step_is_variant2'
363+
; CHECK-NEXT: Monotonicity check:
364+
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
365+
; CHECK-NEXT: Expr: {%offset.i,+,1}<nsw><%loop.j>
366+
; CHECK-NEXT: Monotonicity: Unknown
367+
; CHECK-NEXT: Reason: %offset.i
368+
; CHECK-EMPTY:
369+
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
370+
; CHECK-NEXT: da analyze - confused!
371+
;
372+
entry:
373+
br label %loop.i.header
374+
375+
loop.i.header:
376+
%i = phi i64 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
377+
%offset.i = phi i64 [ 0, %entry ], [ %offset.i.next, %loop.i.latch ]
378+
%step.i.0 = phi i64 [ -1, %entry ], [ %step.i.1, %loop.i.latch ]
379+
%step.i.1 = phi i64 [ 3, %entry ], [ %step.i.0, %loop.i.latch ]
380+
br label %loop.j
381+
382+
loop.j:
383+
%j = phi i64 [ 0, %loop.i.header ], [ %j.inc, %loop.j ]
384+
%offset = add nsw i64 %offset.i, %j
385+
%idx = getelementptr inbounds i8, ptr %a, i64 %offset
386+
store i8 0, ptr %idx
387+
%j.inc = add nsw i64 %j, 1
388+
%exitcond.j = icmp eq i64 %j.inc, 100
389+
br i1 %exitcond.j, label %loop.i.latch, label %loop.j
390+
391+
loop.i.latch:
392+
%i.inc = add nsw i64 %i, 1
393+
%offset.i.next = add nsw i64 %offset.i, %step.i.0
394+
%exitcond.i = icmp eq i64 %i.inc, 100
395+
br i1 %exitcond.i, label %exit, label %loop.i.header
396+
397+
exit:
398+
ret void
399+
}
400+
349401
; The AddRec doesn't have nsw flag for the j-loop, since the store may not be
350402
; executed.
351403
;

0 commit comments

Comments
 (0)