Skip to content

Commit edf56f1

Browse files
authored
[LoopInterchange] Don't rely on ASSERTS build for tests. NFC. (#116780)
A lot of interchange tests unnecessary relied on a build with ASSERTS enabled. Instead, simply check the IR output for both negative and positive tests so that we don't rely on debug messages. This increases test coverage as these tests will now also run with non-assert builds. For a couple of files keeping some of the debug tests was useful, so separated out them out and moved them to a similarly named *-remarks.ll file.
1 parent a874406 commit edf56f1

11 files changed

+691
-308
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; REQUIRES: asserts
2+
; RUN: opt < %s -passes=loop-interchange -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
3+
; RUN: -verify-dom-info -verify-loop-info 2>&1
4+
; RUN: FileCheck --input-file=%t %s
5+
6+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7+
8+
@A = common global [100 x [100 x i32]] zeroinitializer
9+
10+
declare void @foo(i64 %a)
11+
declare void @bar(i64 %a) readnone
12+
13+
;;--------------------------------------Test case 01------------------------------------
14+
;; Not safe to interchange, because the called function `foo` is not marked as
15+
;; readnone, so it could introduce dependences.
16+
;;
17+
;; for(int i=0;i<100;i++) {
18+
;; for(int j=1;j<100;j++) {
19+
;; foo(i);
20+
;; A[j][i] = A[j][i]+k;
21+
;; }
22+
;; }
23+
24+
; CHECK: --- !Missed
25+
; CHECK-NEXT: Pass: loop-interchange
26+
; CHECK-NEXT: Name: CallInst
27+
; CHECK-NEXT: Function: interchange_01
28+
; CHECK-NEXT: Args:
29+
; CHECK-NEXT: - String: Cannot interchange loops due to call instruction.
30+
31+
define void @interchange_01(i32 %k) {
32+
entry:
33+
br label %for1.header
34+
35+
for1.header:
36+
%indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc10 ]
37+
br label %for2
38+
39+
for2:
40+
%indvars.iv = phi i64 [ %indvars.iv.next, %for2 ], [ 1, %for1.header ]
41+
call void @foo(i64 %indvars.iv23)
42+
%arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %indvars.iv, i64 %indvars.iv23
43+
%lv = load i32, ptr %arrayidx5
44+
%add = add nsw i32 %lv, %k
45+
store i32 %add, ptr %arrayidx5
46+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
47+
%exitcond = icmp eq i64 %indvars.iv, 99
48+
br i1 %exitcond, label %for2.loopexit , label %for2
49+
50+
for2.loopexit:
51+
br label %for1.inc10
52+
53+
for1.inc10:
54+
%indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
55+
%exitcond26 = icmp eq i64 %indvars.iv23, 99
56+
br i1 %exitcond26, label %for1.loopexit, label %for1.header
57+
58+
for1.loopexit:
59+
br label %exit
60+
61+
exit:
62+
ret void
63+
}
Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
; REQUIRES: asserts
2-
; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t -S \
3-
; RUN: -verify-dom-info -verify-loop-info -stats 2>&1 | FileCheck -check-prefix=STATS %s
4-
; RUN: FileCheck --input-file=%t %s
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=loop-interchange -S -verify-dom-info -verify-loop-info 2>&1 | FileCheck %s
53

64
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
75

@@ -10,58 +8,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
108
declare void @foo(i64 %a)
119
declare void @bar(i64 %a) readnone
1210

