1 //===- FunctionPropertiesAnalysisTest.cpp - Function Properties Unit Tests-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Analysis/FunctionPropertiesAnalysis.h" 10 #include "llvm/Analysis/LoopInfo.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/IR/Dominators.h" 13 #include "llvm/IR/Instructions.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/Support/SourceMgr.h" 17 #include "gtest/gtest.h" 18 19 using namespace llvm; 20 namespace { 21 22 class FunctionPropertiesAnalysisTest : public testing::Test { 23 protected: 24 std::unique_ptr<DominatorTree> DT; 25 std::unique_ptr<LoopInfo> LI; 26 27 FunctionPropertiesInfo buildFPI(Function &F) { 28 DT.reset(new DominatorTree(F)); 29 LI.reset(new LoopInfo(*DT)); 30 return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, *LI); 31 } 32 33 std::unique_ptr<Module> makeLLVMModule(LLVMContext &C, const char *IR) { 34 SMDiagnostic Err; 35 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 36 if (!Mod) 37 Err.print("MLAnalysisTests", errs()); 38 return Mod; 39 } 40 }; 41 42 TEST_F(FunctionPropertiesAnalysisTest, BasicTest) { 43 LLVMContext C; 44 std::unique_ptr<Module> M = makeLLVMModule(C, 45 R"IR( 46 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 47 target triple = "x86_64-pc-linux-gnu" 48 declare i32 @f1(i32) 49 declare i32 @f2(i32) 50 define i32 @branches(i32) { 51 %cond = icmp slt i32 %0, 3 52 br i1 %cond, label %then, label %else 53 then: 54 %ret.1 = call i32 @f1(i32 %0) 55 br label %last.block 56 else: 57 %ret.2 = call i32 @f2(i32 %0) 58 br label %last.block 59 last.block: 60 %ret = phi i32 [%ret.1, %then], [%ret.2, %else] 61 ret i32 %ret 62 } 63 define internal i32 @top() { 64 %1 = call i32 @branches(i32 2) 65 %2 = call i32 @f1(i32 %1) 66 ret i32 %2 67 } 68 )IR"); 69 70 Function *BranchesFunction = M->getFunction("branches"); 71 FunctionPropertiesInfo BranchesFeatures = buildFPI(*BranchesFunction); 72 EXPECT_EQ(BranchesFeatures.BasicBlockCount, 4); 73 EXPECT_EQ(BranchesFeatures.BlocksReachedFromConditionalInstruction, 2); 74 // 2 Users: top is one. The other is added because @branches is not internal, 75 // so it may have external callers. 76 EXPECT_EQ(BranchesFeatures.Uses, 2); 77 EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0); 78 EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); 79 EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); 80 EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); 81 EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); 82 83 Function *TopFunction = M->getFunction("top"); 84 FunctionPropertiesInfo TopFeatures = buildFPI(*TopFunction); 85 EXPECT_EQ(TopFeatures.BasicBlockCount, 1); 86 EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0); 87 EXPECT_EQ(TopFeatures.Uses, 0); 88 EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1); 89 EXPECT_EQ(BranchesFeatures.LoadInstCount, 0); 90 EXPECT_EQ(BranchesFeatures.StoreInstCount, 0); 91 EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0); 92 EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0); 93 } 94 } // end anonymous namespace 95