| ; 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} |
| ;. |