mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	* Use StringRef instead of std::string& * Return a std::unique_ptr<Module> instead of taking an optional module to write to (was not really used). * Use current comment style. * Use current naming convention. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215989 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			345 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/AsmParser/Parser.h"
 | |
| #include "llvm/IR/Function.h"
 | |
| #include "llvm/IR/LLVMContext.h"
 | |
| #include "llvm/IR/Module.h"
 | |
| #include "llvm/IR/PassManager.h"
 | |
| #include "llvm/Support/SourceMgr.h"
 | |
| #include "gtest/gtest.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| class TestFunctionAnalysis {
 | |
| public:
 | |
|   struct Result {
 | |
|     Result(int Count) : InstructionCount(Count) {}
 | |
|     int InstructionCount;
 | |
|   };
 | |
| 
 | |
|   /// \brief Returns an opaque, unique ID for this pass type.
 | |
|   static void *ID() { return (void *)&PassID; }
 | |
| 
 | |
|   TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
 | |
| 
 | |
|   /// \brief Run the analysis pass over the function and return a result.
 | |
|   Result run(Function *F, FunctionAnalysisManager *AM) {
 | |
|     ++Runs;
 | |
|     int Count = 0;
 | |
|     for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI)
 | |
|       for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
 | |
|            ++II)
 | |
|         ++Count;
 | |
|     return Result(Count);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   /// \brief Private static data to provide unique ID.
 | |
|   static char PassID;
 | |
| 
 | |
|   int &Runs;
 | |
| };
 | |
| 
 | |
| char TestFunctionAnalysis::PassID;
 | |
| 
 | |
| class TestModuleAnalysis {
 | |
| public:
 | |
|   struct Result {
 | |
|     Result(int Count) : FunctionCount(Count) {}
 | |
|     int FunctionCount;
 | |
|   };
 | |
| 
 | |
|   static void *ID() { return (void *)&PassID; }
 | |
| 
 | |
|   TestModuleAnalysis(int &Runs) : Runs(Runs) {}
 | |
| 
 | |
|   Result run(Module *M, ModuleAnalysisManager *AM) {
 | |
|     ++Runs;
 | |
|     int Count = 0;
 | |
|     for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
 | |
|       ++Count;
 | |
|     return Result(Count);
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   static char PassID;
 | |
| 
 | |
|   int &Runs;
 | |
| };
 | |
| 
 | |
| char TestModuleAnalysis::PassID;
 | |
| 
 | |
| struct TestModulePass {
 | |
|   TestModulePass(int &RunCount) : RunCount(RunCount) {}
 | |
| 
 | |
|   PreservedAnalyses run(Module *M) {
 | |
|     ++RunCount;
 | |
|     return PreservedAnalyses::none();
 | |
|   }
 | |
| 
 | |
|   static StringRef name() { return "TestModulePass"; }
 | |
| 
 | |
|   int &RunCount;
 | |
| };
 | |
| 
 | |
| struct TestPreservingModulePass {
 | |
|   PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }
 | |
| 
 | |
|   static StringRef name() { return "TestPreservingModulePass"; }
 | |
| };
 | |
| 
 | |
| struct TestMinPreservingModulePass {
 | |
|   PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) {
 | |
|     PreservedAnalyses PA;
 | |
| 
 | |
|     // Force running an analysis.
 | |
|     (void)AM->getResult<TestModuleAnalysis>(M);
 | |
| 
 | |
|     PA.preserve<FunctionAnalysisManagerModuleProxy>();
 | |
|     return PA;
 | |
|   }
 | |
| 
 | |
|   static StringRef name() { return "TestMinPreservingModulePass"; }
 | |
| };
 | |
| 
 | |
| struct TestFunctionPass {
 | |
|   TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
 | |
|                    int &AnalyzedFunctionCount,
 | |
|                    bool OnlyUseCachedResults = false)
 | |
|       : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
 | |
|         AnalyzedFunctionCount(AnalyzedFunctionCount),
 | |
|         OnlyUseCachedResults(OnlyUseCachedResults) {}
 | |
| 
 | |
|   PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) {
 | |
|     ++RunCount;
 | |
| 
 | |
|     const ModuleAnalysisManager &MAM =
 | |
|         AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
 | |
|     if (TestModuleAnalysis::Result *TMA =
 | |
|             MAM.getCachedResult<TestModuleAnalysis>(F->getParent()))
 | |
|       AnalyzedFunctionCount += TMA->FunctionCount;
 | |
| 
 | |
|     if (OnlyUseCachedResults) {
 | |
|       // Hack to force the use of the cached interface.
 | |
|       if (TestFunctionAnalysis::Result *AR =
 | |
|               AM->getCachedResult<TestFunctionAnalysis>(F))
 | |
|         AnalyzedInstrCount += AR->InstructionCount;
 | |
|     } else {
 | |
|       // Typical path just runs the analysis as needed.
 | |
|       TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F);
 | |
|       AnalyzedInstrCount += AR.InstructionCount;
 | |
|     }
 | |
