Implement rdar://9009151, transforming strided loop stores of
[oota-llvm.git] / test / Transforms / LoopIdiom / basic.ll
1 ; RUN: opt -basicaa -loop-idiom < %s -S | FileCheck %s
2 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
3 target triple = "x86_64-apple-darwin10.0.0"
4
5 define void @test1(i8* %Base, i64 %Size) nounwind ssp {
6 bb.nph:                                           ; preds = %entry
7   br label %for.body
8
9 for.body:                                         ; preds = %bb.nph, %for.body
10   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
11   %I.0.014 = getelementptr i8* %Base, i64 %indvar
12   store i8 0, i8* %I.0.014, align 1
13   %indvar.next = add i64 %indvar, 1
14   %exitcond = icmp eq i64 %indvar.next, %Size
15   br i1 %exitcond, label %for.end, label %for.body
16
17 for.end:                                          ; preds = %for.body, %entry
18   ret void
19 ; CHECK: @test1
20 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base, i8 0, i64 %Size, i32 1, i1 false)
21 ; CHECK-NOT: store
22 }
23
24 ; This is a loop that was rotated but where the blocks weren't merged.  This
25 ; shouldn't perturb us.
26 define void @test1a(i8* %Base, i64 %Size) nounwind ssp {
27 bb.nph:                                           ; preds = %entry
28   br label %for.body
29
30 for.body:                                         ; preds = %bb.nph, %for.body
31   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ]
32   %I.0.014 = getelementptr i8* %Base, i64 %indvar
33   store i8 0, i8* %I.0.014, align 1
34   %indvar.next = add i64 %indvar, 1
35   br label %for.body.cont
36 for.body.cont:
37   %exitcond = icmp eq i64 %indvar.next, %Size
38   br i1 %exitcond, label %for.end, label %for.body
39
40 for.end:                                          ; preds = %for.body, %entry
41   ret void
42 ; CHECK: @test1a
43 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base, i8 0, i64 %Size, i32 1, i1 false)
44 ; CHECK-NOT: store
45 }
46
47
48 define void @test2(i32* %Base, i64 %Size) nounwind ssp {
49 entry:
50   %cmp10 = icmp eq i64 %Size, 0
51   br i1 %cmp10, label %for.end, label %for.body
52
53 for.body:                                         ; preds = %entry, %for.body
54   %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
55   %add.ptr.i = getelementptr i32* %Base, i64 %i.011
56   store i32 16843009, i32* %add.ptr.i, align 4
57   %inc = add nsw i64 %i.011, 1
58   %exitcond = icmp eq i64 %inc, %Size
59   br i1 %exitcond, label %for.end, label %for.body
60
61 for.end:                                          ; preds = %for.body, %entry
62   ret void
63 ; CHECK: @test2
64 ; CHECK: br i1 %cmp10,
65 ; CHECK: %tmp = mul i64 %Size, 4
66 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base1, i8 1, i64 %tmp, i32 4, i1 false)
67 ; CHECK-NOT: store
68 }
69
70 ; This is a case where there is an extra may-aliased store in the loop, we can't
71 ; promote the memset.
72 define void @test3(i32* %Base, i64 %Size, i8 *%MayAlias) nounwind ssp {
73 entry:
74   br label %for.body
75
76 for.body:                                         ; preds = %entry, %for.body
77   %i.011 = phi i64 [ %inc, %for.body ], [ 0, %entry ]
78   %add.ptr.i = getelementptr i32* %Base, i64 %i.011
79   store i32 16843009, i32* %add.ptr.i, align 4
80   
81   store i8 42, i8* %MayAlias
82   %inc = add nsw i64 %i.011, 1
83   %exitcond = icmp eq i64 %inc, %Size
84   br i1 %exitcond, label %for.end, label %for.body
85
86 for.end:                                          ; preds = %entry
87   ret void
88 ; CHECK: @test3
89 ; CHECK-NOT: memset
90 ; CHECK: ret void
91 }
92
93
94 ;; TODO: We should be able to promote this memset.  Not yet though.
95 define void @test4(i8* %Base) nounwind ssp {
96 bb.nph:                                           ; preds = %entry
97   %Base100 = getelementptr i8* %Base, i64 1000
98   br label %for.body
99
100 for.body:                                         ; preds = %bb.nph, %for.body
101   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
102   %I.0.014 = getelementptr i8* %Base, i64 %indvar
103   store i8 0, i8* %I.0.014, align 1
104   
105   ;; Store beyond the range memset, should be safe to promote.
106   store i8 42, i8* %Base100
107   
108   %indvar.next = add i64 %indvar, 1
109   %exitcond = icmp eq i64 %indvar.next, 100
110   br i1 %exitcond, label %for.end, label %for.body
111
112 for.end:                                          ; preds = %for.body, %entry
113   ret void
114 ; CHECK-TODO: @test4
115 ; CHECK-TODO: call void @llvm.memset.p0i8.i64(i8* %Base, i8 0, i64 100, i32 1, i1 false)
116 ; CHECK-TODO-NOT: store
117 }
118
119 ; This can't be promoted: the memset is a store of a loop variant value.
120 define void @test5(i8* %Base, i64 %Size) nounwind ssp {
121 bb.nph:                                           ; preds = %entry
122   br label %for.body
123
124 for.body:                                         ; preds = %bb.nph, %for.body
125   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
126   %I.0.014 = getelementptr i8* %Base, i64 %indvar
127   
128   %V = trunc i64 %indvar to i8
129   store i8 %V, i8* %I.0.014, align 1
130   %indvar.next = add i64 %indvar, 1
131   %exitcond = icmp eq i64 %indvar.next, %Size
132   br i1 %exitcond, label %for.end, label %for.body
133
134 for.end:                                          ; preds = %for.body, %entry
135   ret void
136 ; CHECK: @test5
137 ; CHECK-NOT: memset
138 ; CHECK: ret void
139 }
140
141
142 ;; memcpy formation
143 define void @test6(i64 %Size) nounwind ssp {
144 bb.nph:
145   %Base = alloca i8, i32 10000
146   %Dest = alloca i8, i32 10000
147   br label %for.body
148
149 for.body:                                         ; preds = %bb.nph, %for.body
150   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
151   %I.0.014 = getelementptr i8* %Base, i64 %indvar
152   %DestI = getelementptr i8* %Dest, i64 %indvar
153   %V = load i8* %I.0.014, align 1
154   store i8 %V, i8* %DestI, align 1
155   %indvar.next = add i64 %indvar, 1
156   %exitcond = icmp eq i64 %indvar.next, %Size
157   br i1 %exitcond, label %for.end, label %for.body
158
159 for.end:                                          ; preds = %for.body, %entry
160   ret void
161 ; CHECK: @test6
162 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %Dest, i8* %Base, i64 %Size, i32 1, i1 false)
163 ; CHECK-NOT: store
164 ; CHECK: ret void
165 }
166
167
168 ; This is a loop that was rotated but where the blocks weren't merged.  This
169 ; shouldn't perturb us.
170 define void @test7(i8* %Base, i64 %Size) nounwind ssp {
171 bb.nph:                                           ; preds = %entry
172   br label %for.body
173
174 for.body:                                         ; preds = %bb.nph, %for.body
175   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body.cont ]
176   br label %for.body.cont
177 for.body.cont:
178   %I.0.014 = getelementptr i8* %Base, i64 %indvar
179   store i8 0, i8* %I.0.014, align 1
180   %indvar.next = add i64 %indvar, 1
181   %exitcond = icmp eq i64 %indvar.next, %Size
182   br i1 %exitcond, label %for.end, label %for.body
183
184 for.end:                                          ; preds = %for.body, %entry
185   ret void
186 ; CHECK: @test7
187 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %Base, i8 0, i64 %Size, i32 1, i1 false)
188 ; CHECK-NOT: store
189 }
190
191 ; This is a loop should not be transformed, it only executes one iteration.
192 define void @test8(i64* %Ptr, i64 %Size) nounwind ssp {
193 bb.nph:                                           ; preds = %entry
194   br label %for.body
195
196 for.body:                                         ; preds = %bb.nph, %for.body
197   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
198   %PI = getelementptr i64* %Ptr, i64 %indvar
199   store i64 0, i64 *%PI
200   %indvar.next = add i64 %indvar, 1
201   %exitcond = icmp eq i64 %indvar.next, 1
202   br i1 %exitcond, label %for.end, label %for.body
203
204 for.end:                                          ; preds = %for.body, %entry
205   ret void
206 ; CHECK: @test8
207 ; CHECK: store i64 0, i64* %PI
208 }
209
210 declare i8* @external(i8*)
211
212 ;; This cannot be transformed into a memcpy, because the read-from location is
213 ;; mutated by the loop.
214 define void @test9(i64 %Size) nounwind ssp {
215 bb.nph:
216   %Base = alloca i8, i32 10000
217   %Dest = alloca i8, i32 10000
218   
219   %BaseAlias = call i8* @external(i8* %Base)
220   br label %for.body
221
222 for.body:                                         ; preds = %bb.nph, %for.body
223   %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %for.body ]
224   %I.0.014 = getelementptr i8* %Base, i64 %indvar
225   %DestI = getelementptr i8* %Dest, i64 %indvar
226   %V = load i8* %I.0.014, align 1
227   store i8 %V, i8* %DestI, align 1
228
229   ;; This store can clobber the input.
230   store i8 4, i8* %BaseAlias
231  
232   %indvar.next = add i64 %indvar, 1
233   %exitcond = icmp eq i64 %indvar.next, %Size
234   br i1 %exitcond, label %for.end, label %for.body
235
236 for.end:                                          ; preds = %for.body, %entry
237   ret void
238 ; CHECK: @test9
239 ; CHECK-NOT: llvm.memcpy
240 ; CHECK: ret void
241 }
242
243 ; Two dimensional nested loop should be promoted to one big memset.
244 define void @test10(i8* %X) nounwind ssp {
245 entry:
246   br label %bb.nph
247
248 bb.nph:                                           ; preds = %entry, %for.inc10
249   %i.04 = phi i32 [ 0, %entry ], [ %inc12, %for.inc10 ]
250   br label %for.body5
251
252 for.body5:                                        ; preds = %for.body5, %bb.nph
253   %j.02 = phi i32 [ 0, %bb.nph ], [ %inc, %for.body5 ]
254   %mul = mul nsw i32 %i.04, 100
255   %add = add nsw i32 %j.02, %mul
256   %idxprom = sext i32 %add to i64
257   %arrayidx = getelementptr inbounds i8* %X, i64 %idxprom
258   store i8 0, i8* %arrayidx, align 1
259   %inc = add nsw i32 %j.02, 1
260   %cmp4 = icmp eq i32 %inc, 100
261   br i1 %cmp4, label %for.inc10, label %for.body5
262
263 for.inc10:                                        ; preds = %for.body5
264   %inc12 = add nsw i32 %i.04, 1
265   %cmp = icmp eq i32 %inc12, 100
266   br i1 %cmp, label %for.end13, label %bb.nph
267
268 for.end13:                                        ; preds = %for.inc10
269   ret void
270 ; CHECK: @test10
271 ; CHECK: entry:
272 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* %X, i8 0, i64 10000, i32 1, i1 false)
273 ; CHECK-NOT: store
274 ; CHECK: ret void
275 }
276
277 ; On darwin10 (which is the triple in this .ll file) this loop can be turned
278 ; into a memset_pattern call.
279 ; rdar://9009151
280 define void @test11(i32* nocapture %P) nounwind ssp {
281 entry:
282   br label %for.body
283
284 for.body:                                         ; preds = %entry, %for.body
285   %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.body ]
286   %arrayidx = getelementptr i32* %P, i64 %indvar
287   store i32 1, i32* %arrayidx, align 4
288   %indvar.next = add i64 %indvar, 1
289   %exitcond = icmp eq i64 %indvar.next, 10000
290   br i1 %exitcond, label %for.end, label %for.body
291
292 for.end:                                          ; preds = %for.body
293   ret void
294 ; CHECK: @test11
295 ; CHECK-NEXT: entry:
296 ; CHECK-NEXT: bitcast
297 ; CHECK-NEXT: memset_pattern
298 ; CHECK-NOT: store
299 ; CHECK: ret void
300 }
301
302