Chromium Code Reviews| 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 |