| 
 | |
|     return PreservedAnalyses::all();
 | |
|   }
 | |
| 
 | |
|   static StringRef name() { return "TestFunctionPass"; }
 | |
| 
 | |
|   int &RunCount;
 | |
|   int &AnalyzedInstrCount;
 | |
|   int &AnalyzedFunctionCount;
 | |
|   bool OnlyUseCachedResults;
 | |
| };
 | |
| 
 | |
| // A test function pass that invalidates all function analyses for a function
 | |
| // with a specific name.
 | |
| struct TestInvalidationFunctionPass {
 | |
|   TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
 | |
| 
 | |
|   PreservedAnalyses run(Function *F) {
 | |
|     return F->getName() == Name ? PreservedAnalyses::none()
 | |
|                                 : PreservedAnalyses::all();
 | |
|   }
 | |
| 
 | |
|   static StringRef name() { return "TestInvalidationFunctionPass"; }
 | |
| 
 | |
|   StringRef Name;
 | |
| };
 | |
| 
 | |
| Module *parseIR(const char *IR) {
 | |
|   LLVMContext &C = getGlobalContext();
 | |
|   SMDiagnostic Err;
 | |
|   return parseAssemblyString(IR, Err, C).release();
 | |
| }
 | |
| 
 | |
| class PassManagerTest : public ::testing::Test {
 | |
| protected:
 | |
|   std::unique_ptr<Module> M;
 | |
| 
 | |
| public:
 | |
|   PassManagerTest()
 | |
|       : M(parseIR("define void @f() {\n"
 | |
|                   "entry:\n"
 | |
|                   "  call void @g()\n"
 | |
|                   "  call void @h()\n"
 | |
|                   "  ret void\n"
 | |
|                   "}\n"
 | |
|                   "define void @g() {\n"
 | |
|                   "  ret void\n"
 | |
|                   "}\n"
 | |
|                   "define void @h() {\n"
 | |
|                   "  ret void\n"
 | |
|                   "}\n")) {}
 | |
| };
 | |
| 
 | |
| TEST_F(PassManagerTest, BasicPreservedAnalyses) {
 | |
|   PreservedAnalyses PA1 = PreservedAnalyses();
 | |
|   EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
 | |
|   PreservedAnalyses PA2 = PreservedAnalyses::none();
 | |
|   EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
 | |
|   PreservedAnalyses PA3 = PreservedAnalyses::all();
 | |
|   EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
 | |
|   PreservedAnalyses PA4 = PA1;
 | |
|   EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
 | |
|   PA4 = PA3;
 | |
|   EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
 | |
|   PA4 = std::move(PA2);
 | |
|   EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
 | |
|   PA4.preserve<TestFunctionAnalysis>();
 | |
|   EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
 | |
|   PA1.preserve<TestModuleAnalysis>();
 | |
|   EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
 | |
|   PA1.preserve<TestFunctionAnalysis>();
 | |
|   EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
 | |
|   PA1.intersect(PA4);
 | |
|   EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
 | |
|   EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
 | |
| }
 | |
| 
 | |
| TEST_F(PassManagerTest, Basic) {
 | |
|   FunctionAnalysisManager FAM;
 | |
|   int FunctionAnalysisRuns = 0;
 | |
|   FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns));
 | |
| 
 | |
|   ModuleAnalysisManager MAM;
 | |
|   int ModuleAnalysisRuns = 0;
 | |
|   MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns));
 | |
|   MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
 | |
|   FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
 | |
| 
 | |
|   ModulePassManager MPM;
 | |
| 
 | |
|   // Count the runs over a Function.
 | |
|   int FunctionPassRunCount1 = 0;
 | |
|   int AnalyzedInstrCount1 = 0;
 | |
|   int AnalyzedFunctionCount1 = 0;
 | |
|   {
 | |
|     // Pointless scoped copy to test move assignment.
 | |
|     ModulePassManager NestedMPM;
 | |
|     FunctionPassManager FPM;
 | |
|     {
 | |
|       // Pointless scope to test move assignment.
 | |
|       FunctionPassManager NestedFPM;
 | |
|       NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1,
 | |
|                                    AnalyzedFunctionCount1));
 | |
