| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility < %s | FileCheck %s | |
| ; Do not perform constant propagation through interposable functions, as we | |
| ; may not be seeing the prevailing definition. | |
| ; We can perform constant propagation through inexact definitions though, | |
| ; as we effectively inline the function. | |
| @vt1_weak = constant [1 x ptr] [ptr @vf1_weak], !type !0 | |
| @vt2_weak = constant [1 x ptr] [ptr @vf2_weak], !type !0 | |
| @vt1_linkonce_odr = constant [1 x ptr] [ptr @vf1_linkonce_odr], !type !1 | |
| @vt2_linkonce_odr = constant [1 x ptr] [ptr @vf2_linkonce_odr], !type !1 | |
| define weak i32 @vf1_weak(ptr %this, i32 %arg) { | |
| ; CHECK-LABEL: define weak i32 @vf1_weak( | |
| ; CHECK-SAME: ptr [[THIS:%.*]], i32 [[ARG:%.*]]) !guid [[META6:![0-9]+]] { | |
| ; CHECK-NEXT: ret i32 [[ARG]] | |
| ; | |
| ret i32 %arg | |
| } | |
| define weak i32 @vf2_weak(ptr %this, i32 %arg) { | |
| ; CHECK-LABEL: define weak i32 @vf2_weak( | |
| ; CHECK-SAME: ptr [[THIS:%.*]], i32 [[ARG:%.*]]) !guid [[META7:![0-9]+]] { | |
| ; CHECK-NEXT: ret i32 [[ARG]] | |
| ; | |
| ret i32 %arg | |
| } | |
| define linkonce_odr i32 @vf1_linkonce_odr(ptr %this, i32 %arg) { | |
| ; CHECK-LABEL: define linkonce_odr i32 @vf1_linkonce_odr( | |
| ; CHECK-SAME: ptr [[THIS:%.*]], i32 [[ARG:%.*]]) !guid [[META8:![0-9]+]] { | |
| ; CHECK-NEXT: ret i32 [[ARG]] | |
| ; | |
| ret i32 %arg | |
| } | |
| define linkonce_odr i32 @vf2_linkonce_odr(ptr %this, i32 %arg) { | |
| ; CHECK-LABEL: define linkonce_odr i32 @vf2_linkonce_odr( | |
| ; CHECK-SAME: ptr [[THIS:%.*]], i32 [[ARG:%.*]]) !guid [[META9:![0-9]+]] { | |
| ; CHECK-NEXT: ret i32 [[ARG]] | |
| ; | |
| ret i32 %arg | |
| } | |
| define i32 @test_weak(ptr %obj) { | |
| ; CHECK-LABEL: define i32 @test_weak( | |
| ; CHECK-SAME: ptr [[OBJ:%.*]]) !guid [[META10:![0-9]+]] { | |
| ; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[OBJ]], align 8 | |
| ; CHECK-NEXT: [[P:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"typeid_weak") | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[P]]) | |
| ; CHECK-NEXT: [[FPTR:%.*]] = load ptr, ptr [[VTABLE]], align 8 | |
| ; CHECK-NEXT: [[RESULT:%.*]] = call i32 [[FPTR]](ptr [[OBJ]], i32 1) | |
| ; CHECK-NEXT: ret i32 [[RESULT]] | |
| ; | |
| %vtable = load ptr, ptr %obj | |
| %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid_weak") | |
| call void @llvm.assume(i1 %p) | |
| %fptr = load ptr, ptr %vtable | |
| %result = call i32 %fptr(ptr %obj, i32 1) | |
| ret i32 %result | |
| } | |
| define i32 @test_linkonce_odr(ptr %obj) { | |
| ; CHECK-LABEL: define i32 @test_linkonce_odr( | |
| ; CHECK-SAME: ptr [[OBJ:%.*]]) !guid [[META11:![0-9]+]] { | |
| ; CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[OBJ]], align 8 | |
| ; CHECK-NEXT: [[P:%.*]] = call i1 @llvm.type.test(ptr [[VTABLE]], metadata !"typeid_linkonce_odr") | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[P]]) | |
| ; CHECK-NEXT: [[FPTR:%.*]] = load ptr, ptr [[VTABLE]], align 8 | |
| ; CHECK-NEXT: ret i32 1 | |
| ; | |
| %vtable = load ptr, ptr %obj | |
| %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid_linkonce_odr") | |
| call void @llvm.assume(i1 %p) | |
| %fptr = load ptr, ptr %vtable | |
| %result = call i32 %fptr(ptr %obj, i32 1) | |
| ret i32 %result | |
| } | |
| !0 = !{i32 0, !"typeid_weak"} | |
| !1 = !{i32 0, !"typeid_linkonce_odr"} | |
| ;. | |
| ; CHECK: [[META6]] = !{i64 -7067669819462802158} | |
| ; CHECK: [[META7]] = !{i64 7788932116295580834} | |
| ; CHECK: [[META8]] = !{i64 -7271860403678991523} | |
| ; CHECK: [[META9]] = !{i64 3179538762998407930} | |
| ; CHECK: [[META10]] = !{i64 1773407144618971966} | |
| ; CHECK: [[META11]] = !{i64 2326665858058907152} | |
| ;. |