Skip to content

Commit cb64c3c

Browse files
authored
[LoopInterchange] Precommit tests for scalar dependencies. NFC. (#115900)
We are miscompiling and incorrectly interchanging loops with scalar dependencies that are live-out and conditionally set. This precommits some tests demonstrating this. This is based on the tests in https://reviews.llvm.org/D87879 by `mdchen`.
1 parent 2aa6ced commit cb64c3c

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=loop-interchange -S | FileCheck %s
3+
4+
@f = dso_local local_unnamed_addr global [4 x [9 x i32]] [[9 x i32] [i32 5, i32 3, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], [9 x i32] zeroinitializer, [9 x i32] zeroinitializer, [9 x i32] zeroinitializer], align 4
5+
@g = common dso_local local_unnamed_addr global i32 0, align 4
6+
7+
; int32_t f[3][3];
8+
; int32_t g;
9+
;
10+
; int32_t test1(_Bool cond) {
11+
; for (int64_t i = 0; i < 3; i++) {
12+
; for (int64_t j = 0; j < 3; j++) {
13+
; int32_t val = f[i][j];
14+
; if (val == 0)
15+
; if (!cond)
16+
; g++;
17+
; else
18+
; g = 3;
19+
; if (!cond)
20+
; g++;
21+
; }
22+
; }
23+
; return g;
24+
; }
25+
;
26+
; FIXME: if there's an output dependency inside the loop and Src doesn't
27+
; dominate Dst, we should not interchange. Thus, this currently miscompiles.
28+
;
29+
define dso_local i32 @test1(i1 %cond) {
30+
; CHECK-LABEL: define dso_local i32 @test1(
31+
; CHECK-SAME: i1 [[COND:%.*]]) {
32+
; CHECK-NEXT: [[FOR_PREHEADER:.*:]]
33+
; CHECK-NEXT: br label %[[INNERLOOP_PREHEADER:.*]]
34+
; CHECK: [[OUTERLOOP_PREHEADER:.*]]:
35+
; CHECK-NEXT: br label %[[OUTERLOOP:.*]]
36+
; CHECK: [[OUTERLOOP]]:
37+
; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[INDVARS_IV_NEXT21_I:%.*]], %[[FOR_LATCH:.*]] ], [ 0, %[[OUTERLOOP_PREHEADER]] ]
38+
; CHECK-NEXT: br label %[[INNERLOOP_SPLIT:.*]]
39+
; CHECK: [[INNERLOOP_PREHEADER]]:
40+
; CHECK-NEXT: br label %[[INNERLOOP:.*]]
41+
; CHECK: [[INNERLOOP]]:
42+
; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[TMP0:%.*]], %[[IF_END_SPLIT:.*]] ], [ 0, %[[INNERLOOP_PREHEADER]] ]
43+
; CHECK-NEXT: br label %[[OUTERLOOP_PREHEADER]]
44+
; CHECK: [[INNERLOOP_SPLIT]]:
45+
; CHECK-NEXT: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x [9 x i32]], ptr @f, i64 0, i64 [[J]], i64 [[I]]
46+
; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX6_I]], align 4
47+
; CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp eq i32 [[I1]], 0
48+
; CHECK-NEXT: br i1 [[TOBOOL_I]], label %[[LAND_END:.*]], label %[[LAND_RHS:.*]]
49+
; CHECK: [[LAND_RHS]]:
50+
; CHECK-NEXT: store i32 3, ptr @g, align 4
51+
; CHECK-NEXT: br label %[[LAND_END]]
52+
; CHECK: [[LAND_END]]:
53+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
54+
; CHECK: [[IF_THEN]]:
55+
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr @g, align 4
56+
; CHECK-NEXT: [[INC_I:%.*]] = add i32 [[I2]], 1
57+
; CHECK-NEXT: store i32 [[INC_I]], ptr @g, align 4
58+
; CHECK-NEXT: br label %[[IF_END]]
59+
; CHECK: [[IF_END]]:
60+
; CHECK-NEXT: [[J_NEXT:%.*]] = add nuw nsw i64 [[J]], 1
61+
; CHECK-NEXT: [[EXITCOND_I:%.*]] = icmp eq i64 [[J_NEXT]], 3
62+
; CHECK-NEXT: br label %[[FOR_LATCH]]
63+
; CHECK: [[IF_END_SPLIT]]:
64+
; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[J]], 1
65+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 3
66+
; CHECK-NEXT: br i1 [[TMP1]], label %[[EXIT:.*]], label %[[INNERLOOP]]
67+
; CHECK: [[FOR_LATCH]]:
68+
; CHECK-NEXT: [[INDVARS_IV_NEXT21_I]] = add nsw i64 [[I]], 1
69+
; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i64 [[I]], 2
70+
; CHECK-NEXT: br i1 [[CMP_I]], label %[[OUTERLOOP]], label %[[IF_END_SPLIT]]
71+
; CHECK: [[EXIT]]:
72+
; CHECK-NEXT: [[I3:%.*]] = load i32, ptr @g, align 4
73+
; CHECK-NEXT: ret i32 [[I3]]
74+
;
75+
for.preheader:
76+
br label %outerloop
77+
78+
outerloop:
79+
%i = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next21.i, %for.latch ]
80+
br label %innerloop
81+
82+
innerloop:
83+
%j = phi i64 [ 0, %outerloop ], [ %j.next, %if.end ]
84+
%arrayidx6.i = getelementptr inbounds [4 x [9 x i32]], [4 x [9 x i32]]* @f, i64 0, i64 %j, i64 %i
85+
%i1 = load i32, i32* %arrayidx6.i, align 4
86+
%tobool.i = icmp eq i32 %i1, 0
87+
br i1 %tobool.i, label %land.end, label %land.rhs
88+
89+
land.rhs:
90+
store i32 3, i32* @g, align 4
91+
br label %land.end
92+
93+
land.end:
94+
br i1 %cond, label %if.end, label %if.then
95+
96+
if.then:
97+
%i2 = load i32, i32* @g, align 4
98+
%inc.i = add i32 %i2, 1
99+
store i32 %inc.i, i32* @g, align 4
100+
br label %if.end
101+
102+
if.end:
103+
%j.next = add nuw nsw i64 %j, 1
104+
%exitcond.i = icmp eq i64 %j.next, 3
105+
br i1 %exitcond.i, label %for.latch, label %innerloop
106+
107+
for.latch:
108+
%indvars.iv.next21.i = add nsw i64 %i, 1
109+
%cmp.i = icmp slt i64 %i, 2
110+
br i1 %cmp.i, label %outerloop, label %exit
111+
112+
exit:
113+
%i3 = load i32, i32* @g, align 4
114+
ret i32 %i3
115+
}
116+
117+
; int32_t f[3][3];
118+
; int32_t g;
119+
;
120+
; int32_t test2(_Bool cond) {
121+
; for (int64_t i = 0; i < 3; i++) {
122+
; for (int64_t j = 0; j < 3; j++) {
123+
; int32_t val = f[i][j];
124+
; g = 3;
125+
; if (val == 0)
126+
; if (!cond)
127+
; g++;
128+
; else
129+
; if (!cond)
130+
; g++;
131+
; }
132+
; }
133+
; return g;
134+
; }
135+
;
136+
; FIXME: if there's an output dependency inside the loop and Src doesn't
137+
; dominate Dst, we should not interchange. Thus, this currently miscompiles.
138+
;
139+
define dso_local i32 @test2(i1 %cond) {
140+
; CHECK-LABEL: define dso_local i32 @test2(
141+
; CHECK-SAME: i1 [[COND:%.*]]) {
142+
; CHECK-NEXT: [[FOR_PREHEADER:.*:]]
143+
; CHECK-NEXT: br label %[[INNERLOOP_PREHEADER:.*]]
144+
; CHECK: [[OUTERLOOP_PREHEADER:.*]]:
145+
; CHECK-NEXT: br label %[[OUTERLOOP:.*]]
146+
; CHECK: [[OUTERLOOP]]:
147+
; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[INDVARS_IV_NEXT21_I:%.*]], %[[FOR_LATCH:.*]] ], [ 0, %[[OUTERLOOP_PREHEADER]] ]
148+
; CHECK-NEXT: br label %[[INNERLOOP_SPLIT:.*]]
149+
; CHECK: [[INNERLOOP_PREHEADER]]:
150+
; CHECK-NEXT: br label %[[INNERLOOP:.*]]
151+
; CHECK: [[INNERLOOP]]:
152+
; CHECK-NEXT: [[J:%.*]] = phi i64 [ [[TMP0:%.*]], %[[IF_END_SPLIT:.*]] ], [ 0, %[[INNERLOOP_PREHEADER]] ]
153+
; CHECK-NEXT: br label %[[OUTERLOOP_PREHEADER]]
154+
; CHECK: [[INNERLOOP_SPLIT]]:
155+
; CHECK-NEXT: [[ARRAYIDX6_I:%.*]] = getelementptr inbounds [4 x [9 x i32]], ptr @f, i64 0, i64 [[J]], i64 [[I]]
156+
; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX6_I]], align 4
157+
; CHECK-NEXT: [[TOBOOL_I:%.*]] = icmp eq i32 [[I1]], 0
158+
; CHECK-NEXT: store i32 3, ptr @g, align 4
159+
; CHECK-NEXT: br i1 [[TOBOOL_I]], label %[[LAND_END:.*]], label %[[LAND_RHS:.*]]
160+
; CHECK: [[LAND_RHS]]:
161+
; CHECK-NEXT: br label %[[LAND_END]]
162+
; CHECK: [[LAND_END]]:
163+
; CHECK-NEXT: br i1 [[COND]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
164+
; CHECK: [[IF_THEN]]:
165+
; CHECK-NEXT: [[I2:%.*]] = load i32, ptr @g, align 4
166+
; CHECK-NEXT: [[INC_I:%.*]] = add i32 [[I2]], 1
167+
; CHECK-NEXT: store i32 [[INC_I]], ptr @g, align 4
168+
; CHECK-NEXT: br label %[[IF_END]]
169+
; CHECK: [[IF_END]]:
170+
; CHECK-NEXT: [[J_NEXT:%.*]] = add nuw nsw i64 [[J]], 1
171+
; CHECK-NEXT: [[EXITCOND_I:%.*]] = icmp eq i64 [[J_NEXT]], 3
172+
; CHECK-NEXT: br label %[[FOR_LATCH]]
173+
; CHECK: [[IF_END_SPLIT]]:
174+
; CHECK-NEXT: [[TMP0]] = add nuw nsw i64 [[J]], 1
175+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 3
176+
; CHECK-NEXT: br i1 [[TMP1]], label %[[EXIT:.*]], label %[[INNERLOOP]]
177+
; CHECK: [[FOR_LATCH]]:
178+
; CHECK-NEXT: [[INDVARS_IV_NEXT21_I]] = add nsw i64 [[I]], 1
179+
; CHECK-NEXT: [[CMP_I:%.*]] = icmp slt i64 [[I]], 2
180+
; CHECK-NEXT: br i1 [[CMP_I]], label %[[OUTERLOOP]], label %[[IF_END_SPLIT]]
181+
; CHECK: [[EXIT]]:
182+
; CHECK-NEXT: [[I3:%.*]] = load i32, ptr @g, align 4
183+
; CHECK-NEXT: ret i32 [[I3]]
184+
;
185+
for.preheader:
186+
br label %outerloop
187+
188+
outerloop:
189+
%i = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next21.i, %for.latch ]
190+
br label %innerloop
191+
192+
innerloop:
193+
%j = phi i64 [ 0, %outerloop ], [ %j.next, %if.end ]
194+
%arrayidx6.i = getelementptr inbounds [4 x [9 x i32]], [4 x [9 x i32]]* @f, i64 0, i64 %j, i64 %i
195+
%i1 = load i32, i32* %arrayidx6.i, align 4
196+
%tobool.i = icmp eq i32 %i1, 0
197+
store i32 3, i32* @g, align 4
198+
br i1 %tobool.i, label %land.end, label %land.rhs
199+
200+
land.rhs:
201+
br label %land.end
202+
203+
land.end:
204+
br i1 %cond, label %if.end, label %if.then
205+
206+
if.then:
207+
%i2 = load i32, i32* @g, align 4
208+
%inc.i = add i32 %i2, 1
209+
store i32 %inc.i, i32* @g, align 4
210+
br label %if.end
211+
212+
if.end:
213+
%j.next = add nuw nsw i64 %j, 1
214+
%exitcond.i = icmp eq i64 %j.next, 3
215+
br i1 %exitcond.i, label %for.latch, label %innerloop
216+
217+
for.latch:
218+
%indvars.iv.next21.i = add nsw i64 %i, 1
219+
%cmp.i = icmp slt i64 %i, 2
220+
br i1 %cmp.i, label %outerloop, label %exit
221+
222+
exit:
223+
%i3 = load i32, i32* @g, align 4
224+
ret i32 %i3
225+
}

0 commit comments

Comments
 (0)