1; RUN: opt -S -basic-aa -licm %s | FileCheck %s
2; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
3
4declare i32 @load(i32* %p) argmemonly readonly nounwind
5
6define void @test_load(i32* noalias %loc, i32* noalias %sink) {
7; CHECK-LABEL: @test_load
8; CHECK-LABEL: entry:
9; CHECK: call i32 @load
10; CHECK-LABEL: loop:
11entry:
12  br label %loop
13
14loop:
15  %iv = phi i32 [0, %entry], [%iv.next, %loop]
16  %ret = call i32 @load(i32* %loc)
17  store volatile i32 %ret, i32* %sink
18  %iv.next = add i32 %iv, 1
19  %cmp = icmp slt i32 %iv, 200
20  br i1 %cmp, label %loop, label %exit
21
22exit:
23  ret void
24}
25
26
27declare void @store(i32 %val, i32* %p) argmemonly writeonly nounwind
28
29define void @test(i32* %loc) {
30; CHECK-LABEL: @test
31; CHECK-LABEL: loop:
32; CHECK: call void @store
33; CHECK-LABEL: exit:
34entry:
35  br label %loop
36
37loop:
38  %iv = phi i32 [0, %entry], [%iv.next, %loop]
39  call void @store(i32 0, i32* %loc)
40  %iv.next = add i32 %iv, 1
41  %cmp = icmp slt i32 %iv, 200
42  br i1 %cmp, label %loop, label %exit
43
44exit:
45  ret void
46}
47
48define void @test_multiexit(i32* %loc, i1 %earlycnd) {
49; CHECK-LABEL: @test_multiexit
50; CHECK-LABEL: loop:
51; CHECK: call void @store
52; CHECK-LABEL: backedge:
53entry:
54  br label %loop
55
56loop:
57  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
58  call void @store(i32 0, i32* %loc)
59  %iv.next = add i32 %iv, 1
60  br i1 %earlycnd, label %exit1, label %backedge
61
62backedge:
63  %cmp = icmp slt i32 %iv, 200
64  br i1 %cmp, label %loop, label %exit2
65
66exit1:
67  ret void
68exit2:
69  ret void
70}
71
72define void @neg_lv_value(i32* %loc) {
73; CHECK-LABEL: @neg_lv_value
74; CHECK-LABEL: loop:
75; CHECK: call void @store
76; CHECK-LABEL: exit:
77entry:
78  br label %loop
79
80loop:
81  %iv = phi i32 [0, %entry], [%iv.next, %loop]
82  call void @store(i32 %iv, i32* %loc)
83  %iv.next = add i32 %iv, 1
84  %cmp = icmp slt i32 %iv, 200
85  br i1 %cmp, label %loop, label %exit
86
87exit:
88  ret void
89}
90
91define void @neg_lv_addr(i32* %loc) {
92; CHECK-LABEL: @neg_lv_addr
93; CHECK-LABEL: loop:
94; CHECK: call void @store
95; CHECK-LABEL: exit:
96entry:
97  br label %loop
98
99loop:
100  %iv = phi i32 [0, %entry], [%iv.next, %loop]
101  %p = getelementptr i32, i32* %loc, i32 %iv
102  call void @store(i32 0, i32* %p)
103  %iv.next = add i32 %iv, 1
104  %cmp = icmp slt i32 %iv, 200
105  br i1 %cmp, label %loop, label %exit
106
107exit:
108  ret void
109}
110
111define void @neg_mod(i32* %loc) {
112; CHECK-LABEL: @neg_mod
113; CHECK-LABEL: loop:
114; CHECK: call void @store
115; CHECK-LABEL: exit:
116entry:
117  br label %loop
118
119loop:
120  %iv = phi i32 [0, %entry], [%iv.next, %loop]
121  call void @store(i32 0, i32* %loc)
122  store i32 %iv, i32* %loc
123  %iv.next = add i32 %iv, 1
124  %cmp = icmp slt i32 %iv, 200
125  br i1 %cmp, label %loop, label %exit
126
127exit:
128  ret void
129}
130
131define void @neg_ref(i32* %loc) {
132; CHECK-LABEL: @neg_ref
133; CHECK-LABEL: loop:
134; CHECK: call void @store
135; CHECK-LABEL: exit1:
136entry:
137  br label %loop
138
139loop:
140  %iv = phi i32 [0, %entry], [%iv.next, %backedge]
141  call void @store(i32 0, i32* %loc)
142  %v = load i32, i32* %loc
143  %earlycnd = icmp eq i32 %v, 198
144  br i1 %earlycnd, label %exit1, label %backedge
145
146backedge:
147  %iv.next = add i32 %iv, 1
148  %cmp = icmp slt i32 %iv, 200
149  br i1 %cmp, label %loop, label %exit2
150
151exit1:
152  ret void
153exit2:
154  ret void
155}
156
157declare void @modref()
158
159define void @neg_modref(i32* %loc) {
160; CHECK-LABEL: @neg_modref
161; CHECK-LABEL: loop:
162; CHECK: call void @store
163; CHECK-LABEL: exit:
164entry:
165  br label %loop
166
167loop:
168  %iv = phi i32 [0, %entry], [%iv.next, %loop]
169  call void @store(i32 0, i32* %loc)
170  call void @modref()
171  %iv.next = add i32 %iv, 1
172  %cmp = icmp slt i32 %iv, 200
173  br i1 %cmp, label %loop, label %exit
174
175exit:
176  ret void
177}
178
179define void @neg_fence(i32* %loc) {
180; CHECK-LABEL: @neg_fence
181; CHECK-LABEL: loop:
182; CHECK: call void @store
183; CHECK-LABEL: exit:
184entry:
185  br label %loop
186
187loop:
188  %iv = phi i32 [0, %entry], [%iv.next, %loop]
189  call void @store(i32 0, i32* %loc)
190  fence seq_cst
191  %iv.next = add i32 %iv, 1
192  %cmp = icmp slt i32 %iv, 200
193  br i1 %cmp, label %loop, label %exit
194
195exit:
196  ret void
197}
198
199declare void @not_nounwind(i32 %v, i32* %p) writeonly argmemonly
200declare void @not_argmemonly(i32 %v, i32* %p) writeonly nounwind
201declare void @not_writeonly(i32 %v, i32* %p) argmemonly nounwind
202
203define void @neg_not_nounwind(i32* %loc) {
204; CHECK-LABEL: @neg_not_nounwind
205; CHECK-LABEL: loop:
206; CHECK: call void @not_nounwind
207; CHECK-LABEL: exit:
208entry:
209  br label %loop
210
211loop:
212  %iv = phi i32 [0, %entry], [%iv.next, %loop]
213  call void @not_nounwind(i32 0, i32* %loc)
214  %iv.next = add i32 %iv, 1
215  %cmp = icmp slt i32 %iv, 200
216  br i1 %cmp, label %loop, label %exit
217
218exit:
219  ret void
220}
221
222define void @neg_not_argmemonly(i32* %loc) {
223; CHECK-LABEL: @neg_not_argmemonly
224; CHECK-LABEL: loop:
225; CHECK: call void @not_argmemonly
226; CHECK-LABEL: exit:
227entry:
228  br label %loop
229
230loop:
231  %iv = phi i32 [0, %entry], [%iv.next, %loop]
232  call void @not_argmemonly(i32 0, i32* %loc)
233  %iv.next = add i32 %iv, 1
234  %cmp = icmp slt i32 %iv, 200
235  br i1 %cmp, label %loop, label %exit
236
237exit:
238  ret void
239}
240
241define void @neg_not_writeonly(i32* %loc) {
242; CHECK-LABEL: @neg_not_writeonly
243; CHECK-LABEL: loop:
244; CHECK: call void @not_writeonly
245; CHECK-LABEL: exit:
246entry:
247  br label %loop
248
249loop:
250  %iv = phi i32 [0, %entry], [%iv.next, %loop]
251  call void @not_writeonly(i32 0, i32* %loc)
252  %iv.next = add i32 %iv, 1
253  %cmp = icmp slt i32 %iv, 200
254  br i1 %cmp, label %loop, label %exit
255
256exit:
257  ret void
258}
259
260