brintos

brintos / llvm-project-archived public Read only

0
0
Text · 38.8 KiB · dc5d0a8 Raw
1217 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Analysis/FunctionPropertiesAnalysis.h"10#include "llvm/Analysis/AliasAnalysis.h"11#include "llvm/Analysis/IR2Vec.h"12#include "llvm/Analysis/LoopInfo.h"13#include "llvm/AsmParser/Parser.h"14#include "llvm/IR/Dominators.h"15#include "llvm/IR/Instructions.h"16#include "llvm/IR/LLVMContext.h"17#include "llvm/IR/Module.h"18#include "llvm/IR/PassManager.h"19#include "llvm/Passes/PassBuilder.h"20#include "llvm/Passes/StandardInstrumentations.h"21#include "llvm/Support/Compiler.h"22#include "llvm/Support/SourceMgr.h"23#include "llvm/Transforms/Utils/Cloning.h"24#include "gmock/gmock.h"25#include "gtest/gtest.h"26#include <cstring>27 28using namespace llvm;29using namespace testing;30 31namespace llvm {32LLVM_ABI extern cl::opt<bool> EnableDetailedFunctionProperties;33LLVM_ABI extern cl::opt<bool> BigBasicBlockInstructionThreshold;34LLVM_ABI extern cl::opt<bool> MediumBasicBlockInstrutionThreshold;35LLVM_ABI extern cl::opt<float> ir2vec::OpcWeight;36LLVM_ABI extern cl::opt<float> ir2vec::TypeWeight;37LLVM_ABI extern cl::opt<float> ir2vec::ArgWeight;38} // namespace llvm39 40namespace {41 42class FunctionPropertiesAnalysisTest : public testing::Test {43public:44  FunctionPropertiesAnalysisTest() {45    auto VocabVector = ir2vec::Vocabulary::createDummyVocabForTest(1);46    MAM.registerPass([VocabVector = std::move(VocabVector)]() mutable {47      return IR2VecVocabAnalysis(std::move(VocabVector));48    });49    IR2VecVocab = std::make_unique<ir2vec::Vocabulary>(50        ir2vec::Vocabulary::createDummyVocabForTest(1));51    MAM.registerPass([&] { return PassInstrumentationAnalysis(); });52    FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });53    FAM.registerPass([&] { return DominatorTreeAnalysis(); });54    FAM.registerPass([&] { return LoopAnalysis(); });55    FAM.registerPass([&] { return PassInstrumentationAnalysis(); });56 57    ir2vec::OpcWeight = 1.0;58    ir2vec::TypeWeight = 1.0;59    ir2vec::ArgWeight = 1.0;60  }61 62private:63  float OriginalOpcWeight = ir2vec::OpcWeight;64  float OriginalTypeWeight = ir2vec::TypeWeight;65  float OriginalArgWeight = ir2vec::ArgWeight;66 67protected:68  std::unique_ptr<DominatorTree> DT;69  std::unique_ptr<LoopInfo> LI;70  FunctionAnalysisManager FAM;71  ModuleAnalysisManager MAM;72  std::unique_ptr<ir2vec::Vocabulary> IR2VecVocab;73 74  void TearDown() override {75    // Restore original IR2Vec weights76    ir2vec::OpcWeight = OriginalOpcWeight;77    ir2vec::TypeWeight = OriginalTypeWeight;78    ir2vec::ArgWeight = OriginalArgWeight;79  }80 81  FunctionPropertiesInfo buildFPI(Function &F) {82    // FunctionPropertiesInfo assumes IR2VecVocabAnalysis has been run to83    // use IR2Vec.84    auto &VocabResult = MAM.getResult<IR2VecVocabAnalysis>(*F.getParent());85    (void)VocabResult;86    return FunctionPropertiesInfo::getFunctionPropertiesInfo(F, FAM);87  }88 89  void invalidate(Function &F) {90    PreservedAnalyses PA = PreservedAnalyses::none();91    FAM.invalidate(F, PA);92  }93 94  std::unique_ptr<Module> makeLLVMModule(LLVMContext &C, const char *IR) {95    SMDiagnostic Err;96    std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);97    if (!Mod)98      Err.print("MLAnalysisTests", errs());99    return Mod;100  }101 102  CallBase *findCall(Function &F, const char *Name = nullptr) {103    for (auto &BB : F)104      for (auto &I : BB)105        if (auto *CB = dyn_cast<CallBase>(&I))106          if (!Name || CB->getName() == Name)107            return CB;108    return nullptr;109  }110 111  std::unique_ptr<ir2vec::Embedder> createEmbedder(const Function &F) {112    auto Emb = ir2vec::Embedder::create(IR2VecKind::Symbolic, F, *IR2VecVocab);113    EXPECT_TRUE(static_cast<bool>(Emb));114    return Emb;115  }116};117 118TEST_F(FunctionPropertiesAnalysisTest, BasicTest) {119  LLVMContext C;120  std::unique_ptr<Module> M = makeLLVMModule(C,121                                             R"IR(122target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"123target triple = "x86_64-pc-linux-gnu"124declare i32 @f1(i32)125declare i32 @f2(i32)126define i32 @branches(i32) {127  %cond = icmp slt i32 %0, 3128  br i1 %cond, label %then, label %else129then:130  %ret.1 = call i32 @f1(i32 %0)131  br label %last.block132else:133  %ret.2 = call i32 @f2(i32 %0)134  br label %last.block135last.block:136  %ret = phi i32 [%ret.1, %then], [%ret.2, %else]137  ret i32 %ret138}139define internal i32 @top() {140  %1 = call i32 @branches(i32 2)141  %2 = call i32 @f1(i32 %1)142  ret i32 %2143}144)IR");145 146  Function *BranchesFunction = M->getFunction("branches");147  FunctionPropertiesInfo BranchesFeatures = buildFPI(*BranchesFunction);148  EXPECT_EQ(BranchesFeatures.BasicBlockCount, 4);149  EXPECT_EQ(BranchesFeatures.BlocksReachedFromConditionalInstruction, 2);150  // 2 Users: top is one. The other is added because @branches is not internal,151  // so it may have external callers.152  EXPECT_EQ(BranchesFeatures.Uses, 2);153  EXPECT_EQ(BranchesFeatures.DirectCallsToDefinedFunctions, 0);154  EXPECT_EQ(BranchesFeatures.LoadInstCount, 0);155  EXPECT_EQ(BranchesFeatures.StoreInstCount, 0);156  EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0);157  EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0);158  EXPECT_TRUE(BranchesFeatures.getFunctionEmbedding().approximatelyEquals(159      createEmbedder(*BranchesFunction)->getFunctionVector()));160 161  Function *TopFunction = M->getFunction("top");162  FunctionPropertiesInfo TopFeatures = buildFPI(*TopFunction);163  EXPECT_EQ(TopFeatures.BasicBlockCount, 1);164  EXPECT_EQ(TopFeatures.BlocksReachedFromConditionalInstruction, 0);165  EXPECT_EQ(TopFeatures.Uses, 0);166  EXPECT_EQ(TopFeatures.DirectCallsToDefinedFunctions, 1);167  EXPECT_TRUE(TopFeatures.getFunctionEmbedding().approximatelyEquals(168      createEmbedder(*TopFunction)->getFunctionVector()));169  EXPECT_EQ(BranchesFeatures.LoadInstCount, 0);170  EXPECT_EQ(BranchesFeatures.StoreInstCount, 0);171  EXPECT_EQ(BranchesFeatures.MaxLoopDepth, 0);172  EXPECT_EQ(BranchesFeatures.TopLevelLoopCount, 0);173 174  EnableDetailedFunctionProperties.setValue(true);175  FunctionPropertiesInfo DetailedBranchesFeatures = buildFPI(*BranchesFunction);176  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSingleSuccessor, 2);177  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoSuccessors, 1);178  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoSuccessors, 0);179  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithSinglePredecessor, 2);180  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithTwoPredecessors, 1);181  EXPECT_EQ(DetailedBranchesFeatures.BasicBlocksWithMoreThanTwoPredecessors, 0);182  EXPECT_EQ(DetailedBranchesFeatures.BigBasicBlocks, 0);183  EXPECT_EQ(DetailedBranchesFeatures.MediumBasicBlocks, 0);184  EXPECT_EQ(DetailedBranchesFeatures.SmallBasicBlocks, 4);185  EXPECT_EQ(DetailedBranchesFeatures.CastInstructionCount, 0);186  EXPECT_EQ(DetailedBranchesFeatures.FloatingPointInstructionCount, 0);187  EXPECT_EQ(DetailedBranchesFeatures.IntegerInstructionCount, 4);188  EXPECT_EQ(DetailedBranchesFeatures.ConstantIntOperandCount, 1);189  EXPECT_EQ(DetailedBranchesFeatures.ConstantFPOperandCount, 0);190  EXPECT_EQ(DetailedBranchesFeatures.ConstantOperandCount, 0);191  EXPECT_EQ(DetailedBranchesFeatures.InstructionOperandCount, 4);192  EXPECT_EQ(DetailedBranchesFeatures.BasicBlockOperandCount, 4);193  EXPECT_EQ(DetailedBranchesFeatures.GlobalValueOperandCount, 2);194  EXPECT_EQ(DetailedBranchesFeatures.InlineAsmOperandCount, 0);195  EXPECT_EQ(DetailedBranchesFeatures.ArgumentOperandCount, 3);196  EXPECT_EQ(DetailedBranchesFeatures.UnknownOperandCount, 0);197  EXPECT_EQ(DetailedBranchesFeatures.CriticalEdgeCount, 0);198  EXPECT_EQ(DetailedBranchesFeatures.ControlFlowEdgeCount, 4);199  EXPECT_EQ(DetailedBranchesFeatures.UnconditionalBranchCount, 2);200  EXPECT_EQ(DetailedBranchesFeatures.IntrinsicCount, 0);201  EXPECT_EQ(DetailedBranchesFeatures.DirectCallCount, 2);202  EXPECT_EQ(DetailedBranchesFeatures.IndirectCallCount, 0);203  EXPECT_EQ(DetailedBranchesFeatures.CallReturnsIntegerCount, 2);204  EXPECT_EQ(DetailedBranchesFeatures.CallReturnsFloatCount, 0);205  EXPECT_EQ(DetailedBranchesFeatures.CallReturnsPointerCount, 0);206  EXPECT_EQ(DetailedBranchesFeatures.CallWithManyArgumentsCount, 0);207  EXPECT_EQ(DetailedBranchesFeatures.CallWithPointerArgumentCount, 0);208  EXPECT_TRUE(209      DetailedBranchesFeatures.getFunctionEmbedding().approximatelyEquals(210          createEmbedder(*BranchesFunction)->getFunctionVector()));211  EnableDetailedFunctionProperties.setValue(false);212}213 214TEST_F(FunctionPropertiesAnalysisTest, DifferentPredecessorSuccessorCounts) {215  LLVMContext C;216  std::unique_ptr<Module> M = makeLLVMModule(C,217                                             R"IR(218define i64 @f1() {219  br i1 0, label %br1, label %finally220br1:221  ret i64 0222finally:223  ret i64 3224}225)IR");226 227  Function *F1 = M->getFunction("f1");228  EnableDetailedFunctionProperties.setValue(true);229  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);230  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSingleSuccessor, 0);231  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoSuccessors, 1);232  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoSuccessors, 0);233  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSinglePredecessor, 2);234  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoPredecessors, 0);235  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoPredecessors, 0);236  EXPECT_EQ(DetailedF1Properties.BigBasicBlocks, 0);237  EXPECT_EQ(DetailedF1Properties.MediumBasicBlocks, 0);238  EXPECT_EQ(DetailedF1Properties.SmallBasicBlocks, 3);239  EXPECT_EQ(DetailedF1Properties.CastInstructionCount, 0);240  EXPECT_EQ(DetailedF1Properties.FloatingPointInstructionCount, 0);241  EXPECT_EQ(DetailedF1Properties.IntegerInstructionCount, 0);242  EXPECT_EQ(DetailedF1Properties.ConstantIntOperandCount, 3);243  EXPECT_EQ(DetailedF1Properties.ConstantFPOperandCount, 0);244  EXPECT_EQ(DetailedF1Properties.ConstantOperandCount, 0);245  EXPECT_EQ(DetailedF1Properties.InstructionOperandCount, 0);246  EXPECT_EQ(DetailedF1Properties.BasicBlockOperandCount, 2);247  EXPECT_EQ(DetailedF1Properties.GlobalValueOperandCount, 0);248  EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 0);249  EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 0);250  EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0);251  EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0);252  EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 2);253  EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0);254  EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);255  EXPECT_EQ(DetailedF1Properties.DirectCallCount, 0);256  EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);257  EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0);258  EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0);259  EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);260  EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);261  EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);262  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(263      createEmbedder(*F1)->getFunctionVector()));264  EnableDetailedFunctionProperties.setValue(false);265}266 267TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBSimple) {268  LLVMContext C;269  std::unique_ptr<Module> M = makeLLVMModule(C,270                                             R"IR(271target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"272target triple = "x86_64-pc-linux-gnu"273define i32 @f1(i32 %a) {274  %b = call i32 @f2(i32 %a)275  %c = add i32 %b, 2276  ret i32 %c277}278 279define i32 @f2(i32 %a) {280  %b = add i32 %a, 1281  ret i32 %b282}283)IR");284 285  Function *F1 = M->getFunction("f1");286  CallBase *CB = findCall(*F1, "b");287  EXPECT_NE(CB, nullptr);288 289  FunctionPropertiesInfo ExpectedInitial;290  ExpectedInitial.BasicBlockCount = 1;291  ExpectedInitial.TotalInstructionCount = 3;292  ExpectedInitial.Uses = 1;293  ExpectedInitial.DirectCallsToDefinedFunctions = 1;294  ExpectedInitial.setFunctionEmbeddingForTest(295      createEmbedder(*F1)->getFunctionVector());296 297  FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;298  ExpectedFinal.DirectCallsToDefinedFunctions = 0;299 300  auto FPI = buildFPI(*F1);301  EXPECT_EQ(FPI, ExpectedInitial);302 303  FunctionPropertiesUpdater FPU(FPI, *CB);304  InlineFunctionInfo IFI;305  auto IR = llvm::InlineFunction(*CB, IFI);306  EXPECT_TRUE(IR.isSuccess());307  invalidate(*F1);308  ExpectedFinal.setFunctionEmbeddingForTest(309      createEmbedder(*F1)->getFunctionVector());310 311  EXPECT_TRUE(FPU.finishAndTest(FAM));312  EXPECT_EQ(FPI, ExpectedFinal);313}314 315TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLargerCFG) {316  LLVMContext C;317  std::unique_ptr<Module> M = makeLLVMModule(C,318                                             R"IR(319target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"320target triple = "x86_64-pc-linux-gnu"321define i32 @f1(i32 %a) {322entry:323  %i = icmp slt i32 %a, 0324  br i1 %i, label %if.then, label %if.else325if.then:326  %b = call i32 @f2(i32 %a)327  %c1 = add i32 %b, 2328  br label %end329if.else:330  %c2 = add i32 %a, 1331  br label %end332end:333  %ret = phi i32 [%c1, %if.then],[%c2, %if.else]334  ret i32 %ret335}336 337define i32 @f2(i32 %a) {338  %b = add i32 %a, 1339  ret i32 %b340}341)IR");342 343  Function *F1 = M->getFunction("f1");344  CallBase *CB = findCall(*F1, "b");345  EXPECT_NE(CB, nullptr);346 347  FunctionPropertiesInfo ExpectedInitial;348  ExpectedInitial.BasicBlockCount = 4;349  ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;350  ExpectedInitial.TotalInstructionCount = 9;351  ExpectedInitial.Uses = 1;352  ExpectedInitial.DirectCallsToDefinedFunctions = 1;353  ExpectedInitial.setFunctionEmbeddingForTest(354      createEmbedder(*F1)->getFunctionVector());355 356  FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;357  ExpectedFinal.DirectCallsToDefinedFunctions = 0;358 359  auto FPI = buildFPI(*F1);360  EXPECT_EQ(FPI, ExpectedInitial);361 362  FunctionPropertiesUpdater FPU(FPI, *CB);363  InlineFunctionInfo IFI;364  auto IR = llvm::InlineFunction(*CB, IFI);365  EXPECT_TRUE(IR.isSuccess());366  invalidate(*F1);367  EXPECT_TRUE(FPU.finishAndTest(FAM));368 369  ExpectedFinal.setFunctionEmbeddingForTest(370      createEmbedder(*F1)->getFunctionVector());371  EXPECT_EQ(FPI, ExpectedFinal);372}373 374TEST_F(FunctionPropertiesAnalysisTest, InlineSameBBLoops) {375  LLVMContext C;376  std::unique_ptr<Module> M = makeLLVMModule(C,377                                             R"IR(378target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"379target triple = "x86_64-pc-linux-gnu"380define i32 @f1(i32 %a) {381entry:382  %i = icmp slt i32 %a, 0383  br i1 %i, label %if.then, label %if.else384if.then:385  %b = call i32 @f2(i32 %a)386  %c1 = add i32 %b, 2387  br label %end388if.else:389  %c2 = add i32 %a, 1390  br label %end391end:392  %ret = phi i32 [%c1, %if.then],[%c2, %if.else]393  ret i32 %ret394}395 396define i32 @f2(i32 %a) {397entry:398  br label %loop399loop:400  %indvar = phi i32 [%indvar.next, %loop], [0, %entry]401  %b = add i32 %a, %indvar402  %indvar.next = add i32 %indvar, 1403  %cond = icmp slt i32 %indvar.next, %a404  br i1 %cond, label %loop, label %exit405exit:406  ret i32 %b407}408)IR");409 410  Function *F1 = M->getFunction("f1");411  CallBase *CB = findCall(*F1, "b");412  EXPECT_NE(CB, nullptr);413 414  FunctionPropertiesInfo ExpectedInitial;415  ExpectedInitial.BasicBlockCount = 4;416  ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;417  ExpectedInitial.TotalInstructionCount = 9;418  ExpectedInitial.Uses = 1;419  ExpectedInitial.DirectCallsToDefinedFunctions = 1;420  ExpectedInitial.setFunctionEmbeddingForTest(421      createEmbedder(*F1)->getFunctionVector());422 423  FunctionPropertiesInfo ExpectedFinal;424  ExpectedFinal.BasicBlockCount = 6;425  ExpectedFinal.BlocksReachedFromConditionalInstruction = 4;426  ExpectedFinal.Uses = 1;427  ExpectedFinal.MaxLoopDepth = 1;428  ExpectedFinal.TopLevelLoopCount = 1;429  ExpectedFinal.TotalInstructionCount = 14;430 431  auto FPI = buildFPI(*F1);432  EXPECT_EQ(FPI, ExpectedInitial);433  FunctionPropertiesUpdater FPU(FPI, *CB);434  InlineFunctionInfo IFI;435 436  auto IR = llvm::InlineFunction(*CB, IFI);437  EXPECT_TRUE(IR.isSuccess());438  invalidate(*F1);439  EXPECT_TRUE(FPU.finishAndTest(FAM));440 441  ExpectedFinal.setFunctionEmbeddingForTest(442      createEmbedder(*F1)->getFunctionVector());443  EXPECT_EQ(FPI, ExpectedFinal);444}445 446TEST_F(FunctionPropertiesAnalysisTest, InvokeSimple) {447  LLVMContext C;448  std::unique_ptr<Module> M = makeLLVMModule(C,449                                             R"IR(450target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"451target triple = "x86_64-pc-linux-gnu"452declare void @might_throw()453 454define internal void @callee() {455entry:456  call void @might_throw()457  ret void458}459 460define i32 @caller() personality ptr @__gxx_personality_v0 {461entry:462  invoke void @callee()463      to label %cont unwind label %exc464 465cont:466  ret i32 0467 468exc:469  %exn = landingpad {ptr, i32}470         cleanup471  ret i32 1472}473 474declare i32 @__gxx_personality_v0(...)475)IR");476 477  Function *F1 = M->getFunction("caller");478  CallBase *CB = findCall(*F1);479  EXPECT_NE(CB, nullptr);480 481  auto FPI = buildFPI(*F1);482  FunctionPropertiesUpdater FPU(FPI, *CB);483  InlineFunctionInfo IFI;484  auto IR = llvm::InlineFunction(*CB, IFI);485  EXPECT_TRUE(IR.isSuccess());486  invalidate(*F1);487  EXPECT_TRUE(FPU.finishAndTest(FAM));488  EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size());489  EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),490            F1->getInstructionCount());491  EXPECT_TRUE(FPI.getFunctionEmbedding().approximatelyEquals(492      createEmbedder(*F1)->getFunctionVector()));493}494 495TEST_F(FunctionPropertiesAnalysisTest, InvokeUnreachableHandler) {496  LLVMContext C;497  std::unique_ptr<Module> M = makeLLVMModule(C,498                                             R"IR(499declare void @might_throw()500 501define internal i32 @callee() personality ptr @__gxx_personality_v0 {502entry:503  invoke void @might_throw()504      to label %cont unwind label %exc505 506cont:507  ret i32 0508 509exc:510  %exn = landingpad {ptr, i32}511         cleanup512  resume { ptr, i32 } %exn513}514 515define i32 @caller() personality ptr @__gxx_personality_v0 {516entry:517  %X = invoke i32 @callee()518           to label %cont unwind label %Handler519 520cont:521  ret i32 %X522 523Handler:524  %exn = landingpad {ptr, i32}525         cleanup526  ret i32 1527}528 529declare i32 @__gxx_personality_v0(...)530)IR");531 532  Function *F1 = M->getFunction("caller");533  CallBase *CB = findCall(*F1);534  EXPECT_NE(CB, nullptr);535 536  auto FPI = buildFPI(*F1);537  FunctionPropertiesUpdater FPU(FPI, *CB);538  InlineFunctionInfo IFI;539  auto IR = llvm::InlineFunction(*CB, IFI);540  EXPECT_TRUE(IR.isSuccess());541  invalidate(*F1);542  EXPECT_TRUE(FPU.finishAndTest(FAM));543  EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1);544  EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),545            F1->getInstructionCount() - 2);546  EXPECT_TRUE(FPI.getFunctionEmbedding().approximatelyEquals(547      createEmbedder(*F1)->getFunctionVector()));548  EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));549}550 551TEST_F(FunctionPropertiesAnalysisTest, Rethrow) {552  LLVMContext C;553  std::unique_ptr<Module> M = makeLLVMModule(C,554                                             R"IR(555declare void @might_throw()556 557define internal i32 @callee() personality ptr @__gxx_personality_v0 {558entry:559  invoke void @might_throw()560      to label %cont unwind label %exc561 562cont:563  ret i32 0564 565exc:566  %exn = landingpad {ptr, i32}567         cleanup568  resume { ptr, i32 } %exn569}570 571define i32 @caller() personality ptr @__gxx_personality_v0 {572entry:573  %X = invoke i32 @callee()574           to label %cont unwind label %Handler575 576cont:577  ret i32 %X578 579Handler:580  %exn = landingpad {ptr, i32}581         cleanup582  ret i32 1583}584 585declare i32 @__gxx_personality_v0(...)586)IR");587 588  Function *F1 = M->getFunction("caller");589  CallBase *CB = findCall(*F1);590  EXPECT_NE(CB, nullptr);591 592  auto FPI = buildFPI(*F1);593  FunctionPropertiesUpdater FPU(FPI, *CB);594  InlineFunctionInfo IFI;595  auto IR = llvm::InlineFunction(*CB, IFI);596  EXPECT_TRUE(IR.isSuccess());597  invalidate(*F1);598  EXPECT_TRUE(FPU.finishAndTest(FAM));599  EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1);600  EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),601            F1->getInstructionCount() - 2);602  EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));603}604 605TEST_F(FunctionPropertiesAnalysisTest, LPadChanges) {606  LLVMContext C;607  std::unique_ptr<Module> M = makeLLVMModule(C,608                                             R"IR(609declare void @external_func()610 611@exception_type1 = external global i8612@exception_type2 = external global i8613 614 615define internal void @inner() personality ptr null {616  invoke void @external_func()617      to label %cont unwind label %lpad618cont:619  ret void620lpad:621  %lp = landingpad i32622      catch ptr @exception_type1623  resume i32 %lp624}625 626define void @outer() personality ptr null {627  invoke void @inner()628      to label %cont unwind label %lpad629cont:630  ret void631lpad:632  %lp = landingpad i32633      cleanup634      catch ptr @exception_type2635  resume i32 %lp636}637 638)IR");639 640  Function *F1 = M->getFunction("outer");641  CallBase *CB = findCall(*F1);642  EXPECT_NE(CB, nullptr);643 644  auto FPI = buildFPI(*F1);645  FunctionPropertiesUpdater FPU(FPI, *CB);646  InlineFunctionInfo IFI;647  auto IR = llvm::InlineFunction(*CB, IFI);648  EXPECT_TRUE(IR.isSuccess());649  invalidate(*F1);650  EXPECT_TRUE(FPU.finishAndTest(FAM));651  EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1);652  EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),653            F1->getInstructionCount() - 2);654  EXPECT_TRUE(FPI.getFunctionEmbedding().approximatelyEquals(655      createEmbedder(*F1)->getFunctionVector()));656  EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));657}658 659TEST_F(FunctionPropertiesAnalysisTest, LPadChangesConditional) {660  LLVMContext C;661  std::unique_ptr<Module> M = makeLLVMModule(C,662                                             R"IR(663declare void @external_func()664 665@exception_type1 = external global i8666@exception_type2 = external global i8667 668 669define internal void @inner() personality ptr null {670  invoke void @external_func()671      to label %cont unwind label %lpad672cont:673  ret void674lpad:675  %lp = landingpad i32676      catch ptr @exception_type1677  resume i32 %lp678}679 680define void @outer(i32 %a) personality ptr null {681entry:682  %i = icmp slt i32 %a, 0683  br i1 %i, label %if.then, label %cont684if.then:685  invoke void @inner()686      to label %cont unwind label %lpad687cont:688  ret void689lpad:690  %lp = landingpad i32691      cleanup692      catch ptr @exception_type2693  resume i32 %lp694}695 696)IR");697 698  Function *F1 = M->getFunction("outer");699  CallBase *CB = findCall(*F1);700  EXPECT_NE(CB, nullptr);701 702  auto FPI = buildFPI(*F1);703  FunctionPropertiesUpdater FPU(FPI, *CB);704  InlineFunctionInfo IFI;705  auto IR = llvm::InlineFunction(*CB, IFI);706  EXPECT_TRUE(IR.isSuccess());707  invalidate(*F1);708  EXPECT_TRUE(FPU.finishAndTest(FAM));709  EXPECT_EQ(static_cast<size_t>(FPI.BasicBlockCount), F1->size() - 1);710  EXPECT_EQ(static_cast<size_t>(FPI.TotalInstructionCount),711            F1->getInstructionCount() - 2);712  EXPECT_TRUE(FPI.getFunctionEmbedding().approximatelyEquals(713      createEmbedder(*F1)->getFunctionVector()));714  EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM));715}716 717TEST_F(FunctionPropertiesAnalysisTest, InlineSameLoopBB) {718  LLVMContext C;719  std::unique_ptr<Module> M = makeLLVMModule(C,720                                             R"IR(721target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"722target triple = "x86_64-pc-linux-gnu"723 724declare i32 @a()725declare i32 @b()726 727define i32 @f1(i32 %a) {728entry:729  br label %loop730loop:731  %i = call i32 @f2(i32 %a)732  %c = icmp slt i32 %i, %a733  br i1 %c, label %loop, label %end734end:735  %r = phi i32 [%i, %loop], [%a, %entry]736  ret i32 %r737}738 739define i32 @f2(i32 %a) {740  %cnd = icmp slt i32 %a, 0741  br i1 %cnd, label %then, label %else742then:743  %r1 = call i32 @a()744  br label %end745else:746  %r2 = call i32 @b()747  br label %end748end:749  %r = phi i32 [%r1, %then], [%r2, %else]750  ret i32 %r751}752)IR");753 754  Function *F1 = M->getFunction("f1");755  CallBase *CB = findCall(*F1);756  EXPECT_NE(CB, nullptr);757 758  FunctionPropertiesInfo ExpectedInitial;759  ExpectedInitial.BasicBlockCount = 3;760  ExpectedInitial.TotalInstructionCount = 6;761  ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;762  ExpectedInitial.Uses = 1;763  ExpectedInitial.DirectCallsToDefinedFunctions = 1;764  ExpectedInitial.MaxLoopDepth = 1;765  ExpectedInitial.TopLevelLoopCount = 1;766  ExpectedInitial.setFunctionEmbeddingForTest(767      createEmbedder(*F1)->getFunctionVector());768 769  FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;770  ExpectedFinal.BasicBlockCount = 6;771  ExpectedFinal.DirectCallsToDefinedFunctions = 0;772  ExpectedFinal.BlocksReachedFromConditionalInstruction = 4;773  ExpectedFinal.TotalInstructionCount = 12;774 775  auto FPI = buildFPI(*F1);776  EXPECT_EQ(FPI, ExpectedInitial);777 778  FunctionPropertiesUpdater FPU(FPI, *CB);779  InlineFunctionInfo IFI;780  auto IR = llvm::InlineFunction(*CB, IFI);781  EXPECT_TRUE(IR.isSuccess());782  invalidate(*F1);783  EXPECT_TRUE(FPU.finishAndTest(FAM));784 785  ExpectedFinal.setFunctionEmbeddingForTest(786      createEmbedder(*F1)->getFunctionVector());787  EXPECT_EQ(FPI, ExpectedFinal);788}789 790TEST_F(FunctionPropertiesAnalysisTest, Unreachable) {791  LLVMContext C;792  std::unique_ptr<Module> M = makeLLVMModule(C,793                                             R"IR(794target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"795target triple = "x86_64-pc-linux-gnu"796 797define i64 @f1(i32 noundef %value) {798entry:799  br i1 true, label %cond.true, label %cond.false800 801cond.true:                                        ; preds = %entry802  %conv2 = sext i32 %value to i64803  br label %cond.end804 805cond.false:                                       ; preds = %entry806  %call3 = call noundef i64 @f2()807  br label %extra808 809extra:810  br label %extra2811 812extra2:813  br label %cond.end814 815cond.end:                                         ; preds = %extra2, %cond.true816  %cond = phi i64 [ %conv2, %cond.true ], [ %call3, %extra ]817  ret i64 %cond818}819 820define i64 @f2() {821entry:822  tail call void @llvm.trap()823  unreachable824}825 826declare void @llvm.trap()827)IR");828 829  Function *F1 = M->getFunction("f1");830  CallBase *CB = findCall(*F1);831  EXPECT_NE(CB, nullptr);832 833  FunctionPropertiesInfo ExpectedInitial;834  ExpectedInitial.BasicBlockCount = 6;835  ExpectedInitial.TotalInstructionCount = 9;836  ExpectedInitial.BlocksReachedFromConditionalInstruction = 2;837  ExpectedInitial.Uses = 1;838  ExpectedInitial.DirectCallsToDefinedFunctions = 1;839  ExpectedInitial.setFunctionEmbeddingForTest(840      createEmbedder(*F1)->getFunctionVector());841 842  FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;843  ExpectedFinal.BasicBlockCount = 4;844  ExpectedFinal.DirectCallsToDefinedFunctions = 0;845  ExpectedFinal.TotalInstructionCount = 7;846 847  auto FPI = buildFPI(*F1);848  EXPECT_EQ(FPI, ExpectedInitial);849 850  FunctionPropertiesUpdater FPU(FPI, *CB);851  InlineFunctionInfo IFI;852  auto IR = llvm::InlineFunction(*CB, IFI);853  EXPECT_TRUE(IR.isSuccess());854  invalidate(*F1);855  EXPECT_TRUE(FPU.finishAndTest(FAM));856 857  ExpectedFinal.setFunctionEmbeddingForTest(858      createEmbedder(*F1)->getFunctionVector());859  EXPECT_EQ(FPI, ExpectedFinal);860}861 862TEST_F(FunctionPropertiesAnalysisTest, InvokeSkipLP) {863  LLVMContext C;864  std::unique_ptr<Module> M = makeLLVMModule(C,865                                             R"IR(866target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"867target triple = "x86_64-pc-linux-gnu"868 869define i64 @f1(i32 noundef %value) {870entry:871  invoke fastcc void @f2() to label %cont unwind label %lpad872cont:873  ret i64 1874lpad:875  %lp = landingpad i32 cleanup876  br label %ehcleanup877ehcleanup:878  resume i32 0879}880define void @f2() {881  invoke noundef void @f3() to label %exit unwind label %lpad882exit:883  ret void884lpad:885  %lp = landingpad i32 cleanup886  resume i32 %lp887}888declare void @f3()889)IR");890 891  // The outcome of inlining will be that lpad becomes unreachable. The landing892  // pad of the invoke inherited from f2 will land on a new bb which will branch893  // to a bb containing the body of lpad.894  Function *F1 = M->getFunction("f1");895  CallBase *CB = findCall(*F1);896  EXPECT_NE(CB, nullptr);897 898  FunctionPropertiesInfo ExpectedInitial;899  ExpectedInitial.BasicBlockCount = 4;900  ExpectedInitial.TotalInstructionCount = 5;901  ExpectedInitial.BlocksReachedFromConditionalInstruction = 0;902  ExpectedInitial.Uses = 1;903  ExpectedInitial.DirectCallsToDefinedFunctions = 1;904  ExpectedInitial.setFunctionEmbeddingForTest(905      createEmbedder(*F1)->getFunctionVector());906 907  FunctionPropertiesInfo ExpectedFinal = ExpectedInitial;908  ExpectedFinal.BasicBlockCount = 6;909  ExpectedFinal.DirectCallsToDefinedFunctions = 0;910  ExpectedFinal.TotalInstructionCount = 8;911 912  auto FPI = buildFPI(*F1);913  EXPECT_EQ(FPI, ExpectedInitial);914 915  FunctionPropertiesUpdater FPU(FPI, *CB);916  InlineFunctionInfo IFI;917  auto IR = llvm::InlineFunction(*CB, IFI);918  EXPECT_TRUE(IR.isSuccess());919  invalidate(*F1);920  EXPECT_TRUE(FPU.finishAndTest(FAM));921 922  ExpectedFinal.setFunctionEmbeddingForTest(923      createEmbedder(*F1)->getFunctionVector());924  EXPECT_EQ(FPI, ExpectedFinal);925}926 927TEST_F(FunctionPropertiesAnalysisTest, DetailedOperandCount) {928  LLVMContext C;929  std::unique_ptr<Module> M = makeLLVMModule(C,930                                             R"IR(931@a = global i64 1932 933define i64 @f1(i64 %e) {934	%b = load i64, ptr @a935  %c = add i64 %b, 2936  %d = call i64 asm "mov $1,$0", "=r,r" (i64 %c)937	%f = add i64 %d, %e938	ret i64 %f939}940)IR");941 942  Function *F1 = M->getFunction("f1");943  EnableDetailedFunctionProperties.setValue(true);944  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);945  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSingleSuccessor, 0);946  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoSuccessors, 0);947  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoSuccessors, 0);948  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithSinglePredecessor, 0);949  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithTwoPredecessors, 0);950  EXPECT_EQ(DetailedF1Properties.BasicBlocksWithMoreThanTwoPredecessors, 0);951  EXPECT_EQ(DetailedF1Properties.BigBasicBlocks, 0);952  EXPECT_EQ(DetailedF1Properties.MediumBasicBlocks, 0);953  EXPECT_EQ(DetailedF1Properties.SmallBasicBlocks, 1);954  EXPECT_EQ(DetailedF1Properties.CastInstructionCount, 0);955  EXPECT_EQ(DetailedF1Properties.FloatingPointInstructionCount, 0);956  EXPECT_EQ(DetailedF1Properties.IntegerInstructionCount, 4);957  EXPECT_EQ(DetailedF1Properties.ConstantIntOperandCount, 1);958  EXPECT_EQ(DetailedF1Properties.ConstantFPOperandCount, 0);959  EXPECT_EQ(DetailedF1Properties.ConstantOperandCount, 0);960  EXPECT_EQ(DetailedF1Properties.InstructionOperandCount, 4);961  EXPECT_EQ(DetailedF1Properties.BasicBlockOperandCount, 0);962  EXPECT_EQ(DetailedF1Properties.GlobalValueOperandCount, 1);963  EXPECT_EQ(DetailedF1Properties.InlineAsmOperandCount, 1);964  EXPECT_EQ(DetailedF1Properties.ArgumentOperandCount, 1);965  EXPECT_EQ(DetailedF1Properties.UnknownOperandCount, 0);966  EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 0);967  EXPECT_EQ(DetailedF1Properties.ControlFlowEdgeCount, 0);968  EXPECT_EQ(DetailedF1Properties.UnconditionalBranchCount, 0);969  EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);970  EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1);971  EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);972  EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 1);973  EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 0);974  EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);975  EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);976  EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);977  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(978      createEmbedder(*F1)->getFunctionVector()));979  EnableDetailedFunctionProperties.setValue(false);980}981 982TEST_F(FunctionPropertiesAnalysisTest, IntrinsicCount) {983  LLVMContext C;984  std::unique_ptr<Module> M = makeLLVMModule(C,985                                             R"IR(986define float @f1(float %a) {987  %b = call float @llvm.cos.f32(float %a)988  ret float %b989}990declare float @llvm.cos.f32(float)991)IR");992 993  Function *F1 = M->getFunction("f1");994  EnableDetailedFunctionProperties.setValue(true);995  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);996  EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 1);997  EXPECT_EQ(DetailedF1Properties.DirectCallCount, 1);998  EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 0);999  EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 0);1000  EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1);1001  EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 0);1002  EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 0);1003  EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 0);1004  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(1005      createEmbedder(*F1)->getFunctionVector()));1006  EnableDetailedFunctionProperties.setValue(false);1007}1008 1009TEST_F(FunctionPropertiesAnalysisTest, FunctionCallMetrics) {1010  LLVMContext C;1011  std::unique_ptr<Module> M = makeLLVMModule(C,1012                                             R"IR(1013define i64 @f1(i64 %a) {1014  %b = call i64 @f2(i64 %a, i64 %a, i64 %a, i64 %a, i64 %a)1015  %c = call ptr @f3()1016  call void @f4(ptr %c)1017  %d = call float @f5()1018  %e = call i64 %c(i64 %b)1019  ret i64 %b1020}1021 1022declare i64 @f2(i64,i64,i64,i64,i64)1023declare ptr @f3()1024declare void @f4(ptr)1025declare float @f5()1026)IR");1027 1028  Function *F1 = M->getFunction("f1");1029  EnableDetailedFunctionProperties.setValue(true);1030  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);1031  EXPECT_EQ(DetailedF1Properties.IntrinsicCount, 0);1032  EXPECT_EQ(DetailedF1Properties.DirectCallCount, 4);1033  EXPECT_EQ(DetailedF1Properties.IndirectCallCount, 1);1034  EXPECT_EQ(DetailedF1Properties.CallReturnsIntegerCount, 2);1035  EXPECT_EQ(DetailedF1Properties.CallReturnsFloatCount, 1);1036  EXPECT_EQ(DetailedF1Properties.CallReturnsPointerCount, 1);1037  EXPECT_EQ(DetailedF1Properties.CallWithManyArgumentsCount, 1);1038  EXPECT_EQ(DetailedF1Properties.CallWithPointerArgumentCount, 1);1039  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(1040      createEmbedder(*F1)->getFunctionVector()));1041  EnableDetailedFunctionProperties.setValue(false);1042}1043 1044TEST_F(FunctionPropertiesAnalysisTest, CriticalEdge) {1045  LLVMContext C;1046  std::unique_ptr<Module> M = makeLLVMModule(C,1047                                             R"IR(1048define i64 @f1(i64 %a) {1049  %b = icmp eq i64 %a, 11050  br i1 %b, label %TopBlock1, label %TopBlock21051TopBlock1:1052  %c = add i64 %a, 11053  %e = icmp eq i64 %c, 21054  br i1 %e, label %BottomBlock1, label %BottomBlock21055TopBlock2:1056  %d = add i64 %a, 21057  br label %BottomBlock21058BottomBlock1:1059  ret i64 01060BottomBlock2:1061  %f = phi i64 [ %c, %TopBlock1 ], [ %d, %TopBlock2 ]1062  ret i64 %f1063}1064)IR");1065 1066  Function *F1 = M->getFunction("f1");1067  EnableDetailedFunctionProperties.setValue(true);1068  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);1069  EXPECT_EQ(DetailedF1Properties.CriticalEdgeCount, 1);1070  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(1071      createEmbedder(*F1)->getFunctionVector()));1072  EnableDetailedFunctionProperties.setValue(false);1073}1074 1075TEST_F(FunctionPropertiesAnalysisTest, FunctionReturnVectors) {1076  LLVMContext C;1077  std::unique_ptr<Module> M = makeLLVMModule(C,1078                                             R"IR(1079define <4 x i64> @f1(<4 x i64> %a) {1080  %b = call <4 x i64> @f2()1081  %c = call <4 x float> @f3()1082  %d = call <4 x ptr> @f4()1083  ret <4 x i64> %b1084}1085 1086declare <4 x i64> @f2()1087declare <4 x float> @f3()1088declare <4 x ptr> @f4()1089)IR");1090 1091  Function *F1 = M->getFunction("f1");1092  EnableDetailedFunctionProperties.setValue(true);1093  FunctionPropertiesInfo DetailedF1Properties = buildFPI(*F1);1094  EXPECT_EQ(DetailedF1Properties.CallReturnsVectorIntCount, 1);1095  EXPECT_EQ(DetailedF1Properties.CallReturnsVectorFloatCount, 1);1096  EXPECT_EQ(DetailedF1Properties.CallReturnsVectorPointerCount, 1);1097  EXPECT_TRUE(DetailedF1Properties.getFunctionEmbedding().approximatelyEquals(1098      createEmbedder(*F1)->getFunctionVector()));1099  EnableDetailedFunctionProperties.setValue(false);1100}1101 1102TEST_F(FunctionPropertiesAnalysisTest, ReAddEdges) {1103  LLVMContext C;1104  std::unique_ptr<Module> M = makeLLVMModule(C, R"IR(1105define hidden void @f1(ptr noundef %destatep, i32 noundef %offset, i8 noundef zeroext %byte1) {1106entry:1107  %cmp = icmp eq i8 %byte1, 01108  br i1 %cmp, label %if.then, label %if.else1109 1110if.then:                                          ; preds = %entry1111  call fastcc void @f2(ptr noundef %destatep, i32 noundef 37, i32 noundef 600)1112  %and = and i32 %offset, 31113  switch i32 %and, label %default.unreachable [1114    i32 0, label %sw.bb1115    i32 1, label %sw.bb11116    i32 2, label %sw.bb11117    i32 3, label %if.end1118  ]1119 1120sw.bb:                                            ; preds = %if.then1121  call fastcc void @f2(ptr noundef %destatep, i32 noundef 57, i32 noundef 600)1122  br label %if.end1123 1124sw.bb1:                                           ; preds = %if.then, %if.then1125  call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600) #341126  br label %if.end1127 1128default.unreachable:                              ; preds = %if.then1129  unreachable1130 1131if.else:                                          ; preds = %entry1132  call fastcc void @f2(ptr noundef %destatep, i32 noundef 56, i32 noundef 600)1133  br label %if.end1134 1135if.end:                                           ; preds = %sw.bb, %sw.bb1, %if.then, %if.else1136  ret void1137}1138 1139define internal fastcc void @f2(ptr nocapture noundef %destatep, i32 noundef %r_enc, i32 noundef %whack) {1140entry:1141  %enc_prob = getelementptr inbounds nuw i8, ptr %destatep, i32 5121142  %arrayidx = getelementptr inbounds [67 x i32], ptr %enc_prob, i32 0, i32 %r_enc1143  %0 = load i32, ptr %arrayidx, align 41144  %sub = sub nsw i32 %0, %whack1145  store i32 %sub, ptr %arrayidx, align 41146  ret void1147}1148  )IR");1149  auto *F1 = M->getFunction("f1");1150  auto *F2 = M->getFunction("f2");1151  auto *CB = [&]() -> CallBase * {1152    for (auto &BB : *F1)1153      for (auto &I : BB)1154        if (auto *CB = dyn_cast<CallBase>(&I);1155            CB && CB->getCalledFunction() && CB->getCalledFunction() == F2)1156          return CB;1157    return nullptr;1158  }();1159  ASSERT_NE(CB, nullptr);1160  auto FPI = buildFPI(*F1);1161  FunctionPropertiesUpdater FPU(FPI, *CB);1162  InlineFunctionInfo IFI;1163  auto IR = llvm::InlineFunction(*CB, IFI);1164  EXPECT_TRUE(IR.isSuccess());1165  invalidate(*F1);1166  EXPECT_TRUE(FPU.finishAndTest(FAM));1167}1168 1169TEST_F(FunctionPropertiesAnalysisTest, InvokeLandingCanStillBeReached) {1170  LLVMContext C;1171  // %lpad is reachable from a block not involved in the inlining decision. We1172  // make sure that's not the entry - otherwise the DT will be recomputed from1173  // scratch. The idea here is that the edge known to the inliner to potentially1174  // disappear - %lpad->%ehcleanup -should survive because it is still reachable1175  // from %middle.1176  std::unique_ptr<Module> M = makeLLVMModule(C,1177                                             R"IR(1178target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"1179target triple = "x86_64-pc-linux-gnu"1180 1181define i64 @f1(i32 noundef %value) {1182entry:1183  br label %middle1184middle:1185  %c = icmp eq i32 %value, 01186  br i1 %c, label %invoke, label %lpad1187invoke:1188  invoke fastcc void @f2() to label %cont unwind label %lpad1189cont:1190  br label %exit1191lpad:1192  %lp = landingpad i32 cleanup1193  br label %ehcleanup1194ehcleanup:1195  resume i32 01196exit:1197  ret i64 11198}1199define void @f2() {1200  ret void1201}1202)IR");1203 1204  Function *F1 = M->getFunction("f1");1205  CallBase *CB = findCall(*F1);1206  EXPECT_NE(CB, nullptr);1207 1208  auto FPI = buildFPI(*F1);1209  FunctionPropertiesUpdater FPU(FPI, *CB);1210  InlineFunctionInfo IFI;1211  auto IR = llvm::InlineFunction(*CB, IFI);1212  EXPECT_TRUE(IR.isSuccess());1213  invalidate(*F1);1214  EXPECT_TRUE(FPU.finishAndTest(FAM));1215}1216} // end anonymous namespace1217