OLD | NEW |
---|---|
(Empty) | |
1 ; RUN: opt %s -replace-ptrs-with-ints -S | FileCheck %s | |
2 | |
3 target datalayout = "p:32:32:32" | |
4 | |
5 | |
6 declare %struct* @addr_taken_func(%struct*) | |
7 | |
8 @addr_of_func = global %struct* (%struct*)* @addr_taken_func | |
9 ; CHECK: @addr_of_func = global %struct* (%struct*)* bitcast (i32 (i32)* @addr_t aken_func to %struct* (%struct*)*) | |
10 | |
11 @blockaddr = global i8* blockaddress(@indirectbr, %l1) | |
12 ; CHECK: @blockaddr = global i8* blockaddress(@indirectbr, %l1) | |
13 | |
14 | |
15 define i8* @pointer_arg(i8* %ptr, i64 %non_ptr) { | |
16 ret i8* %ptr | |
17 } | |
18 ; CHECK: define i32 @pointer_arg(i32 %ptr, i64 %non_ptr) { | |
19 ; CHECK-NEXT: ret i32 %ptr | |
20 ; CHECK-NEXT: } | |
21 | |
22 | |
23 declare i8* @declared_func(i8*, i64) | |
24 ; CHECK: declare i32 @declared_func(i32, i64) | |
25 | |
26 | |
27 define void @self_reference(i8* %ptr) { | |
28 entry: | |
29 br label %loop | |
30 loop: | |
31 %x = phi i8* [ %x, %loop ], [ %ptr, %entry ] | |
32 br label %loop | |
33 } | |
34 ; CHECK: define void @self_reference(i32 %ptr) { | |
35 ; CHECK: %x = phi i32 [ %x, %loop ], [ %ptr, %entry ] | |
36 | |
37 define i8* @phi_multiple_entry(i1 %arg, i8* %ptr) { | |
38 entry: | |
39 br i1 %arg, label %done, label %done | |
40 done: | |
41 %result = phi i8* [ %ptr, %entry ], [ %ptr, %entry ] | |
42 ret i8* %result | |
43 } | |
44 ; CHECK: define i32 @phi_multiple_entry(i1 %arg, i32 %ptr) { | |
45 ; CHECK: %result = phi i32 [ %ptr, %entry ], [ %ptr, %entry ] | |
46 | |
47 | |
48 define i8* @select(i1 %cond, i8* %val1, i8* %val2) { | |
49 %r = select i1 %cond, i8* %val1, i8* %val2 | |
50 ret i8* %r | |
51 } | |
52 ; CHECK: define i32 @select(i1 %cond, i32 %val1, i32 %val2) { | |
53 ; CHECK-NEXT: %r = select i1 %cond, i32 %val1, i32 %val2 | |
54 | |
55 | |
56 define i32* @ptrtoint_same_size(i32* %ptr) { | |
57 %a = ptrtoint i32* %ptr to i32 | |
58 %b = add i32 %a, 4 | |
59 %c = inttoptr i32 %b to i32* | |
60 ret i32* %c | |
61 } | |
62 ; CHECK: define i32 @ptrtoint_same_size(i32 %ptr) { | |
63 ; CHECK-NEXT: %b = add i32 %ptr, 4 | |
64 ; CHECK-NEXT: ret i32 %b | |
65 | |
66 | |
67 define i32* @ptrtoint_different_size(i32* %ptr) { | |
68 %a = ptrtoint i32* %ptr to i64 | |
69 %b = add i64 %a, 4 | |
70 %c = inttoptr i64 %b to i32* | |
71 ret i32* %c | |
72 } | |
73 ; CHECK: define i32 @ptrtoint_different_size(i32 %ptr) { | |
74 ; CHECK-NEXT: %a = zext i32 %ptr to i64 | |
75 ; CHECK-NEXT: %b = add i64 %a, 4 | |
76 ; CHECK-NEXT: %c = trunc i64 %b to i32 | |
77 ; CHECK-NEXT: ret i32 %c | |
78 | |
79 | |
80 define i32* @pointer_bitcast(i64* %ptr) { | |
81 %cast = bitcast i64* %ptr to i32* | |
82 ret i32* %cast | |
83 } | |
84 ; CHECK: define i32 @pointer_bitcast(i32 %ptr) { | |
85 ; CHECK-NEXT: ret i32 %ptr | |
86 | |
87 ; Same-type non-pointer bitcasts happen to be left alone by this pass. | |
88 define i32 @no_op_bitcast(i32 %val) { | |
89 %val2 = bitcast i32 %val to i32 | |
90 ret i32 %val2 | |
91 } | |
92 ; CHECK: define i32 @no_op_bitcast(i32 %val) { | |
93 ; CHECK-NEXT: %val2 = bitcast i32 %val to i32 | |
94 | |
95 define i64 @kept_bitcast(double %d) { | |
96 %i = bitcast double %d to i64 | |
97 ret i64 %i | |
98 } | |
99 ; CHECK: define i64 @kept_bitcast(double %d) { | |
100 ; CHECK-NEXT: %i = bitcast double %d to i64 | |
101 | |
102 | |
103 define i32 @constant_pointer_null() { | |
104 %val = ptrtoint i32* null to i32 | |
105 ret i32 %val | |
106 } | |
107 ; CHECK: define i32 @constant_pointer_null() { | |
108 ; CHECK-NEXT: ret i32 0 | |
109 | |
110 define i32 @constant_pointer_undef() { | |
111 %val = ptrtoint i32* undef to i32 | |
112 ret i32 %val | |
113 } | |
114 ; CHECK: define i32 @constant_pointer_undef() { | |
115 ; CHECK-NEXT: ret i32 undef | |
116 | |
117 define i16* @constant_pointer_null_load() { | |
118 %val = load i16** null | |
119 ret i16* %val | |
120 } | |
121 ; CHECK: define i32 @constant_pointer_null_load() { | |
122 ; CHECK-NEXT: %.asptr = inttoptr i32 0 to i32* | |
123 ; CHECK-NEXT: %val = load i32* %.asptr | |
124 | |
125 | |
126 define i8 @load(i8* %ptr) { | |
127 %x = load i8* %ptr | |
128 ret i8 %x | |
129 } | |
130 ; CHECK: define i8 @load(i32 %ptr) { | |
131 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
132 ; CHECK-NEXT: %x = load i8* %ptr.asptr | |
133 | |
134 define void @store(i8* %ptr, i8 %val) { | |
135 store i8 %val, i8* %ptr | |
136 ret void | |
137 } | |
138 ; CHECK: define void @store(i32 %ptr, i8 %val) { | |
139 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
140 ; CHECK-NEXT: store i8 %val, i8* %ptr.asptr | |
141 | |
142 | |
143 define i8* @load_ptr(i8** %ptr) { | |
144 %x = load i8** %ptr | |
145 ret i8* %x | |
146 } | |
147 ; CHECK: define i32 @load_ptr(i32 %ptr) { | |
148 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
149 ; CHECK-NEXT: %x = load i32* %ptr.asptr | |
150 | |
151 define void @store_ptr(i8** %ptr, i8* %val) { | |
152 store i8* %val, i8** %ptr | |
153 ret void | |
154 } | |
155 ; CHECK: define void @store_ptr(i32 %ptr, i32 %val) { | |
156 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
157 ; CHECK-NEXT: store i32 %val, i32* %ptr.asptr | |
158 | |
159 | |
160 define i8 @load_attrs(i8* %ptr) { | |
161 %x = load atomic volatile i8* %ptr seq_cst, align 128 | |
162 ret i8 %x | |
163 } | |
164 ; CHECK: define i8 @load_attrs(i32 %ptr) { | |
165 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
166 ; CHECK-NEXT: %x = load atomic volatile i8* %ptr.asptr seq_cst, align 128 | |
167 | |
168 define void @store_attrs(i8* %ptr, i8 %val) { | |
169 store atomic volatile i8 %val, i8* %ptr singlethread release, align 256 | |
170 ret void | |
171 } | |
172 ; CHECK: define void @store_attrs(i32 %ptr, i8 %val) { | |
173 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
174 ; CHECK-NEXT: store atomic volatile i8 %val, i8* %ptr.asptr singlethread release , align 256 | |
175 | |
176 | |
177 define i32 @cmpxchg(i32* %ptr, i32 %a, i32 %b) { | |
178 %r = cmpxchg i32* %ptr, i32 %a, i32 %b seq_cst | |
179 ret i32 %r | |
180 } | |
181 ; CHECK: define i32 @cmpxchg(i32 %ptr, i32 %a, i32 %b) { | |
182 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
183 ; CHECK-NEXT: %r = cmpxchg i32* %ptr.asptr, i32 %a, i32 %b seq_cst | |
184 | |
185 define i32 @atomicrmw(i32* %ptr, i32 %x) { | |
186 %r = atomicrmw add i32* %ptr, i32 %x seq_cst | |
187 ret i32 %r | |
188 } | |
189 ; CHECK: define i32 @atomicrmw(i32 %ptr, i32 %x) { | |
190 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
191 ; CHECK-NEXT: %r = atomicrmw add i32* %ptr.asptr, i32 %x seq_cst | |
192 | |
193 | |
194 define i8* @indirect_call(i8* (i8*)* %func, i8* %arg) { | |
195 %result = call i8* %func(i8* %arg) | |
196 ret i8* %result | |
197 } | |
198 ; CHECK: define i32 @indirect_call(i32 %func, i32 %arg) { | |
199 ; CHECK-NEXT: %func.asfuncptr = inttoptr i32 %func to i32 (i32)* | |
200 ; CHECK-NEXT: %result = call i32 %func.asfuncptr(i32 %arg) | |
201 ; CHECK-NEXT: ret i32 %result | |
202 | |
203 | |
204 ; Test forwards reference | |
205 define i8* @direct_call1(i8* %arg) { | |
206 %result = call i8* @direct_call2(i8* %arg) | |
207 ret i8* %result | |
208 } | |
209 ; CHECK: define i32 @direct_call1(i32 %arg) { | |
210 ; CHECK-NEXT: %result = call i32 @direct_call2(i32 %arg) | |
211 ; CHECK-NEXT: ret i32 %result | |
212 | |
213 ; Test backwards reference | |
214 define i8* @direct_call2(i8* %arg) { | |
215 %result = call i8* @direct_call1(i8* %arg) | |
216 ret i8* %result | |
217 } | |
218 ; CHECK: define i32 @direct_call2(i32 %arg) { | |
219 ; CHECK-NEXT: %result = call i32 @direct_call1(i32 %arg) | |
220 ; CHECK-NEXT: ret i32 %result | |
221 | |
222 | |
223 @var = global i32 0 | |
224 | |
225 define i32* @get_addr_of_global() { | |
226 ret i32* @var | |
227 } | |
228 ; CHECK: define i32 @get_addr_of_global() { | |
229 ; CHECK-NEXT: %expanded = ptrtoint i32* @var to i32 | |
230 ; CHECK-NEXT: ret i32 %expanded | |
231 | |
232 define %struct* (%struct*)* @get_addr_of_func() { | |
233 ret %struct* (%struct*)* @addr_taken_func | |
234 } | |
235 ; CHECK: define i32 @get_addr_of_func() { | |
236 ; CHECK-NEXT: %expanded = ptrtoint i32 (i32)* @addr_taken_func to i32 | |
237 ; CEHCK-NEXT: ret i32 %expanded | |
238 | |
239 | |
240 define i32 @load_global() { | |
241 %val = load i32* @var | |
242 ret i32 %val | |
243 } | |
244 ; CHECK: define i32 @load_global() { | |
245 ; CHECK-NEXT: %val = load i32* @var | |
246 ; CHECK-NEXT: ret i32 %val | |
247 | |
248 define i16 @load_global_bitcast() { | |
249 %ptr = bitcast i32* @var to i16* | |
250 %val = load i16* %ptr | |
251 ret i16 %val | |
252 } | |
253 ; CHECK: define i16 @load_global_bitcast() { | |
254 ; CHECK-NEXT: %var.bc = bitcast i32* @var to i16* | |
255 ; CHECK-NEXT: %val = load i16* %var.bc | |
256 ; CHECK-NEXT: ret i16 %val | |
257 | |
258 | |
259 %struct = type { i32, i32 } | |
Derek Schuff
2013/05/17 23:16:05
can you move this decl to the top since there are
Mark Seaborn
2013/05/20 15:08:12
Done.
| |
260 | |
261 declare void @receive_alloca(%struct* %ptr) | |
262 | |
263 define void @alloca_fixed() { | |
264 %buf = alloca %struct, align 128 | |
265 call void @receive_alloca(%struct* %buf) | |
266 ret void | |
267 } | |
268 ; CHECK: define void @alloca_fixed() { | |
269 ; CHECK-NEXT: %buf = alloca [8 x i8], align 128 | |
270 ; CHECK-NEXT: %buf.asint = ptrtoint [8 x i8]* %buf to i32 | |
271 ; CHECK-NEXT: call void @receive_alloca(i32 %buf.asint) | |
272 | |
273 define void @alloca_variable(i32 %size) { | |
274 %buf = alloca %struct, i32 %size | |
275 call void @receive_alloca(%struct* %buf) | |
276 ret void | |
277 } | |
278 ; CHECK: define void @alloca_variable(i32 %size) { | |
279 ; CHECK-NEXT: %buf = alloca [8 x i8], i32 %size | |
280 ; CHECK-NEXT: %buf.asint = ptrtoint [8 x i8]* %buf to i32 | |
281 ; CHECK-NEXT: call void @receive_alloca(i32 %buf.asint) | |
282 | |
283 | |
284 define i1 @compare(i8* %ptr1, i8* %ptr2) { | |
285 %cmp = icmp ult i8* %ptr1, %ptr2 | |
286 ret i1 %cmp | |
287 } | |
288 ; CHECK: define i1 @compare(i32 %ptr1, i32 %ptr2) { | |
289 ; CHECK-NEXT: %cmp = icmp ult i32 %ptr1, %ptr2 | |
290 | |
291 | |
292 declare i8* @llvm.some.intrinsic(i8* %ptr) | |
293 | |
294 define i8* @preserve_intrinsic_type(i8* %ptr) { | |
295 %result = call i8* @llvm.some.intrinsic(i8* %ptr) | |
296 ret i8* %result | |
297 } | |
298 ; CHECK: define i32 @preserve_intrinsic_type(i32 %ptr) { | |
299 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
300 ; CHECK-NEXT: %result = call i8* @llvm.some.intrinsic(i8* %ptr.asptr) | |
301 ; CHECK-NEXT: %result.asint = ptrtoint i8* %result to i32 | |
302 ; CHECK-NEXT: ret i32 %result.asint | |
303 | |
304 | |
305 ; Just check that the pass does not crash on inline asm. | |
306 define i16* @inline_asm1(i8* %ptr) { | |
307 %val = call i16* asm "foo", "=r,r"(i8* %ptr) | |
308 ret i16* %val | |
309 } | |
310 | |
311 define i16** @inline_asm2(i8** %ptr) { | |
312 %val = call i16** asm "foo", "=r,r"(i8** %ptr) | |
313 ret i16** %val | |
314 } | |
315 | |
316 | |
317 declare void @llvm.dbg.declare(metadata, metadata) | |
318 declare void @llvm.dbg.value(metadata, i64, metadata) | |
319 | |
320 define void @debug_declare(i32 %val) { | |
321 ; We normally expect llvm.dbg.declare to be used on an alloca. | |
322 %var = alloca i32 | |
323 tail call void @llvm.dbg.declare(metadata !{i32* %var}, metadata !{}) | |
324 tail call void @llvm.dbg.declare(metadata !{i32 %val}, metadata !{}) | |
325 ret void | |
326 } | |
327 ; CHECK: define void @debug_declare(i32 %val) { | |
328 ; CHECK-NEXT: %var = alloca [4 x i8] | |
329 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata !{[4 x i8]* %var}, metadata ! 0) | |
330 ; This case is currently not converted. | |
331 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata !{null}, metadata !0) | |
332 ; CHECK-NEXT: ret void | |
333 | |
334 ; For now, debugging info for values is lost. replaceAllUsesWith() | |
335 ; does not work for metadata references -- it converts them to nulls. | |
336 ; This makes dbg.value too tricky to handle for now. | |
337 define void @debug_value(i32 %val, i8* %ptr) { | |
338 tail call void @llvm.dbg.value(metadata !{i32 %val}, i64 1, metadata !{}) | |
339 tail call void @llvm.dbg.value(metadata !{i8* %ptr}, i64 2, metadata !{}) | |
340 ret void | |
341 } | |
342 ; CHECK: define void @debug_value(i32 %val, i32 %ptr) { | |
343 ; CHECK-NEXT: call void @llvm.dbg.value(metadata !{null}, i64 1, metadata !0) | |
344 ; CHECK-NEXT: call void @llvm.dbg.value(metadata !{null}, i64 2, metadata !0) | |
345 ; CHECK-NEXT: ret void | |
346 | |
347 | |
348 declare void @llvm.lifetime.start(i64 %size, i8* %ptr) | |
349 | |
350 define void @alloca_lifetime() { | |
351 %buf = alloca i8 | |
352 call void @llvm.lifetime.start(i64 1, i8* %buf) | |
353 ret void | |
354 } | |
355 ; For lifetime.start to have an effect, it must be given a bitcast of | |
356 ; the alloca (or the alloca itself). It doesn't work on | |
357 ; ptrtoint+inttoptr. | |
358 ; CHECK: define void @alloca_lifetime() { | |
359 ; CHECK-NEXT: %buf = alloca [1 x i8] | |
360 ; CHECK-NEXT: %buf.bc = bitcast [1 x i8]* %buf to i8* | |
361 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* %buf.bc) | |
362 | |
363 define void @alloca_lifetime_via_bitcast() { | |
364 %buf = alloca i32 | |
365 %buf_cast = bitcast i32* %buf to i8* | |
366 call void @llvm.lifetime.start(i64 1, i8* %buf_cast) | |
367 ret void | |
368 } | |
369 ; CHECK: define void @alloca_lifetime_via_bitcast() { | |
370 ; CHECK-NEXT: %buf = alloca [4 x i8] | |
371 ; CHECK-NEXT: %buf.bc = bitcast [4 x i8]* %buf to i8* | |
372 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* %buf.bc) | |
373 | |
374 | |
375 ; "nocapture" and "noalias" only apply to pointers, so must be stripped. | |
376 define void @nocapture_attr(i8* nocapture noalias %ptr) { | |
377 ret void | |
378 } | |
379 ; CHECK: define void @nocapture_attr(i32 %ptr) { | |
380 | |
381 ; "nounwind" should be preserved. | |
382 define void @nounwind_func_attr() nounwind { | |
383 ret void | |
384 } | |
385 ; CHECK: define void @nounwind_func_attr() [[NOUNWIND:#[0-9]+]] { | |
386 | |
387 define void @nounwind_call_attr() { | |
388 call void @nounwind_func_attr() nounwind | |
389 ret void | |
390 } | |
391 ; CHECK: define void @nounwind_call_attr() { | |
392 ; CHECK: call void @nounwind_func_attr() {{.*}}[[NOUNWIND]] | |
393 | |
394 define fastcc void @fastcc_func() { | |
395 ret void | |
396 } | |
397 ; CHECK: define fastcc void @fastcc_func() { | |
398 | |
399 define void @fastcc_call() { | |
400 call fastcc void @fastcc_func() | |
401 ret void | |
402 } | |
403 ; CHECK: define void @fastcc_call() { | |
404 ; CHECK-NEXT: call fastcc void @fastcc_func() | |
405 | |
406 | |
407 ; Just check that the pass does not crash on getelementptr. (The pass | |
408 ; should not depend unnecessarily on ExpandGetElementPtr having been | |
409 ; run.) | |
410 define i8* @getelementptr(i8* %ptr) { | |
411 %gep = getelementptr i8* %ptr, i32 10 | |
412 ret i8* %gep | |
413 } | |
414 | |
415 ; Just check that the pass does not crash on va_arg. | |
416 define i32* @va_arg(i8* %valist) { | |
417 %r = va_arg i8* %valist, i32* | |
418 ret i32* %r | |
419 } | |
420 | |
421 | |
422 define void @indirectbr(i8* %addr) { | |
423 indirectbr i8* %addr, [ label %l1, label %l2 ] | |
424 l1: | |
425 ret void | |
426 l2: | |
427 ret void | |
428 } | |
429 ; CHECK: define void @indirectbr(i32 %addr) { | |
430 ; CHECK-NEXT: %addr.asptr = inttoptr i32 %addr to i8* | |
431 ; CHECK-NEXT: indirectbr i8* %addr.asptr, [label %l1, label %l2] | |
432 | |
433 | |
434 define i8* @invoke(i8* %val) { | |
435 %result = invoke i8* @direct_call1(i8* %val) | |
436 to label %cont unwind label %lpad | |
437 cont: | |
438 ret i8* %result | |
439 lpad: | |
440 %lp = landingpad { i8*, i32 } personality void (i8*)* @personality_func cleanu p | |
441 %p = extractvalue { i8*, i32 } %lp, 0 | |
442 %s = insertvalue { i8*, i32 } %lp, i8* %val, 0 | |
443 ret i8* %p | |
444 } | |
445 ; CHECK: define i32 @invoke(i32 %val) { | |
446 ; CHECK-NEXT: %result = invoke i32 @direct_call1(i32 %val) | |
447 ; CHECK-NEXT: to label %cont unwind label %lpad | |
448 ; CHECK: %lp = landingpad { i8*, i32 } personality void (i8*)* bitcast (void (i3 2)* @personality_func to void (i8*)*) | |
449 ; CHECK: %p = extractvalue { i8*, i32 } %lp, 0 | |
450 ; CHECK-NEXT: %p.asint = ptrtoint i8* %p to i32 | |
451 ; CHECK-NEXT: %val.asptr = inttoptr i32 %val to i8* | |
452 ; CHECK-NEXT: %s = insertvalue { i8*, i32 } %lp, i8* %val.asptr, 0 | |
453 ; CHECK-NEXT: ret i32 %p.asint | |
454 | |
455 define void @personality_func(i8* %arg) { | |
456 ret void | |
457 } | |
458 | |
459 | |
460 declare i32 @llvm.eh.typeid.for(i8*) | |
461 | |
462 @typeid = global i32 0 | |
463 | |
464 ; The argument here must be left as a bitcast, otherwise the backend | |
465 ; rejects it. | |
466 define void @typeid_for() { | |
467 %bc = bitcast i32* @typeid to i8* | |
468 call i32 @llvm.eh.typeid.for(i8* %bc) | |
469 ret void | |
470 } | |
471 ; CHECK: define void @typeid_for() { | |
472 ; CHECK-NEXT: %typeid.bc = bitcast i32* @typeid to i8* | |
473 ; CHECK-NEXT: call i32 @llvm.eh.typeid.for(i8* %typeid.bc) | |
474 | |
475 | |
476 ; CHECK: attributes {{.*}}[[NOUNWIND]] = { nounwind } | |
OLD | NEW |