Skip to content

Commit aceb708

Browse files
committed
revise the definition of monotonicity
1 parent da8859c commit aceb708

File tree

5 files changed

+60
-55
lines changed

5 files changed

+60
-55
lines changed

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -191,52 +191,55 @@ void DependenceAnalysisWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
191191

192192
namespace {
193193

194-
/// The type of monotonicity of a SCEV. This property is defined with respect to
195-
/// the outermost loop that DA is analyzing.
194+
/// The property of monotonicity of a SCEV. To define the monotonicity, assume
195+
/// a SCEV defined within N-nested loops. Let i_k denote the iteration number
196+
/// of the k-th loop. Then we can regard the SCEV as an N-ary function:
196197
///
197-
/// This is designed to classify the behavior of AddRec expressions, and does
198-
/// not care about other SCEVs. For example, given the two loop-invariant values
199-
/// `A` and `B`, `A + B` is treated as Invariant even if the addition wraps.
198+
/// F(i_1, i_2, ..., i_N)
199+
///
200+
/// The domain of i_k is the closed range [0, BTC_k], where BTC_k is the
201+
/// backedge-taken count of the k-th loop.
202+
///
203+
/// A function F is said to be "monotonically increasing with respect to the
204+
/// k-th loop" if x <= y implies the following condition:
205+
///
206+
/// F(i_1, ..., i_{k-1}, x, i_{k+1}, ..., i_N) <=
207+
/// F(i_1, ..., i_{k-1}, y, i_{k+1}, ..., i_N)
208+
///
209+
/// where i_1, ..., i_{k-1}, i_{k+1}, ..., i_N, x, y in their domains.
210+
///
211+
/// Likewise F is "monotonically decreasing with respect to the k-th loop"
212+
/// if x <= y implies
213+
///
214+
/// F(i_1, ..., i_{k-1}, x, i_{k+1}, ..., i_N) >=
215+
/// F(i_1, ..., i_{k-1}, y, i_{k+1}, ..., i_N)
216+
///
217+
/// A function F with either monotonically increasing or decreasing with
218+
/// respect to the k-th loop is simply called
219+
/// "monotonic with respect to k-th loop".
220+
///
221+
/// A function F is said to be "multimonotonic" when it is monotonic with
222+
/// respect to all of the N loops.
223+
///
224+
/// Since integer comparison can be either signed or unsigned, we need to
225+
/// distinguish monotonicity in the signed sense from that in the unsigned
226+
/// sense. Note that the inequality "x <= y" merely indicates loop progression
227+
/// and is not affected by the difference between signed and unsigned order.
228+
///
229+
/// Currently we only consider monotonicity in a signed sense.
200230
enum class SCEVMonotonicityType {
201-
/// The expression is neither loop-invariant nor monotonic (or we fail to
202-
/// prove it).
231+
/// We don't know anything about the monotonicity of the SCEV.
203232
Unknown,
204233

205-
/// The expression is loop-invariant with respect to the outermost loop.
234+
/// The SCEV is loop-invariant with respect to the outermost loop. In other
235+
/// words, the function F corresponding to the SCEV is a constant function.
206236
Invariant,
207237

208-
/// The expression is a (nested) affine AddRec and is monotonically increasing
209-
/// or decreasing in a signed sense with respect to each loop. Monotonicity is
210-
/// checked independently for each loop, and the expression is classified as
211-
/// MultiSignedMonotonic if all AddRecs are nsw. For example, in the following
212-
/// loop:
213-
///
214-
/// for (i = 0; i < 100; i++)
215-
/// for (j = 0; j < 100; j++)
216-
/// A[i + j] = ...;
217-
///
218-
/// The SCEV for `i + j` is classified as MultiSignedMonotonic. On the other
219-
/// hand, in the following loop:
220-
///
221-
/// for (i = 0; i < 100; i++)
222-
/// for (j = 0; j <= (1ULL << 63); j++)
223-
/// A[i + j] = ...;
224-
///
225-
/// The SCEV for `i + j` is NOT classified as MultiMonotonic, because the
226-
/// AddRec for `j` wraps in a signed sense. We don't consider the "direction"
227-
/// of each AddRec. For example, in the following loop:
228-
///
229-
/// for (int i = 0; i < 100; i++)
230-
/// for (int j = 0; j < 100; j++)
231-
/// A[i - j] = ...;
232-
///
233-
/// The SCEV for `i - j` is classified as MultiSignedMonotonic, even though it
234-
/// contains both increasing and decreasing AddRecs.
235-
///
236-
/// Note that we don't check if the step recurrence can be zero. For
237-
/// example,an AddRec `{0,+,%a}<nsw> is classifed as Monotonic if `%a` can be
238-
/// zero. That is, the expression can be Invariant.
239-
MultiSignedMonotonic,
238+
/// The function F corresponding to the SCEV is multimonotonic in a signed
239+
/// sense. Note that the multimonotonic function may also be a constant
240+
/// function. The order employed in the definition of monotonicity is not
241+
/// strict order.
242+
MultivariateSignedMonotonic,
240243
};
241244

242245
struct SCEVMonotonicity {
@@ -881,8 +884,8 @@ void SCEVMonotonicity::print(raw_ostream &OS, unsigned Depth) const {
881884
case SCEVMonotonicityType::Invariant:
882885
OS << "Invariant\n";
883886
break;
884-
case SCEVMonotonicityType::MultiSignedMonotonic:
885-
OS << "MultiSignedMonotonic\n";
887+
case SCEVMonotonicityType::MultivariateSignedMonotonic:
888+
OS << "MultivariateSignedMonotonic\n";
886889
break;
887890
}
888891
}
@@ -905,6 +908,8 @@ SCEVMonotonicityChecker::checkMonotonicity(const SCEV *Expr,
905908
return visit(Expr);
906909
}
907910

911+
/// We only care about an affine AddRec at the moment. For an affine AddRec,
912+
/// the monotonicity can be inferred from its nowrap property.
908913
SCEVMonotonicity
909914
SCEVMonotonicityChecker::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
910915
if (!Expr->isAffine() || !Expr->hasNoSignedWrap())
@@ -920,7 +925,7 @@ SCEVMonotonicityChecker::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
920925
if (!isLoopInvariant(Step))
921926
return createUnknown(Expr);
922927

923-
return SCEVMonotonicity(SCEVMonotonicityType::MultiSignedMonotonic);
928+
return SCEVMonotonicity(SCEVMonotonicityType::MultivariateSignedMonotonic);
924929
}
925930

