[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / Transforms / Utils / CallPromotionUtilsTest.cpp
blobeff8e27d36d64131ac09edd1bd21b250cd02b2b8
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 //===----------------------------------------------------------------------===//
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"
17 using namespace llvm;
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;
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 (...)** }
34 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (void (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
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
51 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
52 )IR");
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());
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 (...)** }
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
85 )IR");
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);
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 (...)** }
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
112 )IR");
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);
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 (...)** }
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
146 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
147 )IR");
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);
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 (...)** }
168 @_ZTV4Impl = external global { [3 x i8*] }
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
185 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
186 )IR");
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);
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 (...)** }
210 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* null] }
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
227 declare void @_ZN4Impl3RunEv(%class.Impl* %this)
228 )IR");
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);
245 // Based on clang/test/CodeGenCXX/member-function-pointer-calls.cpp
246 TEST(CallPromotionUtilsTest, TryPromoteCall_MemberFunctionCalls) {
247 LLVMContext C;
248 std::unique_ptr<Module> M = parseIR(C,
249 R"IR(
250 %struct.A = type { i32 (...)** }
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
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
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
285 declare i32 @_ZN1A3vf1Ev(%struct.A* %this)
286 declare i32 @_ZN1A3vf2Ev(%struct.A* %this)
287 )IR");
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());
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());
326 // Check that it isn't crashing due to missing promotion 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 }>
334 %class.Impl = type <{ %class.Interface, i32, [4 x i8] }>
335 %class.Interface = type { i32 (...)** }
337 @_ZTV4Impl = constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* null, i8* bitcast (%struct2 (%class.Impl*)* @_ZN4Impl3RunEv to i8*)] }
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
354 declare %struct2 @_ZN4Impl3RunEv(%class.Impl* %this)
355 )IR");
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);