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 i8*] [i8* bitcast (i32 (i8*, i32)* @vf1a to i8*), i8* bitcast (i32 (i8*, i32)* @vf1b to i8*)], !type !0 7@vt2 = constant [2 x i8*] [i8* bitcast (i32 (i8*, i32)* @vf2a to i8*), i8* bitcast (i32 (i8*, i32)* @vf2b to i8*)], !type !0 8 9@sink = external global i32 10 11define i32 @vf1a(i8* %this, i32 %arg) { 12 store i32 %arg, i32* @sink 13 ret i32 %arg 14} 15 16define i32 @vf2a(i8* %this, i32 %arg) { 17 store i32 %arg, i32* @sink 18 ret i32 %arg 19} 20 21define i32 @vf1b(i8* %this, i32 %arg) { 22 ret i32 %arg 23} 24 25define i32 @vf2b(i8* %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(i8* %obj) { 34 %vtableptr = bitcast i8* %obj to [1 x i8*]** 35 %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr 36 %vtablei8 = bitcast [1 x i8*]* %vtable to i8* 37 %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid") 38 call void @llvm.assume(i1 %p) 39 %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0 40 %fptr = load i8*, i8** %fptrptr 41 %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)* 42 ; CHECK: call i32 % 43 %result = call i32 %fptr_casted(i8* %obj, i32 1) 44 ret i32 %result 45} 46 47; Test that we can apply VCP regardless of the function attributes by analyzing 48; the function body itself. 49 50; CHECK: define i32 @call2 51define i32 @call2(i8* %obj) { 52 %vtableptr = bitcast i8* %obj to [1 x i8*]** 53 %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr 54 %vtablei8 = bitcast [1 x i8*]* %vtable to i8* 55 %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid") 56 call void @llvm.assume(i1 %p) 57 %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 1 58 %fptr = load i8*, i8** %fptrptr 59 %fptr_casted = bitcast i8* %fptr to i32 (i8*, i32)* 60 %result = call i32 %fptr_casted(i8* %obj, i32 1) 61 ; CHECK: ret i32 1 62 ret i32 %result 63} 64 65declare i1 @llvm.type.test(i8*, metadata) 66declare void @llvm.assume(i1) 67 68!0 = !{i32 0, !"typeid"} 69