926931
//===----------------------------------------------------------------------===//

llvm/test/Analysis/DependenceAnalysis/monotonicity-cast.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ define void @sext_nsw(ptr %a, i8 %start, i8 %step) {
1111
; CHECK-NEXT: Monotonicity check:
1212
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
1313
; CHECK-NEXT: Expr: {(sext i8 %start to i64),+,(sext i8 %step to i64)}<nsw><%loop>
14-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
14+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
1515
; CHECK-EMPTY:
1616
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
1717
; CHECK-NEXT: da analyze - none!
@@ -77,7 +77,7 @@ define void @zext_pos(ptr %a) {
7777
; CHECK-NEXT: Monotonicity check:
7878
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
7979
; CHECK-NEXT: Expr: {0,+,1}<nuw><nsw><%loop>
80-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
80+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
8181
; CHECK-EMPTY:
8282
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
8383
; CHECK-NEXT: da analyze - none!

llvm/test/Analysis/DependenceAnalysis/monotonicity-invariant.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ define void @invariant_plus_monotonic0(ptr %a, i64 %x, i64 %n, i64 %m) {
6969
; CHECK-NEXT: Monotonicity check:
7070
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
7171
; CHECK-NEXT: Expr: {%x,+,1}<nsw><%loop.i.header>
72-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
72+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
7373
; CHECK-EMPTY:
7474
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
7575
; CHECK-NEXT: da analyze - consistent output [0 S]!
@@ -113,7 +113,7 @@ define void @invariant_plus_monotonic1(ptr %a, i64 %x, i64 %n, i64 %m) {
113113
; CHECK-NEXT: Monotonicity check:
114114
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
115115
; CHECK-NEXT: Expr: {%x,+,1}<nsw><%loop.j>
116-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
116+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
117117
; CHECK-EMPTY:
118118
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
119119
; CHECK-NEXT: da analyze - consistent output [S 0]!

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ define void @single_loop_nsw(ptr %a, i64 %n) {
1010
; CHECK-NEXT: Monotonicity check:
1111
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
1212
; CHECK-NEXT: Expr: {0,+,1}<nuw><nsw><%loop>
13-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
13+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
1414
; CHECK-EMPTY:
1515
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
1616
; CHECK-NEXT: da analyze - none!
@@ -73,7 +73,7 @@ define void @nested_loop_nsw0(ptr %a, i64 %n, i64 %m) {
7373
; CHECK-NEXT: Monotonicity check:
7474
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
7575
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j>
76-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
76+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
7777
; CHECK-EMPTY:
7878
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
7979
; CHECK-NEXT: da analyze - output [* *]!
@@ -117,7 +117,7 @@ define void @nested_loop_nsw1(ptr %a, i64 %n, i64 %m) {
117117
; CHECK-NEXT: Monotonicity check:
118118
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
119119
; CHECK-NEXT: Expr: {{\{\{}}(-1 + %n),+,-1}<nsw><%loop.i.header>,+,1}<nsw><%loop.j>
120-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
120+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
121121
; CHECK-EMPTY:
122122
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
123123
; CHECK-NEXT: da analyze - output [* *]!
@@ -161,7 +161,7 @@ define void @nested_loop_nsw2(ptr %a, i64 %n, i64 %m) {
161161
; CHECK-NEXT: Monotonicity check:
162162
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
163163
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,-1}<nsw><%loop.j>
164-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
164+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
165165
; CHECK-EMPTY:
166166
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
167167
; CHECK-NEXT: da analyze - output [* *]!
@@ -260,7 +260,7 @@ define void @nested_loop_step(ptr %a, i64 %n, i64 %m, i64 %step) {
260260
; CHECK-NEXT: Monotonicity check:
261261
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
262262
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,%step}<nsw><%loop.j>
263-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
263+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
264264
; CHECK-EMPTY:
265265
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
266266
; CHECK-NEXT: da analyze - output [* *]!
@@ -312,7 +312,7 @@ define void @step_is_variant(ptr %a) {
312312
; CHECK-NEXT: Monotonicity check:
313313
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
314314
; CHECK-NEXT: Expr: {%offset.i,+,1}<nuw><nsw><%loop.j>
315-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
315+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
316316
; CHECK-EMPTY:
317317
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
318318
; CHECK-NEXT: da analyze - confused!
@@ -415,7 +415,7 @@ define void @conditional_store1(ptr %a, i64 %n, i64 %m) {
415415
; CHECK-NEXT: Monotonicity check:
416416
; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
417417
; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j.header>
418-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
418+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
419419
; CHECK-EMPTY:
420420
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
421421
; CHECK-NEXT: da analyze - output [* *]!

llvm/test/Analysis/DependenceAnalysis/non-monotonic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ define void @f(ptr %A) {
2929
; CHECK-NEXT: Monotonicity check:
3030
; CHECK-NEXT: Inst: store i8 1, ptr %idx.0, align 1
3131
; CHECK-NEXT: Expr: {0,+,1}<nuw><nsw><%loop.header>
32-
; CHECK-NEXT: Monotonicity: MultiSignedMonotonic
32+
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
3333
; CHECK-NEXT: Inst: store i8 2, ptr %idx.1, align 1
3434
; CHECK-NEXT: Expr: {4611686018427387904,+,32}<%loop.header>
3535
; CHECK-NEXT: Monotonicity: Unknown

0 commit comments

Comments
 (0)