//===- AnalysisManagerTest.cpp - AnalysisManager unit tests ---------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "mlir/Pass/AnalysisManager.h" #include "mlir/IR/Builders.h" #include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "gtest/gtest.h" using namespace mlir; using namespace mlir::detail; namespace { /// Minimal class definitions for two analyses. struct MyAnalysis { MyAnalysis(Operation *) {} }; struct OtherAnalysis { OtherAnalysis(Operation *) {} }; struct OpSpecificAnalysis { OpSpecificAnalysis(ModuleOp) {} }; TEST(AnalysisManagerTest, FineGrainModuleAnalysisPreservation) { MLIRContext context; // Test fine grain invalidation of the module analysis manager. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Query two different analyses, but only preserve one before invalidating. am.getAnalysis(); am.getAnalysis(); detail::PreservedAnalyses pa; pa.preserve(); am.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(am.getCachedAnalysis().hasValue()); EXPECT_FALSE(am.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, FineGrainFunctionAnalysisPreservation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); FuncOp func1 = FuncOp::create(builder.getUnknownLoc(), "foo", builder.getFunctionType(llvm::None, llvm::None)); func1.setPrivate(); module->push_back(func1); // Test fine grain invalidation of the function analysis manager. ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; AnalysisManager fam = am.nest(func1); // Query two different analyses, but only preserve one before invalidating. fam.getAnalysis(); fam.getAnalysis(); detail::PreservedAnalyses pa; pa.preserve(); fam.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(fam.getCachedAnalysis().hasValue()); EXPECT_FALSE(fam.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, FineGrainChildFunctionAnalysisPreservation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); FuncOp func1 = FuncOp::create(builder.getUnknownLoc(), "foo", builder.getFunctionType(llvm::None, llvm::None)); func1.setPrivate(); module->push_back(func1); // Test fine grain invalidation of a function analysis from within a module // analysis manager. ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Check that the analysis cache is initially empty. EXPECT_FALSE(am.getCachedChildAnalysis(func1).hasValue()); // Query two different analyses, but only preserve one before invalidating. am.getChildAnalysis(func1); am.getChildAnalysis(func1); detail::PreservedAnalyses pa; pa.preserve(); am.invalidate(pa); // Check that only MyAnalysis is preserved. EXPECT_TRUE(am.getCachedChildAnalysis(func1).hasValue()); EXPECT_FALSE(am.getCachedChildAnalysis(func1).hasValue()); } /// Test analyses with custom invalidation logic. struct TestAnalysisSet {}; struct CustomInvalidatingAnalysis { CustomInvalidatingAnalysis(Operation *) {} bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) { return !pa.isPreserved(); } }; TEST(AnalysisManagerTest, CustomInvalidation) { MLIRContext context; Builder builder(&context); // Create a function and a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; detail::PreservedAnalyses pa; // Check that the analysis is invalidated properly. am.getAnalysis(); am.invalidate(pa); EXPECT_FALSE(am.getCachedAnalysis().hasValue()); // Check that the analysis is preserved properly. am.getAnalysis(); pa.preserve(); am.invalidate(pa); EXPECT_TRUE(am.getCachedAnalysis().hasValue()); } TEST(AnalysisManagerTest, OpSpecificAnalysis) { MLIRContext context; // Create a module. OwningModuleRef module(ModuleOp::create(UnknownLoc::get(&context))); ModuleAnalysisManager mam(*module, /*passInstrumentor=*/nullptr); AnalysisManager am = mam; // Query the op specific analysis for the module and verify that its cached. am.getAnalysis(); EXPECT_TRUE(am.getCachedAnalysis().hasValue()); } } // end namespace