//===---------- MachinePassManager.cpp ------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file contains the pass management machinery for machine functions. // //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MachinePassManager.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/PassManagerImpl.h" using namespace llvm; namespace llvm { AnalysisKey FunctionAnalysisManagerMachineFunctionProxy::Key; template class AnalysisManager; template class PassManager; template class InnerAnalysisManagerProxy; template class OuterAnalysisManagerProxy; bool FunctionAnalysisManagerMachineFunctionProxy::Result::invalidate( MachineFunction &IR, const PreservedAnalyses &PA, MachineFunctionAnalysisManager::Invalidator &Inv) { // MachineFunction passes should not invalidate Function analyses. // TODO: verify that PA doesn't invalidate Function analyses. return false; } template <> bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate( Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv) { // If literally everything is preserved, we're done. if (PA.areAllPreserved()) return false; // This is still a valid proxy. // If this proxy isn't marked as preserved, then even if the result remains // valid, the key itself may no longer be valid, so we clear everything. // // Note that in order to preserve this proxy, a module pass must ensure that // the MFAM has been completely updated to handle the deletion of functions. // Specifically, any MFAM-cached results for those functions need to have been // forcibly cleared. When preserved, this proxy will only invalidate results // cached on functions *still in the module* at the end of the module pass. auto PAC = PA.getChecker(); if (!PAC.preserved() && !PAC.preservedSet>()) { InnerAM->clear(); return true; } // FIXME: be more precise, see // FunctionAnalysisManagerModuleProxy::Result::invalidate. if (!PA.allAnalysesInSetPreserved>()) { InnerAM->clear(); return true; } // Return false to indicate that this result is still a valid proxy. return false; } PreservedAnalyses ModuleToMachineFunctionPassAdaptor::run(Module &M, ModuleAnalysisManager &AM) { auto &MMI = AM.getResult(M).getMMI(); MachineFunctionAnalysisManager &MFAM = AM.getResult(M).getManager(); PassInstrumentation PI = AM.getResult(M); PreservedAnalyses PA = PreservedAnalyses::all(); for (Function &F : M) { // Do not codegen any 'available_externally' functions at all, they have // definitions outside the translation unit. if (F.isDeclaration() || F.hasAvailableExternallyLinkage()) continue; MachineFunction &MF = MMI.getOrCreateMachineFunction(F); if (!PI.runBeforePass(*Pass, MF)) continue; PreservedAnalyses PassPA = Pass->run(MF, MFAM); if (MMI.getMachineFunction(F)) { MFAM.invalidate(MF, PassPA); PI.runAfterPass(*Pass, MF, PassPA); } else { MFAM.clear(MF, F.getName()); PI.runAfterPassInvalidated(*Pass, PassPA); } PA.intersect(std::move(PassPA)); } return PA; } void ModuleToMachineFunctionPassAdaptor::printPipeline( raw_ostream &OS, function_ref MapClassName2PassName) { OS << "machine-function("; Pass->printPipeline(OS, MapClassName2PassName); OS << ')'; } template <> PreservedAnalyses PassManager::run(MachineFunction &MF, AnalysisManager &MFAM) { PassInstrumentation PI = MFAM.getResult(MF); Function &F = MF.getFunction(); MachineModuleInfo &MMI = MFAM.getResult(MF) .getCachedResult(*F.getParent()) ->getMMI(); PreservedAnalyses PA = PreservedAnalyses::all(); for (auto &Pass : Passes) { if (!PI.runBeforePass(*Pass, MF)) continue; PreservedAnalyses PassPA = Pass->run(MF, MFAM); if (MMI.getMachineFunction(F)) { MFAM.invalidate(MF, PassPA); PI.runAfterPass(*Pass, MF, PassPA); } else { MFAM.clear(MF, F.getName()); PI.runAfterPassInvalidated(*Pass, PassPA); } PA.intersect(std::move(PassPA)); } return PA; } } // namespace llvm