1; RUN: opt -S -passes=wholeprogramdevirt -whole-program-visibility %s | FileCheck %s 2 3target datalayout = "e-p:64:64" 4target triple = "x86_64-unknown-linux-gnu" 5 6; CHECK: private constant { [8 x i8], [1 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", [1 x ptr] [ptr @vf1], [0 x i8] zeroinitializer }, !type [[T8:![0-9]+]] 7; CHECK: private constant { [8 x i8], [1 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\02", [1 x ptr] [ptr @vf2], [0 x i8] zeroinitializer }, !type [[T8]] 8; CHECK: private constant { [8 x i8], [1 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\01", [1 x ptr] [ptr @vf4], [0 x i8] zeroinitializer }, !type [[T8]] 9; CHECK: private constant { [8 x i8], [1 x ptr], [0 x i8] } { [8 x i8] c"\00\00\00\00\00\00\00\02", [1 x ptr] [ptr @vf8], [0 x i8] zeroinitializer }, !type [[T8]] 10; CHECK: private constant { [4 x i8], [1 x i32], [0 x i8] } { [4 x i8] c"\00\00\00\01", [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1 to i64), i64 ptrtoint (ptr @vt1_rv to i64)) to i32)], [0 x i8] zeroinitializer }, align 4, !type [[T4:![0-9]+]] 11; CHECK: private constant { [4 x i8], [1 x i32], [0 x i8] } { [4 x i8] c"\00\00\00\02", [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2 to i64), i64 ptrtoint (ptr @vt2_rv to i64)) to i32)], [0 x i8] zeroinitializer }, align 4, !type [[T4]] 12; CHECK: private constant { [4 x i8], [1 x i32], [0 x i8] } { [4 x i8] c"\00\00\00\01", [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf4 to i64), i64 ptrtoint (ptr @vt4_rv to i64)) to i32)], [0 x i8] zeroinitializer }, align 4, !type [[T4]] 13; CHECK: private constant { [4 x i8], [1 x i32], [0 x i8] } { [4 x i8] c"\00\00\00\02", [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf8 to i64), i64 ptrtoint (ptr @vt8_rv to i64)) to i32)], [0 x i8] zeroinitializer }, align 4, !type [[T4]] 14 15@vt1 = constant [1 x ptr] [ptr @vf1], !type !0 16@vt2 = constant [1 x ptr] [ptr @vf2], !type !0 17@vt4 = constant [1 x ptr] [ptr @vf4], !type !0 18@vt8 = constant [1 x ptr] [ptr @vf8], !type !0 19 20define i1 @vf1(ptr %this, i32 %arg) readnone { 21 %and = and i32 %arg, 1 22 %cmp = icmp ne i32 %and, 0 23 ret i1 %cmp 24} 25 26define i1 @vf2(ptr %this, i32 %arg) readnone { 27 %and = and i32 %arg, 2 28 %cmp = icmp ne i32 %and, 0 29 ret i1 %cmp 30} 31 32define i1 @vf4(ptr %this, i32 %arg) readnone { 33 %and = and i32 %arg, 4 34 %cmp = icmp ne i32 %and, 0 35 ret i1 %cmp 36} 37 38define i1 @vf8(ptr %this, i32 %arg) readnone { 39 %and = and i32 %arg, 8 40 %cmp = icmp ne i32 %and, 0 41 ret i1 %cmp 42} 43 44; CHECK: define i1 @call1 45define i1 @call1(ptr %obj) { 46 %vtable = load ptr, ptr %obj 47 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") 48 call void @llvm.assume(i1 %p) 49 %fptr = load ptr, ptr %vtable 50 ; CHECK: getelementptr {{.*}} -1 51 ; CHECK: and {{.*}}, 1 52 %result = call i1 %fptr(ptr %obj, i32 5) 53 ret i1 %result 54} 55 56; CHECK: define i1 @call2 57define i1 @call2(ptr %obj) { 58 %vtable = load ptr, ptr %obj 59 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") 60 call void @llvm.assume(i1 %p) 61 %fptr = load ptr, ptr %vtable 62 ; CHECK: getelementptr {{.*}} -1 63 ; CHECK: and {{.*}}, 2 64 %result = call i1 %fptr(ptr %obj, i32 10) 65 ret i1 %result 66} 67 68declare ptr @llvm.load.relative.i32(ptr, i32) 69 70@vt1_rv = private unnamed_addr constant [1 x i32] [ 71 i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf1 to i64), i64 ptrtoint (ptr @vt1_rv to i64)) to i32) 72], align 4, !type !1 73@vt2_rv = private unnamed_addr constant [1 x i32] [ 74 i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf2 to i64), i64 ptrtoint (ptr @vt2_rv to i64)) to i32) 75], align 4, !type !1 76@vt4_rv = private unnamed_addr constant [1 x i32] [ 77 i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf4 to i64), i64 ptrtoint (ptr @vt4_rv to i64)) to i32) 78], align 4, !type !1 79@vt8_rv = private unnamed_addr constant [1 x i32] [ 80 i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf8 to i64), i64 ptrtoint (ptr @vt8_rv to i64)) to i32) 81], align 4, !type !1 82 83; CHECK: define i1 @call3 84define i1 @call3(ptr %obj) { 85 %vtable = load ptr, ptr %obj 86 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid2") 87 call void @llvm.assume(i1 %p) 88 %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0) 89 ; CHECK: getelementptr {{.*}} -1 90 ; CHECK: and {{.*}}, 1 91 %result = call i1 %fptr(ptr %obj, i32 5) 92 ret i1 %result 93} 94 95; CHECK: define i1 @call4 96define i1 @call4(ptr %obj) { 97 %vtable = load ptr, ptr %obj 98 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid2") 99 call void @llvm.assume(i1 %p) 100 %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0) 101 ; CHECK: getelementptr {{.*}} -1 102 ; CHECK: and {{.*}}, 2 103 %result = call i1 %fptr(ptr %obj, i32 10) 104 ret i1 %result 105} 106 107declare i1 @llvm.type.test(ptr, metadata) 108declare void @llvm.assume(i1) 109 110; CHECK: [[T8]] = !{i32 8, !"typeid"} 111; CHECK: [[T4]] = !{i32 4, !"typeid2"} 112!0 = !{i32 0, !"typeid"} 113!1 = !{i32 0, !"typeid2"} 114