1 //===- CallPromotionUtilsTest.cpp - CallPromotionUtils unit tests ---------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/CallPromotionUtils.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/IRBuilder.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/MDBuilder.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/IR/NoFolder.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gtest/gtest.h"
22 static std::unique_ptr
<Module
> parseIR(LLVMContext
&C
, const char *IR
) {
24 std::unique_ptr
<Module
> Mod
= parseAssemblyString(IR
, Err
, C
);
26 Err
.print("UtilsTests", errs());
30 // Returns a constant representing the vtable's address point specified by the
32 static Constant
*getVTableAddressPointOffset(GlobalVariable
*VTable
,
33 uint32_t AddressPointOffset
) {
34 Module
&M
= *VTable
->getParent();
35 LLVMContext
&Context
= M
.getContext();
36 assert(AddressPointOffset
<
37 M
.getDataLayout().getTypeAllocSize(VTable
->getValueType()) &&
38 "Out-of-bound access");
40 return ConstantExpr::getInBoundsGetElementPtr(
41 Type::getInt8Ty(Context
), VTable
,
42 llvm::ConstantInt::get(Type::getInt32Ty(Context
), AddressPointOffset
));
45 TEST(CallPromotionUtilsTest
, TryPromoteCall
) {
47 std::unique_ptr
<Module
> M
= parseIR(C
,
49 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
50 %class.Interface = type { i32 (...)** }
52 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
56 %o = alloca %class.Impl
57 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
58 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
59 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
61 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
62 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
63 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
64 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
65 call void %fp(%class.Interface* nonnull %base.i)
69 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
72 auto *GV
= M
->getNamedValue("f");
74 auto *F
= dyn_cast
<Function
>(GV
);
76 Instruction
*Inst
= &F
->front().front();
77 auto *AI
= dyn_cast
<AllocaInst
>(Inst
);
79 Inst
= &*++F
->front().rbegin();
80 auto *CI
= dyn_cast
<CallInst
>(Inst
);
82 ASSERT_FALSE(CI
->getCalledFunction());
83 bool IsPromoted
= tryPromoteCall(*CI
);
84 EXPECT_TRUE(IsPromoted
);
85 GV
= M
->getNamedValue("_ZN4Impl3RunEv");
87 auto *F1
= dyn_cast
<Function
>(GV
);
88 EXPECT_EQ(F1
, CI
->getCalledFunction());
91 TEST(CallPromotionUtilsTest
, TryPromoteCall_NoFPLoad
) {
93 std::unique_ptr
<Module
> M
= parseIR(C
,
95 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
96 %class.Interface = type { i32 (...)** }
98 define void @f(void (%class.Interface*)* %fp, %class.Interface* nonnull %base.i) {
100 call void %fp(%class.Interface* nonnull %base.i)
105 auto *GV
= M
->getNamedValue("f");
107 auto *F
= dyn_cast
<Function
>(GV
);
109 Instruction
*Inst
= &F
->front().front();
110 auto *CI
= dyn_cast
<CallInst
>(Inst
);
112 ASSERT_FALSE(CI
->getCalledFunction());
113 bool IsPromoted
= tryPromoteCall(*CI
);
114 EXPECT_FALSE(IsPromoted
);
117 TEST(CallPromotionUtilsTest
, TryPromoteCall_NoVTablePtrLoad
) {
119 std::unique_ptr
<Module
> M
= parseIR(C
,
121 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
122 %class.Interface = type { i32 (...)** }
124 define void @f(void (%class.Interface*)** %vtable.i, %class.Interface* nonnull %base.i) {
126 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
127 call void %fp(%class.Interface* nonnull %base.i)
132 auto *GV
= M
->getNamedValue("f");
134 auto *F
= dyn_cast
<Function
>(GV
);
136 Instruction
*Inst
= &*++F
->front().rbegin();
137 auto *CI
= dyn_cast
<CallInst
>(Inst
);
139 ASSERT_FALSE(CI
->getCalledFunction());
140 bool IsPromoted
= tryPromoteCall(*CI
);
141 EXPECT_FALSE(IsPromoted
);
144 TEST(CallPromotionUtilsTest
, TryPromoteCall_NoVTableInitFound
) {
146 std::unique_ptr
<Module
> M
= parseIR(C
,
148 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
149 %class.Interface = type { i32 (...)** }
153 %o = alloca %class.Impl
154 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
156 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
157 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
158 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
159 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
160 call void %fp(%class.Interface* nonnull %base.i)
164 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
167 auto *GV
= M
->getNamedValue("f");
169 auto *F
= dyn_cast
<Function
>(GV
);
171 Instruction
*Inst
= &*++F
->front().rbegin();
172 auto *CI
= dyn_cast
<CallInst
>(Inst
);
174 ASSERT_FALSE(CI
->getCalledFunction());
175 bool IsPromoted
= tryPromoteCall(*CI
);
176 EXPECT_FALSE(IsPromoted
);
179 TEST(CallPromotionUtilsTest
, TryPromoteCall_EmptyVTable
) {
181 std::unique_ptr
<Module
> M
= parseIR(C
,
183 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
184 %class.Interface = type { i32 (...)** }
186 @_ZTV4Impl = external global { [3 x i8*] }
190 %o = alloca %class.Impl
191 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
192 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
193 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
195 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
196 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
197 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
198 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
199 call void %fp(%class.Interface* nonnull %base.i)
203 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
206 auto *GV
= M
->getNamedValue("f");
208 auto *F
= dyn_cast
<Function
>(GV
);
210 Instruction
*Inst
= &F
->front().front();
211 auto *AI
= dyn_cast
<AllocaInst
>(Inst
);
213 Inst
= &*++F
->front().rbegin();
214 auto *CI
= dyn_cast
<CallInst
>(Inst
);
216 ASSERT_FALSE(CI
->getCalledFunction());
217 bool IsPromoted
= tryPromoteCall(*CI
);
218 EXPECT_FALSE(IsPromoted
);
221 TEST(CallPromotionUtilsTest
, TryPromoteCall_NullFP
) {
223 std::unique_ptr
<Module
> M
= parseIR(C
,
225 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
226 %class.Interface = type { i32 (...)** }
228 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* null] }
232 %o = alloca %class.Impl
233 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
234 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
235 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
237 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
238 %c = bitcast %class.Interface* %base.i to void (%class.Interface*)***
239 %vtable.i = load void (%class.Interface*)**, void (%class.Interface*)*** %c
240 %fp = load void (%class.Interface*)*, void (%class.Interface*)** %vtable.i
241 call void %fp(%class.Interface* nonnull %base.i)
245 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
248 auto *GV
= M
->getNamedValue("f");
250 auto *F
= dyn_cast
<Function
>(GV
);
252 Instruction
*Inst
= &F
->front().front();
253 auto *AI
= dyn_cast
<AllocaInst
>(Inst
);
255 Inst
= &*++F
->front().rbegin();
256 auto *CI
= dyn_cast
<CallInst
>(Inst
);
258 ASSERT_FALSE(CI
->getCalledFunction());
259 bool IsPromoted
= tryPromoteCall(*CI
);
260 EXPECT_FALSE(IsPromoted
);
263 // Based on clang/test/CodeGenCXX/member-function-pointer-calls.cpp
264 TEST(CallPromotionUtilsTest
, TryPromoteCall_MemberFunctionCalls
) {
266 std::unique_ptr
<Module
> M
= parseIR(C
,
268 %struct.A = type { i32 (...)** }
270 @_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
272 define i32 @_Z2g1v() {
274 %a = alloca %struct.A, align 8
275 %0 = bitcast %struct.A* %a to i8*
276 %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0
277 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8
278 %2 = bitcast %struct.A* %a to i8*
279 %3 = bitcast i8* %2 to i8**
280 %vtable.i = load i8*, i8** %3, align 8
281 %4 = bitcast i8* %vtable.i to i32 (%struct.A*)**
282 %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %4, align 8
283 %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a)
287 define i32 @_Z2g2v() {
289 %a = alloca %struct.A, align 8
290 %0 = bitcast %struct.A* %a to i8*
291 %1 = getelementptr %struct.A, %struct.A* %a, i64 0, i32 0
292 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTV1A, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %1, align 8
293 %2 = bitcast %struct.A* %a to i8*
294 %3 = bitcast i8* %2 to i8**
295 %vtable.i = load i8*, i8** %3, align 8
296 %4 = getelementptr i8, i8* %vtable.i, i64 8
297 %5 = bitcast i8* %4 to i32 (%struct.A*)**
298 %memptr.virtualfn.i = load i32 (%struct.A*)*, i32 (%struct.A*)** %5, align 8
299 %call.i = call i32 %memptr.virtualfn.i(%struct.A* %a)
303 declare i32 @_ZN1A3vf1Ev(%struct.A* %this)
304 declare i32 @_ZN1A3vf2Ev(%struct.A* %this)
307 auto *GV
= M
->getNamedValue("_Z2g1v");
309 auto *F
= dyn_cast
<Function
>(GV
);
311 Instruction
*Inst
= &F
->front().front();
312 auto *AI
= dyn_cast
<AllocaInst
>(Inst
);
314 Inst
= &*++F
->front().rbegin();
315 auto *CI
= dyn_cast
<CallInst
>(Inst
);
317 ASSERT_FALSE(CI
->getCalledFunction());
318 bool IsPromoted1
= tryPromoteCall(*CI
);
319 EXPECT_TRUE(IsPromoted1
);
320 GV
= M
->getNamedValue("_ZN1A3vf1Ev");
322 F
= dyn_cast
<Function
>(GV
);
323 EXPECT_EQ(F
, CI
->getCalledFunction());
325 GV
= M
->getNamedValue("_Z2g2v");
327 F
= dyn_cast
<Function
>(GV
);
329 Inst
= &F
->front().front();
330 AI
= dyn_cast
<AllocaInst
>(Inst
);
332 Inst
= &*++F
->front().rbegin();
333 CI
= dyn_cast
<CallInst
>(Inst
);
335 ASSERT_FALSE(CI
->getCalledFunction());
336 bool IsPromoted2
= tryPromoteCall(*CI
);
337 EXPECT_TRUE(IsPromoted2
);
338 GV
= M
->getNamedValue("_ZN1A3vf2Ev");
340 F
= dyn_cast
<Function
>(GV
);
341 EXPECT_EQ(F
, CI
->getCalledFunction());
344 // Check that it isn't crashing due to missing promotion legality.
345 TEST(CallPromotionUtilsTest
, TryPromoteCall_Legality
) {
347 std::unique_ptr
<Module
> M
= parseIR(C
,
349 %struct1 = type <{ i32, i64 }>
350 %struct2 = type <{ i32, i64 }>
352 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
353 %class.Interface = type { i32 (...)** }
355 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (%struct2 (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
357 define %struct1 @f() {
359 %o = alloca %class.Impl
360 %base = getelementptr %class.Impl, %class.Impl* %o, i64 0, i32 0, i32 0
361 store i32 (...)** bitcast (i8** getelementptr inbounds ({ [3 x i8*] }, { [3 x i8*] }* @_ZTV4Impl, i64 0, i32 0, i64 2) to i32 (...)**), i32 (...)*** %base
362 %f = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 1
364 %base.i = getelementptr inbounds %class.Impl, %class.Impl* %o, i64 0, i32 0
365 %c = bitcast %class.Interface* %base.i to %struct1 (%class.Interface*)***
366 %vtable.i = load %struct1 (%class.Interface*)**, %struct1 (%class.Interface*)*** %c
367 %fp = load %struct1 (%class.Interface*)*, %struct1 (%class.Interface*)** %vtable.i
368 %rv = call %struct1 %fp(%class.Interface* nonnull %base.i)
372 declare %struct2 @_ZN4Impl3RunEv(%class.Impl* %this)
375 auto *GV
= M
->getNamedValue("f");
377 auto *F
= dyn_cast
<Function
>(GV
);
379 Instruction
*Inst
= &F
->front().front();
380 auto *AI
= dyn_cast
<AllocaInst
>(Inst
);
382 Inst
= &*++F
->front().rbegin();
383 auto *CI
= dyn_cast
<CallInst
>(Inst
);
385 ASSERT_FALSE(CI
->getCalledFunction());
386 bool IsPromoted
= tryPromoteCall(*CI
);
387 EXPECT_FALSE(IsPromoted
);
390 TEST(CallPromotionUtilsTest
, promoteCallWithVTableCmp
) {
392 std::unique_ptr
<Module
> M
= parseIR(C
,
394 target datalayout = "e
-m
:e
-p270
:32:32-p271
:32:32-p272
:64:64-i64
:64-f80
:128-n8
:16:32:64-S128
"
395 target triple = "x86_64
-unknown
-linux
-gnu
"
397 @_ZTV5Base1 = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev] }, !type !0
398 @_ZTV8Derived1 = constant { [4 x ptr], [3 x ptr] } { [4 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev], [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base25func2Ev] }, !type !0, !type !1, !type !2
399 @_ZTV8Derived2 = constant { [3 x ptr], [3 x ptr], [4 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base35func3Ev], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base25func2Ev], [4 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr null, ptr @_ZN5Base15func0Ev, ptr @_ZN5Base15func1Ev] }, !type !3, !type !4, !type !5, !type !6
401 define i32 @testfunc(ptr %d) {
403 %vtable = load ptr, ptr %d, !prof !7
404 %vfn = getelementptr inbounds ptr, ptr %vtable, i64 1
405 %0 = load ptr, ptr %vfn
406 %call = tail call i32 %0(ptr %d), !prof !8
410 define i32 @_ZN5Base15func1Ev(ptr %this) {
415 declare i32 @_ZN5Base25func2Ev(ptr)
416 declare i32 @_ZN5Base15func0Ev(ptr)
417 declare void @_ZN5Base35func3Ev(ptr)
419 !0 = !{i64 16, !"_ZTS5Base1
"}
420 !1 = !{i64 48, !"_ZTS5Base2
"}
421 !2 = !{i64 16, !"_ZTS8Derived1
"}
422 !3 = !{i64 64, !"_ZTS5Base1
"}
423 !4 = !{i64 40, !"_ZTS5Base2
"}
424 !5 = !{i64 16, !"_ZTS5Base3
"}
425 !6 = !{i64 16, !"_ZTS8Derived2
"}
426 !7 = !{!"VP
", i32 2, i64 1600, i64 -9064381665493407289, i64 800, i64 5035968517245772950, i64 500, i64 3215870116411581797, i64 300}
427 !8 = !{!"VP
", i32 0, i64 1600, i64 6804820478065511155, i64 1600})IR");
429 Function
*F
= M
->getFunction("testfunc");
430 CallInst
*CI
= dyn_cast
<CallInst
>(&*std::next(F
->front().rbegin()));
431 ASSERT_TRUE(CI
&& CI
->isIndirectCall());
433 // Create the constant and the branch weights
434 SmallVector
<Constant
*, 3> VTableAddressPoints
;
436 for (auto &[VTableName
, AddressPointOffset
] : {std::pair
{"_ZTV5Base1", 16},
437 {"_ZTV8Derived1", 16},
438 {"_ZTV8Derived2", 64}})
439 VTableAddressPoints
.push_back(getVTableAddressPointOffset(
440 M
->getGlobalVariable(VTableName
), AddressPointOffset
));
443 MDNode
*BranchWeights
= MDB
.createBranchWeights(1600, 0);
445 size_t OrigEntryBBSize
= F
->front().size();
447 LoadInst
*VPtr
= dyn_cast
<LoadInst
>(&*F
->front().begin());
449 Function
*Callee
= M
->getFunction("_ZN5Base15func1Ev");
450 // Tests that promoted direct call is returned.
451 CallBase
&DirectCB
= promoteCallWithVTableCmp(
452 *CI
, VPtr
, Callee
, VTableAddressPoints
, BranchWeights
);
453 EXPECT_EQ(DirectCB
.getCalledOperand(), Callee
);
455 // Promotion inserts 3 icmp instructions and 2 or instructions, and removes
456 // 1 call instruction from the entry block.
457 EXPECT_EQ(F
->front().size(), OrigEntryBBSize
+ 4);