brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 0b31b08 Raw
247 lines · cpp
1#include "llvm/Analysis/CallGraph.h"2#include "llvm/AsmParser/Parser.h"3#include "llvm/Config/config.h"4#include "llvm/IR/Module.h"5#include "llvm/Passes/PassBuilder.h"6#include "llvm/Passes/PassPlugin.h"7#include "llvm/Support/CommandLine.h"8#include "llvm/Support/raw_ostream.h"9#include "llvm/Testing/Support/Error.h"10#include "gtest/gtest.h"11 12#include "llvm/Analysis/InlineOrder.h"13 14namespace llvm {15 16namespace {17 18void anchor() {}19 20std::string libPath(const std::string Name = "InlineOrderPlugin") {21  const auto &Argvs = testing::internal::GetArgvs();22  const char *Argv0 =23      Argvs.size() > 0 ? Argvs[0].c_str() : "PluginInlineOrderAnalysisTest";24  void *Ptr = (void *)(intptr_t)anchor;25  std::string Path = sys::fs::getMainExecutable(Argv0, Ptr);26  llvm::SmallString<256> Buf{sys::path::parent_path(Path)};27  sys::path::append(Buf, (Name + LLVM_PLUGIN_EXT).c_str());28  return std::string(Buf.str());29}30 31struct CompilerInstance {32  LLVMContext Ctx;33  ModulePassManager MPM;34  InlineParams IP;35 36  PassBuilder PB;37  LoopAnalysisManager LAM;38  FunctionAnalysisManager FAM;39  CGSCCAnalysisManager CGAM;40  ModuleAnalysisManager MAM;41 42  SMDiagnostic Error;43 44  // Connect the plugin to our compiler instance.45  void setupPlugin() {46    auto PluginPath = libPath();47    ASSERT_NE("", PluginPath);48    Expected<PassPlugin> Plugin = PassPlugin::Load(PluginPath);49    ASSERT_TRUE(!!Plugin) << "Plugin path: " << PluginPath;50    Plugin->registerPassBuilderCallbacks(PB);51  }52 53  CompilerInstance() {54    IP = getInlineParams(3, 0);55    PB.registerModuleAnalyses(MAM);56    PB.registerCGSCCAnalyses(CGAM);57    PB.registerFunctionAnalyses(FAM);58    PB.registerLoopAnalyses(LAM);59    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);60    MPM.addPass(ModuleInlinerPass(IP, InliningAdvisorMode::Default,61                                  ThinOrFullLTOPhase::None));62  }63 64  std::string Output;65  std::unique_ptr<Module> OutputM;66 67  // Run with the dynamic inline order.68  auto run(StringRef IR) {69    OutputM = parseAssemblyString(IR, Error, Ctx);70    MPM.run(*OutputM, MAM);71    ASSERT_TRUE(OutputM);72    Output.clear();73    raw_string_ostream OStream{Output};74    OutputM->print(OStream, nullptr);75    ASSERT_TRUE(true);76  }77};78 79StringRef TestIRS[] = {80    // Simple 3 function inline case.81    R"(82define void @f1() {83  call void @foo()84  ret void85}86define void @foo() {87  call void @f3()88  ret void89}90define void @f3() {91  ret void92}93  )",94    // Test that has 5 functions of which 2 are recursive.95    R"(96define void @f1() {97  call void @foo()98  ret void99}100define void @f2() {101  call void @foo()102  ret void103}104define void @foo() {105  call void @f4()106  call void @f5()107  ret void108}109define void @f4() {110  ret void111}112define void @f5() {113  call void @foo()114  ret void115}116  )",117    // Test with 2 mutually recursive functions and 1 function with a loop.118    R"(119define void @f1() {120  call void @f2()121  ret void122}123define void @f2() {124  call void @foo()125  ret void126}127define void @foo() {128  call void @f1()129  ret void130}131define void @f4() {132  br label %loop133loop:134  call void @f5()135  br label %loop136}137define void @f5() {138  ret void139}140  )",141    // Test that has a function that computes fibonacci in a loop, one in a142    // recursive manner, and one that calls both and compares them.143    R"(144define i32 @fib_loop(i32 %n){145    %curr = alloca i32146    %last = alloca i32147    %i = alloca i32148    store i32 1, i32* %curr149    store i32 1, i32* %last150    store i32 2, i32* %i151    br label %loop_cond152  loop_cond:153    %i_val = load i32, i32* %i154    %cmp = icmp slt i32 %i_val, %n155    br i1 %cmp, label %loop_body, label %loop_end156  loop_body:157    %curr_val = load i32, i32* %curr158    %last_val = load i32, i32* %last159    %add = add i32 %curr_val, %last_val160    store i32 %add, i32* %last161    store i32 %curr_val, i32* %curr162    %i_val2 = load i32, i32* %i163    %add2 = add i32 %i_val2, 1164    store i32 %add2, i32* %i165    br label %loop_cond166  loop_end:167    %curr_val3 = load i32, i32* %curr168    ret i32 %curr_val3169}170 171define i32 @foo(i32 %n){172    %cmp = icmp eq i32 %n, 0173    %cmp2 = icmp eq i32 %n, 1174    %or = or i1 %cmp, %cmp2175    br i1 %or, label %if_true, label %if_false176  if_true:177    ret i32 1178  if_false:179    %sub = sub i32 %n, 1180    %call = call i32 @foo(i32 %sub)181    %sub2 = sub i32 %n, 2182    %call2 = call i32 @foo(i32 %sub2)183    %add = add i32 %call, %call2184    ret i32 %add185}186 187define i32 @fib_check(){188    %correct = alloca i32189    %i = alloca i32190    store i32 1, i32* %correct191    store i32 0, i32* %i192    br label %loop_cond193  loop_cond:194    %i_val = load i32, i32* %i195    %cmp = icmp slt i32 %i_val, 10196    br i1 %cmp, label %loop_body, label %loop_end197  loop_body:198    %i_val2 = load i32, i32* %i199    %call = call i32 @fib_loop(i32 %i_val2)200    %i_val3 = load i32, i32* %i201    %call2 = call i32 @foo(i32 %i_val3)202    %cmp2 = icmp ne i32 %call, %call2203    br i1 %cmp2, label %if_true, label %if_false204  if_true:205    store i32 0, i32* %correct206    br label %if_end207  if_false:208    br label %if_end209  if_end:210    %i_val4 = load i32, i32* %i211    %add = add i32 %i_val4, 1212    store i32 %add, i32* %i213    br label %loop_cond214  loop_end:215    %correct_val = load i32, i32* %correct216    ret i32 %correct_val217}218  )"};219 220} // namespace221 222// Check that the behaviour of a custom inline order is correct.223// The custom order drops any functions named "foo" so all tests224// should contain at least one function named foo.225TEST(PluginInlineOrderTest, NoInlineFoo) {226#if !defined(LLVM_ENABLE_PLUGINS)227  // Skip the test if plugins are disabled.228  GTEST_SKIP();229#endif230  CompilerInstance CI{};231  CI.setupPlugin();232 233  for (StringRef IR : TestIRS) {234    bool FoundFoo = false;235    CI.run(IR);236    CallGraph CGraph = CallGraph(*CI.OutputM);237    for (auto &Node : CGraph) {238      for (auto &Edge : *Node.second) {239        FoundFoo |= Edge.second->getFunction()->getName() == "foo";240      }241    }242    ASSERT_TRUE(FoundFoo);243  }244}245 246} // namespace llvm247