1bb383ae6SHiroshi Yamauchi //===- CallPromotionUtilsTest.cpp - CallPromotionUtils unit tests ---------===//
2bb383ae6SHiroshi Yamauchi //
3bb383ae6SHiroshi Yamauchi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb383ae6SHiroshi Yamauchi // See https://llvm.org/LICENSE.txt for license information.
5bb383ae6SHiroshi Yamauchi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb383ae6SHiroshi Yamauchi //
7bb383ae6SHiroshi Yamauchi //===----------------------------------------------------------------------===//
8bb383ae6SHiroshi Yamauchi 
9bb383ae6SHiroshi Yamauchi #include "llvm/Transforms/Utils/CallPromotionUtils.h"
10bb383ae6SHiroshi Yamauchi #include "llvm/AsmParser/Parser.h"
11bb383ae6SHiroshi Yamauchi #include "llvm/IR/Instructions.h"
12bb383ae6SHiroshi Yamauchi #include "llvm/IR/LLVMContext.h"
13bb383ae6SHiroshi Yamauchi #include "llvm/IR/Module.h"
14bb383ae6SHiroshi Yamauchi #include "llvm/Support/SourceMgr.h"
15bb383ae6SHiroshi Yamauchi #include "gtest/gtest.h"
16bb383ae6SHiroshi Yamauchi 
17bb383ae6SHiroshi Yamauchi using namespace llvm;
18bb383ae6SHiroshi Yamauchi 
parseIR(LLVMContext & C,const char * IR)19bb383ae6SHiroshi Yamauchi static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
20bb383ae6SHiroshi Yamauchi   SMDiagnostic Err;
21bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
22bb383ae6SHiroshi Yamauchi   if (!Mod)
23bb383ae6SHiroshi Yamauchi     Err.print("UtilsTests", errs());
24bb383ae6SHiroshi Yamauchi   return Mod;
25bb383ae6SHiroshi Yamauchi }
26bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall)27bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall) {
28bb383ae6SHiroshi Yamauchi   LLVMContext C;
29bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
30bb383ae6SHiroshi Yamauchi                                       R"IR(
31bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
32bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
33bb383ae6SHiroshi Yamauchi 
34bb383ae6SHiroshi Yamauchi @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
35bb383ae6SHiroshi Yamauchi 
36bb383ae6SHiroshi Yamauchi define void @f() {
37bb383ae6SHiroshi Yamauchi entry:
38bb383ae6SHiroshi Yamauchi   %o = alloca %class.Impl
39bb383ae6SHiroshi Yamauchi   %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
40bb383ae6SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
41bb383ae6SHiroshi Yamauchi   %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
42bb383ae6SHiroshi Yamauchi   store i32 3, i32* %f
43bb383ae6SHiroshi Yamauchi   %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
44bb383ae6SHiroshi Yamauchi   %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
45bb383ae6SHiroshi Yamauchi   %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
46bb383ae6SHiroshi Yamauchi   %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
47bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
48bb383ae6SHiroshi Yamauchi   ret void
49bb383ae6SHiroshi Yamauchi }
50bb383ae6SHiroshi Yamauchi 
51bb383ae6SHiroshi Yamauchi declare void @_ZN4Impl3RunEv(%class.Impl* %this)
52bb383ae6SHiroshi Yamauchi )IR");
53bb383ae6SHiroshi Yamauchi 
54bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
55bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
56bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
57bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
58bb383ae6SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
59bb383ae6SHiroshi Yamauchi   auto *AI = dyn_cast<AllocaInst>(Inst);
60bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(AI);
61bb383ae6SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
62bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
63bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
64*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
65*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
66bb383ae6SHiroshi Yamauchi   EXPECT_TRUE(IsPromoted);
67bb383ae6SHiroshi Yamauchi   GV = M->getNamedValue("_ZN4Impl3RunEv");
68bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
69bb383ae6SHiroshi Yamauchi   auto *F1 = dyn_cast<Function>(GV);
70*d2f1cd5dSMircea Trofin   EXPECT_EQ(F1, CI->getCalledFunction());
71bb383ae6SHiroshi Yamauchi }
72bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall_NoFPLoad)73bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_NoFPLoad) {
74bb383ae6SHiroshi Yamauchi   LLVMContext C;
75bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
76bb383ae6SHiroshi Yamauchi                                       R"IR(
77bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
78bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
79bb383ae6SHiroshi Yamauchi 
80bb383ae6SHiroshi Yamauchi define void @f(void (%class.Interface*)* %fp, %class.Interface* nonnull %base.i) {
81bb383ae6SHiroshi Yamauchi entry:
82bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
83bb383ae6SHiroshi Yamauchi   ret void
84bb383ae6SHiroshi Yamauchi }
85bb383ae6SHiroshi Yamauchi )IR");
86bb383ae6SHiroshi Yamauchi 
87bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
88bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
89bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
90bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
91bb383ae6SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
92bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
93bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
94*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
95*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
96bb383ae6SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
97bb383ae6SHiroshi Yamauchi }
98bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall_NoVTablePtrLoad)99bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_NoVTablePtrLoad) {
100bb383ae6SHiroshi Yamauchi   LLVMContext C;
101bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
102bb383ae6SHiroshi Yamauchi                                       R"IR(
103bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
104bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
105bb383ae6SHiroshi Yamauchi 
106bb383ae6SHiroshi Yamauchi define void @f(void (%class.Interface*)** %vtable.i, %class.Interface* nonnull %base.i) {
107bb383ae6SHiroshi Yamauchi entry:
108bb383ae6SHiroshi Yamauchi   %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
109bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
110bb383ae6SHiroshi Yamauchi   ret void
111bb383ae6SHiroshi Yamauchi }
112bb383ae6SHiroshi Yamauchi )IR");
113bb383ae6SHiroshi Yamauchi 
114bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
115bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
116bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
117bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
118bb383ae6SHiroshi Yamauchi   Instruction *Inst = &*++F->front().rbegin();
119bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
120bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
121*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
122*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
123bb383ae6SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
124bb383ae6SHiroshi Yamauchi }
125bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall_NoVTableInitFound)126bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_NoVTableInitFound) {
127bb383ae6SHiroshi Yamauchi   LLVMContext C;
128bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
129bb383ae6SHiroshi Yamauchi                                       R"IR(
130bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
131bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
132bb383ae6SHiroshi Yamauchi 
133bb383ae6SHiroshi Yamauchi define void @f() {
134bb383ae6SHiroshi Yamauchi entry:
135bb383ae6SHiroshi Yamauchi   %o = alloca %class.Impl
136bb383ae6SHiroshi Yamauchi   %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
137bb383ae6SHiroshi Yamauchi   store i32 3, i32* %f
138bb383ae6SHiroshi Yamauchi   %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
139bb383ae6SHiroshi Yamauchi   %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
140bb383ae6SHiroshi Yamauchi   %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
141bb383ae6SHiroshi Yamauchi   %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
142bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
143bb383ae6SHiroshi Yamauchi   ret void
144bb383ae6SHiroshi Yamauchi }
145bb383ae6SHiroshi Yamauchi 
146bb383ae6SHiroshi Yamauchi declare void @_ZN4Impl3RunEv(%class.Impl* %this)
147bb383ae6SHiroshi Yamauchi )IR");
148bb383ae6SHiroshi Yamauchi 
149bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
150bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
151bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
152bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
153bb383ae6SHiroshi Yamauchi   Instruction *Inst = &*++F->front().rbegin();
154bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
155bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
156*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
157*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
158bb383ae6SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
159bb383ae6SHiroshi Yamauchi }
160bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall_EmptyVTable)161bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_EmptyVTable) {
162bb383ae6SHiroshi Yamauchi   LLVMContext C;
163bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
164bb383ae6SHiroshi Yamauchi                                       R"IR(
165bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
166bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
167bb383ae6SHiroshi Yamauchi 
168bb383ae6SHiroshi Yamauchi @_ZTV4Impl = external global { [3 x i8*] }
169bb383ae6SHiroshi Yamauchi 
170bb383ae6SHiroshi Yamauchi define void @f() {
171bb383ae6SHiroshi Yamauchi entry:
172bb383ae6SHiroshi Yamauchi   %o = alloca %class.Impl
173bb383ae6SHiroshi Yamauchi   %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
174bb383ae6SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
175bb383ae6SHiroshi Yamauchi   %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
176bb383ae6SHiroshi Yamauchi   store i32 3, i32* %f
177bb383ae6SHiroshi Yamauchi   %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
178bb383ae6SHiroshi Yamauchi   %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
179bb383ae6SHiroshi Yamauchi   %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
180bb383ae6SHiroshi Yamauchi   %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
181bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
182bb383ae6SHiroshi Yamauchi   ret void
183bb383ae6SHiroshi Yamauchi }
184bb383ae6SHiroshi Yamauchi 
185bb383ae6SHiroshi Yamauchi declare void @_ZN4Impl3RunEv(%class.Impl* %this)
186bb383ae6SHiroshi Yamauchi )IR");
187bb383ae6SHiroshi Yamauchi 
188bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
189bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
190bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
191bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
192bb383ae6SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
193bb383ae6SHiroshi Yamauchi   auto *AI = dyn_cast<AllocaInst>(Inst);
194bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(AI);
195bb383ae6SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
196bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
197bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
198*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
199*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
200bb383ae6SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
201bb383ae6SHiroshi Yamauchi }
202bb383ae6SHiroshi Yamauchi 
TEST(CallPromotionUtilsTest,TryPromoteCall_NullFP)203bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_NullFP) {
204bb383ae6SHiroshi Yamauchi   LLVMContext C;
205bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
206bb383ae6SHiroshi Yamauchi                                       R"IR(
207bb383ae6SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
208bb383ae6SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
209bb383ae6SHiroshi Yamauchi 
210bb383ae6SHiroshi Yamauchi @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* null] }
211bb383ae6SHiroshi Yamauchi 
212bb383ae6SHiroshi Yamauchi define void @f() {
213bb383ae6SHiroshi Yamauchi entry:
214bb383ae6SHiroshi Yamauchi   %o = alloca %class.Impl
215bb383ae6SHiroshi Yamauchi   %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
216bb383ae6SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
217bb383ae6SHiroshi Yamauchi   %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
218bb383ae6SHiroshi Yamauchi   store i32 3, i32* %f
219bb383ae6SHiroshi Yamauchi   %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
220bb383ae6SHiroshi Yamauchi   %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
221bb383ae6SHiroshi Yamauchi   %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
222bb383ae6SHiroshi Yamauchi   %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
223bb383ae6SHiroshi Yamauchi   call void %fp(%class.Interface* nonnull %base.i)
224bb383ae6SHiroshi Yamauchi   ret void
225bb383ae6SHiroshi Yamauchi }
226bb383ae6SHiroshi Yamauchi 
227bb383ae6SHiroshi Yamauchi declare void @_ZN4Impl3RunEv(%class.Impl* %this)
228bb383ae6SHiroshi Yamauchi )IR");
229bb383ae6SHiroshi Yamauchi 
230bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
231bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
232bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
233bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
234bb383ae6SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
235bb383ae6SHiroshi Yamauchi   auto *AI = dyn_cast<AllocaInst>(Inst);
236bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(AI);
237bb383ae6SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
238bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
239bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
240*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
241*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
242bb383ae6SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
243bb383ae6SHiroshi Yamauchi }
244bb383ae6SHiroshi Yamauchi 
245bb383ae6SHiroshi Yamauchi // Based on clang/test/CodeGenCXX/member-function-pointer-calls.cpp
TEST(CallPromotionUtilsTest,TryPromoteCall_MemberFunctionCalls)246bb383ae6SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_MemberFunctionCalls) {
247bb383ae6SHiroshi Yamauchi   LLVMContext C;
248bb383ae6SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
249bb383ae6SHiroshi Yamauchi                                       R"IR(
250bb383ae6SHiroshi Yamauchi %struct.A = type { i32 (...)** }
251bb383ae6SHiroshi Yamauchi 
252bb383ae6SHiroshi Yamauchi @_ZTV1A = linkonce_odr unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* null, i8* bitcast (i32 (%struct.A*)* @_ZN1A3vf1Ev to i8*), i8* bitcast (i32 (%struct.A*)* @_ZN1A3vf2Ev to i8*)] }, align 8
253bb383ae6SHiroshi Yamauchi 
254bb383ae6SHiroshi Yamauchi define i32 @_Z2g1v() {
255bb383ae6SHiroshi Yamauchi entry:
256bb383ae6SHiroshi Yamauchi   %a = alloca %struct.A, align 8
257bb383ae6SHiroshi Yamauchi   %0 = bitcast %struct.A* %a to i8*
258bb383ae6SHiroshi Yamauchi   %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0
259bb383ae6SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8
260bb383ae6SHiroshi Yamauchi   %2 = bitcast %struct.A* %a to i8*
261bb383ae6SHiroshi Yamauchi   %3 = bitcast i8* %2 to i8**
262bb383ae6SHiroshi Yamauchi   %vtable.i = load i8*, i8** %3, align 8
263bb383ae6SHiroshi Yamauchi   %4 = bitcast i8* %vtable.i to i32 (%struct.A*)**
264bb383ae6SHiroshi Yamauchi   %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %4, align 8
265bb383ae6SHiroshi Yamauchi   %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a)
266bb383ae6SHiroshi Yamauchi   ret i32 %call.i
267bb383ae6SHiroshi Yamauchi }
268bb383ae6SHiroshi Yamauchi 
269bb383ae6SHiroshi Yamauchi define i32 @_Z2g2v() {
270bb383ae6SHiroshi Yamauchi entry:
271bb383ae6SHiroshi Yamauchi   %a = alloca %struct.A, align 8
272bb383ae6SHiroshi Yamauchi   %0 = bitcast %struct.A* %a to i8*
273bb383ae6SHiroshi Yamauchi   %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0
274bb383ae6SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8
275bb383ae6SHiroshi Yamauchi   %2 = bitcast %struct.A* %a to i8*
276bb383ae6SHiroshi Yamauchi   %3 = bitcast i8* %2 to i8**
277bb383ae6SHiroshi Yamauchi   %vtable.i = load i8*, i8** %3, align 8
278bb383ae6SHiroshi Yamauchi   %4 = getelementptr i8, i8* %vtable.i, i64 8
279bb383ae6SHiroshi Yamauchi   %5 = bitcast i8* %4 to i32 (%struct.A*)**
280bb383ae6SHiroshi Yamauchi   %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %5, align 8
281bb383ae6SHiroshi Yamauchi   %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a)
282bb383ae6SHiroshi Yamauchi   ret i32 %call.i
283bb383ae6SHiroshi Yamauchi }
284bb383ae6SHiroshi Yamauchi 
285bb383ae6SHiroshi Yamauchi declare i32 @_ZN1A3vf1Ev(%struct.A* %this)
286bb383ae6SHiroshi Yamauchi declare i32 @_ZN1A3vf2Ev(%struct.A* %this)
287bb383ae6SHiroshi Yamauchi )IR");
288bb383ae6SHiroshi Yamauchi 
289bb383ae6SHiroshi Yamauchi   auto *GV = M->getNamedValue("_Z2g1v");
290bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
291bb383ae6SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
292bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
293bb383ae6SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
294bb383ae6SHiroshi Yamauchi   auto *AI = dyn_cast<AllocaInst>(Inst);
295bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(AI);
296bb383ae6SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
297bb383ae6SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
298bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
299*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
300*d2f1cd5dSMircea Trofin   bool IsPromoted1 = tryPromoteCall(*CI);
301bb383ae6SHiroshi Yamauchi   EXPECT_TRUE(IsPromoted1);
302bb383ae6SHiroshi Yamauchi   GV = M->getNamedValue("_ZN1A3vf1Ev");
303bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
304bb383ae6SHiroshi Yamauchi   F = dyn_cast<Function>(GV);
305*d2f1cd5dSMircea Trofin   EXPECT_EQ(F, CI->getCalledFunction());
306bb383ae6SHiroshi Yamauchi 
307bb383ae6SHiroshi Yamauchi   GV = M->getNamedValue("_Z2g2v");
308bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
309bb383ae6SHiroshi Yamauchi   F = dyn_cast<Function>(GV);
310bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(F);
311bb383ae6SHiroshi Yamauchi   Inst = &F->front().front();
312bb383ae6SHiroshi Yamauchi   AI = dyn_cast<AllocaInst>(Inst);
313bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(AI);
314bb383ae6SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
315bb383ae6SHiroshi Yamauchi   CI = dyn_cast<CallInst>(Inst);
316bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(CI);
317*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
318*d2f1cd5dSMircea Trofin   bool IsPromoted2 = tryPromoteCall(*CI);
319bb383ae6SHiroshi Yamauchi   EXPECT_TRUE(IsPromoted2);
320bb383ae6SHiroshi Yamauchi   GV = M->getNamedValue("_ZN1A3vf2Ev");
321bb383ae6SHiroshi Yamauchi   ASSERT_TRUE(GV);
322bb383ae6SHiroshi Yamauchi   F = dyn_cast<Function>(GV);
323*d2f1cd5dSMircea Trofin   EXPECT_EQ(F, CI->getCalledFunction());
324bb383ae6SHiroshi Yamauchi }
32541e06ae7SHiroshi Yamauchi 
32641e06ae7SHiroshi Yamauchi // Check that it isn't crashing due to missing promotion legality.
TEST(CallPromotionUtilsTest,TryPromoteCall_Legality)32741e06ae7SHiroshi Yamauchi TEST(CallPromotionUtilsTest, TryPromoteCall_Legality) {
32841e06ae7SHiroshi Yamauchi   LLVMContext C;
32941e06ae7SHiroshi Yamauchi   std::unique_ptr<Module> M = parseIR(C,
33041e06ae7SHiroshi Yamauchi                                       R"IR(
33141e06ae7SHiroshi Yamauchi %struct1 = type <{ i32, i64 }>
33241e06ae7SHiroshi Yamauchi %struct2 = type <{ i32, i64 }>
33341e06ae7SHiroshi Yamauchi 
33441e06ae7SHiroshi Yamauchi %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
33541e06ae7SHiroshi Yamauchi %class.Interface = type { i32 (...)** }
33641e06ae7SHiroshi Yamauchi 
33741e06ae7SHiroshi Yamauchi @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (%struct2 (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
33841e06ae7SHiroshi Yamauchi 
33941e06ae7SHiroshi Yamauchi define %struct1 @f() {
34041e06ae7SHiroshi Yamauchi entry:
34141e06ae7SHiroshi Yamauchi   %o = alloca %class.Impl
34241e06ae7SHiroshi Yamauchi   %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
34341e06ae7SHiroshi Yamauchi   store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, inrange i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
34441e06ae7SHiroshi Yamauchi   %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
34541e06ae7SHiroshi Yamauchi   store i32 3, i32* %f
34641e06ae7SHiroshi Yamauchi   %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
34741e06ae7SHiroshi Yamauchi   %c = bitcast %class.Interface* %base.i to %struct1 (%class.Interface*)***
34841e06ae7SHiroshi Yamauchi   %vtable.i = load %struct1 (%class.Interface*)**, %struct1 (%class.Interface*)*** %c
34941e06ae7SHiroshi Yamauchi   %fp = load %struct1 (%class.Interface*)*, %struct1 (%class.Interface*)** %vtable.i
35041e06ae7SHiroshi Yamauchi   %rv = call %struct1 %fp(%class.Interface* nonnull %base.i)
35141e06ae7SHiroshi Yamauchi   ret %struct1 %rv
35241e06ae7SHiroshi Yamauchi }
35341e06ae7SHiroshi Yamauchi 
35441e06ae7SHiroshi Yamauchi declare %struct2 @_ZN4Impl3RunEv(%class.Impl* %this)
35541e06ae7SHiroshi Yamauchi )IR");
35641e06ae7SHiroshi Yamauchi 
35741e06ae7SHiroshi Yamauchi   auto *GV = M->getNamedValue("f");
35841e06ae7SHiroshi Yamauchi   ASSERT_TRUE(GV);
35941e06ae7SHiroshi Yamauchi   auto *F = dyn_cast<Function>(GV);
36041e06ae7SHiroshi Yamauchi   ASSERT_TRUE(F);
36141e06ae7SHiroshi Yamauchi   Instruction *Inst = &F->front().front();
36241e06ae7SHiroshi Yamauchi   auto *AI = dyn_cast<AllocaInst>(Inst);
36341e06ae7SHiroshi Yamauchi   ASSERT_TRUE(AI);
36441e06ae7SHiroshi Yamauchi   Inst = &*++F->front().rbegin();
36541e06ae7SHiroshi Yamauchi   auto *CI = dyn_cast<CallInst>(Inst);
36641e06ae7SHiroshi Yamauchi   ASSERT_TRUE(CI);
367*d2f1cd5dSMircea Trofin   ASSERT_FALSE(CI->getCalledFunction());
368*d2f1cd5dSMircea Trofin   bool IsPromoted = tryPromoteCall(*CI);
36941e06ae7SHiroshi Yamauchi   EXPECT_FALSE(IsPromoted);
37041e06ae7SHiroshi Yamauchi }
371