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@vt1 = constant [2 x ptr] [ptr @vf1a, ptr @vf1b], !type !0 7@vt2 = constant [2 x ptr] [ptr @vf2a, ptr @vf2b], !type !0 8 9@sink = external global i32 10 11define i32 @vf1a(ptr %this, i32 %arg) { 12 store i32 %arg, ptr @sink 13 ret i32 %arg 14} 15 16define i32 @vf2a(ptr %this, i32 %arg) { 17 store i32 %arg, ptr @sink 18 ret i32 %arg 19} 20 21define i32 @vf1b(ptr %this, i32 %arg) { 22 ret i32 %arg 23} 24 25define i32 @vf2b(ptr %this, i32 %arg) { 26 ret i32 %arg 27} 28 29; Test that we don't apply VCP if the virtual function body accesses memory, 30; even if the function returns a constant. 31 32; CHECK: define i32 @call1 33define i32 @call1(ptr %obj) { 34 %vtable = load ptr, ptr %obj 35 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") 36 call void @llvm.assume(i1 %p) 37 %fptr = load ptr, ptr %vtable 38 ; CHECK: call i32 % 39 %result = call i32 %fptr(ptr %obj, i32 1) 40 ret i32 %result 41} 42 43; Test that we can apply VCP regardless of the function attributes by analyzing 44; the function body itself. 45 46; CHECK: define i32 @call2 47define i32 @call2(ptr %obj) { 48 %vtable = load ptr, ptr %obj 49 %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid") 50 call void @llvm.assume(i1 %p) 51 %fptrptr = getelementptr [1 x ptr], ptr %vtable, i32 0, i32 1 52 %fptr = load ptr, ptr %fptrptr 53 %result = call i32 %fptr(ptr %obj, i32 1) 54 ; CHECK: ret i32 1 55 ret i32 %result 56} 57 58declare i1 @llvm.type.test(ptr, metadata) 59declare void @llvm.assume(i1) 60 61!0 = !{i32 0, !"typeid"} 62