1; RUN: opt < %s -basicaa -loop-interchange -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t
2; RUN: cat %t |  FileCheck --check-prefix REMARK %s
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5target triple = "x86_64-unknown-linux-gnu"
6
7@A = common global [100 x [100 x i32]] zeroinitializer
8@C = common global [100 x [100 x i32]] zeroinitializer
9@X = common global i32 0
10@Y = common global i64 0
11@F = common global float 0.0
12
13; We cannot interchange this loop at the moment, because iv.outer.next is
14; produced in the outer loop latch and used in the loop exit block. If the inner
15; loop body is not executed, the outer loop latch won't be executed either
16; after interchanging.
17; REMARK: UnsupportedExitPHI
18; REMARK-NEXT: lcssa_01
19
20define void @lcssa_01(){
21entry:
22  %cmp21 = icmp sgt i64 100, 1
23  br i1 %cmp21, label %outer.ph, label %for.end16
24
25outer.ph:
26  %cmp218 = icmp sgt i64 100, 1
27  br label %outer.header
28
29outer.header:
30  %iv.outer= phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
31  br i1 %cmp218, label %for.body3, label %outer.inc
32
33for.body3:
34  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
35  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer
36  %vA = load i32, i32* %arrayidx5
37  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer
38  %vC = load i32, i32* %arrayidx9
39  %add = add nsw i32 %vA, %vC
40  store i32 %add, i32* %arrayidx5
41  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
42  %exitcond = icmp eq i64 %iv.inner.next, 100
43  br i1 %exitcond, label %outer.inc, label %for.body3
44
45outer.inc:
46  %iv.outer.next = add nsw i64 %iv.outer, 1
47  %cmp = icmp eq i64 %iv.outer.next, 100
48  br i1 %cmp, label %outer.header, label %for.exit
49
50for.exit:
51  store i64 %iv.outer.next, i64 * @Y
52  br label %for.end16
53
54for.end16:
55  ret void
56}
57
58; REMARK: UnsupportedExitPHI
59; REMARK-NEXT: lcssa_02
60define void @lcssa_02(){
61entry:
62  %cmp21 = icmp sgt i64 100, 1
63  br i1 %cmp21, label %outer.ph, label %for.end16
64
65outer.ph:
66  %cmp218 = icmp sgt i64 100, 1
67  br label %outer.header
68
69outer.header:
70  %iv.outer= phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ]
71  br i1 %cmp218, label %for.body3, label %outer.inc
72
73for.body3:
74  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
75  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer
76  %vA = load i32, i32* %arrayidx5
77  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer
78  %vC = load i32, i32* %arrayidx9
79  %add = add nsw i32 %vA, %vC
80  store i32 %add, i32* %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
84
85outer.inc:
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
90
91for.exit:
92  store i64 %iv.inner.end, i64 * @Y
93  br label %for.end16
94
95for.end16:
96  ret void
97}
98
99
100; REMARK: Interchanged
101; REMARK-NEXT: lcssa_03
102define void @lcssa_03(){
103entry:
104  br label %outer.header
105
106outer.header:
107  %iv.outer= phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
108  br label %for.body3
109
110for.body3:
111  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
112  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer
113  %vA = load i32, i32* %arrayidx5
114  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer
115  %vC = load i32, i32* %arrayidx9
116  %add = add nsw i32 %vA, %vC
117  store i32 %add, i32* %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
121
122outer.inc:
123  %iv.outer.next = add nsw i64 %iv.outer, 1
124  %cmp = icmp eq i64 %iv.outer.next, 100
125  br i1 %cmp, label %outer.header, label %for.exit
126
127for.exit:
128  store i64 %iv.inner, i64 * @Y
129  br label %for.end16
130
131for.end16:
132  ret void
133}
134
135; FIXME: We currently do not support LCSSA phi nodes involving floating point
136;        types, as we fail to detect floating point reductions for now.
137; REMARK: UnsupportedPHIOuter
138; REMARK-NEXT: lcssa_04
139define void @lcssa_04(){
140entry:
141  br label %outer.header
142
143outer.header:
144  %iv.outer= phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ]
145  %float.outer= phi float [ 1.0, %entry ], [ 2.0, %outer.inc ]
146  br label %for.body3
147
148for.body3:
149  %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ]
150  %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer
151  %vA = load i32, i32* %arrayidx5
152  %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer
153  %vC = load i32, i32* %arrayidx9
154  %add = add nsw i32 %vA, %vC
155  store i32 %add, i32* %arrayidx5
156  %iv.inner.next = add nuw nsw i64 %iv.inner, 1
157  %exitcond = icmp eq i64 %iv.inner.next, 100
158  br i1 %exitcond, label %outer.inc, label %for.body3
159
160outer.inc:
161  %iv.outer.next = add nsw i64 %iv.outer, 1
162  %cmp = icmp eq i64 %iv.outer.next, 100
163  br i1 %cmp, label %outer.header, label %for.exit
164
165for.exit:
166  store float %float.outer, float* @F
167  br label %for.end16
168
169for.end16:
170  ret void
171}
172