13-
;;--------------------------------------Test case 01------------------------------------
14-
;; Not safe to interchange, because the called function `foo` is not marked as
15-
;; readnone, so it could introduce dependences.
16-
;;
17-
;; for(int i=0;i<100;i++) {
18-
;; for(int j=1;j<100;j++) {
19-
;; foo(i);
20-
;; A[j][i] = A[j][i]+k;
21-
;; }
22-
;; }
23-
24-
; CHECK: --- !Missed
25-
; CHECK-NEXT: Pass: loop-interchange
26-
; CHECK-NEXT: Name: CallInst
27-
; CHECK-NEXT: Function: interchange_01
28-
; CHECK-NEXT: Args:
29-
; CHECK-NEXT: - String: Cannot interchange loops due to call instruction.
30-
31-
define void @interchange_01(i32 %k) {
32-
entry:
33-
br label %for1.header
34-
35-
for1.header:
36-
%indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc10 ]
37-
br label %for2
38-
39-
for2:
40-
%indvars.iv = phi i64 [ %indvars.iv.next, %for2 ], [ 1, %for1.header ]
41-
call void @foo(i64 %indvars.iv23)
42-
%arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %indvars.iv, i64 %indvars.iv23
43-
%lv = load i32, ptr %arrayidx5
44-
%add = add nsw i32 %lv, %k
45-
store i32 %add, ptr %arrayidx5
46-
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
47-
%exitcond = icmp eq i64 %indvars.iv, 99
48-
br i1 %exitcond, label %for2.loopexit , label %for2
49-
50-
for2.loopexit:
51-
br label %for1.inc10
52-
53-
for1.inc10:
54-
%indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
55-
%exitcond26 = icmp eq i64 %indvars.iv23, 99
56-
br i1 %exitcond26, label %for1.loopexit, label %for1.header
57-
58-
for1.loopexit:
59-
br label %exit
60-
61-
exit:
62-
ret void
63-
}
64-
6511
;;--------------------------------------Test case 02------------------------------------
6612
;; Safe to interchange, because the called function `bar` is marked as readnone,
6713
;; so it cannot introduce dependences.
@@ -72,16 +18,46 @@ exit:
7218
;; A[j][i] = A[j][i]+k;
7319
;; }
7420
;; }
75-
76-
; CHECK: --- !Passed
77-
; CHECK-NEXT: Pass: loop-interchange
78-
; CHECK-NEXT: Name: Interchanged
79-
; CHECK-NEXT: Function: interchange_02
80-
; CHECK-NEXT: Args:
81-
; CHECK-NEXT: - String: Loop interchanged with enclosing loop.
82-
; CHECK-NEXT: ...
83-
21+
;
8422
define void @interchange_02(i32 %k) {
23+
; CHECK-LABEL: define void @interchange_02(
24+
; CHECK-SAME: i32 [[K:%.*]]) {
25+
; CHECK-NEXT: [[ENTRY:.*:]]
26+
; CHECK-NEXT: br label %[[FOR2_PREHEADER:.*]]
27+
; CHECK: [[FOR1_HEADER_PREHEADER:.*]]:
28+
; CHECK-NEXT: br label %[[FOR1_HEADER:.*]]
29+
; CHECK: [[FOR1_HEADER]]:
30+
; CHECK-NEXT: [[INDVARS_IV23:%.*]] = phi i64 [ [[INDVARS_IV_NEXT24:%.*]], %[[FOR1_INC10:.*]] ], [ 0, %[[FOR1_HEADER_PREHEADER]] ]
31+
; CHECK-NEXT: br label %[[FOR2_SPLIT1:.*]]
32+
; CHECK: [[FOR2_PREHEADER]]:
33+
; CHECK-NEXT: br label %[[FOR2:.*]]
34+
; CHECK: [[FOR2]]:
35+
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0:%.*]], %[[FOR2_SPLIT:.*]] ], [ 1, %[[FOR2_PREHEADER]] ]
36+
; CHECK-NEXT: br label %[[FOR1_HEADER_PREHEADER]]
37+
; CHECK: [[FOR2_SPLIT1]]:
38+
; CHECK-NEXT: call void @bar(i64 [[INDVARS_IV23]])
39+
; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 [[INDVARS_IV]], i64 [[INDVARS_IV23]]
40+
; CHECK-NEXT: [[LV:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4
41+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LV]], [[K]]
42+
; CHECK-NEXT: store i32 [[ADD]], ptr [[ARRAYIDX5]], align 4
43+
; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV]], 1
44+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV]], 99
45+
; CHECK-NEXT: br label %[[FOR2_LOOPEXIT:.*]]
46+
; CHECK: [[FOR2_SPLIT]]:
47+
; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[INDVARS_IV]], 1
48+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[INDVARS_IV]], 99
49+
; CHECK-NEXT: br i1 [[TMP1]], label %[[FOR1_LOOPEXIT:.*]], label %[[FOR2]]
50+
; CHECK: [[FOR2_LOOPEXIT]]:
51+
; CHECK-NEXT: br label %[[FOR1_INC10]]
52+
; CHECK: [[FOR1_INC10]]:
53+
; CHECK-NEXT: [[INDVARS_IV_NEXT24]] = add nuw nsw i64 [[INDVARS_IV23]], 1
54+
; CHECK-NEXT: [[EXITCOND26:%.*]] = icmp eq i64 [[INDVARS_IV23]], 99
55+
; CHECK-NEXT: br i1 [[EXITCOND26]], label %[[FOR2_SPLIT]], label %[[FOR1_HEADER]]
56+
; CHECK: [[FOR1_LOOPEXIT]]:
57+
; CHECK-NEXT: br label %[[EXIT:.*]]
58+
; CHECK: [[EXIT]]:
59+
; CHECK-NEXT: ret void
60+
;
8561
entry:
8662
br label %for1.header
8763