|       FPM = std::move(NestedFPM);
 | |
|     }
 | |
|     NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
 | |
|     MPM = std::move(NestedMPM);
 | |
|   }
 | |
| 
 | |
|   // Count the runs over a module.
 | |
|   int ModulePassRunCount = 0;
 | |
|   MPM.addPass(TestModulePass(ModulePassRunCount));
 | |
| 
 | |
|   // Count the runs over a Function in a separate manager.
 | |
|   int FunctionPassRunCount2 = 0;
 | |
|   int AnalyzedInstrCount2 = 0;
 | |
|   int AnalyzedFunctionCount2 = 0;
 | |
|   {
 | |
|     FunctionPassManager FPM;
 | |
|     FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
 | |
|                                  AnalyzedFunctionCount2));
 | |
|     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
 | |
|   }
 | |
| 
 | |
|   // A third function pass manager but with only preserving intervening passes
 | |
|   // and with a function pass that invalidates exactly one analysis.
 | |
|   MPM.addPass(TestPreservingModulePass());
 | |
|   int FunctionPassRunCount3 = 0;
 | |
|   int AnalyzedInstrCount3 = 0;
 | |
|   int AnalyzedFunctionCount3 = 0;
 | |
|   {
 | |
|     FunctionPassManager FPM;
 | |
|     FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
 | |
|                                  AnalyzedFunctionCount3));
 | |
|     FPM.addPass(TestInvalidationFunctionPass("f"));
 | |
|     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
 | |
|   }
 | |
| 
 | |
|   // A fourth function pass manager but with a minimal intervening passes.
 | |
|   MPM.addPass(TestMinPreservingModulePass());
 | |
|   int FunctionPassRunCount4 = 0;
 | |
|   int AnalyzedInstrCount4 = 0;
 | |
|   int AnalyzedFunctionCount4 = 0;
 | |
|   {
 | |
|     FunctionPassManager FPM;
 | |
|     FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
 | |
|                                  AnalyzedFunctionCount4));
 | |
|     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
 | |
|   }
 | |
| 
 | |
|   // A fifth function pass manager but which uses only cached results.
 | |
|   int FunctionPassRunCount5 = 0;
 | |
|   int AnalyzedInstrCount5 = 0;
 | |
|   int AnalyzedFunctionCount5 = 0;
 | |
|   {
 | |
|     FunctionPassManager FPM;
 | |
|     FPM.addPass(TestInvalidationFunctionPass("f"));
 | |
|     FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
 | |
|                                  AnalyzedFunctionCount5,
 | |
|                                  /*OnlyUseCachedResults=*/true));
 | |
|     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
 | |
|   }
 | |
| 
 | |
|   MPM.run(M.get(), &MAM);
 | |
| 
 | |
|   // Validate module pass counters.
 | |
|   EXPECT_EQ(1, ModulePassRunCount);
 | |
| 
 | |
|   // Validate all function pass counter sets are the same.
 | |
|   EXPECT_EQ(3, FunctionPassRunCount1);
 | |
|   EXPECT_EQ(5, AnalyzedInstrCount1);
 | |
|   EXPECT_EQ(0, AnalyzedFunctionCount1);
 | |
|   EXPECT_EQ(3, FunctionPassRunCount2);
 | |
|   EXPECT_EQ(5, AnalyzedInstrCount2);
 | |
|   EXPECT_EQ(0, AnalyzedFunctionCount2);
 | |
|   EXPECT_EQ(3, FunctionPassRunCount3);
 | |
|   EXPECT_EQ(5, AnalyzedInstrCount3);
 | |
|   EXPECT_EQ(0, AnalyzedFunctionCount3);
 | |
|   EXPECT_EQ(3, FunctionPassRunCount4);
 | |
|   EXPECT_EQ(5, AnalyzedInstrCount4);
 | |
|   EXPECT_EQ(0, AnalyzedFunctionCount4);
 | |
|   EXPECT_EQ(3, FunctionPassRunCount5);
 | |
|   EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
 | |
|   EXPECT_EQ(0, AnalyzedFunctionCount5);
 | |
| 
 | |
|   // Validate the analysis counters:
 | |
|   //   first run over 3 functions, then module pass invalidates
 | |
|   //   second run over 3 functions, nothing invalidates
 | |
|   //   third run over 0 functions, but 1 function invalidated
 | |
|   //   fourth run over 1 function
 | |
|   EXPECT_EQ(7, FunctionAnalysisRuns);
 | |
| 
 | |
|   EXPECT_EQ(1, ModuleAnalysisRuns);
 | |
| }
 | |
| }
 |