Home | History | Annotate | Download | only in IR
      1 //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/AsmParser/Parser.h"
     11 #include "llvm/IR/Function.h"
     12 #include "llvm/IR/LLVMContext.h"
     13 #include "llvm/IR/Module.h"
     14 #include "llvm/IR/PassManager.h"
     15 #include "llvm/Support/SourceMgr.h"
     16 #include "gtest/gtest.h"
     17 
     18 using namespace llvm;
     19 
     20 namespace {
     21 
     22 class TestFunctionAnalysis {
     23 public:
     24   struct Result {
     25     Result(int Count) : InstructionCount(Count) {}
     26     int InstructionCount;
     27   };
     28 
     29   /// \brief Returns an opaque, unique ID for this pass type.
     30   static void *ID() { return (void *)&PassID; }
     31 
     32   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
     33 
     34   /// \brief Run the analysis pass over the function and return a result.
     35   Result run(Function *F, FunctionAnalysisManager *AM) {
     36     ++Runs;
     37     int Count = 0;
     38     for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI)
     39       for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
     40            ++II)
     41         ++Count;
     42     return Result(Count);
     43   }
     44 
     45 private:
     46   /// \brief Private static data to provide unique ID.
     47   static char PassID;
     48 
     49   int &Runs;
     50 };
     51 
     52 char TestFunctionAnalysis::PassID;
     53 
     54 class TestModuleAnalysis {
     55 public:
     56   struct Result {
     57     Result(int Count) : FunctionCount(Count) {}
     58     int FunctionCount;
     59   };
     60 
     61   static void *ID() { return (void *)&PassID; }
     62 
     63   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
     64 
     65   Result run(Module *M, ModuleAnalysisManager *AM) {
     66     ++Runs;
     67     int Count = 0;
     68     for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
     69       ++Count;
     70     return Result(Count);
     71   }
     72 
     73 private:
     74   static char PassID;
     75 
     76   int &Runs;
     77 };
     78 
     79 char TestModuleAnalysis::PassID;
     80 
     81 struct TestModulePass {
     82   TestModulePass(int &RunCount) : RunCount(RunCount) {}
     83 
     84   PreservedAnalyses run(Module *M) {
     85     ++RunCount;
     86     return PreservedAnalyses::none();
     87   }
     88 
     89   static StringRef name() { return "TestModulePass"; }
     90 
     91   int &RunCount;
     92 };
     93 
     94 struct TestPreservingModulePass {
     95   PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }
     96 
     97   static StringRef name() { return "TestPreservingModulePass"; }
     98 };
     99 
    100 struct TestMinPreservingModulePass {
    101   PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
    102     PreservedAnalyses PA;
    103 
    104     // Force running an analysis.
    105     (void)AM->getResult<TestModuleAnalysis>(M);
    106 
    107     PA.preserve<FunctionAnalysisManagerModuleProxy>();
    108     return PA;
    109   }
    110 
    111   static StringRef name() { return "TestMinPreservingModulePass"; }
    112 };
    113 
    114 struct TestFunctionPass {
    115   TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
    116                    int &AnalyzedFunctionCount,
    117                    bool OnlyUseCachedResults = false)
    118       : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
    119         AnalyzedFunctionCount(AnalyzedFunctionCount),
    120         OnlyUseCachedResults(OnlyUseCachedResults) {}
    121 
    122   PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) {
    123     ++RunCount;
    124 
    125     const ModuleAnalysisManager &MAM =
    126         AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
    127     if (TestModuleAnalysis::Result *TMA =
    128             MAM.getCachedResult<TestModuleAnalysis>(F->getParent()))
    129       AnalyzedFunctionCount += TMA->FunctionCount;
    130 
    131     if (OnlyUseCachedResults) {
    132       // Hack to force the use of the cached interface.
    133       if (TestFunctionAnalysis::Result *AR =
    134               AM->getCachedResult<TestFunctionAnalysis>(F))
    135         AnalyzedInstrCount += AR->InstructionCount;
    136     } else {
    137       // Typical path just runs the analysis as needed.
    138       TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F);
    139       AnalyzedInstrCount += AR.InstructionCount;
    140     }
    141 
    142     return PreservedAnalyses::all();
    143   }
    144 
    145   static StringRef name() { return "TestFunctionPass"; }
    146 
    147   int &RunCount;
    148   int &AnalyzedInstrCount;
    149   int &AnalyzedFunctionCount;
    150   bool OnlyUseCachedResults;
    151 };
    152 
    153 // A test function pass that invalidates all function analyses for a function
    154 // with a specific name.
    155 struct TestInvalidationFunctionPass {
    156   TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
    157 
    158   PreservedAnalyses run(Function *F) {
    159     return F->getName() == Name ? PreservedAnalyses::none()
    160                                 : PreservedAnalyses::all();
    161   }
    162 
    163   static StringRef name() { return "TestInvalidationFunctionPass"; }
    164 
    165   StringRef Name;
    166 };
    167 
    168 Module *parseIR(const char *IR) {
    169   LLVMContext &C = getGlobalContext();
    170   SMDiagnostic Err;
    171   return ParseAssemblyString(IR, nullptr, Err, C);
    172 }
    173 
    174 class PassManagerTest : public ::testing::Test {
    175 protected:
    176   std::unique_ptr<Module> M;
    177 
    178 public:
    179   PassManagerTest()
    180       : M(parseIR("define void @f() {\n"
    181                   "entry:\n"
    182                   "  call void @g()\n"
    183                   "  call void @h()\n"
    184                   "  ret void\n"
    185                   "}\n"
    186                   "define void @g() {\n"
    187                   "  ret void\n"
    188                   "}\n"
    189                   "define void @h() {\n"
    190                   "  ret void\n"
    191                   "}\n")) {}
    192 };
    193 
    194 TEST_F(PassManagerTest, BasicPreservedAnalyses) {
    195   PreservedAnalyses PA1 = PreservedAnalyses();
    196   EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
    197   EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
    198   PreservedAnalyses PA2 = PreservedAnalyses::none();
    199   EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
    200   EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
    201   PreservedAnalyses PA3 = PreservedAnalyses::all();
    202   EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
    203   EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
    204   PreservedAnalyses PA4 = PA1;
    205   EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
    206   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
    207   PA4 = PA3;
    208   EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
    209   EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
    210   PA4 = std::move(PA2);
    211   EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
    212   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
    213   PA4.preserve<TestFunctionAnalysis>();
    214   EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
    215   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
    216   PA1.preserve<TestModuleAnalysis>();
    217   EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
    218   EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
    219   PA1.preserve<TestFunctionAnalysis>();
    220   EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
    221   EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
    222   PA1.intersect(PA4);
    223   EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
    224   EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
    225 }
    226 
    227 TEST_F(PassManagerTest, Basic) {
    228   FunctionAnalysisManager FAM;
    229   int FunctionAnalysisRuns = 0;
    230   FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns));
    231 
    232   ModuleAnalysisManager MAM;
    233   int ModuleAnalysisRuns = 0;
    234   MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns));
    235   MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
    236   FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
    237 
    238   ModulePassManager MPM;
    239 
    240   // Count the runs over a Function.
    241   int FunctionPassRunCount1 = 0;
    242   int AnalyzedInstrCount1 = 0;
    243   int AnalyzedFunctionCount1 = 0;
    244   {
    245     // Pointless scoped copy to test move assignment.
    246     ModulePassManager NestedMPM;
    247     FunctionPassManager FPM;
    248     {
    249       // Pointless scope to test move assignment.
    250       FunctionPassManager NestedFPM;
    251       NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1,
    252                                    AnalyzedFunctionCount1));
    253       FPM = std::move(NestedFPM);
    254     }
    255     NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
    256     MPM = std::move(NestedMPM);
    257   }
    258 
    259   // Count the runs over a module.
    260   int ModulePassRunCount = 0;
    261   MPM.addPass(TestModulePass(ModulePassRunCount));
    262 
    263   // Count the runs over a Function in a separate manager.
    264   int FunctionPassRunCount2 = 0;
    265   int AnalyzedInstrCount2 = 0;
    266   int AnalyzedFunctionCount2 = 0;
    267   {
    268     FunctionPassManager FPM;
    269     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
    270                                  AnalyzedFunctionCount2));
    271     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
    272   }
    273 
    274   // A third function pass manager but with only preserving intervening passes
    275   // and with a function pass that invalidates exactly one analysis.
    276   MPM.addPass(TestPreservingModulePass());
    277   int FunctionPassRunCount3 = 0;
    278   int AnalyzedInstrCount3 = 0;
    279   int AnalyzedFunctionCount3 = 0;
    280   {
    281     FunctionPassManager FPM;
    282     FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
    283                                  AnalyzedFunctionCount3));
    284     FPM.addPass(TestInvalidationFunctionPass("f"));
    285     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
    286   }
    287 
    288   // A fourth function pass manager but with a minimal intervening passes.
    289   MPM.addPass(TestMinPreservingModulePass());
    290   int FunctionPassRunCount4 = 0;
    291   int AnalyzedInstrCount4 = 0;
    292   int AnalyzedFunctionCount4 = 0;
    293   {
    294     FunctionPassManager FPM;
    295     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
    296                                  AnalyzedFunctionCount4));
    297     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
    298   }
    299 
    300   // A fifth function pass manager but which uses only cached results.
    301   int FunctionPassRunCount5 = 0;
    302   int AnalyzedInstrCount5 = 0;
    303   int AnalyzedFunctionCount5 = 0;
    304   {
    305     FunctionPassManager FPM;
    306     FPM.addPass(TestInvalidationFunctionPass("f"));
    307     FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
    308                                  AnalyzedFunctionCount5,
    309                                  /*OnlyUseCachedResults=*/true));
    310     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
    311   }
    312 
    313   MPM.run(M.get(), &MAM);
    314 
    315   // Validate module pass counters.
    316   EXPECT_EQ(1, ModulePassRunCount);
    317 
    318   // Validate all function pass counter sets are the same.
    319   EXPECT_EQ(3, FunctionPassRunCount1);
    320   EXPECT_EQ(5, AnalyzedInstrCount1);
    321   EXPECT_EQ(0, AnalyzedFunctionCount1);
    322   EXPECT_EQ(3, FunctionPassRunCount2);
    323   EXPECT_EQ(5, AnalyzedInstrCount2);
    324   EXPECT_EQ(0, AnalyzedFunctionCount2);
    325   EXPECT_EQ(3, FunctionPassRunCount3);
    326   EXPECT_EQ(5, AnalyzedInstrCount3);
    327   EXPECT_EQ(0, AnalyzedFunctionCount3);
    328   EXPECT_EQ(3, FunctionPassRunCount4);
    329   EXPECT_EQ(5, AnalyzedInstrCount4);
    330   EXPECT_EQ(0, AnalyzedFunctionCount4);
    331   EXPECT_EQ(3, FunctionPassRunCount5);
    332   EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
    333   EXPECT_EQ(0, AnalyzedFunctionCount5);
    334 
    335   // Validate the analysis counters:
    336   //   first run over 3 functions, then module pass invalidates
    337   //   second run over 3 functions, nothing invalidates
    338   //   third run over 0 functions, but 1 function invalidated
    339   //   fourth run over 1 function
    340   EXPECT_EQ(7, FunctionAnalysisRuns);
    341 
    342   EXPECT_EQ(1, ModuleAnalysisRuns);
    343 }
    344 }
    345