xref: /llvm-project/llvm/test/Transforms/LoopInterchange/lcssa.ll (revision 456ec1c2f4e487de235c953e8f2832b97372e7b0)
1; Remove 'S' Scalar Dependencies #119345
2; Scalar dependencies are not handled correctly, so they were removed to avoid
3; miscompiles. The loop nest in this test case used to be interchanged, but it's
4; no longer triggering. XFAIL'ing this test to indicate that this test should
5; interchanged if scalar deps are handled correctly.
6;
7; XFAIL: *
8
9; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -verify-loop-lcssa -pass-remarks-output=%t -S
10; RUN: FileCheck --input-file %t --check-prefix REMARK %s
11
12target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
13
14@A = common global [100 x [100 x i32]] zeroinitializer
15@C = common global [100 x [100 x i32]] zeroinitializer
16@X = common global i32 0
17@Y = common global i64 0
18@F = common global float 0.0
19
20; We cannot interchange this loop at the moment, because iv.outer.next is
21; produced in the outer loop latch and used in the loop exit block. If the inner
22; loop body is not executed, the outer loop latch won't be executed either
23; after interchanging.
24; REMARK: UnsupportedExitPHI
25; REMARK-NEXT: lcssa_01
26
27define void @lcssa_01() {
28entry:
29  %cmp21 = icmp sgt i64 100, 1
30  br i1 %cmp21, label %outer.ph, label %for.end16
31
32outer.ph:                                         ; preds = %entry
33  %cmp218 = icmp sgt i64 100, 1
34  br label %outer.header
35
36outer.header:                                     ; preds = %outer.inc, %outer.ph
37  %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
38  br i1 %cmp218, label %for.body3, label %outer.inc
39
40for.body3:                                        ; preds = %for.body3, %outer.header
41  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
42  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
43  %vA = load i32, ptr %arrayidx5
44  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
45  %vC = load i32, ptr %arrayidx9
46  %add = add nsw i32 %vA, %vC
47  store i32 %add, ptr %arrayidx5
48  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
49  %exitcond = icmp eq i64 %iv.inner.next, 100
50  br i1 %exitcond, label %outer.inc, label %for.body3
51
52outer.inc:                                        ; preds = %for.body3, %outer.header
53  %iv.outer.next = add nsw i64 %iv.outer, 1
54  %cmp = icmp eq i64 %iv.outer.next, 100
55  br i1 %cmp, label %outer.header, label %for.exit
56
57for.exit:                                         ; preds = %outer.inc
58  %iv.outer.next.lcssa = phi i64 [ %iv.outer.next, %outer.inc ]
59  store i64 %iv.outer.next.lcssa, ptr @Y
60  br label %for.end16
61
62for.end16:                                        ; preds = %for.exit, %entry
63  ret void
64}
65
66; REMARK: UnsupportedExitPHI
67; REMARK-NEXT: lcssa_02
68define void @lcssa_02() {
69entry:
70  %cmp21 = icmp sgt i64 100, 1
71  br i1 %cmp21, label %outer.ph, label %for.end16
72
73outer.ph:                                         ; preds = %entry
74  %cmp218 = icmp sgt i64 100, 1
75  br label %outer.header
76
77outer.header:                                     ; preds = %outer.inc, %outer.ph
78  %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
79  br i1 %cmp218, label %for.body3, label %outer.inc
80
81for.body3:                                        ; preds = %for.body3, %outer.header
82  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
83  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
84  %vA = load i32, ptr %arrayidx5
85  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
86  %vC = load i32, ptr %arrayidx9
87  %add = add nsw i32 %vA, %vC
88  store i32 %add, ptr %arrayidx5
89  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
90  %exitcond = icmp eq i64 %iv.inner.next, 100
91  br i1 %exitcond, label %outer.inc, label %for.body3
92
93outer.inc:                                        ; preds = %for.body3, %outer.header
94  %iv.inner.end = phi i64 [ 0, %outer.header ], [ %iv.inner.next, %for.body3 ]
95  %iv.outer.next = add nsw i64 %iv.outer, 1
96  %cmp = icmp eq i64 %iv.outer.next, 100
97  br i1 %cmp, label %outer.header, label %for.exit
98
99for.exit:                                         ; preds = %outer.inc
100  %iv.inner.end.lcssa = phi i64 [ %iv.inner.end, %outer.inc ]
101  store i64 %iv.inner.end.lcssa, ptr @Y
102  br label %for.end16
103
104for.end16:                                        ; preds = %for.exit, %entry
105  ret void
106}
107
108; REMARK: Interchanged
109; REMARK-NEXT: lcssa_03
110define void @lcssa_03() {
111entry:
112  br label %outer.header
113
114outer.header:                                     ; preds = %outer.inc, %entry
115  %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
116  br label %for.body3
117
118for.body3:                                        ; preds = %for.body3, %outer.header
119  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
120  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
121  %vA = load i32, ptr %arrayidx5
122  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
123  %vC = load i32, ptr %arrayidx9
124  %add = add nsw i32 %vA, %vC
125  store i32 %add, ptr %arrayidx5
126  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
127  %exitcond = icmp eq i64 %iv.inner.next, 100
128  br i1 %exitcond, label %outer.inc, label %for.body3
129
130outer.inc:                                        ; preds = %for.body3
131  %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ]
132  %iv.outer.next = add nsw i64 %iv.outer, 1
133  %cmp = icmp eq i64 %iv.outer.next, 100
134  br i1 %cmp, label %outer.header, label %for.exit
135
136for.exit:                                         ; preds = %outer.inc
137  %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
138  store i64 %iv.inner.lcssa.lcssa, ptr @Y
139  br label %for.end16
140
141for.end16:                                        ; preds = %for.exit
142  ret void
143}
144
145; Loops with floating point reductions are interchanged with fastmath.
146; REMARK: Interchanged
147; REMARK-NEXT: lcssa_04
148
149define void @lcssa_04() {
150entry:
151  br label %outer.header
152
153outer.header:                                     ; preds = %outer.inc, %entry
154  %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
155  %float.outer = phi float [ 1.000000e+00, %entry ], [ %float.outer.next, %outer.inc ]
156  br label %for.body3
157
158for.body3:                                        ; preds = %for.body3, %outer.header
159  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
160  %float.inner = phi float [ %float.inner.next, %for.body3 ], [ %float.outer, %outer.header ]
161  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
162  %vA = load i32, ptr %arrayidx5
163  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
164  %vC = load i32, ptr %arrayidx9
165  %add = add nsw i32 %vA, %vC
166  %float.inner.next = fadd fast float %float.inner, 1.000000e+00
167  store i32 %add, ptr %arrayidx5
168  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
169  %exitcond = icmp eq i64 %iv.inner.next, 100
170  br i1 %exitcond, label %outer.inc, label %for.body3
171
172outer.inc:                                        ; preds = %for.body3
173  %float.outer.next = phi float [ %float.inner.next, %for.body3 ]
174  %iv.outer.next = add nsw i64 %iv.outer, 1
175  %cmp = icmp eq i64 %iv.outer.next, 100
176  br i1 %cmp, label %outer.header, label %for.exit
177
178for.exit:                                         ; preds = %outer.inc
179  %float.outer.lcssa = phi float [ %float.outer.next, %outer.inc ]
180  store float %float.outer.lcssa, ptr @F
181  br label %for.end16
182
183for.end16:                                        ; preds = %for.exit
184  ret void
185}
186
187; PHI node in inner latch with multiple predecessors.
188; REMARK:      Interchanged
189; REMARK-NEXT: lcssa_05
190
191define void @lcssa_05(ptr %ptr, i1 %arg) {
192entry:
193  br label %outer.header
194
195outer.header:                                     ; preds = %outer.inc, %entry
196  %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
197  br label %for.body3
198
199for.body3:                                        ; preds = %bb3, %outer.header
200  %iv.inner = phi i64 [ %iv.inner.next, %bb3 ], [ 1, %outer.header ]
201  br i1 %arg, label %bb2, label %bb3
202
203bb2:                                              ; preds = %for.body3
204  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
205  %vA = load i32, ptr %arrayidx5
206  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
207  %vC = load i32, ptr %arrayidx9
208  %add = add nsw i32 %vA, %vC
209  br label %bb3
210
211bb3:                                              ; preds = %bb2, %for.body3
212  %addp = phi i32 [ %add, %bb2 ], [ 0, %for.body3 ]
213  store i32 %addp, ptr %ptr
214  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
215  %exitcond = icmp eq i64 %iv.inner.next, 100
216  br i1 %exitcond, label %outer.inc, label %for.body3
217
218outer.inc:                                        ; preds = %bb3
219  %iv.inner.lcssa = phi i64 [ %iv.inner, %bb3 ]
220  %iv.outer.next = add nsw i64 %iv.outer, 1
221  %cmp = icmp eq i64 %iv.outer.next, 100
222  br i1 %cmp, label %outer.header, label %for.exit
223
224for.exit:                                         ; preds = %outer.inc
225  %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
226  store i64 %iv.inner.lcssa.lcssa, ptr @Y
227  br label %for.end16
228
229for.end16:                                        ; preds = %for.exit
230  ret void
231}
232
233; REMARK:      UnsupportedExitPHI
234; REMARK-NEXT: lcssa_06
235
236define void @lcssa_06(ptr %ptr, ptr %ptr1, i1 %arg) {
237entry:
238  br label %outer.header
239
240outer.header:                                     ; preds = %outer.inc, %entry
241  %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
242  br i1 %arg, label %for.body3, label %outer.inc
243
244for.body3:                                        ; preds = %for.body3, %outer.header
245  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
246  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
247  %vA = load i32, ptr %arrayidx5
248  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
249  %vC = load i32, ptr %arrayidx9
250  %add = add nsw i32 %vA, %vC
251  store i32 %add, ptr %ptr1
252  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
253  %exitcond = icmp eq i64 %iv.inner.next, 100
254  br i1 %exitcond, label %outer.inc, label %for.body3
255
256outer.inc:                                        ; preds = %for.body3, %outer.header
257  %sv = phi i64 [ 0, %outer.header ], [ 1, %for.body3 ]
258  %iv.outer.next = add nsw i64 %iv.outer, 1
259  %cmp = icmp eq i64 %iv.outer.next, 100
260  br i1 %cmp, label %outer.header, label %for.exit
261
262for.exit:                                         ; preds = %outer.inc
263  %sv.lcssa = phi i64 [ %sv, %outer.inc ]
264  store i64 %sv.lcssa, ptr @Y
265  br label %for.end16
266
267for.end16:                                        ; preds = %for.exit
268  ret void
269}
270
271; REMARK: Interchanged
272; REMARK-NEXT: lcssa_07
273define void @lcssa_07() {
274entry:
275  br label %outer.header
276
277outer.header:                                     ; preds = %outer.inc, %entry
278  %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
279  br label %for.body3
280
281for.body3:                                        ; preds = %for.body3, %outer.header
282  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
283  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
284  %vA = load i32, ptr %arrayidx5
285  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
286  %vC = load i32, ptr %arrayidx9
287  %add = add nsw i32 %vA, %vC
288  store i32 %add, ptr %arrayidx5
289  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
290  %exitcond = icmp eq i64 %iv.inner.next, 100
291  br i1 %exitcond, label %outer.bb, label %for.body3
292
293outer.bb:                                         ; preds = %for.body3
294  %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ]
295  br label %outer.inc
296
297outer.inc:                                        ; preds = %outer.bb
298  %iv.outer.next = add nsw i64 %iv.outer, 1
299  %cmp = icmp eq i64 %iv.outer.next, 100
300  br i1 %cmp, label %outer.header, label %for.exit
301
302for.exit:                                         ; preds = %outer.inc
303  %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
304  store i64 %iv.inner.lcssa.lcssa, ptr @Y
305  br label %for.end16
306
307for.end16:                                        ; preds = %for.exit
308  ret void
309}
310
311; Should not crash when the outer header branches to
312; both the inner loop and the outer latch, and there
313; is an lcssa phi node outside the loopnest.
314; REMARK: Interchanged
315; REMARK-NEXT: lcssa_08
316define i64 @lcssa_08(ptr %Arr, i1 %arg) {
317entry:
318  br label %for1.header
319
320for1.header:                                         ; preds = %for1.inc, %entry
321  %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc ]
322  br i1 %arg, label %for2, label %for1.inc
323
324for2:                                        ; preds = %for2, %for1.header
325  %indvars.iv = phi i64 [ 0, %for1.header ], [ %indvars.iv.next.3, %for2 ]
326  %arrayidx = getelementptr inbounds [100 x [100 x i64]], ptr %Arr, i64 0, i64 %indvars.iv, i64 %indvars.iv23
327  %lv = load i64, ptr %arrayidx, align 4
328  %indvars.iv.next.3 = add nuw nsw i64 %indvars.iv, 1
329  %exit1 = icmp eq i64 %indvars.iv.next.3, 100
330  br i1 %exit1, label %for1.inc, label %for2
331
332for1.inc:                                ; preds = %for2, %for1.header
333  %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
334  %exit2 = icmp eq i64 %indvars.iv.next24, 100
335  br i1 %exit2, label %for1.loopexit, label %for1.header
336
337for1.loopexit:                                 ; preds = %for1.inc
338  %sum.outer.lcssa = phi i64 [ %indvars.iv23, %for1.inc ]
339  ret i64 %sum.outer.lcssa
340}
341
342