1 ; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -verify-loop-lcssa -pass-remarks-output=%t -S
2 ; RUN: FileCheck --input-file %t --check-prefix REMARK %s
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6 @A = common global [100 x [100 x i32]] zeroinitializer
7 @C = common global [100 x [100 x i32]] zeroinitializer
8 @X = common global i32 0
9 @Y = common global i64 0
10 @F = common global float 0.0
12 ; We cannot interchange this loop at the moment, because iv.outer.next is
13 ; produced in the outer loop latch and used in the loop exit block. If the inner
14 ; loop body is not executed, the outer loop latch won't be executed either
15 ; after interchanging.
16 ; REMARK: UnsupportedExitPHI
17 ; REMARK-NEXT: lcssa_01
19 define void @lcssa_01() {
21 %cmp21 = icmp sgt i64 100, 1
22 br i1 %cmp21, label %outer.ph, label %for.end16
24 outer.ph: ; preds = %entry
25 %cmp218 = icmp sgt i64 100, 1
26 br label %outer.header
28 outer.header: ; preds = %outer.inc, %outer.ph
29 %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
30 br i1 %cmp218, label %for.body3, label %outer.inc
32 for.body3: ; preds = %for.body3, %outer.header
33 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
34 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
35 %vA = load i32, ptr %arrayidx5
36 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
37 %vC = load i32, ptr %arrayidx9
38 %add = add nsw i32 %vA, %vC
39 store i32 %add, ptr %arrayidx5
40 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
41 %exitcond = icmp eq i64 %iv.inner.next, 100
42 br i1 %exitcond, label %outer.inc, label %for.body3
44 outer.inc: ; preds = %for.body3, %outer.header
45 %iv.outer.next = add nsw i64 %iv.outer, 1
46 %cmp = icmp eq i64 %iv.outer.next, 100
47 br i1 %cmp, label %outer.header, label %for.exit
49 for.exit: ; preds = %outer.inc
50 %iv.outer.next.lcssa = phi i64 [ %iv.outer.next, %outer.inc ]
51 store i64 %iv.outer.next.lcssa, ptr @Y
54 for.end16: ; preds = %for.exit, %entry
58 ; REMARK: UnsupportedExitPHI
59 ; REMARK-NEXT: lcssa_02
60 define void @lcssa_02() {
62 %cmp21 = icmp sgt i64 100, 1
63 br i1 %cmp21, label %outer.ph, label %for.end16
65 outer.ph: ; preds = %entry
66 %cmp218 = icmp sgt i64 100, 1
67 br label %outer.header
69 outer.header: ; preds = %outer.inc, %outer.ph
70 %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
71 br i1 %cmp218, label %for.body3, label %outer.inc
73 for.body3: ; preds = %for.body3, %outer.header
74 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
75 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
76 %vA = load i32, ptr %arrayidx5
77 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
78 %vC = load i32, ptr %arrayidx9
79 %add = add nsw i32 %vA, %vC
80 store i32 %add, ptr %arrayidx5
81 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
82 %exitcond = icmp eq i64 %iv.inner.next, 100
83 br i1 %exitcond, label %outer.inc, label %for.body3
85 outer.inc: ; preds = %for.body3, %outer.header
86 %iv.inner.end = phi i64 [ 0, %outer.header ], [ %iv.inner.next, %for.body3 ]
87 %iv.outer.next = add nsw i64 %iv.outer, 1
88 %cmp = icmp eq i64 %iv.outer.next, 100
89 br i1 %cmp, label %outer.header, label %for.exit
91 for.exit: ; preds = %outer.inc
92 %iv.inner.end.lcssa = phi i64 [ %iv.inner.end, %outer.inc ]
93 store i64 %iv.inner.end.lcssa, ptr @Y
96 for.end16: ; preds = %for.exit, %entry
100 ; REMARK: Interchanged
101 ; REMARK-NEXT: lcssa_03
102 define void @lcssa_03() {
104 br label %outer.header
106 outer.header: ; preds = %outer.inc, %entry
107 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
110 for.body3: ; preds = %for.body3, %outer.header
111 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
112 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
113 %vA = load i32, ptr %arrayidx5
114 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
115 %vC = load i32, ptr %arrayidx9
116 %add = add nsw i32 %vA, %vC
117 store i32 %add, ptr %arrayidx5
118 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
119 %exitcond = icmp eq i64 %iv.inner.next, 100
120 br i1 %exitcond, label %outer.inc, label %for.body3
122 outer.inc: ; preds = %for.body3
123 %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ]
124 %iv.outer.next = add nsw i64 %iv.outer, 1
125 %cmp = icmp eq i64 %iv.outer.next, 100
126 br i1 %cmp, label %outer.header, label %for.exit
128 for.exit: ; preds = %outer.inc
129 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
130 store i64 %iv.inner.lcssa.lcssa, ptr @Y
133 for.end16: ; preds = %for.exit
137 ; Loops with floating point reductions are interchanged with fastmath.
138 ; REMARK: Interchanged
139 ; REMARK-NEXT: lcssa_04
141 define void @lcssa_04() {
143 br label %outer.header
145 outer.header: ; preds = %outer.inc, %entry
146 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
147 %float.outer = phi float [ 1.000000e+00, %entry ], [ %float.outer.next, %outer.inc ]
150 for.body3: ; preds = %for.body3, %outer.header
151 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
152 %float.inner = phi float [ %float.inner.next, %for.body3 ], [ %float.outer, %outer.header ]
153 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
154 %vA = load i32, ptr %arrayidx5
155 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
156 %vC = load i32, ptr %arrayidx9
157 %add = add nsw i32 %vA, %vC
158 %float.inner.next = fadd fast float %float.inner, 1.000000e+00
159 store i32 %add, ptr %arrayidx5
160 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
161 %exitcond = icmp eq i64 %iv.inner.next, 100
162 br i1 %exitcond, label %outer.inc, label %for.body3
164 outer.inc: ; preds = %for.body3
165 %float.outer.next = phi float [ %float.inner.next, %for.body3 ]
166 %iv.outer.next = add nsw i64 %iv.outer, 1
167 %cmp = icmp eq i64 %iv.outer.next, 100
168 br i1 %cmp, label %outer.header, label %for.exit
170 for.exit: ; preds = %outer.inc
171 %float.outer.lcssa = phi float [ %float.outer.next, %outer.inc ]
172 store float %float.outer.lcssa, ptr @F
175 for.end16: ; preds = %for.exit
179 ; PHI node in inner latch with multiple predecessors.
180 ; REMARK: Interchanged
181 ; REMARK-NEXT: lcssa_05
183 define void @lcssa_05(ptr %ptr, i1 %arg) {
185 br label %outer.header
187 outer.header: ; preds = %outer.inc, %entry
188 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
191 for.body3: ; preds = %bb3, %outer.header
192 %iv.inner = phi i64 [ %iv.inner.next, %bb3 ], [ 1, %outer.header ]
193 br i1 %arg, label %bb2, label %bb3
195 bb2: ; preds = %for.body3
196 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
197 %vA = load i32, ptr %arrayidx5
198 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
199 %vC = load i32, ptr %arrayidx9
200 %add = add nsw i32 %vA, %vC
203 bb3: ; preds = %bb2, %for.body3
204 %addp = phi i32 [ %add, %bb2 ], [ 0, %for.body3 ]
205 store i32 %addp, ptr %ptr
206 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
207 %exitcond = icmp eq i64 %iv.inner.next, 100
208 br i1 %exitcond, label %outer.inc, label %for.body3
210 outer.inc: ; preds = %bb3
211 %iv.inner.lcssa = phi i64 [ %iv.inner, %bb3 ]
212 %iv.outer.next = add nsw i64 %iv.outer, 1
213 %cmp = icmp eq i64 %iv.outer.next, 100
214 br i1 %cmp, label %outer.header, label %for.exit
216 for.exit: ; preds = %outer.inc
217 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
218 store i64 %iv.inner.lcssa.lcssa, ptr @Y
221 for.end16: ; preds = %for.exit
225 ; REMARK: UnsupportedExitPHI
226 ; REMARK-NEXT: lcssa_06
228 define void @lcssa_06(ptr %ptr, ptr %ptr1, i1 %arg) {
230 br label %outer.header
232 outer.header: ; preds = %outer.inc, %entry
233 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
234 br i1 %arg, label %for.body3, label %outer.inc
236 for.body3: ; preds = %for.body3, %outer.header
237 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
238 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
239 %vA = load i32, ptr %arrayidx5
240 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
241 %vC = load i32, ptr %arrayidx9
242 %add = add nsw i32 %vA, %vC
243 store i32 %add, ptr %ptr1
244 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
245 %exitcond = icmp eq i64 %iv.inner.next, 100
246 br i1 %exitcond, label %outer.inc, label %for.body3
248 outer.inc: ; preds = %for.body3, %outer.header
249 %sv = phi i64 [ 0, %outer.header ], [ 1, %for.body3 ]
250 %iv.outer.next = add nsw i64 %iv.outer, 1
251 %cmp = icmp eq i64 %iv.outer.next, 100
252 br i1 %cmp, label %outer.header, label %for.exit
254 for.exit: ; preds = %outer.inc
255 %sv.lcssa = phi i64 [ %sv, %outer.inc ]
256 store i64 %sv.lcssa, ptr @Y
259 for.end16: ; preds = %for.exit
263 ; REMARK: Interchanged
264 ; REMARK-NEXT: lcssa_07
265 define void @lcssa_07() {
267 br label %outer.header
269 outer.header: ; preds = %outer.inc, %entry
270 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
273 for.body3: ; preds = %for.body3, %outer.header
274 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
275 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer
276 %vA = load i32, ptr %arrayidx5
277 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer
278 %vC = load i32, ptr %arrayidx9
279 %add = add nsw i32 %vA, %vC
280 store i32 %add, ptr %arrayidx5
281 %iv.inner.next = add nuw nsw i64 %iv.inner, 1
282 %exitcond = icmp eq i64 %iv.inner.next, 100
283 br i1 %exitcond, label %outer.bb, label %for.body3
285 outer.bb: ; preds = %for.body3
286 %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ]
289 outer.inc: ; preds = %outer.bb
290 %iv.outer.next = add nsw i64 %iv.outer, 1
291 %cmp = icmp eq i64 %iv.outer.next, 100
292 br i1 %cmp, label %outer.header, label %for.exit
294 for.exit: ; preds = %outer.inc
295 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ]
296 store i64 %iv.inner.lcssa.lcssa, ptr @Y
299 for.end16: ; preds = %for.exit
303 ; Should not crash when the outer header branches to
304 ; both the inner loop and the outer latch, and there
305 ; is an lcssa phi node outside the loopnest.
306 ; REMARK: Interchanged
307 ; REMARK-NEXT: lcssa_08
308 define i64 @lcssa_08(ptr %Arr, i1 %arg) {
310 br label %for1.header
312 for1.header: ; preds = %for1.inc, %entry
313 %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc ]
314 br i1 %arg, label %for2, label %for1.inc
316 for2: ; preds = %for2, %for1.header
317 %indvars.iv = phi i64 [ 0, %for1.header ], [ %indvars.iv.next.3, %for2 ]
318 %arrayidx = getelementptr inbounds [100 x [100 x i64]], ptr %Arr, i64 0, i64 %indvars.iv, i64 %indvars.iv23
319 %lv = load i64, ptr %arrayidx, align 4
320 %indvars.iv.next.3 = add nuw nsw i64 %indvars.iv, 1
321 %exit1 = icmp eq i64 %indvars.iv.next.3, 100
322 br i1 %exit1, label %for1.inc, label %for2
324 for1.inc: ; preds = %for2, %for1.header
325 %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1
326 %exit2 = icmp eq i64 %indvars.iv.next24, 100
327 br i1 %exit2, label %for1.loopexit, label %for1.header
329 for1.loopexit: ; preds = %for1.inc
330 %sum.outer.lcssa = phi i64 [ %indvars.iv23, %for1.inc ]
331 ret i64 %sum.outer.lcssa