12f56046dSTarindu Jayatilaka //===- FunctionPropertiesAnalysisTest.cpp - Function Properties Unit Tests-===//
2418121c3STarindu Jayatilaka //
3418121c3STarindu Jayatilaka // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4418121c3STarindu Jayatilaka // See https://llvm.org/LICENSE.txt for license information.
5418121c3STarindu Jayatilaka // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6418121c3STarindu Jayatilaka //
7418121c3STarindu Jayatilaka //===----------------------------------------------------------------------===//
8418121c3STarindu Jayatilaka
9418121c3STarindu Jayatilaka #include "llvm/Analysis/FunctionPropertiesAnalysis.h"
10f46dd19bSMircea Trofin #include "llvm/ADT/iterator_range.h"
11f46dd19bSMircea Trofin #include "llvm/Analysis/AliasAnalysis.h"
1271c3a551Sserge-sans-paille #include "llvm/Analysis/LoopInfo.h"
13418121c3STarindu Jayatilaka #include "llvm/AsmParser/Parser.h"
1406283661STarindu Jayatilaka #include "llvm/IR/Dominators.h"
15418121c3STarindu Jayatilaka #include "llvm/IR/Instructions.h"
16418121c3STarindu Jayatilaka #include "llvm/IR/LLVMContext.h"
17418121c3STarindu Jayatilaka #include "llvm/IR/Module.h"
18f46dd19bSMircea Trofin #include "llvm/IR/PassManager.h"
19f46dd19bSMircea Trofin #include "llvm/Passes/PassBuilder.h"
2022a1f998SMircea Trofin #include "llvm/Passes/StandardInstrumentations.h"
21418121c3STarindu Jayatilaka #include "llvm/Support/SourceMgr.h"
22f46dd19bSMircea Trofin #include "llvm/Transforms/Utils/Cloning.h"
23418121c3STarindu Jayatilaka #include "gtest/gtest.h"
24f46dd19bSMircea Trofin #include <cstring>
25418121c3STarindu Jayatilaka
26418121c3STarindu Jayatilaka using namespace llvm;
2706283661STarindu Jayatilaka namespace {
28418121c3STarindu Jayatilaka
2906283661STarindu Jayatilaka class FunctionPropertiesAnalysisTest : public testing::Test {
3022a1f998SMircea Trofin public:
FunctionPropertiesAnalysisTest()3122a1f998SMircea Trofin FunctionPropertiesAnalysisTest() {
3222a1f998SMircea Trofin FAM.registerPass([&] { return DominatorTreeAnalysis(); });
3322a1f998SMircea Trofin FAM.registerPass([&] { return LoopAnalysis(); });
3422a1f998SMircea Trofin FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
3522a1f998SMircea Trofin }
3622a1f998SMircea Trofin
3706283661STarindu Jayatilaka protected:
3806283661STarindu Jayatilaka std::unique_ptr<DominatorTree> DT;
3906283661STarindu Jayatilaka std::unique_ptr<LoopInfo> LI;
4022a1f998SMircea Trofin FunctionAnalysisManager FAM;
4106283661STarindu Jayatilaka
buildFPI(Function & F)4206283661STarindu Jayatilaka FunctionPropertiesInfo buildFPI(Function &F) {
4322a1f998SMircea Trofin return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, FAM);
4422a1f998SMircea Trofin }
4522a1f998SMircea Trofin
invalidate(Function & F)4622a1f998SMircea Trofin void invalidate(Function &F) {
4722a1f998SMircea Trofin PreservedAnalyses PA = PreservedAnalyses::none();
4822a1f998SMircea Trofin FAM.invalidate(F, PA);
4906283661STarindu Jayatilaka }
5006283661STarindu Jayatilaka
makeLLVMModule(LLVMContext & C,const char * IR)5106283661STarindu Jayatilaka std::unique_ptr<Module> makeLLVMModule(LLVMContext &C, const char *IR) {
52418121c3STarindu Jayatilaka SMDiagnostic Err;
53418121c3STarindu Jayatilaka std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
54418121c3STarindu Jayatilaka if (!Mod)
55418121c3STarindu Jayatilaka Err.print("MLAnalysisTests", errs());
56418121c3STarindu Jayatilaka return Mod;
57418121c3STarindu Jayatilaka }
58f46dd19bSMircea Trofin
findCall(Function & F,const char * Name=nullptr)59f46dd19bSMircea Trofin CallBase* findCall(Function& F, const char* Name = nullptr) {
60f46dd19bSMircea Trofin for (auto &BB : F)
61f46dd19bSMircea Trofin for (auto &I : BB )
62f46dd19bSMircea Trofin if (auto *CB = dyn_cast<CallBase>(&I))
63f46dd19bSMircea Trofin if (!Name || CB->getName() == Name)
64f46dd19bSMircea Trofin return CB;
65f46dd19bSMircea Trofin return nullptr;
66f46dd19bSMircea Trofin }
6706283661STarindu Jayatilaka };
68418121c3STarindu Jayatilaka
TEST_F(FunctionPropertiesAnalysisTest,BasicTest)6906283661STarindu Jayatilaka TEST_F(FunctionPropertiesAnalysisTest, BasicTest) {
70418121c3STarindu Jayatilaka LLVMContext C;
7106283661STarindu Jayatilaka std::unique_ptr<Module> M = makeLLVMModule(C,
72418121c3STarindu Jayatilaka R"IR(
73418121c3STarindu Jayatilaka target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
74418121c3STarindu Jayatilaka target triple = "x86_64-pc-linux-gnu"
75418121c3STarindu Jayatilaka declare i32 @f1(i32)
76418121c3STarindu Jayatilaka declare i32 @f2(i32)
77418121c3STarindu Jayatilaka define i32 @branches(i32) {
78418121c3STarindu Jayatilaka %cond = icmp slt i32 %0, 3
79418121c3STarindu Jayatilaka br i1 %cond, label %then, label %else
80418121c3STarindu Jayatilaka then:
81418121c3STarindu Jayatilaka %ret.1 = call i32 @f1(i32 %0)
82418121c3STarindu Jayatilaka br label %last.block
83418121c3STarindu Jayatilaka else:
84418121c3STarindu Jayatilaka %ret.2 = call i32 @f2(i32 %0)
85418121c3STarindu Jayatilaka br label %last.block
86418121c3STarindu Jayatilaka last.block:
87418121c3STarindu Jayatilaka %ret = phi i32 [%ret.1, %then], [%ret.2, %else]
88418121c3STarindu Jayatilaka ret i32 %ret
89418121c3STarindu Jayatilaka }
90418121c3STarindu Jayatilaka define internal i32 @top() {
91418121c3STarindu Jayatilaka %1 = call i32 @branches(i32 2)
92418121c3STarindu Jayatilaka %2 = call i32 @f1(i32 %1)
93418121c3STarindu Jayatilaka ret i32 %2
94418121c3STarindu Jayatilaka }
95418121c3STarindu Jayatilaka )IR");
96418121c3STarindu Jayatilaka
9706283661STarindu Jayatilaka Function *BranchesFunction = M->getFunction("branches");
9806283661STarindu Jayatilaka FunctionPropertiesInfo BranchesFeatures = buildFPI(*BranchesFunction);
99418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.BasicBlockCount, 4);
100418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.BlocksReachedFromConditionalInstruction, 2);
101418121c3STarindu Jayatilaka // 2 Users: top is one. The other is added because @branches is not internal,
102418121c3STarindu Jayatilaka // so it may have external callers.
103418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.Uses, 2);
10406283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0);
10506283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.LoadInstCount, 0);
10606283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.StoreInstCount, 0);
10706283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0);
10806283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0);
109418121c3STarindu Jayatilaka
11006283661STarindu Jayatilaka Function *TopFunction = M->getFunction("top");
11106283661STarindu Jayatilaka FunctionPropertiesInfo TopFeatures = buildFPI(*TopFunction);
112418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.BasicBlockCount, 1);
113418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0);
114418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.Uses, 0);
11506283661STarindu Jayatilaka EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1);
11606283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.LoadInstCount, 0);
11706283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.StoreInstCount, 0);
11806283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0);
11906283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0);
120418121c3STarindu Jayatilaka }
121f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InlineSameBBSimple)122f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBSimple) {
123f46dd19bSMircea Trofin LLVMContext C;
124f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
125f46dd19bSMircea Trofin R"IR(
126f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
127f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu"
128f46dd19bSMircea Trofin define i32 @f1(i32 %a) {
129f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a)
130f46dd19bSMircea Trofin %c = add i32 %b, 2
131f46dd19bSMircea Trofin ret i32 %c
132f46dd19bSMircea Trofin }
133f46dd19bSMircea Trofin
134f46dd19bSMircea Trofin define i32 @f2(i32 %a) {
135f46dd19bSMircea Trofin %b = add i32 %a, 1
136f46dd19bSMircea Trofin ret i32 %b
137f46dd19bSMircea Trofin }
138f46dd19bSMircea Trofin )IR");
139f46dd19bSMircea Trofin
140f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1");
141f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b");
142f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
143f46dd19bSMircea Trofin
144f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial;
145f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 1;
146f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 3;
147f46dd19bSMircea Trofin ExpectedInitial.Uses = 1;
148f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
149f46dd19bSMircea Trofin
150f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
151f46dd19bSMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0;
152f46dd19bSMircea Trofin
153f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
154f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
155f46dd19bSMircea Trofin
156f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
157f46dd19bSMircea Trofin InlineFunctionInfo IFI;
158f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
159f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
16022a1f998SMircea Trofin invalidate(*F1);
16122a1f998SMircea Trofin FPU.finish(FAM);
162f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
163f46dd19bSMircea Trofin }
164f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InlineSameBBLargerCFG)165f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLargerCFG) {
166f46dd19bSMircea Trofin LLVMContext C;
167f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
168f46dd19bSMircea Trofin R"IR(
169f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
170f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu"
171f46dd19bSMircea Trofin define i32 @f1(i32 %a) {
172f46dd19bSMircea Trofin entry:
173f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0
174f46dd19bSMircea Trofin br i1 %i, label %if.then, label %if.else
175f46dd19bSMircea Trofin if.then:
176f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a)
177f46dd19bSMircea Trofin %c1 = add i32 %b, 2
178f46dd19bSMircea Trofin br label %end
179f46dd19bSMircea Trofin if.else:
180f46dd19bSMircea Trofin %c2 = add i32 %a, 1
181f46dd19bSMircea Trofin br label %end
182f46dd19bSMircea Trofin end:
183f46dd19bSMircea Trofin %ret = phi i32 [%c1, %if.then],[%c2, %if.else]
184f46dd19bSMircea Trofin ret i32 %ret
185f46dd19bSMircea Trofin }
186f46dd19bSMircea Trofin
187f46dd19bSMircea Trofin define i32 @f2(i32 %a) {
188f46dd19bSMircea Trofin %b = add i32 %a, 1
189f46dd19bSMircea Trofin ret i32 %b
190f46dd19bSMircea Trofin }
191f46dd19bSMircea Trofin )IR");
192f46dd19bSMircea Trofin
193f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1");
194f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b");
195f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
196f46dd19bSMircea Trofin
197f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial;
198f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 4;
199f46dd19bSMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;
200f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 9;
201f46dd19bSMircea Trofin ExpectedInitial.Uses = 1;
202f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
203f46dd19bSMircea Trofin
204f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
205f46dd19bSMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0;
206f46dd19bSMircea Trofin
207f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
208f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
209f46dd19bSMircea Trofin
210f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
211f46dd19bSMircea Trofin InlineFunctionInfo IFI;
212f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
213f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
21422a1f998SMircea Trofin invalidate(*F1);
21522a1f998SMircea Trofin FPU.finish(FAM);
216f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
217f46dd19bSMircea Trofin }
218f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InlineSameBBLoops)219f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLoops) {
220f46dd19bSMircea Trofin LLVMContext C;
221f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
222f46dd19bSMircea Trofin R"IR(
223f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
224f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu"
225f46dd19bSMircea Trofin define i32 @f1(i32 %a) {
226f46dd19bSMircea Trofin entry:
227f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0
228f46dd19bSMircea Trofin br i1 %i, label %if.then, label %if.else
229f46dd19bSMircea Trofin if.then:
230f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a)
231f46dd19bSMircea Trofin %c1 = add i32 %b, 2
232f46dd19bSMircea Trofin br label %end
233f46dd19bSMircea Trofin if.else:
234f46dd19bSMircea Trofin %c2 = add i32 %a, 1
235f46dd19bSMircea Trofin br label %end
236f46dd19bSMircea Trofin end:
237f46dd19bSMircea Trofin %ret = phi i32 [%c1, %if.then],[%c2, %if.else]
238f46dd19bSMircea Trofin ret i32 %ret
239f46dd19bSMircea Trofin }
240f46dd19bSMircea Trofin
241f46dd19bSMircea Trofin define i32 @f2(i32 %a) {
242f46dd19bSMircea Trofin entry:
243f46dd19bSMircea Trofin br label %loop
244f46dd19bSMircea Trofin loop:
245f46dd19bSMircea Trofin %indvar = phi i32 [%indvar.next, %loop], [0, %entry]
246f46dd19bSMircea Trofin %b = add i32 %a, %indvar
247f46dd19bSMircea Trofin %indvar.next = add i32 %indvar, 1
248f46dd19bSMircea Trofin %cond = icmp slt i32 %indvar.next, %a
249f46dd19bSMircea Trofin br i1 %cond, label %loop, label %exit
250f46dd19bSMircea Trofin exit:
251f46dd19bSMircea Trofin ret i32 %b
252f46dd19bSMircea Trofin }
253f46dd19bSMircea Trofin )IR");
254f46dd19bSMircea Trofin
255f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1");
256f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b");
257f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
258f46dd19bSMircea Trofin
259f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial;
260f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 4;
261f46dd19bSMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;
262f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 9;
263f46dd19bSMircea Trofin ExpectedInitial.Uses = 1;
264f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
265f46dd19bSMircea Trofin
266f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal;
267f46dd19bSMircea Trofin ExpectedFinal.BasicBlockCount = 6;
268f46dd19bSMircea Trofin ExpectedFinal.BlocksReachedFromConditionalInstruction = 4;
269f46dd19bSMircea Trofin ExpectedFinal.Uses = 1;
270f46dd19bSMircea Trofin ExpectedFinal.MaxLoopDepth = 1;
271f46dd19bSMircea Trofin ExpectedFinal.TopLevelLoopCount = 1;
272f46dd19bSMircea Trofin ExpectedFinal.TotalInstructionCount = 14;
273f46dd19bSMircea Trofin
274f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
275f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
276f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
277f46dd19bSMircea Trofin InlineFunctionInfo IFI;
278f46dd19bSMircea Trofin
279f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
280f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
28122a1f998SMircea Trofin invalidate(*F1);
28222a1f998SMircea Trofin FPU.finish(FAM);
283f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
284f46dd19bSMircea Trofin }
285f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InvokeSimple)286f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeSimple) {
287f46dd19bSMircea Trofin LLVMContext C;
288f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
289f46dd19bSMircea Trofin R"IR(
290f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
291f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu"
292f46dd19bSMircea Trofin declare void @might_throw()
293f46dd19bSMircea Trofin
294f46dd19bSMircea Trofin define internal void @callee() {
295f46dd19bSMircea Trofin entry:
296f46dd19bSMircea Trofin call void @might_throw()
297f46dd19bSMircea Trofin ret void
298f46dd19bSMircea Trofin }
299f46dd19bSMircea Trofin
300f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
301f46dd19bSMircea Trofin entry:
302f46dd19bSMircea Trofin invoke void @callee()
303f46dd19bSMircea Trofin to label %cont unwind label %exc
304f46dd19bSMircea Trofin
305f46dd19bSMircea Trofin cont:
306f46dd19bSMircea Trofin ret i32 0
307f46dd19bSMircea Trofin
308f46dd19bSMircea Trofin exc:
309f46dd19bSMircea Trofin %exn = landingpad {i8*, i32}
310f46dd19bSMircea Trofin cleanup
311f46dd19bSMircea Trofin ret i32 1
312f46dd19bSMircea Trofin }
313f46dd19bSMircea Trofin
314f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...)
315f46dd19bSMircea Trofin )IR");
316f46dd19bSMircea Trofin
317f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller");
318f46dd19bSMircea Trofin CallBase* CB = findCall(*F1);
319f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
320f46dd19bSMircea Trofin
321f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
322f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
323f46dd19bSMircea Trofin InlineFunctionInfo IFI;
324f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
325f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
32622a1f998SMircea Trofin invalidate(*F1);
32722a1f998SMircea Trofin FPU.finish(FAM);
328f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount),
329f46dd19bSMircea Trofin F1->getBasicBlockList().size());
330f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),
331f46dd19bSMircea Trofin F1->getInstructionCount());
332f46dd19bSMircea Trofin }
333f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InvokeUnreachableHandler)334f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeUnreachableHandler) {
335f46dd19bSMircea Trofin LLVMContext C;
336f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
337f46dd19bSMircea Trofin R"IR(
338f46dd19bSMircea Trofin declare void @might_throw()
339f46dd19bSMircea Trofin
340f46dd19bSMircea Trofin define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 {
341f46dd19bSMircea Trofin entry:
342f46dd19bSMircea Trofin invoke void @might_throw()
343f46dd19bSMircea Trofin to label %cont unwind label %exc
344f46dd19bSMircea Trofin
345f46dd19bSMircea Trofin cont:
346f46dd19bSMircea Trofin ret i32 0
347f46dd19bSMircea Trofin
348f46dd19bSMircea Trofin exc:
349f46dd19bSMircea Trofin %exn = landingpad {i8*, i32}
350f46dd19bSMircea Trofin cleanup
351f46dd19bSMircea Trofin resume { i8*, i32 } %exn
352f46dd19bSMircea Trofin }
353f46dd19bSMircea Trofin
354f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
355f46dd19bSMircea Trofin entry:
356f46dd19bSMircea Trofin %X = invoke i32 @callee()
357f46dd19bSMircea Trofin to label %cont unwind label %Handler
358f46dd19bSMircea Trofin
359f46dd19bSMircea Trofin cont:
360f46dd19bSMircea Trofin ret i32 %X
361f46dd19bSMircea Trofin
362f46dd19bSMircea Trofin Handler:
363f46dd19bSMircea Trofin %exn = landingpad {i8*, i32}
364f46dd19bSMircea Trofin cleanup
365f46dd19bSMircea Trofin ret i32 1
366f46dd19bSMircea Trofin }
367f46dd19bSMircea Trofin
368f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...)
369f46dd19bSMircea Trofin )IR");
370f46dd19bSMircea Trofin
371f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller");
372f46dd19bSMircea Trofin CallBase* CB = findCall(*F1);
373f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
374f46dd19bSMircea Trofin
375f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
376f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
377f46dd19bSMircea Trofin InlineFunctionInfo IFI;
378f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
379f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
38022a1f998SMircea Trofin invalidate(*F1);
38122a1f998SMircea Trofin FPU.finish(FAM);
382f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount),
383f46dd19bSMircea Trofin F1->getBasicBlockList().size() - 1);
384f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),
385f46dd19bSMircea Trofin F1->getInstructionCount() - 2);
38622a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));
387f46dd19bSMircea Trofin }
388f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,Rethrow)389f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, Rethrow) {
390f46dd19bSMircea Trofin LLVMContext C;
391f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
392f46dd19bSMircea Trofin R"IR(
393f46dd19bSMircea Trofin declare void @might_throw()
394f46dd19bSMircea Trofin
395f46dd19bSMircea Trofin define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 {
396f46dd19bSMircea Trofin entry:
397f46dd19bSMircea Trofin invoke void @might_throw()
398f46dd19bSMircea Trofin to label %cont unwind label %exc
399f46dd19bSMircea Trofin
400f46dd19bSMircea Trofin cont:
401f46dd19bSMircea Trofin ret i32 0
402f46dd19bSMircea Trofin
403f46dd19bSMircea Trofin exc:
404f46dd19bSMircea Trofin %exn = landingpad {i8*, i32}
405f46dd19bSMircea Trofin cleanup
406f46dd19bSMircea Trofin resume { i8*, i32 } %exn
407f46dd19bSMircea Trofin }
408f46dd19bSMircea Trofin
409f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 {
410f46dd19bSMircea Trofin entry:
411f46dd19bSMircea Trofin %X = invoke i32 @callee()
412f46dd19bSMircea Trofin to label %cont unwind label %Handler
413f46dd19bSMircea Trofin
414f46dd19bSMircea Trofin cont:
415f46dd19bSMircea Trofin ret i32 %X
416f46dd19bSMircea Trofin
417f46dd19bSMircea Trofin Handler:
418f46dd19bSMircea Trofin %exn = landingpad {i8*, i32}
419f46dd19bSMircea Trofin cleanup
420f46dd19bSMircea Trofin ret i32 1
421f46dd19bSMircea Trofin }
422f46dd19bSMircea Trofin
423f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...)
424f46dd19bSMircea Trofin )IR");
425f46dd19bSMircea Trofin
426f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller");
427f46dd19bSMircea Trofin CallBase* CB = findCall(*F1);
428f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
429f46dd19bSMircea Trofin
430f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
431f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
432f46dd19bSMircea Trofin InlineFunctionInfo IFI;
433f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
434f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
43522a1f998SMircea Trofin invalidate(*F1);
43622a1f998SMircea Trofin FPU.finish(FAM);
437f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount),
438f46dd19bSMircea Trofin F1->getBasicBlockList().size() - 1);
439f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),
440f46dd19bSMircea Trofin F1->getInstructionCount() - 2);
44122a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));
442f46dd19bSMircea Trofin }
443f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,LPadChanges)444f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, LPadChanges) {
445f46dd19bSMircea Trofin LLVMContext C;
446f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
447f46dd19bSMircea Trofin R"IR(
448f46dd19bSMircea Trofin declare void @external_func()
449f46dd19bSMircea Trofin
450f46dd19bSMircea Trofin @exception_type1 = external global i8
451f46dd19bSMircea Trofin @exception_type2 = external global i8
452f46dd19bSMircea Trofin
453f46dd19bSMircea Trofin
454f46dd19bSMircea Trofin define internal void @inner() personality i8* null {
455f46dd19bSMircea Trofin invoke void @external_func()
456f46dd19bSMircea Trofin to label %cont unwind label %lpad
457f46dd19bSMircea Trofin cont:
458f46dd19bSMircea Trofin ret void
459f46dd19bSMircea Trofin lpad:
460f46dd19bSMircea Trofin %lp = landingpad i32
461f46dd19bSMircea Trofin catch i8* @exception_type1
462f46dd19bSMircea Trofin resume i32 %lp
463f46dd19bSMircea Trofin }
464f46dd19bSMircea Trofin
465f46dd19bSMircea Trofin define void @outer() personality i8* null {
466f46dd19bSMircea Trofin invoke void @inner()
467f46dd19bSMircea Trofin to label %cont unwind label %lpad
468f46dd19bSMircea Trofin cont:
469f46dd19bSMircea Trofin ret void
470f46dd19bSMircea Trofin lpad:
471f46dd19bSMircea Trofin %lp = landingpad i32
472f46dd19bSMircea Trofin cleanup
473f46dd19bSMircea Trofin catch i8* @exception_type2
474f46dd19bSMircea Trofin resume i32 %lp
475f46dd19bSMircea Trofin }
476f46dd19bSMircea Trofin
477f46dd19bSMircea Trofin )IR");
478f46dd19bSMircea Trofin
479f46dd19bSMircea Trofin Function *F1 = M->getFunction("outer");
480f46dd19bSMircea Trofin CallBase* CB = findCall(*F1);
481f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
482f46dd19bSMircea Trofin
483f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
484f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
485f46dd19bSMircea Trofin InlineFunctionInfo IFI;
486f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
487f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
48822a1f998SMircea Trofin invalidate(*F1);
48922a1f998SMircea Trofin FPU.finish(FAM);
490f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount),
491f46dd19bSMircea Trofin F1->getBasicBlockList().size() - 1);
492f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),
493f46dd19bSMircea Trofin F1->getInstructionCount() - 2);
49422a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));
495f46dd19bSMircea Trofin }
496f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,LPadChangesConditional)497f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, LPadChangesConditional) {
498f46dd19bSMircea Trofin LLVMContext C;
499f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
500f46dd19bSMircea Trofin R"IR(
501f46dd19bSMircea Trofin declare void @external_func()
502f46dd19bSMircea Trofin
503f46dd19bSMircea Trofin @exception_type1 = external global i8
504f46dd19bSMircea Trofin @exception_type2 = external global i8
505f46dd19bSMircea Trofin
506f46dd19bSMircea Trofin
507f46dd19bSMircea Trofin define internal void @inner() personality i8* null {
508f46dd19bSMircea Trofin invoke void @external_func()
509f46dd19bSMircea Trofin to label %cont unwind label %lpad
510f46dd19bSMircea Trofin cont:
511f46dd19bSMircea Trofin ret void
512f46dd19bSMircea Trofin lpad:
513f46dd19bSMircea Trofin %lp = landingpad i32
514f46dd19bSMircea Trofin catch i8* @exception_type1
515f46dd19bSMircea Trofin resume i32 %lp
516f46dd19bSMircea Trofin }
517f46dd19bSMircea Trofin
518f46dd19bSMircea Trofin define void @outer(i32 %a) personality i8* null {
519f46dd19bSMircea Trofin entry:
520f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0
521f46dd19bSMircea Trofin br i1 %i, label %if.then, label %cont
522f46dd19bSMircea Trofin if.then:
523f46dd19bSMircea Trofin invoke void @inner()
524f46dd19bSMircea Trofin to label %cont unwind label %lpad
525f46dd19bSMircea Trofin cont:
526f46dd19bSMircea Trofin ret void
527f46dd19bSMircea Trofin lpad:
528f46dd19bSMircea Trofin %lp = landingpad i32
529f46dd19bSMircea Trofin cleanup
530f46dd19bSMircea Trofin catch i8* @exception_type2
531f46dd19bSMircea Trofin resume i32 %lp
532f46dd19bSMircea Trofin }
533f46dd19bSMircea Trofin
534f46dd19bSMircea Trofin )IR");
535f46dd19bSMircea Trofin
536f46dd19bSMircea Trofin Function *F1 = M->getFunction("outer");
537f46dd19bSMircea Trofin CallBase* CB = findCall(*F1);
538f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr);
539f46dd19bSMircea Trofin
540f46dd19bSMircea Trofin auto FPI = buildFPI(*F1);
541f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
542f46dd19bSMircea Trofin InlineFunctionInfo IFI;
543f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
544f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess());
54522a1f998SMircea Trofin invalidate(*F1);
54622a1f998SMircea Trofin FPU.finish(FAM);
547f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount),
548f46dd19bSMircea Trofin F1->getBasicBlockList().size() - 1);
549f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),
550f46dd19bSMircea Trofin F1->getInstructionCount() - 2);
55122a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));
552f46dd19bSMircea Trofin }
553f46dd19bSMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InlineSameLoopBB)554b8c39eb2SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameLoopBB) {
555b8c39eb2SMircea Trofin LLVMContext C;
556b8c39eb2SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
557b8c39eb2SMircea Trofin R"IR(
558b8c39eb2SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
559b8c39eb2SMircea Trofin target triple = "x86_64-pc-linux-gnu"
560b8c39eb2SMircea Trofin
561b8c39eb2SMircea Trofin declare i32 @a()
562b8c39eb2SMircea Trofin declare i32 @b()
563b8c39eb2SMircea Trofin
564b8c39eb2SMircea Trofin define i32 @f1(i32 %a) {
565b8c39eb2SMircea Trofin entry:
566b8c39eb2SMircea Trofin br label %loop
567b8c39eb2SMircea Trofin loop:
568b8c39eb2SMircea Trofin %i = call i32 @f2(i32 %a)
569b8c39eb2SMircea Trofin %c = icmp slt i32 %i, %a
570b8c39eb2SMircea Trofin br i1 %c, label %loop, label %end
571b8c39eb2SMircea Trofin end:
572b8c39eb2SMircea Trofin %r = phi i32 [%i, %loop], [%a, %entry]
573b8c39eb2SMircea Trofin ret i32 %r
574b8c39eb2SMircea Trofin }
575b8c39eb2SMircea Trofin
576b8c39eb2SMircea Trofin define i32 @f2(i32 %a) {
577b8c39eb2SMircea Trofin %cnd = icmp slt i32 %a, 0
578b8c39eb2SMircea Trofin br i1 %cnd, label %then, label %else
579b8c39eb2SMircea Trofin then:
580b8c39eb2SMircea Trofin %r1 = call i32 @a()
581b8c39eb2SMircea Trofin br label %end
582b8c39eb2SMircea Trofin else:
583b8c39eb2SMircea Trofin %r2 = call i32 @b()
584b8c39eb2SMircea Trofin br label %end
585b8c39eb2SMircea Trofin end:
586b8c39eb2SMircea Trofin %r = phi i32 [%r1, %then], [%r2, %else]
587b8c39eb2SMircea Trofin ret i32 %r
588b8c39eb2SMircea Trofin }
589b8c39eb2SMircea Trofin )IR");
590b8c39eb2SMircea Trofin
591b8c39eb2SMircea Trofin Function *F1 = M->getFunction("f1");
592b8c39eb2SMircea Trofin CallBase *CB = findCall(*F1);
593b8c39eb2SMircea Trofin EXPECT_NE(CB, nullptr);
594b8c39eb2SMircea Trofin
595b8c39eb2SMircea Trofin FunctionPropertiesInfo ExpectedInitial;
596b8c39eb2SMircea Trofin ExpectedInitial.BasicBlockCount = 3;
597b8c39eb2SMircea Trofin ExpectedInitial.TotalInstructionCount = 6;
598b8c39eb2SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;
599b8c39eb2SMircea Trofin ExpectedInitial.Uses = 1;
600b8c39eb2SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
601b8c39eb2SMircea Trofin ExpectedInitial.MaxLoopDepth = 1;
602b8c39eb2SMircea Trofin ExpectedInitial.TopLevelLoopCount = 1;
603b8c39eb2SMircea Trofin
604b8c39eb2SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
605b8c39eb2SMircea Trofin ExpectedFinal.BasicBlockCount = 6;
606b8c39eb2SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0;
607b8c39eb2SMircea Trofin ExpectedFinal.BlocksReachedFromConditionalInstruction = 4;
608b8c39eb2SMircea Trofin ExpectedFinal.TotalInstructionCount = 12;
609b8c39eb2SMircea Trofin
610b8c39eb2SMircea Trofin auto FPI = buildFPI(*F1);
611b8c39eb2SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
612b8c39eb2SMircea Trofin
613b8c39eb2SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
614b8c39eb2SMircea Trofin InlineFunctionInfo IFI;
615b8c39eb2SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
616b8c39eb2SMircea Trofin EXPECT_TRUE(IR.isSuccess());
61722a1f998SMircea Trofin invalidate(*F1);
61822a1f998SMircea Trofin FPU.finish(FAM);
61922a1f998SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
62022a1f998SMircea Trofin }
62122a1f998SMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,Unreachable)62222a1f998SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, Unreachable) {
62322a1f998SMircea Trofin LLVMContext C;
62422a1f998SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
62522a1f998SMircea Trofin R"IR(
62622a1f998SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
62722a1f998SMircea Trofin target triple = "x86_64-pc-linux-gnu"
62822a1f998SMircea Trofin
62922a1f998SMircea Trofin define i64 @f1(i32 noundef %value) {
63022a1f998SMircea Trofin entry:
63122a1f998SMircea Trofin br i1 true, label %cond.true, label %cond.false
63222a1f998SMircea Trofin
63322a1f998SMircea Trofin cond.true: ; preds = %entry
63422a1f998SMircea Trofin %conv2 = sext i32 %value to i64
63522a1f998SMircea Trofin br label %cond.end
63622a1f998SMircea Trofin
63722a1f998SMircea Trofin cond.false: ; preds = %entry
63822a1f998SMircea Trofin %call3 = call noundef i64 @f2()
639*3f8e4169SMircea Trofin br label %extra
640*3f8e4169SMircea Trofin
641*3f8e4169SMircea Trofin extra:
642*3f8e4169SMircea Trofin br label %extra2
643*3f8e4169SMircea Trofin
644*3f8e4169SMircea Trofin extra2:
64522a1f998SMircea Trofin br label %cond.end
64622a1f998SMircea Trofin
64722a1f998SMircea Trofin cond.end: ; preds = %cond.false, %cond.true
648*3f8e4169SMircea Trofin %cond = phi i64 [ %conv2, %cond.true ], [ %call3, %extra ]
64922a1f998SMircea Trofin ret i64 %cond
65022a1f998SMircea Trofin }
65122a1f998SMircea Trofin
65222a1f998SMircea Trofin define i64 @f2() {
65322a1f998SMircea Trofin entry:
65422a1f998SMircea Trofin tail call void @llvm.trap()
65522a1f998SMircea Trofin unreachable
65622a1f998SMircea Trofin }
65722a1f998SMircea Trofin
65822a1f998SMircea Trofin declare void @llvm.trap()
65922a1f998SMircea Trofin )IR");
66022a1f998SMircea Trofin
66122a1f998SMircea Trofin Function *F1 = M->getFunction("f1");
66222a1f998SMircea Trofin CallBase *CB = findCall(*F1);
66322a1f998SMircea Trofin EXPECT_NE(CB, nullptr);
66422a1f998SMircea Trofin
66522a1f998SMircea Trofin FunctionPropertiesInfo ExpectedInitial;
666*3f8e4169SMircea Trofin ExpectedInitial.BasicBlockCount = 6;
667*3f8e4169SMircea Trofin ExpectedInitial.TotalInstructionCount = 9;
66822a1f998SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;
66922a1f998SMircea Trofin ExpectedInitial.Uses = 1;
67022a1f998SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
67122a1f998SMircea Trofin
67222a1f998SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
67322a1f998SMircea Trofin ExpectedFinal.BasicBlockCount = 4;
67422a1f998SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0;
67522a1f998SMircea Trofin ExpectedFinal.TotalInstructionCount = 7;
67622a1f998SMircea Trofin
67722a1f998SMircea Trofin auto FPI = buildFPI(*F1);
67822a1f998SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
67922a1f998SMircea Trofin
68022a1f998SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
68122a1f998SMircea Trofin InlineFunctionInfo IFI;
68222a1f998SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
68322a1f998SMircea Trofin EXPECT_TRUE(IR.isSuccess());
68422a1f998SMircea Trofin invalidate(*F1);
68522a1f998SMircea Trofin FPU.finish(FAM);
686b8c39eb2SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
687b8c39eb2SMircea Trofin }
688b8c39eb2SMircea Trofin
TEST_F(FunctionPropertiesAnalysisTest,InvokeSkipLP)689*3f8e4169SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeSkipLP) {
690*3f8e4169SMircea Trofin LLVMContext C;
691*3f8e4169SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C,
692*3f8e4169SMircea Trofin R"IR(
693*3f8e4169SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
694*3f8e4169SMircea Trofin target triple = "x86_64-pc-linux-gnu"
695*3f8e4169SMircea Trofin
696*3f8e4169SMircea Trofin define i64 @f1(i32 noundef %value) {
697*3f8e4169SMircea Trofin entry:
698*3f8e4169SMircea Trofin invoke fastcc void @f2() to label %cont unwind label %lpad
699*3f8e4169SMircea Trofin cont:
700*3f8e4169SMircea Trofin ret i64 1
701*3f8e4169SMircea Trofin lpad:
702*3f8e4169SMircea Trofin %lp = landingpad i32 cleanup
703*3f8e4169SMircea Trofin br label %ehcleanup
704*3f8e4169SMircea Trofin ehcleanup:
705*3f8e4169SMircea Trofin resume i32 0
706*3f8e4169SMircea Trofin }
707*3f8e4169SMircea Trofin define void @f2() {
708*3f8e4169SMircea Trofin invoke noundef void @f3() to label %exit unwind label %lpad
709*3f8e4169SMircea Trofin exit:
710*3f8e4169SMircea Trofin ret void
711*3f8e4169SMircea Trofin lpad:
712*3f8e4169SMircea Trofin %lp = landingpad i32 cleanup
713*3f8e4169SMircea Trofin resume i32 %lp
714*3f8e4169SMircea Trofin }
715*3f8e4169SMircea Trofin declare void @f3()
716*3f8e4169SMircea Trofin )IR");
717*3f8e4169SMircea Trofin
718*3f8e4169SMircea Trofin // The outcome of inlining will be that lpad becomes unreachable. The landing
719*3f8e4169SMircea Trofin // pad of the invoke inherited from f2 will land on a new bb which will branch
720*3f8e4169SMircea Trofin // to a bb containing the body of lpad.
721*3f8e4169SMircea Trofin Function *F1 = M->getFunction("f1");
722*3f8e4169SMircea Trofin CallBase *CB = findCall(*F1);
723*3f8e4169SMircea Trofin EXPECT_NE(CB, nullptr);
724*3f8e4169SMircea Trofin
725*3f8e4169SMircea Trofin FunctionPropertiesInfo ExpectedInitial;
726*3f8e4169SMircea Trofin ExpectedInitial.BasicBlockCount = 4;
727*3f8e4169SMircea Trofin ExpectedInitial.TotalInstructionCount = 5;
728*3f8e4169SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 0;
729*3f8e4169SMircea Trofin ExpectedInitial.Uses = 1;
730*3f8e4169SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1;
731*3f8e4169SMircea Trofin
732*3f8e4169SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;
733*3f8e4169SMircea Trofin ExpectedFinal.BasicBlockCount = 6;
734*3f8e4169SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0;
735*3f8e4169SMircea Trofin ExpectedFinal.TotalInstructionCount = 8;
736*3f8e4169SMircea Trofin
737*3f8e4169SMircea Trofin auto FPI = buildFPI(*F1);
738*3f8e4169SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial);
739*3f8e4169SMircea Trofin
740*3f8e4169SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB);
741*3f8e4169SMircea Trofin InlineFunctionInfo IFI;
742*3f8e4169SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI);
743*3f8e4169SMircea Trofin EXPECT_TRUE(IR.isSuccess());
744*3f8e4169SMircea Trofin invalidate(*F1);
745*3f8e4169SMircea Trofin FPU.finish(FAM);
746*3f8e4169SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal);
747*3f8e4169SMircea Trofin }
74806283661STarindu Jayatilaka } // end anonymous namespace
749