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/Analysis/AliasAnalysis.h" 1171c3a551Sserge-sans-paille #include "llvm/Analysis/LoopInfo.h" 12418121c3STarindu Jayatilaka #include "llvm/AsmParser/Parser.h" 1306283661STarindu Jayatilaka #include "llvm/IR/Dominators.h" 14418121c3STarindu Jayatilaka #include "llvm/IR/Instructions.h" 15418121c3STarindu Jayatilaka #include "llvm/IR/LLVMContext.h" 16418121c3STarindu Jayatilaka #include "llvm/IR/Module.h" 17f46dd19bSMircea Trofin #include "llvm/IR/PassManager.h" 18f46dd19bSMircea Trofin #include "llvm/Passes/PassBuilder.h" 1922a1f998SMircea Trofin #include "llvm/Passes/StandardInstrumentations.h" 20418121c3STarindu Jayatilaka #include "llvm/Support/SourceMgr.h" 21f46dd19bSMircea Trofin #include "llvm/Transforms/Utils/Cloning.h" 22418121c3STarindu Jayatilaka #include "gtest/gtest.h" 23f46dd19bSMircea Trofin #include <cstring> 24418121c3STarindu Jayatilaka 25418121c3STarindu Jayatilaka using namespace llvm; 26fe6bb84cSAiden Grossman 272d854dd3SFangrui Song namespace llvm { 28fe6bb84cSAiden Grossman extern cl::opt<bool> EnableDetailedFunctionProperties; 29fe6bb84cSAiden Grossman extern cl::opt<bool> BigBasicBlockInstructionThreshold; 30fe6bb84cSAiden Grossman extern cl::opt<bool> MediumBasicBlockInstrutionThreshold; 312d854dd3SFangrui Song } // namespace llvm 32fe6bb84cSAiden Grossman 3306283661STarindu Jayatilaka namespace { 34418121c3STarindu Jayatilaka 3506283661STarindu Jayatilaka class FunctionPropertiesAnalysisTest : public testing::Test { 3622a1f998SMircea Trofin public: 3722a1f998SMircea Trofin FunctionPropertiesAnalysisTest() { 3822a1f998SMircea Trofin FAM.registerPass([&] { return DominatorTreeAnalysis(); }); 3922a1f998SMircea Trofin FAM.registerPass([&] { return LoopAnalysis(); }); 4022a1f998SMircea Trofin FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); 4122a1f998SMircea Trofin } 4222a1f998SMircea Trofin 4306283661STarindu Jayatilaka protected: 4406283661STarindu Jayatilaka std::unique_ptr<DominatorTree> DT; 4506283661STarindu Jayatilaka std::unique_ptr<LoopInfo> LI; 4622a1f998SMircea Trofin FunctionAnalysisManager FAM; 4706283661STarindu Jayatilaka 4806283661STarindu Jayatilaka FunctionPropertiesInfo buildFPI(Function &F) { 4922a1f998SMircea Trofin return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, FAM); 5022a1f998SMircea Trofin } 5122a1f998SMircea Trofin 5222a1f998SMircea Trofin void invalidate(Function &F) { 5322a1f998SMircea Trofin PreservedAnalyses PA = PreservedAnalyses::none(); 5422a1f998SMircea Trofin FAM.invalidate(F, PA); 5506283661STarindu Jayatilaka } 5606283661STarindu Jayatilaka 5706283661STarindu Jayatilaka std::unique_ptr<Module> makeLLVMModule(LLVMContext &C, const char *IR) { 58418121c3STarindu Jayatilaka SMDiagnostic Err; 59418121c3STarindu Jayatilaka std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 60418121c3STarindu Jayatilaka if (!Mod) 61418121c3STarindu Jayatilaka Err.print("MLAnalysisTests", errs()); 62418121c3STarindu Jayatilaka return Mod; 63418121c3STarindu Jayatilaka } 64f46dd19bSMircea Trofin 65f46dd19bSMircea Trofin CallBase* findCall(Function& F, const char* Name = nullptr) { 66f46dd19bSMircea Trofin for (auto &BB : F) 67f46dd19bSMircea Trofin for (auto &I : BB ) 68f46dd19bSMircea Trofin if (auto *CB = dyn_cast<CallBase>(&I)) 69f46dd19bSMircea Trofin if (!Name || CB->getName() == Name) 70f46dd19bSMircea Trofin return CB; 71f46dd19bSMircea Trofin return nullptr; 72f46dd19bSMircea Trofin } 7306283661STarindu Jayatilaka }; 74418121c3STarindu Jayatilaka 7506283661STarindu Jayatilaka TEST_F(FunctionPropertiesAnalysisTest, BasicTest) { 76418121c3STarindu Jayatilaka LLVMContext C; 7706283661STarindu Jayatilaka std::unique_ptr<Module> M = makeLLVMModule(C, 78418121c3STarindu Jayatilaka R"IR( 79418121c3STarindu Jayatilaka target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 80418121c3STarindu Jayatilaka target triple = "x86_64-pc-linux-gnu" 81418121c3STarindu Jayatilaka declare i32 @f1(i32) 82418121c3STarindu Jayatilaka declare i32 @f2(i32) 83418121c3STarindu Jayatilaka define i32 @branches(i32) { 84418121c3STarindu Jayatilaka %cond = icmp slt i32 %0, 3 85418121c3STarindu Jayatilaka br i1 %cond, label %then, label %else 86418121c3STarindu Jayatilaka then: 87418121c3STarindu Jayatilaka %ret.1 = call i32 @f1(i32 %0) 88418121c3STarindu Jayatilaka br label %last.block 89418121c3STarindu Jayatilaka else: 90418121c3STarindu Jayatilaka %ret.2 = call i32 @f2(i32 %0) 91418121c3STarindu Jayatilaka br label %last.block 92418121c3STarindu Jayatilaka last.block: 93418121c3STarindu Jayatilaka %ret = phi i32 [%ret.1, %then], [%ret.2, %else] 94418121c3STarindu Jayatilaka ret i32 %ret 95418121c3STarindu Jayatilaka } 96418121c3STarindu Jayatilaka define internal i32 @top() { 97418121c3STarindu Jayatilaka %1 = call i32 @branches(i32 2) 98418121c3STarindu Jayatilaka %2 = call i32 @f1(i32 %1) 99418121c3STarindu Jayatilaka ret i32 %2 100418121c3STarindu Jayatilaka } 101418121c3STarindu Jayatilaka )IR"); 102418121c3STarindu Jayatilaka 10306283661STarindu Jayatilaka Function *BranchesFunction = M->getFunction("branches"); 10406283661STarindu Jayatilaka FunctionPropertiesInfo BranchesFeatures = buildFPI(*BranchesFunction); 105418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.BasicBlockCount, 4); 106418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.BlocksReachedFromConditionalInstruction, 2); 107418121c3STarindu Jayatilaka // 2 Users: top is one. The other is added because @branches is not internal, 108418121c3STarindu Jayatilaka // so it may have external callers. 109418121c3STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.Uses, 2); 11006283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0); 11106283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); 11206283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); 11306283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); 11406283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); 115418121c3STarindu Jayatilaka 11606283661STarindu Jayatilaka Function *TopFunction = M->getFunction("top"); 11706283661STarindu Jayatilaka FunctionPropertiesInfo TopFeatures = buildFPI(*TopFunction); 118418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.BasicBlockCount, 1); 119418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0); 120418121c3STarindu Jayatilaka EXPECT_EQ(TopFeatures.Uses, 0); 12106283661STarindu Jayatilaka EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1); 12206283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); 12306283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); 12406283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); 12506283661STarindu Jayatilaka EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); 126fe6bb84cSAiden Grossman 127fe6bb84cSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 128fe6bb84cSAiden Grossman FunctionPropertiesInfo DetailedBranchesFeatures = buildFPI(*BranchesFunction); 129fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSingleSuccessor, 2); 130fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoSuccessors, 1); 131fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoSuccessors, 0); 132fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSinglePredecessor, 2); 133fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoPredecessors, 1); 134fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoPredecessors, 0); 135fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BigBasicBlocks, 0); 136fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.MediumBasicBlocks, 0); 137fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.SmallBasicBlocks, 4); 138fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CastInstructionCount, 0); 139fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.FloatingPointInstructionCount, 0); 140fe6bb84cSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.IntegerInstructionCount, 4); 141b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.ConstantIntOperandCount, 1); 142b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.ConstantFPOperandCount, 0); 143b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.ConstantOperandCount, 0); 144b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.InstructionOperandCount, 4); 145b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.BasicBlockOperandCount, 4); 146b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.GlobalValueOperandCount, 2); 147b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.InlineAsmOperandCount, 0); 148b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.ArgumentOperandCount, 3); 149b8f191e0SAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.UnknownOperandCount, 0); 150aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CriticalEdgeCount, 0); 151aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.ControlFlowEdgeCount, 4); 152aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.UnconditionalBranchCount, 2); 153aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.IntrinsicCount, 0); 154aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.DirectCallCount, 2); 155aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.IndirectCallCount, 0); 156aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CallReturnsIntegerCount, 2); 157aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CallReturnsFloatCount, 0); 158aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CallReturnsPointerCount, 0); 159aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CallWithManyArgumentsCount, 0); 160aad3641eSAiden Grossman EXPECT_EQ(DetailedBranchesFeatures.CallWithPointerArgumentCount, 0); 161fe6bb84cSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 162fe6bb84cSAiden Grossman } 163fe6bb84cSAiden Grossman 164fe6bb84cSAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, DifferentPredecessorSuccessorCounts) { 165fe6bb84cSAiden Grossman LLVMContext C; 166fe6bb84cSAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 167fe6bb84cSAiden Grossman R"IR( 168fe6bb84cSAiden Grossman define i64 @f1() { 169fe6bb84cSAiden Grossman br i1 0, label %br1, label %finally 170fe6bb84cSAiden Grossman br1: 171fe6bb84cSAiden Grossman ret i64 0 172fe6bb84cSAiden Grossman finally: 173fe6bb84cSAiden Grossman ret i64 3 174fe6bb84cSAiden Grossman } 175fe6bb84cSAiden Grossman )IR"); 176fe6bb84cSAiden Grossman 177fe6bb84cSAiden Grossman Function *F1 = M->getFunction("f1"); 178fe6bb84cSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 179fe6bb84cSAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 180fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSingleSuccessor, 0); 181fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoSuccessors, 1); 182fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoSuccessors, 0); 183fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSinglePredecessor, 2); 184fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoPredecessors, 0); 185fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoPredecessors, 0); 186fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.BigBasicBlocks, 0); 187fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.MediumBasicBlocks, 0); 188fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.SmallBasicBlocks, 3); 189fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.CastInstructionCount, 0); 190fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.FloatingPointInstructionCount, 0); 191fe6bb84cSAiden Grossman EXPECT_EQ(DetailedF1Properties.IntegerInstructionCount, 0); 192b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantIntOperandCount, 3); 193b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantFPOperandCount, 0); 194b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantOperandCount, 0); 195b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.InstructionOperandCount, 0); 196b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlockOperandCount, 2); 197b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.GlobalValueOperandCount, 0); 198b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 0); 199b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 0); 200b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0); 201aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0); 202aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 2); 203aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0); 204aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0); 205aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.DirectCallCount, 0); 206aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0); 207aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0); 208aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0); 209aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0); 210aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0); 211aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0); 212fe6bb84cSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 213418121c3STarindu Jayatilaka } 214f46dd19bSMircea Trofin 215f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBSimple) { 216f46dd19bSMircea Trofin LLVMContext C; 217f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 218f46dd19bSMircea Trofin R"IR( 219f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 220f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu" 221f46dd19bSMircea Trofin define i32 @f1(i32 %a) { 222f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a) 223f46dd19bSMircea Trofin %c = add i32 %b, 2 224f46dd19bSMircea Trofin ret i32 %c 225f46dd19bSMircea Trofin } 226f46dd19bSMircea Trofin 227f46dd19bSMircea Trofin define i32 @f2(i32 %a) { 228f46dd19bSMircea Trofin %b = add i32 %a, 1 229f46dd19bSMircea Trofin ret i32 %b 230f46dd19bSMircea Trofin } 231f46dd19bSMircea Trofin )IR"); 232f46dd19bSMircea Trofin 233f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1"); 234f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b"); 235f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 236f46dd19bSMircea Trofin 237f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial; 238f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 1; 239f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 3; 240f46dd19bSMircea Trofin ExpectedInitial.Uses = 1; 241f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 242f46dd19bSMircea Trofin 243f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial; 244f46dd19bSMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0; 245f46dd19bSMircea Trofin 246f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 247f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 248f46dd19bSMircea Trofin 249f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 250f46dd19bSMircea Trofin InlineFunctionInfo IFI; 251f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 252f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 25322a1f998SMircea Trofin invalidate(*F1); 25401c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 255f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 256f46dd19bSMircea Trofin } 257f46dd19bSMircea Trofin 258f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLargerCFG) { 259f46dd19bSMircea Trofin LLVMContext C; 260f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 261f46dd19bSMircea Trofin R"IR( 262f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 263f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu" 264f46dd19bSMircea Trofin define i32 @f1(i32 %a) { 265f46dd19bSMircea Trofin entry: 266f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0 267f46dd19bSMircea Trofin br i1 %i, label %if.then, label %if.else 268f46dd19bSMircea Trofin if.then: 269f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a) 270f46dd19bSMircea Trofin %c1 = add i32 %b, 2 271f46dd19bSMircea Trofin br label %end 272f46dd19bSMircea Trofin if.else: 273f46dd19bSMircea Trofin %c2 = add i32 %a, 1 274f46dd19bSMircea Trofin br label %end 275f46dd19bSMircea Trofin end: 276f46dd19bSMircea Trofin %ret = phi i32 [%c1, %if.then],[%c2, %if.else] 277f46dd19bSMircea Trofin ret i32 %ret 278f46dd19bSMircea Trofin } 279f46dd19bSMircea Trofin 280f46dd19bSMircea Trofin define i32 @f2(i32 %a) { 281f46dd19bSMircea Trofin %b = add i32 %a, 1 282f46dd19bSMircea Trofin ret i32 %b 283f46dd19bSMircea Trofin } 284f46dd19bSMircea Trofin )IR"); 285f46dd19bSMircea Trofin 286f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1"); 287f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b"); 288f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 289f46dd19bSMircea Trofin 290f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial; 291f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 4; 292f46dd19bSMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2; 293f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 9; 294f46dd19bSMircea Trofin ExpectedInitial.Uses = 1; 295f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 296f46dd19bSMircea Trofin 297f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial; 298f46dd19bSMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0; 299f46dd19bSMircea Trofin 300f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 301f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 302f46dd19bSMircea Trofin 303f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 304f46dd19bSMircea Trofin InlineFunctionInfo IFI; 305f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 306f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 30722a1f998SMircea Trofin invalidate(*F1); 30801c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 309f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 310f46dd19bSMircea Trofin } 311f46dd19bSMircea Trofin 312f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLoops) { 313f46dd19bSMircea Trofin LLVMContext C; 314f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 315f46dd19bSMircea Trofin R"IR( 316f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 317f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu" 318f46dd19bSMircea Trofin define i32 @f1(i32 %a) { 319f46dd19bSMircea Trofin entry: 320f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0 321f46dd19bSMircea Trofin br i1 %i, label %if.then, label %if.else 322f46dd19bSMircea Trofin if.then: 323f46dd19bSMircea Trofin %b = call i32 @f2(i32 %a) 324f46dd19bSMircea Trofin %c1 = add i32 %b, 2 325f46dd19bSMircea Trofin br label %end 326f46dd19bSMircea Trofin if.else: 327f46dd19bSMircea Trofin %c2 = add i32 %a, 1 328f46dd19bSMircea Trofin br label %end 329f46dd19bSMircea Trofin end: 330f46dd19bSMircea Trofin %ret = phi i32 [%c1, %if.then],[%c2, %if.else] 331f46dd19bSMircea Trofin ret i32 %ret 332f46dd19bSMircea Trofin } 333f46dd19bSMircea Trofin 334f46dd19bSMircea Trofin define i32 @f2(i32 %a) { 335f46dd19bSMircea Trofin entry: 336f46dd19bSMircea Trofin br label %loop 337f46dd19bSMircea Trofin loop: 338f46dd19bSMircea Trofin %indvar = phi i32 [%indvar.next, %loop], [0, %entry] 339f46dd19bSMircea Trofin %b = add i32 %a, %indvar 340f46dd19bSMircea Trofin %indvar.next = add i32 %indvar, 1 341f46dd19bSMircea Trofin %cond = icmp slt i32 %indvar.next, %a 342f46dd19bSMircea Trofin br i1 %cond, label %loop, label %exit 343f46dd19bSMircea Trofin exit: 344f46dd19bSMircea Trofin ret i32 %b 345f46dd19bSMircea Trofin } 346f46dd19bSMircea Trofin )IR"); 347f46dd19bSMircea Trofin 348f46dd19bSMircea Trofin Function *F1 = M->getFunction("f1"); 349f46dd19bSMircea Trofin CallBase* CB = findCall(*F1, "b"); 350f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 351f46dd19bSMircea Trofin 352f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedInitial; 353f46dd19bSMircea Trofin ExpectedInitial.BasicBlockCount = 4; 354f46dd19bSMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2; 355f46dd19bSMircea Trofin ExpectedInitial.TotalInstructionCount = 9; 356f46dd19bSMircea Trofin ExpectedInitial.Uses = 1; 357f46dd19bSMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 358f46dd19bSMircea Trofin 359f46dd19bSMircea Trofin FunctionPropertiesInfo ExpectedFinal; 360f46dd19bSMircea Trofin ExpectedFinal.BasicBlockCount = 6; 361f46dd19bSMircea Trofin ExpectedFinal.BlocksReachedFromConditionalInstruction = 4; 362f46dd19bSMircea Trofin ExpectedFinal.Uses = 1; 363f46dd19bSMircea Trofin ExpectedFinal.MaxLoopDepth = 1; 364f46dd19bSMircea Trofin ExpectedFinal.TopLevelLoopCount = 1; 365f46dd19bSMircea Trofin ExpectedFinal.TotalInstructionCount = 14; 366f46dd19bSMircea Trofin 367f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 368f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 369f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 370f46dd19bSMircea Trofin InlineFunctionInfo IFI; 371f46dd19bSMircea Trofin 372f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 373f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 37422a1f998SMircea Trofin invalidate(*F1); 37501c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 376f46dd19bSMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 377f46dd19bSMircea Trofin } 378f46dd19bSMircea Trofin 379f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeSimple) { 380f46dd19bSMircea Trofin LLVMContext C; 381f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 382f46dd19bSMircea Trofin R"IR( 383f46dd19bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 384f46dd19bSMircea Trofin target triple = "x86_64-pc-linux-gnu" 385f46dd19bSMircea Trofin declare void @might_throw() 386f46dd19bSMircea Trofin 387f46dd19bSMircea Trofin define internal void @callee() { 388f46dd19bSMircea Trofin entry: 389f46dd19bSMircea Trofin call void @might_throw() 390f46dd19bSMircea Trofin ret void 391f46dd19bSMircea Trofin } 392f46dd19bSMircea Trofin 393f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 { 394f46dd19bSMircea Trofin entry: 395f46dd19bSMircea Trofin invoke void @callee() 396f46dd19bSMircea Trofin to label %cont unwind label %exc 397f46dd19bSMircea Trofin 398f46dd19bSMircea Trofin cont: 399f46dd19bSMircea Trofin ret i32 0 400f46dd19bSMircea Trofin 401f46dd19bSMircea Trofin exc: 402f46dd19bSMircea Trofin %exn = landingpad {i8*, i32} 403f46dd19bSMircea Trofin cleanup 404f46dd19bSMircea Trofin ret i32 1 405f46dd19bSMircea Trofin } 406f46dd19bSMircea Trofin 407f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...) 408f46dd19bSMircea Trofin )IR"); 409f46dd19bSMircea Trofin 410f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller"); 411f46dd19bSMircea Trofin CallBase* CB = findCall(*F1); 412f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 413f46dd19bSMircea Trofin 414f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 415f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 416f46dd19bSMircea Trofin InlineFunctionInfo IFI; 417f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 418f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 41922a1f998SMircea Trofin invalidate(*F1); 42001c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 421a19ae77dSVasileios Porpodas EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size()); 422f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount), 423f46dd19bSMircea Trofin F1->getInstructionCount()); 424f46dd19bSMircea Trofin } 425f46dd19bSMircea Trofin 426f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeUnreachableHandler) { 427f46dd19bSMircea Trofin LLVMContext C; 428f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 429f46dd19bSMircea Trofin R"IR( 430f46dd19bSMircea Trofin declare void @might_throw() 431f46dd19bSMircea Trofin 432f46dd19bSMircea Trofin define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 { 433f46dd19bSMircea Trofin entry: 434f46dd19bSMircea Trofin invoke void @might_throw() 435f46dd19bSMircea Trofin to label %cont unwind label %exc 436f46dd19bSMircea Trofin 437f46dd19bSMircea Trofin cont: 438f46dd19bSMircea Trofin ret i32 0 439f46dd19bSMircea Trofin 440f46dd19bSMircea Trofin exc: 441f46dd19bSMircea Trofin %exn = landingpad {i8*, i32} 442f46dd19bSMircea Trofin cleanup 443f46dd19bSMircea Trofin resume { i8*, i32 } %exn 444f46dd19bSMircea Trofin } 445f46dd19bSMircea Trofin 446f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 { 447f46dd19bSMircea Trofin entry: 448f46dd19bSMircea Trofin %X = invoke i32 @callee() 449f46dd19bSMircea Trofin to label %cont unwind label %Handler 450f46dd19bSMircea Trofin 451f46dd19bSMircea Trofin cont: 452f46dd19bSMircea Trofin ret i32 %X 453f46dd19bSMircea Trofin 454f46dd19bSMircea Trofin Handler: 455f46dd19bSMircea Trofin %exn = landingpad {i8*, i32} 456f46dd19bSMircea Trofin cleanup 457f46dd19bSMircea Trofin ret i32 1 458f46dd19bSMircea Trofin } 459f46dd19bSMircea Trofin 460f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...) 461f46dd19bSMircea Trofin )IR"); 462f46dd19bSMircea Trofin 463f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller"); 464f46dd19bSMircea Trofin CallBase* CB = findCall(*F1); 465f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 466f46dd19bSMircea Trofin 467f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 468f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 469f46dd19bSMircea Trofin InlineFunctionInfo IFI; 470f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 471f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 47222a1f998SMircea Trofin invalidate(*F1); 47301c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 474a19ae77dSVasileios Porpodas EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1); 475f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount), 476f46dd19bSMircea Trofin F1->getInstructionCount() - 2); 47722a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); 478f46dd19bSMircea Trofin } 479f46dd19bSMircea Trofin 480f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, Rethrow) { 481f46dd19bSMircea Trofin LLVMContext C; 482f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 483f46dd19bSMircea Trofin R"IR( 484f46dd19bSMircea Trofin declare void @might_throw() 485f46dd19bSMircea Trofin 486f46dd19bSMircea Trofin define internal i32 @callee() personality i32 (...)* @__gxx_personality_v0 { 487f46dd19bSMircea Trofin entry: 488f46dd19bSMircea Trofin invoke void @might_throw() 489f46dd19bSMircea Trofin to label %cont unwind label %exc 490f46dd19bSMircea Trofin 491f46dd19bSMircea Trofin cont: 492f46dd19bSMircea Trofin ret i32 0 493f46dd19bSMircea Trofin 494f46dd19bSMircea Trofin exc: 495f46dd19bSMircea Trofin %exn = landingpad {i8*, i32} 496f46dd19bSMircea Trofin cleanup 497f46dd19bSMircea Trofin resume { i8*, i32 } %exn 498f46dd19bSMircea Trofin } 499f46dd19bSMircea Trofin 500f46dd19bSMircea Trofin define i32 @caller() personality i32 (...)* @__gxx_personality_v0 { 501f46dd19bSMircea Trofin entry: 502f46dd19bSMircea Trofin %X = invoke i32 @callee() 503f46dd19bSMircea Trofin to label %cont unwind label %Handler 504f46dd19bSMircea Trofin 505f46dd19bSMircea Trofin cont: 506f46dd19bSMircea Trofin ret i32 %X 507f46dd19bSMircea Trofin 508f46dd19bSMircea Trofin Handler: 509f46dd19bSMircea Trofin %exn = landingpad {i8*, i32} 510f46dd19bSMircea Trofin cleanup 511f46dd19bSMircea Trofin ret i32 1 512f46dd19bSMircea Trofin } 513f46dd19bSMircea Trofin 514f46dd19bSMircea Trofin declare i32 @__gxx_personality_v0(...) 515f46dd19bSMircea Trofin )IR"); 516f46dd19bSMircea Trofin 517f46dd19bSMircea Trofin Function *F1 = M->getFunction("caller"); 518f46dd19bSMircea Trofin CallBase* CB = findCall(*F1); 519f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 520f46dd19bSMircea Trofin 521f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 522f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 523f46dd19bSMircea Trofin InlineFunctionInfo IFI; 524f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 525f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 52622a1f998SMircea Trofin invalidate(*F1); 52701c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 528a19ae77dSVasileios Porpodas EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1); 529f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount), 530f46dd19bSMircea Trofin F1->getInstructionCount() - 2); 53122a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); 532f46dd19bSMircea Trofin } 533f46dd19bSMircea Trofin 534f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, LPadChanges) { 535f46dd19bSMircea Trofin LLVMContext C; 536f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 537f46dd19bSMircea Trofin R"IR( 538f46dd19bSMircea Trofin declare void @external_func() 539f46dd19bSMircea Trofin 540f46dd19bSMircea Trofin @exception_type1 = external global i8 541f46dd19bSMircea Trofin @exception_type2 = external global i8 542f46dd19bSMircea Trofin 543f46dd19bSMircea Trofin 544f46dd19bSMircea Trofin define internal void @inner() personality i8* null { 545f46dd19bSMircea Trofin invoke void @external_func() 546f46dd19bSMircea Trofin to label %cont unwind label %lpad 547f46dd19bSMircea Trofin cont: 548f46dd19bSMircea Trofin ret void 549f46dd19bSMircea Trofin lpad: 550f46dd19bSMircea Trofin %lp = landingpad i32 551f46dd19bSMircea Trofin catch i8* @exception_type1 552f46dd19bSMircea Trofin resume i32 %lp 553f46dd19bSMircea Trofin } 554f46dd19bSMircea Trofin 555f46dd19bSMircea Trofin define void @outer() personality i8* null { 556f46dd19bSMircea Trofin invoke void @inner() 557f46dd19bSMircea Trofin to label %cont unwind label %lpad 558f46dd19bSMircea Trofin cont: 559f46dd19bSMircea Trofin ret void 560f46dd19bSMircea Trofin lpad: 561f46dd19bSMircea Trofin %lp = landingpad i32 562f46dd19bSMircea Trofin cleanup 563f46dd19bSMircea Trofin catch i8* @exception_type2 564f46dd19bSMircea Trofin resume i32 %lp 565f46dd19bSMircea Trofin } 566f46dd19bSMircea Trofin 567f46dd19bSMircea Trofin )IR"); 568f46dd19bSMircea Trofin 569f46dd19bSMircea Trofin Function *F1 = M->getFunction("outer"); 570f46dd19bSMircea Trofin CallBase* CB = findCall(*F1); 571f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 572f46dd19bSMircea Trofin 573f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 574f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 575f46dd19bSMircea Trofin InlineFunctionInfo IFI; 576f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 577f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 57822a1f998SMircea Trofin invalidate(*F1); 57901c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 580a19ae77dSVasileios Porpodas EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1); 581f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount), 582f46dd19bSMircea Trofin F1->getInstructionCount() - 2); 58322a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); 584f46dd19bSMircea Trofin } 585f46dd19bSMircea Trofin 586f46dd19bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, LPadChangesConditional) { 587f46dd19bSMircea Trofin LLVMContext C; 588f46dd19bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 589f46dd19bSMircea Trofin R"IR( 590f46dd19bSMircea Trofin declare void @external_func() 591f46dd19bSMircea Trofin 592f46dd19bSMircea Trofin @exception_type1 = external global i8 593f46dd19bSMircea Trofin @exception_type2 = external global i8 594f46dd19bSMircea Trofin 595f46dd19bSMircea Trofin 596f46dd19bSMircea Trofin define internal void @inner() personality i8* null { 597f46dd19bSMircea Trofin invoke void @external_func() 598f46dd19bSMircea Trofin to label %cont unwind label %lpad 599f46dd19bSMircea Trofin cont: 600f46dd19bSMircea Trofin ret void 601f46dd19bSMircea Trofin lpad: 602f46dd19bSMircea Trofin %lp = landingpad i32 603f46dd19bSMircea Trofin catch i8* @exception_type1 604f46dd19bSMircea Trofin resume i32 %lp 605f46dd19bSMircea Trofin } 606f46dd19bSMircea Trofin 607f46dd19bSMircea Trofin define void @outer(i32 %a) personality i8* null { 608f46dd19bSMircea Trofin entry: 609f46dd19bSMircea Trofin %i = icmp slt i32 %a, 0 610f46dd19bSMircea Trofin br i1 %i, label %if.then, label %cont 611f46dd19bSMircea Trofin if.then: 612f46dd19bSMircea Trofin invoke void @inner() 613f46dd19bSMircea Trofin to label %cont unwind label %lpad 614f46dd19bSMircea Trofin cont: 615f46dd19bSMircea Trofin ret void 616f46dd19bSMircea Trofin lpad: 617f46dd19bSMircea Trofin %lp = landingpad i32 618f46dd19bSMircea Trofin cleanup 619f46dd19bSMircea Trofin catch i8* @exception_type2 620f46dd19bSMircea Trofin resume i32 %lp 621f46dd19bSMircea Trofin } 622f46dd19bSMircea Trofin 623f46dd19bSMircea Trofin )IR"); 624f46dd19bSMircea Trofin 625f46dd19bSMircea Trofin Function *F1 = M->getFunction("outer"); 626f46dd19bSMircea Trofin CallBase* CB = findCall(*F1); 627f46dd19bSMircea Trofin EXPECT_NE(CB, nullptr); 628f46dd19bSMircea Trofin 629f46dd19bSMircea Trofin auto FPI = buildFPI(*F1); 630f46dd19bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 631f46dd19bSMircea Trofin InlineFunctionInfo IFI; 632f46dd19bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 633f46dd19bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 63422a1f998SMircea Trofin invalidate(*F1); 63501c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 636a19ae77dSVasileios Porpodas EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1); 637f46dd19bSMircea Trofin EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount), 638f46dd19bSMircea Trofin F1->getInstructionCount() - 2); 63922a1f998SMircea Trofin EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); 640f46dd19bSMircea Trofin } 641f46dd19bSMircea Trofin 642b8c39eb2SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InlineSameLoopBB) { 643b8c39eb2SMircea Trofin LLVMContext C; 644b8c39eb2SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 645b8c39eb2SMircea Trofin R"IR( 646b8c39eb2SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 647b8c39eb2SMircea Trofin target triple = "x86_64-pc-linux-gnu" 648b8c39eb2SMircea Trofin 649b8c39eb2SMircea Trofin declare i32 @a() 650b8c39eb2SMircea Trofin declare i32 @b() 651b8c39eb2SMircea Trofin 652b8c39eb2SMircea Trofin define i32 @f1(i32 %a) { 653b8c39eb2SMircea Trofin entry: 654b8c39eb2SMircea Trofin br label %loop 655b8c39eb2SMircea Trofin loop: 656b8c39eb2SMircea Trofin %i = call i32 @f2(i32 %a) 657b8c39eb2SMircea Trofin %c = icmp slt i32 %i, %a 658b8c39eb2SMircea Trofin br i1 %c, label %loop, label %end 659b8c39eb2SMircea Trofin end: 660b8c39eb2SMircea Trofin %r = phi i32 [%i, %loop], [%a, %entry] 661b8c39eb2SMircea Trofin ret i32 %r 662b8c39eb2SMircea Trofin } 663b8c39eb2SMircea Trofin 664b8c39eb2SMircea Trofin define i32 @f2(i32 %a) { 665b8c39eb2SMircea Trofin %cnd = icmp slt i32 %a, 0 666b8c39eb2SMircea Trofin br i1 %cnd, label %then, label %else 667b8c39eb2SMircea Trofin then: 668b8c39eb2SMircea Trofin %r1 = call i32 @a() 669b8c39eb2SMircea Trofin br label %end 670b8c39eb2SMircea Trofin else: 671b8c39eb2SMircea Trofin %r2 = call i32 @b() 672b8c39eb2SMircea Trofin br label %end 673b8c39eb2SMircea Trofin end: 674b8c39eb2SMircea Trofin %r = phi i32 [%r1, %then], [%r2, %else] 675b8c39eb2SMircea Trofin ret i32 %r 676b8c39eb2SMircea Trofin } 677b8c39eb2SMircea Trofin )IR"); 678b8c39eb2SMircea Trofin 679b8c39eb2SMircea Trofin Function *F1 = M->getFunction("f1"); 680b8c39eb2SMircea Trofin CallBase *CB = findCall(*F1); 681b8c39eb2SMircea Trofin EXPECT_NE(CB, nullptr); 682b8c39eb2SMircea Trofin 683b8c39eb2SMircea Trofin FunctionPropertiesInfo ExpectedInitial; 684b8c39eb2SMircea Trofin ExpectedInitial.BasicBlockCount = 3; 685b8c39eb2SMircea Trofin ExpectedInitial.TotalInstructionCount = 6; 686b8c39eb2SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2; 687b8c39eb2SMircea Trofin ExpectedInitial.Uses = 1; 688b8c39eb2SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 689b8c39eb2SMircea Trofin ExpectedInitial.MaxLoopDepth = 1; 690b8c39eb2SMircea Trofin ExpectedInitial.TopLevelLoopCount = 1; 691b8c39eb2SMircea Trofin 692b8c39eb2SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial; 693b8c39eb2SMircea Trofin ExpectedFinal.BasicBlockCount = 6; 694b8c39eb2SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0; 695b8c39eb2SMircea Trofin ExpectedFinal.BlocksReachedFromConditionalInstruction = 4; 696b8c39eb2SMircea Trofin ExpectedFinal.TotalInstructionCount = 12; 697b8c39eb2SMircea Trofin 698b8c39eb2SMircea Trofin auto FPI = buildFPI(*F1); 699b8c39eb2SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 700b8c39eb2SMircea Trofin 701b8c39eb2SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 702b8c39eb2SMircea Trofin InlineFunctionInfo IFI; 703b8c39eb2SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 704b8c39eb2SMircea Trofin EXPECT_TRUE(IR.isSuccess()); 70522a1f998SMircea Trofin invalidate(*F1); 70601c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 70722a1f998SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 70822a1f998SMircea Trofin } 70922a1f998SMircea Trofin 71022a1f998SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, Unreachable) { 71122a1f998SMircea Trofin LLVMContext C; 71222a1f998SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 71322a1f998SMircea Trofin R"IR( 71422a1f998SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 71522a1f998SMircea Trofin target triple = "x86_64-pc-linux-gnu" 71622a1f998SMircea Trofin 71722a1f998SMircea Trofin define i64 @f1(i32 noundef %value) { 71822a1f998SMircea Trofin entry: 71922a1f998SMircea Trofin br i1 true, label %cond.true, label %cond.false 72022a1f998SMircea Trofin 72122a1f998SMircea Trofin cond.true: ; preds = %entry 72222a1f998SMircea Trofin %conv2 = sext i32 %value to i64 72322a1f998SMircea Trofin br label %cond.end 72422a1f998SMircea Trofin 72522a1f998SMircea Trofin cond.false: ; preds = %entry 72622a1f998SMircea Trofin %call3 = call noundef i64 @f2() 7273f8e4169SMircea Trofin br label %extra 7283f8e4169SMircea Trofin 7293f8e4169SMircea Trofin extra: 7303f8e4169SMircea Trofin br label %extra2 7313f8e4169SMircea Trofin 7323f8e4169SMircea Trofin extra2: 73322a1f998SMircea Trofin br label %cond.end 73422a1f998SMircea Trofin 73522a1f998SMircea Trofin cond.end: ; preds = %cond.false, %cond.true 7363f8e4169SMircea Trofin %cond = phi i64 [ %conv2, %cond.true ], [ %call3, %extra ] 73722a1f998SMircea Trofin ret i64 %cond 73822a1f998SMircea Trofin } 73922a1f998SMircea Trofin 74022a1f998SMircea Trofin define i64 @f2() { 74122a1f998SMircea Trofin entry: 74222a1f998SMircea Trofin tail call void @llvm.trap() 74322a1f998SMircea Trofin unreachable 74422a1f998SMircea Trofin } 74522a1f998SMircea Trofin 74622a1f998SMircea Trofin declare void @llvm.trap() 74722a1f998SMircea Trofin )IR"); 74822a1f998SMircea Trofin 74922a1f998SMircea Trofin Function *F1 = M->getFunction("f1"); 75022a1f998SMircea Trofin CallBase *CB = findCall(*F1); 75122a1f998SMircea Trofin EXPECT_NE(CB, nullptr); 75222a1f998SMircea Trofin 75322a1f998SMircea Trofin FunctionPropertiesInfo ExpectedInitial; 7543f8e4169SMircea Trofin ExpectedInitial.BasicBlockCount = 6; 7553f8e4169SMircea Trofin ExpectedInitial.TotalInstructionCount = 9; 75622a1f998SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 2; 75722a1f998SMircea Trofin ExpectedInitial.Uses = 1; 75822a1f998SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 75922a1f998SMircea Trofin 76022a1f998SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial; 76122a1f998SMircea Trofin ExpectedFinal.BasicBlockCount = 4; 76222a1f998SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0; 76322a1f998SMircea Trofin ExpectedFinal.TotalInstructionCount = 7; 76422a1f998SMircea Trofin 76522a1f998SMircea Trofin auto FPI = buildFPI(*F1); 76622a1f998SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 76722a1f998SMircea Trofin 76822a1f998SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 76922a1f998SMircea Trofin InlineFunctionInfo IFI; 77022a1f998SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 77122a1f998SMircea Trofin EXPECT_TRUE(IR.isSuccess()); 77222a1f998SMircea Trofin invalidate(*F1); 77301c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 774b8c39eb2SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 775b8c39eb2SMircea Trofin } 776b8c39eb2SMircea Trofin 7773f8e4169SMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeSkipLP) { 7783f8e4169SMircea Trofin LLVMContext C; 7793f8e4169SMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 7803f8e4169SMircea Trofin R"IR( 7813f8e4169SMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 7823f8e4169SMircea Trofin target triple = "x86_64-pc-linux-gnu" 7833f8e4169SMircea Trofin 7843f8e4169SMircea Trofin define i64 @f1(i32 noundef %value) { 7853f8e4169SMircea Trofin entry: 7863f8e4169SMircea Trofin invoke fastcc void @f2() to label %cont unwind label %lpad 7873f8e4169SMircea Trofin cont: 7883f8e4169SMircea Trofin ret i64 1 7893f8e4169SMircea Trofin lpad: 7903f8e4169SMircea Trofin %lp = landingpad i32 cleanup 7913f8e4169SMircea Trofin br label %ehcleanup 7923f8e4169SMircea Trofin ehcleanup: 7933f8e4169SMircea Trofin resume i32 0 7943f8e4169SMircea Trofin } 7953f8e4169SMircea Trofin define void @f2() { 7963f8e4169SMircea Trofin invoke noundef void @f3() to label %exit unwind label %lpad 7973f8e4169SMircea Trofin exit: 7983f8e4169SMircea Trofin ret void 7993f8e4169SMircea Trofin lpad: 8003f8e4169SMircea Trofin %lp = landingpad i32 cleanup 8013f8e4169SMircea Trofin resume i32 %lp 8023f8e4169SMircea Trofin } 8033f8e4169SMircea Trofin declare void @f3() 8043f8e4169SMircea Trofin )IR"); 8053f8e4169SMircea Trofin 8063f8e4169SMircea Trofin // The outcome of inlining will be that lpad becomes unreachable. The landing 8073f8e4169SMircea Trofin // pad of the invoke inherited from f2 will land on a new bb which will branch 8083f8e4169SMircea Trofin // to a bb containing the body of lpad. 8093f8e4169SMircea Trofin Function *F1 = M->getFunction("f1"); 8103f8e4169SMircea Trofin CallBase *CB = findCall(*F1); 8113f8e4169SMircea Trofin EXPECT_NE(CB, nullptr); 8123f8e4169SMircea Trofin 8133f8e4169SMircea Trofin FunctionPropertiesInfo ExpectedInitial; 8143f8e4169SMircea Trofin ExpectedInitial.BasicBlockCount = 4; 8153f8e4169SMircea Trofin ExpectedInitial.TotalInstructionCount = 5; 8163f8e4169SMircea Trofin ExpectedInitial.BlocksReachedFromConditionalInstruction = 0; 8173f8e4169SMircea Trofin ExpectedInitial.Uses = 1; 8183f8e4169SMircea Trofin ExpectedInitial.DirectCallsToDefinedFunctions = 1; 8193f8e4169SMircea Trofin 8203f8e4169SMircea Trofin FunctionPropertiesInfo ExpectedFinal = ExpectedInitial; 8213f8e4169SMircea Trofin ExpectedFinal.BasicBlockCount = 6; 8223f8e4169SMircea Trofin ExpectedFinal.DirectCallsToDefinedFunctions = 0; 8233f8e4169SMircea Trofin ExpectedFinal.TotalInstructionCount = 8; 8243f8e4169SMircea Trofin 8253f8e4169SMircea Trofin auto FPI = buildFPI(*F1); 8263f8e4169SMircea Trofin EXPECT_EQ(FPI, ExpectedInitial); 8273f8e4169SMircea Trofin 8283f8e4169SMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 8293f8e4169SMircea Trofin InlineFunctionInfo IFI; 8303f8e4169SMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 8313f8e4169SMircea Trofin EXPECT_TRUE(IR.isSuccess()); 8323f8e4169SMircea Trofin invalidate(*F1); 83301c5ec3dSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 8343f8e4169SMircea Trofin EXPECT_EQ(FPI, ExpectedFinal); 8353f8e4169SMircea Trofin } 836b8f191e0SAiden Grossman 837b8f191e0SAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, DetailedOperandCount) { 838b8f191e0SAiden Grossman LLVMContext C; 839b8f191e0SAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 840b8f191e0SAiden Grossman R"IR( 841b8f191e0SAiden Grossman @a = global i64 1 842b8f191e0SAiden Grossman 843b8f191e0SAiden Grossman define i64 @f1(i64 %e) { 844b8f191e0SAiden Grossman %b = load i64, i64* @a 845b8f191e0SAiden Grossman %c = add i64 %b, 2 846b8f191e0SAiden Grossman %d = call i64 asm "mov $1,$0", "=r,r" (i64 %c) 847b8f191e0SAiden Grossman %f = add i64 %d, %e 848b8f191e0SAiden Grossman ret i64 %f 849b8f191e0SAiden Grossman } 850b8f191e0SAiden Grossman )IR"); 851b8f191e0SAiden Grossman 852b8f191e0SAiden Grossman Function *F1 = M->getFunction("f1"); 853b8f191e0SAiden Grossman EnableDetailedFunctionProperties.setValue(true); 854b8f191e0SAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 855b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSingleSuccessor, 0); 856b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoSuccessors, 0); 857b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoSuccessors, 0); 858b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSinglePredecessor, 0); 859b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoPredecessors, 0); 860b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoPredecessors, 0); 861b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BigBasicBlocks, 0); 862b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.MediumBasicBlocks, 0); 863b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.SmallBasicBlocks, 1); 864b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.CastInstructionCount, 0); 865b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.FloatingPointInstructionCount, 0); 866b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.IntegerInstructionCount, 4); 867b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantIntOperandCount, 1); 868b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantFPOperandCount, 0); 869b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ConstantOperandCount, 0); 870b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.InstructionOperandCount, 4); 871b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.BasicBlockOperandCount, 0); 872b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.GlobalValueOperandCount, 1); 873b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 1); 874b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 1); 875b8f191e0SAiden Grossman EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0); 876aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0); 877aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 0); 878aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0); 879aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0); 880aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1); 881aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0); 882aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 1); 883aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0); 884aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0); 885aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0); 886aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0); 887aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 888aad3641eSAiden Grossman } 889aad3641eSAiden Grossman 890aad3641eSAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, IntrinsicCount) { 891aad3641eSAiden Grossman LLVMContext C; 892aad3641eSAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 893aad3641eSAiden Grossman R"IR( 894aad3641eSAiden Grossman define float @f1(float %a) { 895aad3641eSAiden Grossman %b = call float @llvm.cos.f32(float %a) 896aad3641eSAiden Grossman ret float %b 897aad3641eSAiden Grossman } 898aad3641eSAiden Grossman declare float @llvm.cos.f32(float) 899aad3641eSAiden Grossman )IR"); 900aad3641eSAiden Grossman 901aad3641eSAiden Grossman Function *F1 = M->getFunction("f1"); 902aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 903aad3641eSAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 904aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 1); 905aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1); 906aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0); 907aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0); 908aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1); 909aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0); 910aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0); 911aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0); 912aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 913aad3641eSAiden Grossman } 914aad3641eSAiden Grossman 915aad3641eSAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, FunctionCallMetrics) { 916aad3641eSAiden Grossman LLVMContext C; 917aad3641eSAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 918aad3641eSAiden Grossman R"IR( 919aad3641eSAiden Grossman define i64 @f1(i64 %a) { 920aad3641eSAiden Grossman %b = call i64 @f2(i64 %a, i64 %a, i64 %a, i64 %a, i64 %a) 921aad3641eSAiden Grossman %c = call ptr @f3() 922aad3641eSAiden Grossman call void @f4(ptr %c) 923aad3641eSAiden Grossman %d = call float @f5() 924aad3641eSAiden Grossman %e = call i64 %c(i64 %b) 925aad3641eSAiden Grossman ret i64 %b 926aad3641eSAiden Grossman } 927aad3641eSAiden Grossman 928aad3641eSAiden Grossman declare i64 @f2(i64,i64,i64,i64,i64) 929aad3641eSAiden Grossman declare ptr @f3() 930aad3641eSAiden Grossman declare void @f4(ptr) 931aad3641eSAiden Grossman declare float @f5() 932aad3641eSAiden Grossman )IR"); 933aad3641eSAiden Grossman 934aad3641eSAiden Grossman Function *F1 = M->getFunction("f1"); 935aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 936aad3641eSAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 937aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0); 938aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.DirectCallCount, 4); 939aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 1); 940aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 2); 941aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1); 942aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 1); 943aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 1); 944aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 1); 945aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 946aad3641eSAiden Grossman } 947aad3641eSAiden Grossman 948aad3641eSAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, CriticalEdge) { 949aad3641eSAiden Grossman LLVMContext C; 950aad3641eSAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 951aad3641eSAiden Grossman R"IR( 952aad3641eSAiden Grossman define i64 @f1(i64 %a) { 953aad3641eSAiden Grossman %b = icmp eq i64 %a, 1 954aad3641eSAiden Grossman br i1 %b, label %TopBlock1, label %TopBlock2 955aad3641eSAiden Grossman TopBlock1: 956aad3641eSAiden Grossman %c = add i64 %a, 1 957aad3641eSAiden Grossman %e = icmp eq i64 %c, 2 958aad3641eSAiden Grossman br i1 %e, label %BottomBlock1, label %BottomBlock2 959aad3641eSAiden Grossman TopBlock2: 960aad3641eSAiden Grossman %d = add i64 %a, 2 961aad3641eSAiden Grossman br label %BottomBlock2 962aad3641eSAiden Grossman BottomBlock1: 963aad3641eSAiden Grossman ret i64 0 964aad3641eSAiden Grossman BottomBlock2: 965aad3641eSAiden Grossman %f = phi i64 [ %c, %TopBlock1 ], [ %d, %TopBlock2 ] 966aad3641eSAiden Grossman ret i64 %f 967aad3641eSAiden Grossman } 968aad3641eSAiden Grossman )IR"); 969aad3641eSAiden Grossman 970aad3641eSAiden Grossman Function *F1 = M->getFunction("f1"); 971aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 972aad3641eSAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 973aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 1); 974aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(false); 975aad3641eSAiden Grossman } 976aad3641eSAiden Grossman 977aad3641eSAiden Grossman 978aad3641eSAiden Grossman TEST_F(FunctionPropertiesAnalysisTest, FunctionReturnVectors) { 979aad3641eSAiden Grossman LLVMContext C; 980aad3641eSAiden Grossman std::unique_ptr<Module> M = makeLLVMModule(C, 981aad3641eSAiden Grossman R"IR( 982aad3641eSAiden Grossman define <4 x i64> @f1(<4 x i64> %a) { 983aad3641eSAiden Grossman %b = call <4 x i64> @f2() 984aad3641eSAiden Grossman %c = call <4 x float> @f3() 985aad3641eSAiden Grossman %d = call <4 x ptr> @f4() 986aad3641eSAiden Grossman ret <4 x i64> %b 987aad3641eSAiden Grossman } 988aad3641eSAiden Grossman 989aad3641eSAiden Grossman declare <4 x i64> @f2() 990aad3641eSAiden Grossman declare <4 x float> @f3() 991aad3641eSAiden Grossman declare <4 x ptr> @f4() 992aad3641eSAiden Grossman )IR"); 993aad3641eSAiden Grossman 994aad3641eSAiden Grossman Function *F1 = M->getFunction("f1"); 995aad3641eSAiden Grossman EnableDetailedFunctionProperties.setValue(true); 996aad3641eSAiden Grossman FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1); 997aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsVectorIntCount, 1); 998aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsVectorFloatCount, 1); 999aad3641eSAiden Grossman EXPECT_EQ(DetailedF1Properties.CallReturnsVectorPointerCount, 1); 1000b8f191e0SAiden Grossman EnableDetailedFunctionProperties.setValue(false); 1001b8f191e0SAiden Grossman } 1002*1991aa6bSMircea Trofin 1003*1991aa6bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, ReAddEdges) { 1004*1991aa6bSMircea Trofin LLVMContext C; 1005*1991aa6bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, R"IR( 1006*1991aa6bSMircea Trofin define hidden void @f1(ptr noundef %destatep, i32 noundef %offset, i8 noundef zeroext %byte1) { 1007*1991aa6bSMircea Trofin entry: 1008*1991aa6bSMircea Trofin %cmp = icmp eq i8 %byte1, 0 1009*1991aa6bSMircea Trofin br i1 %cmp, label %if.then, label %if.else 1010*1991aa6bSMircea Trofin 1011*1991aa6bSMircea Trofin if.then: ; preds = %entry 1012*1991aa6bSMircea Trofin call fastcc void @f2(ptr noundef %destatep, i32 noundef 37, i32 noundef 600) 1013*1991aa6bSMircea Trofin %and = and i32 %offset, 3 1014*1991aa6bSMircea Trofin switch i32 %and, label %default.unreachable [ 1015*1991aa6bSMircea Trofin i32 0, label %sw.bb 1016*1991aa6bSMircea Trofin i32 1, label %sw.bb1 1017*1991aa6bSMircea Trofin i32 2, label %sw.bb1 1018*1991aa6bSMircea Trofin i32 3, label %if.end 1019*1991aa6bSMircea Trofin ] 1020*1991aa6bSMircea Trofin 1021*1991aa6bSMircea Trofin sw.bb: ; preds = %if.then 1022*1991aa6bSMircea Trofin call fastcc void @f2(ptr noundef %destatep, i32 noundef 57, i32 noundef 600) 1023*1991aa6bSMircea Trofin br label %if.end 1024*1991aa6bSMircea Trofin 1025*1991aa6bSMircea Trofin sw.bb1: ; preds = %if.then, %if.then 1026*1991aa6bSMircea Trofin call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600) #34 1027*1991aa6bSMircea Trofin br label %if.end 1028*1991aa6bSMircea Trofin 1029*1991aa6bSMircea Trofin default.unreachable: ; preds = %if.then 1030*1991aa6bSMircea Trofin unreachable 1031*1991aa6bSMircea Trofin 1032*1991aa6bSMircea Trofin if.else: ; preds = %entry 1033*1991aa6bSMircea Trofin call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600) 1034*1991aa6bSMircea Trofin br label %if.end 1035*1991aa6bSMircea Trofin 1036*1991aa6bSMircea Trofin if.end: ; preds = %sw.bb, %sw.bb1, %if.then, %if.else 1037*1991aa6bSMircea Trofin ret void 1038*1991aa6bSMircea Trofin } 1039*1991aa6bSMircea Trofin 1040*1991aa6bSMircea Trofin define internal fastcc void @f2(ptr nocapture noundef %destatep, i32 noundef %r_enc, i32 noundef %whack) { 1041*1991aa6bSMircea Trofin entry: 1042*1991aa6bSMircea Trofin %enc_prob = getelementptr inbounds nuw i8, ptr %destatep, i32 512 1043*1991aa6bSMircea Trofin %arrayidx = getelementptr inbounds [67 x i32], ptr %enc_prob, i32 0, i32 %r_enc 1044*1991aa6bSMircea Trofin %0 = load i32, ptr %arrayidx, align 4 1045*1991aa6bSMircea Trofin %sub = sub nsw i32 %0, %whack 1046*1991aa6bSMircea Trofin store i32 %sub, ptr %arrayidx, align 4 1047*1991aa6bSMircea Trofin ret void 1048*1991aa6bSMircea Trofin } 1049*1991aa6bSMircea Trofin )IR"); 1050*1991aa6bSMircea Trofin auto *F1 = M->getFunction("f1"); 1051*1991aa6bSMircea Trofin auto *F2 = M->getFunction("f2"); 1052*1991aa6bSMircea Trofin auto *CB = [&]() -> CallBase * { 1053*1991aa6bSMircea Trofin for (auto &BB : *F1) 1054*1991aa6bSMircea Trofin for (auto &I : BB) 1055*1991aa6bSMircea Trofin if (auto *CB = dyn_cast<CallBase>(&I); 1056*1991aa6bSMircea Trofin CB && CB->getCalledFunction() && CB->getCalledFunction() == F2) 1057*1991aa6bSMircea Trofin return CB; 1058*1991aa6bSMircea Trofin return nullptr; 1059*1991aa6bSMircea Trofin }(); 1060*1991aa6bSMircea Trofin ASSERT_NE(CB, nullptr); 1061*1991aa6bSMircea Trofin auto FPI = buildFPI(*F1); 1062*1991aa6bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 1063*1991aa6bSMircea Trofin InlineFunctionInfo IFI; 1064*1991aa6bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 1065*1991aa6bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 1066*1991aa6bSMircea Trofin invalidate(*F1); 1067*1991aa6bSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 1068*1991aa6bSMircea Trofin } 1069*1991aa6bSMircea Trofin 1070*1991aa6bSMircea Trofin TEST_F(FunctionPropertiesAnalysisTest, InvokeLandingCanStillBeReached) { 1071*1991aa6bSMircea Trofin LLVMContext C; 1072*1991aa6bSMircea Trofin // %lpad is reachable from a block not involved in the inlining decision. We 1073*1991aa6bSMircea Trofin // make sure that's not the entry - otherwise the DT will be recomputed from 1074*1991aa6bSMircea Trofin // scratch. The idea here is that the edge known to the inliner to potentially 1075*1991aa6bSMircea Trofin // disappear - %lpad->%ehcleanup -should survive because it is still reachable 1076*1991aa6bSMircea Trofin // from %middle. 1077*1991aa6bSMircea Trofin std::unique_ptr<Module> M = makeLLVMModule(C, 1078*1991aa6bSMircea Trofin R"IR( 1079*1991aa6bSMircea Trofin target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 1080*1991aa6bSMircea Trofin target triple = "x86_64-pc-linux-gnu" 1081*1991aa6bSMircea Trofin 1082*1991aa6bSMircea Trofin define i64 @f1(i32 noundef %value) { 1083*1991aa6bSMircea Trofin entry: 1084*1991aa6bSMircea Trofin br label %middle 1085*1991aa6bSMircea Trofin middle: 1086*1991aa6bSMircea Trofin %c = icmp eq i32 %value, 0 1087*1991aa6bSMircea Trofin br i1 %c, label %invoke, label %lpad 1088*1991aa6bSMircea Trofin invoke: 1089*1991aa6bSMircea Trofin invoke fastcc void @f2() to label %cont unwind label %lpad 1090*1991aa6bSMircea Trofin cont: 1091*1991aa6bSMircea Trofin br label %exit 1092*1991aa6bSMircea Trofin lpad: 1093*1991aa6bSMircea Trofin %lp = landingpad i32 cleanup 1094*1991aa6bSMircea Trofin br label %ehcleanup 1095*1991aa6bSMircea Trofin ehcleanup: 1096*1991aa6bSMircea Trofin resume i32 0 1097*1991aa6bSMircea Trofin exit: 1098*1991aa6bSMircea Trofin ret i64 1 1099*1991aa6bSMircea Trofin } 1100*1991aa6bSMircea Trofin define void @f2() { 1101*1991aa6bSMircea Trofin ret void 1102*1991aa6bSMircea Trofin } 1103*1991aa6bSMircea Trofin )IR"); 1104*1991aa6bSMircea Trofin 1105*1991aa6bSMircea Trofin Function *F1 = M->getFunction("f1"); 1106*1991aa6bSMircea Trofin CallBase *CB = findCall(*F1); 1107*1991aa6bSMircea Trofin EXPECT_NE(CB, nullptr); 1108*1991aa6bSMircea Trofin 1109*1991aa6bSMircea Trofin auto FPI = buildFPI(*F1); 1110*1991aa6bSMircea Trofin FunctionPropertiesUpdater FPU(FPI, *CB); 1111*1991aa6bSMircea Trofin InlineFunctionInfo IFI; 1112*1991aa6bSMircea Trofin auto IR = llvm::InlineFunction(*CB, IFI); 1113*1991aa6bSMircea Trofin EXPECT_TRUE(IR.isSuccess()); 1114*1991aa6bSMircea Trofin invalidate(*F1); 1115*1991aa6bSMircea Trofin EXPECT_TRUE(FPU.finishAndTest(FAM)); 1116*1991aa6bSMircea Trofin } 111706283661STarindu Jayatilaka } // end anonymous namespace 1118