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 @return_void() { | |
eliben
2013/05/15 22:11:21
What is this for?
Mark Seaborn
2013/05/16 02:08:40
This was just checking that the pass doesn't barf
| |
28 ret void | |
29 } | |
30 | |
31 | |
32 define void @self_reference(i8* %ptr) { | |
33 entry: | |
34 br label %loop | |
35 loop: | |
36 %x = phi i8* [ %x, %loop ], [ %ptr, %entry ] | |
37 br label %loop | |
38 } | |
39 ; CHECK: define void @self_reference(i32 %ptr) { | |
40 ; CHECK: %x = phi i32 [ %x, %loop ], [ %ptr, %entry ] | |
41 | |
42 define i8* @phi_multiple_entry(i1 %arg, i8* %ptr) { | |
43 entry: | |
44 br i1 %arg, label %done, label %done | |
45 done: | |
46 %result = phi i8* [ %ptr, %entry ], [ %ptr, %entry ] | |
47 ret i8* %result | |
48 } | |
49 ; CHECK: define i32 @phi_multiple_entry(i1 %arg, i32 %ptr) { | |
50 ; CHECK: %result = phi i32 [ %ptr, %entry ], [ %ptr, %entry ] | |
51 | |
52 | |
53 define i8* @select(i1 %cond, i8* %val1, i8* %val2) { | |
54 %r = select i1 %cond, i8* %val1, i8* %val2 | |
55 ret i8* %r | |
56 } | |
57 ; CHECK: define i32 @select(i1 %cond, i32 %val1, i32 %val2) { | |
58 ; CHECK-NEXT: %r = select i1 %cond, i32 %val1, i32 %val2 | |
59 | |
60 | |
61 define i32* @ptrtoint_same_size(i32* %ptr) { | |
62 %a = ptrtoint i32* %ptr to i32 | |
63 %b = add i32 %a, 4 | |
64 %c = inttoptr i32 %b to i32* | |
65 ret i32* %c | |
66 } | |
67 ; CHECK: define i32 @ptrtoint_same_size(i32 %ptr) { | |
68 ; CHECK-NEXT: %b = add i32 %ptr, 4 | |
69 ; CHECK-NEXT: ret i32 %b | |
70 | |
71 | |
72 define i32* @ptrtoint_different_size(i32* %ptr) { | |
73 %a = ptrtoint i32* %ptr to i64 | |
74 %b = add i64 %a, 4 | |
75 %c = inttoptr i64 %b to i32* | |
76 ret i32* %c | |
77 } | |
78 ; CHECK: define i32 @ptrtoint_different_size(i32 %ptr) { | |
79 ; CHECK-NEXT: %a = zext i32 %ptr to i64 | |
80 ; CHECK-NEXT: %b = add i64 %a, 4 | |
81 ; CHECK-NEXT: %c = trunc i64 %b to i32 | |
82 ; CHECK-NEXT: ret i32 %c | |
83 | |
84 | |
85 define i32* @pointer_bitcast(i64* %ptr) { | |
86 %cast = bitcast i64* %ptr to i32* | |
87 ret i32* %cast | |
88 } | |
89 ; CHECK: define i32 @pointer_bitcast(i32 %ptr) { | |
90 ; CHECK-NEXT: ret i32 %ptr | |
91 | |
92 ; Same-type non-pointer bitcasts happen to be left alone by this pass. | |
93 define i32 @no_op_bitcast(i32 %val) { | |
94 %val2 = bitcast i32 %val to i32 | |
95 ret i32 %val2 | |
96 } | |
97 ; CHECK: define i32 @no_op_bitcast(i32 %val) { | |
98 ; CHECK-NEXT: %val2 = bitcast i32 %val to i32 | |
99 | |
100 define i64 @kept_bitcast(double %d) { | |
101 %i = bitcast double %d to i64 | |
102 ret i64 %i | |
103 } | |
104 ; CHECK: define i64 @kept_bitcast(double %d) { | |
105 ; CHECK-NEXT: %i = bitcast double %d to i64 | |
106 | |
107 | |
108 define i32 @constant_pointer_null() { | |
109 %val = ptrtoint i32* null to i32 | |
110 ret i32 %val | |
111 } | |
112 ; CHECK: define i32 @constant_pointer_null() { | |
113 ; CHECK-NEXT: ret i32 0 | |
114 | |
115 define i32 @constant_pointer_undef() { | |
116 %val = ptrtoint i32* undef to i32 | |
117 ret i32 %val | |
118 } | |
119 ; CHECK: define i32 @constant_pointer_undef() { | |
120 ; CHECK-NEXT: ret i32 undef | |
121 | |
122 define i16* @constant_pointer_null_load() { | |
123 %val = load i16** null | |
124 ret i16* %val | |
125 } | |
126 ; CHECK: define i32 @constant_pointer_null_load() { | |
127 ; CHECK-NEXT: %.asptr = inttoptr i32 0 to i32* | |
128 ; CHECK-NEXT: %val = load i32* %.asptr | |
129 | |
130 | |
131 define i8 @load(i8* %ptr) { | |
132 %x = load i8* %ptr | |
133 ret i8 %x | |
134 } | |
135 ; CHECK: define i8 @load(i32 %ptr) { | |
136 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
137 ; CHECK-NEXT: %x = load i8* %ptr.asptr | |
138 | |
139 define void @store(i8* %ptr, i8 %val) { | |
140 store i8 %val, i8* %ptr | |
141 ret void | |
142 } | |
143 ; CHECK: define void @store(i32 %ptr, i8 %val) { | |
144 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
145 ; CHECK-NEXT: store i8 %val, i8* %ptr.asptr | |
146 | |
147 | |
148 define i8* @load_ptr(i8** %ptr) { | |
149 %x = load i8** %ptr | |
150 ret i8* %x | |
151 } | |
152 ; CHECK: define i32 @load_ptr(i32 %ptr) { | |
153 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
154 ; CHECK-NEXT: %x = load i32* %ptr.asptr | |
155 | |
156 define void @store_ptr(i8** %ptr, i8* %val) { | |
157 store i8* %val, i8** %ptr | |
158 ret void | |
159 } | |
160 ; CHECK: define void @store_ptr(i32 %ptr, i32 %val) { | |
161 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
162 ; CHECK-NEXT: store i32 %val, i32* %ptr.asptr | |
163 | |
164 | |
165 define i8 @load_attrs(i8* %ptr) { | |
166 %x = load atomic volatile i8* %ptr seq_cst, align 128 | |
167 ret i8 %x | |
168 } | |
169 ; CHECK: define i8 @load_attrs(i32 %ptr) { | |
170 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
171 ; CHECK-NEXT: %x = load atomic volatile i8* %ptr.asptr seq_cst, align 128 | |
172 | |
173 define void @store_attrs(i8* %ptr, i8 %val) { | |
174 store atomic volatile i8 %val, i8* %ptr singlethread release, align 256 | |
175 ret void | |
176 } | |
177 ; CHECK: define void @store_attrs(i32 %ptr, i8 %val) { | |
178 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
179 ; CHECK-NEXT: store atomic volatile i8 %val, i8* %ptr.asptr singlethread release , align 256 | |
180 | |
181 | |
182 define i32 @cmpxchg(i32* %ptr, i32 %a, i32 %b) { | |
183 %r = cmpxchg i32* %ptr, i32 %a, i32 %b seq_cst | |
184 ret i32 %r | |
185 } | |
186 ; CHECK: define i32 @cmpxchg(i32 %ptr, i32 %a, i32 %b) { | |
187 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
188 ; CHECK-NEXT: %r = cmpxchg i32* %ptr.asptr, i32 %a, i32 %b seq_cst | |
189 | |
190 define i32 @atomicrmw(i32* %ptr, i32 %x) { | |
191 %r = atomicrmw add i32* %ptr, i32 %x seq_cst | |
192 ret i32 %r | |
193 } | |
194 ; CHECK: define i32 @atomicrmw(i32 %ptr, i32 %x) { | |
195 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i32* | |
196 ; CHECK-NEXT: %r = atomicrmw add i32* %ptr.asptr, i32 %x seq_cst | |
197 | |
198 | |
199 define i8* @indirect_call(i8* (i8*)* %func, i8* %arg) { | |
200 %result = call i8* %func(i8* %arg) | |
201 ret i8* %result | |
202 } | |
203 ; CHECK: define i32 @indirect_call(i32 %func, i32 %arg) { | |
204 ; CHECK-NEXT: %func.asfuncptr = inttoptr i32 %func to i32 (i32)* | |
205 ; CHECK-NEXT: %result = call i32 %func.asfuncptr(i32 %arg) | |
206 ; CHECK-NEXT: ret i32 %result | |
207 | |
208 | |
209 ; Test forwards reference | |
210 define i8* @direct_call1(i8* %arg) { | |
211 %result = call i8* @direct_call2(i8* %arg) | |
212 ret i8* %result | |
213 } | |
214 ; CHECK: define i32 @direct_call1(i32 %arg) { | |
215 ; CHECK-NEXT: %result = call i32 @direct_call2(i32 %arg) | |
216 ; CHECK-NEXT: ret i32 %result | |
217 | |
218 ; Test backwards reference | |
219 define i8* @direct_call2(i8* %arg) { | |
220 %result = call i8* @direct_call1(i8* %arg) | |
221 ret i8* %result | |
222 } | |
223 ; CHECK: define i32 @direct_call2(i32 %arg) { | |
224 ; CHECK-NEXT: %result = call i32 @direct_call1(i32 %arg) | |
225 ; CHECK-NEXT: ret i32 %result | |
226 | |
227 | |
228 @var = global i32 0 | |
229 | |
230 define i32* @get_addr_of_global() { | |
231 ret i32* @var | |
232 } | |
233 ; CHECK: define i32 @get_addr_of_global() { | |
234 ; CHECK-NEXT: %expanded = ptrtoint i32* @var to i32 | |
235 ; CHECK-NEXT: ret i32 %expanded | |
236 | |
237 define %struct* (%struct*)* @get_addr_of_func() { | |
238 ret %struct* (%struct*)* @addr_taken_func | |
239 } | |
240 ; CHECK: define i32 @get_addr_of_func() { | |
241 ; CHECK-NEXT: %expanded = ptrtoint i32 (i32)* @addr_taken_func to i32 | |
242 ; CEHCK-NEXT: ret i32 %expanded | |
243 | |
244 | |
245 define i32 @load_global() { | |
246 %val = load i32* @var | |
247 ret i32 %val | |
248 } | |
249 ; CHECK: define i32 @load_global() { | |
250 ; CHECK-NEXT: %val = load i32* @var | |
251 ; CHECK-NEXT: ret i32 %val | |
252 | |
253 define i16 @load_global_bitcast() { | |
254 %ptr = bitcast i32* @var to i16* | |
255 %val = load i16* %ptr | |
256 ret i16 %val | |
257 } | |
258 ; CHECK: define i16 @load_global_bitcast() { | |
259 ; CHECK-NEXT: %var.bc = bitcast i32* @var to i16* | |
260 ; CHECK-NEXT: %val = load i16* %var.bc | |
261 ; CHECK-NEXT: ret i16 %val | |
262 | |
263 | |
264 %struct = type { i32, i32 } | |
265 | |
266 declare void @receive_alloca(%struct* %ptr) | |
267 | |
268 define void @alloca_fixed() { | |
269 %buf = alloca %struct, align 128 | |
270 call void @receive_alloca(%struct* %buf) | |
271 ret void | |
272 } | |
273 ; CHECK: define void @alloca_fixed() { | |
274 ; CHECK-NEXT: %buf = alloca [8 x i8], align 128 | |
275 ; CHECK-NEXT: %buf.asint = ptrtoint [8 x i8]* %buf to i32 | |
276 ; CHECK-NEXT: call void @receive_alloca(i32 %buf.asint) | |
277 | |
278 define void @alloca_variable(i32 %size) { | |
279 %buf = alloca %struct, i32 %size | |
280 call void @receive_alloca(%struct* %buf) | |
281 ret void | |
282 } | |
283 ; CHECK: define void @alloca_variable(i32 %size) { | |
284 ; CHECK-NEXT: %buf = alloca [8 x i8], i32 %size | |
285 ; CHECK-NEXT: %buf.asint = ptrtoint [8 x i8]* %buf to i32 | |
286 ; CHECK-NEXT: call void @receive_alloca(i32 %buf.asint) | |
287 | |
288 | |
289 define i1 @compare(i8* %ptr1, i8* %ptr2) { | |
290 %cmp = icmp ult i8* %ptr1, %ptr2 | |
291 ret i1 %cmp | |
292 } | |
293 ; CHECK: define i1 @compare(i32 %ptr1, i32 %ptr2) { | |
294 ; CHECK-NEXT: %cmp = icmp ult i32 %ptr1, %ptr2 | |
295 | |
296 | |
297 declare i8* @llvm.some.intrinsic(i8* %ptr) | |
298 | |
299 define i8* @preserve_intrinsic_type(i8* %ptr) { | |
300 %result = call i8* @llvm.some.intrinsic(i8* %ptr) | |
301 ret i8* %result | |
302 } | |
303 ; CHECK: define i32 @preserve_intrinsic_type(i32 %ptr) { | |
304 ; CHECK-NEXT: %ptr.asptr = inttoptr i32 %ptr to i8* | |
305 ; CHECK-NEXT: %result = call i8* @llvm.some.intrinsic(i8* %ptr.asptr) | |
306 ; CHECK-NEXT: %result.asint = ptrtoint i8* %result to i32 | |
307 ; CHECK-NEXT: ret i32 %result.asint | |
308 | |
309 | |
310 define i16* @inline_asm1(i8* %ptr) { | |
311 %val = call i16* asm "foo", "=r,r"(i8* %ptr) | |
312 ret i16* %val | |
313 } | |
314 | |
315 define i16** @inline_asm2(i8** %ptr) { | |
316 %val = call i16** asm "foo", "=r,r"(i8** %ptr) | |
317 ret i16** %val | |
318 } | |
319 | |
320 | |
321 declare void @llvm.dbg.declare(metadata, metadata) | |
322 declare void @llvm.dbg.value(metadata, i64, metadata) | |
323 | |
324 define void @debug_declare(i32 %val) { | |
325 ; We normally expect llvm.dbg.declare to be used on an alloca. | |
326 %var = alloca i32 | |
327 tail call void @llvm.dbg.declare(metadata !{i32* %var}, metadata !{}) | |
328 tail call void @llvm.dbg.declare(metadata !{i32 %val}, metadata !{}) | |
329 ret void | |
330 } | |
331 ; CHECK: define void @debug_declare(i32 %val) { | |
332 ; CHECK-NEXT: %var = alloca [4 x i8] | |
333 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata !{[4 x i8]* %var}, metadata ! 0) | |
334 ; This case is currently not converted. | |
335 ; CHECK-NEXT: call void @llvm.dbg.declare(metadata !{null}, metadata !0) | |
336 ; CHECK-NEXT: ret void | |
337 | |
338 ; For now, debugging info for values is lost. replaceAllUsesWith() | |
339 ; does not work for metadata references -- it converts them to nulls. | |
340 ; This makes dbg.value too tricky to handle for now. | |
341 define void @debug_value(i32 %val, i8* %ptr) { | |
342 tail call void @llvm.dbg.value(metadata !{i32 %val}, i64 1, metadata !{}) | |
343 tail call void @llvm.dbg.value(metadata !{i8* %ptr}, i64 2, metadata !{}) | |
344 ret void | |
345 } | |
346 ; CHECK: define void @debug_value(i32 %val, i32 %ptr) { | |
347 ; CHECK-NEXT: call void @llvm.dbg.value(metadata !{null}, i64 1, metadata !0) | |
348 ; CHECK-NEXT: call void @llvm.dbg.value(metadata !{null}, i64 2, metadata !0) | |
349 ; CHECK-NEXT: ret void | |
350 | |
351 | |
352 declare void @llvm.lifetime.start(i64 %size, i8* %ptr) | |
353 | |
354 define void @alloca_lifetime() { | |
355 %buf = alloca i8 | |
356 call void @llvm.lifetime.start(i64 1, i8* %buf) | |
357 ret void | |
358 } | |
359 ; For lifetime.start to have an effect, it must be given a bitcast of | |
360 ; the alloca (or the alloca itself). It doesn't work on | |
361 ; ptrtoint+inttoptr. | |
362 ; CHECK: define void @alloca_lifetime() { | |
363 ; CHECK-NEXT: %buf = alloca [1 x i8] | |
364 ; CHECK-NEXT: %buf.bc = bitcast [1 x i8]* %buf to i8* | |
365 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* %buf.bc) | |
366 | |
367 define void @alloca_lifetime_via_bitcast() { | |
368 %buf = alloca i32 | |
369 %buf_cast = bitcast i32* %buf to i8* | |
370 call void @llvm.lifetime.start(i64 1, i8* %buf_cast) | |
371 ret void | |
372 } | |
373 ; CHECK: define void @alloca_lifetime_via_bitcast() { | |
374 ; CHECK-NEXT: %buf = alloca [4 x i8] | |
375 ; CHECK-NEXT: %buf.bc = bitcast [4 x i8]* %buf to i8* | |
376 ; CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* %buf.bc) | |
377 | |
378 | |
379 ; "nocapture" and "noalias" only apply to pointers, so must be stripped. | |
380 define void @nocapture_attr(i8* nocapture noalias %ptr) { | |
381 ret void | |
382 } | |
383 ; CHECK: define void @nocapture_attr(i32 %ptr) { | |
384 | |
385 ; "nounwind" should be preserved. | |
386 define void @nounwind_func_attr() nounwind { | |
387 ret void | |
388 } | |
389 ; CHECK: define void @nounwind_func_attr() [[NOUNWIND:#[0-9]+]] { | |
390 | |
391 define void @nounwind_call_attr() { | |
392 call void @nounwind_func_attr() nounwind | |
393 ret void | |
394 } | |
395 ; CHECK: define void @nounwind_call_attr() { | |
396 ; CHECK: call void @nounwind_func_attr() {{.*}}[[NOUNWIND]] | |
397 | |
398 define fastcc void @fastcc_func() { | |
399 ret void | |
400 } | |
401 ; CHECK: define fastcc void @fastcc_func() { | |
402 | |
403 define void @fastcc_call() { | |
404 call fastcc void @fastcc_func() | |
405 ret void | |
406 } | |
407 ; CHECK: define void @fastcc_call() { | |
408 ; CHECK-NEXT: call fastcc void @fastcc_func() | |
409 | |
410 | |
411 define i8* @getelementptr(i8* %ptr) { | |
eliben
2013/05/15 22:11:21
What is this for?
Mark Seaborn
2013/05/16 02:08:40
This just checks that the pass doesn't barf on get
| |
412 %gep = getelementptr i8* %ptr, i32 10 | |
413 ret i8* %gep | |
414 } | |
415 | |
416 define i32* @va_arg(i8* %valist) { | |
eliben
2013/05/15 22:11:21
Ditto
Mark Seaborn
2013/05/16 02:08:40
Ditto.
| |
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 |