@@ -114,6 +90,3 @@ for1.loopexit:
11490
exit:
11591
ret void
11692
}
117-
118-
; Check stats, we interchanged 1 out of 2 loops.
119-
; STATS: 1 loop-interchange - Number of loops interchanged
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
; REQUIRES: asserts
2+
; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info -S -debug 2>&1 | FileCheck %s
3+
4+
@A = common global [100 x [100 x i64]] zeroinitializer
5+
@N = dso_local local_unnamed_addr global i64 100, align 8
6+
7+
; for(int i=0;i<100;i++)
8+
; for(int j=0;j<i;j++)
9+
; A[j][i] = A[j][i]+k;
10+
;
11+
; Inner loop induction variable exit condition depends on the
12+
; outer loop induction variable, i.e., triangular loops.
13+
;
14+
; CHECK: Loop structure not understood by pass
15+
; CHECK: Not interchanging loops. Cannot prove legality.
16+
;
17+
define void @interchange_01(i64 %k) {
18+
entry:
19+
br label %for1.header
20+
21+
for1.header:
22+
%i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
23+
br label %for2
24+
25+
for2:
26+
%j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
27+
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
28+
%lv = load i64, ptr %arrayidx5
29+
%add = add nsw i64 %lv, %k
30+
store i64 %add, ptr %arrayidx5
31+
%j.next = add nuw nsw i64 %j, 1
32+
%exitcond = icmp eq i64 %j, %i
33+
br i1 %exitcond, label %for1.inc10, label %for2
34+
35+
for1.inc10:
36+
%i.next = add nuw nsw i64 %i, 1
37+
%exitcond26 = icmp eq i64 %i, 99
38+
br i1 %exitcond26, label %for.end12, label %for1.header
39+
40+
for.end12:
41+
ret void
42+
}
43+
44+
45+
; for(int i=0;i<100;i++)
46+
; for(int j=0;j+i<100;j++)
47+
; A[j][i] = A[j][i]+k;
48+
;
49+
; Inner loop induction variable exit condition depends on the
50+
; outer loop induction variable, i.e., triangular loops.
51+
;
52+
; CHECK: Loop structure not understood by pass
53+
; CHECK: Not interchanging loops. Cannot prove legality.
54+
;
55+
define void @interchange_02(i64 %k) {
56+
entry:
57+
br label %for1.header
58+
59+
for1.header:
60+
%i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
61+
br label %for2
62+
63+
for2:
64+
%j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
65+
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
66+
%lv = load i64, ptr %arrayidx5
67+
%add = add nsw i64 %lv, %k
68+
store i64 %add, ptr %arrayidx5
69+
%0 = add nuw nsw i64 %j, %i
70+
%j.next = add nuw nsw i64 %j, 1
71+
%exitcond = icmp eq i64 %0, 100
72+
br i1 %exitcond, label %for1.inc10, label %for2
73+
74+
for1.inc10:
75+
%i.next = add nuw nsw i64 %i, 1
76+
%exitcond26 = icmp eq i64 %i, 99
77+
br i1 %exitcond26, label %for.end12, label %for1.header
78+
79+
for.end12:
80+
ret void
81+
}
82+
83+
; for(int i=0;i<100;i++)
84+
; for(int j=0;i>j;j++)
85+
; A[j][i] = A[j][i]+k;
86+
;
87+
; Inner loop induction variable exit condition depends on the
88+
; outer loop induction variable, i.e., triangular loops.
89+
; CHECK: Loop structure not understood by pass
90+
; CHECK: Not interchanging loops. Cannot prove legality.
91+
;
92+
define void @interchange_03(i64 %k) {
93+
entry:
94+
br label %for1.header
95+
96+
for1.header:
97+
%i = phi i64 [ 0, %entry ], [ %i.next, %for1.inc10 ]
98+
br label %for2
99+
100+
for2:
101+
%j = phi i64 [ %j.next, %for2 ], [ 0, %for1.header ]
102+
%arrayidx5 = getelementptr inbounds [100 x [100 x i64]], ptr @A, i64 0, i64 %j, i64 %i
103+
%lv = load i64, ptr %arrayidx5
104+
%add = add nsw i64 %lv, %k
105+
store i64 %add, ptr %arrayidx5
106+
%j.next = add nuw nsw i64 %j, 1
107+
%exitcond = icmp ne i64 %i, %j
108+
br i1 %exitcond, label %for2, label %for1.inc10
109+
110+
for1.inc10:
111+
%i.next = add nuw nsw i64 %i, 1
112+
%exitcond26 = icmp eq i64 %i, 99
113+
br i1 %exitcond26, label %for.end12, label %for1.header
114+
115+
for.end12:
116+
ret void
117+
}

0 commit comments

Comments
 (0)