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