diff --git a/llvm/include/llvm/CodeGen/MachineCopyPropagation.h b/llvm/include/llvm/CodeGen/MachineCopyPropagation.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/CodeGen/MachineCopyPropagation.h @@ -0,0 +1,56 @@ +//===- MachineCopyPropagation.h - Machine Copy Propagation Pass ---------===// +// +// 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 is an extremely simple MachineInstr-level copy propagation pass. +// +// This pass forwards the source of COPYs to the users of their destinations +// when doing so is legal. For example: +// +// %reg1 = COPY %reg0 +// ... +// ... = OP %reg1 +// +// If +// - %reg0 has not been clobbered by the time of the use of %reg1 +// - the register class constraints are satisfied +// - the COPY def is the only value that reaches OP +// then this pass replaces the above with: +// +// %reg1 = COPY %reg0 +// ... +// ... = OP %reg0 +// +// This pass also removes some redundant COPYs. For example: +// +// %R1 = COPY %R0 +// ... // No clobber of %R1 +// %R0 = COPY %R1 <<< Removed +// +// or +// +// %R1 = COPY %R0 +// ... // No clobber of %R0 +// %R1 = COPY %R0 <<< Removed +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_COPY_PROPAGATION_H +#define LLVM_CODEGEN_MACHINE_COPY_PROPAGATION_H + +#include "llvm/CodeGen/PassManager.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +// The Machine Copy Propagation pass. +struct MachineCopyPropagationPass : PassInfoMixin { + PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &AM); +}; +} // namespace llvm + +#endif // LLVM_CODEGEN_MACHINE_COPY_PROPAGATION_H diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h --- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -33,6 +33,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/IR/PassManager.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Pass.h" @@ -74,7 +75,10 @@ /// made by different debugging and exception handling schemes and reformated /// for specific use. /// -class MachineModuleInfo : public ImmutablePass { +class MachineModuleInfo { + friend class MachineModuleInfoWrapperPass; + friend class MachineModuleAnalysis; + const LLVMTargetMachine &TM; /// This is the MCContext used for the entire code generator. @@ -144,11 +148,14 @@ static char ID; // Pass identification, replacement for typeid explicit MachineModuleInfo(const LLVMTargetMachine *TM = nullptr); - ~MachineModuleInfo() override; - // Initialization and Finalization - bool doInitialization(Module &) override; - bool doFinalization(Module &) override; + MachineModuleInfo(MachineModuleInfo &&MMII); + MachineModuleInfo &operator=(MachineModuleInfo &&MMII) = default; + + ~MachineModuleInfo(); + + void initialize(); + void finalize(); const LLVMTargetMachine &getTarget() const { return TM; } @@ -254,6 +261,39 @@ /// \} }; // End class MachineModuleInfo +class MachineModuleInfoWrapperPass : public ImmutablePass { + MachineModuleInfo MMI; + +public: + static char ID; // Pass identification, replacement for typeid + explicit MachineModuleInfoWrapperPass(const LLVMTargetMachine *TM = nullptr); + explicit MachineModuleInfoWrapperPass(const MachineModuleInfo &MMI); + + // Initialization and Finalization + bool doInitialization(Module &) override; + bool doFinalization(Module &) override; + + MachineModuleInfo &getMMI() { return MMI; } + const MachineModuleInfo &getMMI() const { return MMI; } +}; + +/// An analysis that produces \c MachineInfo for a module. +class MachineModuleAnalysis : public AnalysisInfoMixin { + friend AnalysisInfoMixin; + static AnalysisKey Key; + + const LLVMTargetMachine *TM; + +public: + /// Provide the result type for this analysis pass. + using Result = MachineModuleInfo; + + MachineModuleAnalysis(const LLVMTargetMachine *TM) : TM(TM){}; + + /// Run the analysis pass and produce machine module information. + MachineModuleInfo run(Module &M, ModuleAnalysisManager &); +}; + } // end namespace llvm #endif // LLVM_CODEGEN_MACHINEMODULEINFO_H diff --git a/llvm/include/llvm/CodeGen/PassManager.h b/llvm/include/llvm/CodeGen/PassManager.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/CodeGen/PassManager.h @@ -0,0 +1,133 @@ +//===- PassManager.h ---------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Interface for the pass manager functionality used for CodeGen. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PASS_MANAGER_H +#define LLVM_CODEGEN_PASS_MANAGER_H + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/PassManagerInternal.h" + +namespace llvm { + +/// Convenience typedef for the MachineFunction analysis manager. +using MachineFunctionAnalysisManager = AnalysisManager; +/// Convenience typedef for a pass manager over functions. +using MachineFunctionPassManager = PassManager; + +using MachineFunctionAnalysisManagerFunctionProxy = + InnerAnalysisManagerProxy; + +template +class FunctionToMachineFunctionPassAdaptor + : public PassInfoMixin> { +public: + explicit FunctionToMachineFunctionPassAdaptor(MachineFunctionPassT Pass) + : Pass(std::move(Pass)) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + PreservedAnalyses PA = PreservedAnalyses::all(); + + // Do not codegen any 'available_externally' functions at all, they have + // definitions outside the translation unit. + if (F.hasAvailableExternallyLinkage()) + return PA; + + MachineFunctionAnalysisManager &MFAM = + AM.getResult(F) + .getManager(); + + MachineModuleInfo *MMI = + AM.getResult(F) + .getManager() + .getCachedResult(*F.getParent()); + assert(MMI && + "failed to retrieve MMI. must be initialized first somewhere else."); + MachineFunction &MF = MMI->getOrCreateMachineFunction(F); + + // Collect the MI count of the function before the pass. + unsigned CountBefore, CountAfter; + + // Check if the user asked for size remarks. + bool ShouldEmitSizeRemarks = + F.getParent()->shouldEmitInstrCountChangedRemark(); + + // If we want size remarks, collect the number of MachineInstrs in our + // MachineFunction before the pass runs. + if (ShouldEmitSizeRemarks) + CountBefore = MF.getInstructionCount(); + + // Request PassInstrumentation from analysis manager, will use it to run + // instrumenting callbacks for the passes later. + // TODO PASS INSTRUMENTATION + // PassInstrumentation PI = AM.getResult(F); + + // Check the PassInstrumentation's BeforePass callbacks before running the + // pass, skip its execution completely if asked to (callback returns + // false). + // if (PI.runBeforePass(Pass, MF)) + // PA = Pass.run(MF, MFAM); + + // PI.runAfterPass(Pass, MF); + + Pass.run(MF, MFAM); + + if (ShouldEmitSizeRemarks) { + // We wanted size remarks. Check if there was a change to the number of + // MachineInstrs in the module. Emit a remark if there was a change. + CountAfter = MF.getInstructionCount(); + if (CountBefore != CountAfter) { + MachineOptimizationRemarkEmitter MORE(MF, nullptr); + MORE.emit([&]() { + int64_t Delta = static_cast(CountAfter) - + static_cast(CountBefore); + MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange", + MF.getFunction().getSubprogram(), + &MF.front()); + // R << NV("Pass", getPassName()) + // << ": Function: " << NV("Function", F.getName()) << ": " + // << "MI Instruction count changed from " + // << NV("MIInstrsBefore", CountBefore) << " to " + // << NV("MIInstrsAfter", CountAfter) + // << "; Delta: " << NV("Delta", Delta); + return R; + }); + } + } + + // The FunctionAnalysisManagerModuleProxy is preserved because (we assume) + // the function passes we ran didn't add or remove any functions. + // + // We also preserve all analyses on Machine Functions, because we did all the + // invalidation we needed to do above. + PA.preserveSet>(); + PA.preserve(); + assert(PA.areAllPreserved()); + return PA; + } + +private: + MachineFunctionPassT Pass; +}; + +template +FunctionToMachineFunctionPassAdaptor +createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT Pass) { + return FunctionToMachineFunctionPassAdaptor( + std::move(Pass)); +} + +} // end namespace llvm + +#endif // LLVM_CODEGEN_PASS_MANAGER_H diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -250,20 +250,20 @@ void initializeLowerSwitchPass(PassRegistry&); void initializeLowerTypeTestsPass(PassRegistry&); void initializeMIRCanonicalizerPass(PassRegistry &); -void initializeMIRPrintingPassPass(PassRegistry&); +void initializeMIRPrintingLegacyPassPass(PassRegistry &); void initializeMachineBlockFrequencyInfoPass(PassRegistry&); void initializeMachineBlockPlacementPass(PassRegistry&); void initializeMachineBlockPlacementStatsPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry&); -void initializeMachineCopyPropagationPass(PassRegistry&); +void initializeMachineCopyPropagationLegacyPassPass(PassRegistry&); void initializeMachineDominanceFrontierPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); -void initializeMachineModuleInfoPass(PassRegistry&); +void initializeMachineModuleInfoWrapperPassPass(PassRegistry &); void initializeMachineOptimizationRemarkEmitterPassPass(PassRegistry&); void initializeMachineOutlinerPass(PassRegistry&); void initializeMachinePipelinerPass(PassRegistry&); diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -25,7 +25,7 @@ class Function; class GlobalValue; -class MachineModuleInfo; +class MachineModuleInfoWrapperPass; class Mangler; class MCAsmInfo; class MCContext; @@ -284,12 +284,12 @@ /// emitted. Typically this will involve several steps of code generation. /// This method should return true if emission of this file type is not /// supported, or false on success. - /// \p MMI is an optional parameter that, if set to non-nullptr, + /// \p MMIWP is an optional parameter that, if set to non-nullptr, /// will be used to set the MachineModuloInfo for this PM. virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, raw_pwrite_stream *, CodeGenFileType, bool /*DisableVerify*/ = true, - MachineModuleInfo *MMI = nullptr) { + MachineModuleInfoWrapperPass *MMIWP = nullptr) { return true; } @@ -341,12 +341,12 @@ /// Add passes to the specified pass manager to get the specified file /// emitted. Typically this will involve several steps of code generation. - /// \p MMI is an optional parameter that, if set to non-nullptr, - /// will be used to set the MachineModuloInfofor this PM. + /// \p MMIWP is an optional parameter that, if set to non-nullptr, + /// will be used to set the MachineModuloInfo for this PM. bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, CodeGenFileType FileType, bool DisableVerify = true, - MachineModuleInfo *MMI = nullptr) override; + MachineModuleInfoWrapperPass *MMIWP = nullptr) override; /// Add passes to the specified pass manager to get machine code emitted with /// the MCJIT. This method returns true if machine code is not supported. It @@ -365,7 +365,7 @@ /// Adds an AsmPrinter pass to the pipeline that prints assembly or /// machine code from the MI representation. bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out, - raw_pwrite_stream *DwoOut, CodeGenFileType FileTYpe, + raw_pwrite_stream *DwoOut, CodeGenFileType FileType, MCContext &Context); /// True if the target uses physical regs at Prolog/Epilog insertion diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -247,13 +247,13 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); } bool AsmPrinter::doInitialization(Module &M) { - MMI = getAnalysisIfAvailable(); + MMI = &getAnalysisIfAvailable()->getMMI(); // Initialize TargetLoweringObjectFile. const_cast(getObjFileLowering()) diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp --- a/llvm/lib/CodeGen/BranchFolding.cpp +++ b/llvm/lib/CodeGen/BranchFolding.cpp @@ -129,9 +129,9 @@ getAnalysis()); BranchFolder Folder(EnableTailMerge, /*CommonHoist=*/true, MBBFreqInfo, getAnalysis()); - return Folder.OptimizeFunction(MF, MF.getSubtarget().getInstrInfo(), - MF.getSubtarget().getRegisterInfo(), - getAnalysisIfAvailable()); + return Folder.OptimizeFunction( + MF, MF.getSubtarget().getInstrInfo(), MF.getSubtarget().getRegisterInfo(), + &getAnalysisIfAvailable()->getMMI()); } BranchFolder::BranchFolder(bool defaultEnableTailMerge, bool CommonHoist, diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -100,6 +100,7 @@ MacroFusion.cpp OptimizePHIs.cpp ParallelCG.cpp + PassManager.cpp PeepholeOptimizer.cpp PHIElimination.cpp PHIEliminationUtils.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -58,12 +58,12 @@ initializeMachineBlockPlacementStatsPass(Registry); initializeMachineCSEPass(Registry); initializeMachineCombinerPass(Registry); - initializeMachineCopyPropagationPass(Registry); + initializeMachineCopyPropagationLegacyPassPass(Registry); initializeMachineDominatorTreePass(Registry); initializeMachineFunctionPrinterPassPass(Registry); initializeMachineLICMPass(Registry); initializeMachineLoopInfoPass(Registry); - initializeMachineModuleInfoPass(Registry); + initializeMachineModuleInfoWrapperPassPass(Registry); initializeMachineOptimizationRemarkEmitterPassPass(Registry); initializeMachineOutlinerPass(Registry); initializeMachinePipelinerPass(Registry); diff --git a/llvm/lib/CodeGen/GCRootLowering.cpp b/llvm/lib/CodeGen/GCRootLowering.cpp --- a/llvm/lib/CodeGen/GCRootLowering.cpp +++ b/llvm/lib/CodeGen/GCRootLowering.cpp @@ -249,7 +249,7 @@ void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); AU.addRequired(); } @@ -310,7 +310,7 @@ return false; FI = &getAnalysis().getFunctionInfo(MF.getFunction()); - MMI = &getAnalysis(); + MMI = &getAnalysis().getMMI(); TII = MF.getSubtarget().getInstrInfo(); // Find the size of the stack frame. There may be no correct static frame diff --git a/llvm/lib/CodeGen/IfConversion.cpp b/llvm/lib/CodeGen/IfConversion.cpp --- a/llvm/lib/CodeGen/IfConversion.cpp +++ b/llvm/lib/CodeGen/IfConversion.cpp @@ -356,8 +356,9 @@ if (!PreRegAlloc) { // Tail merge tend to expose more if-conversion opportunities. BranchFolder BF(true, false, MBFI, *MBPI); - BFChange = BF.OptimizeFunction(MF, TII, ST.getRegisterInfo(), - getAnalysisIfAvailable()); + BFChange = BF.OptimizeFunction( + MF, TII, ST.getRegisterInfo(), + &getAnalysisIfAvailable()->getMMI()); } LLVM_DEBUG(dbgs() << "\nIfcvt: function (" << ++FnNum << ") \'" @@ -496,8 +497,9 @@ if (MadeChange && IfCvtBranchFold) { BranchFolder BF(false, false, MBFI, *MBPI); - BF.OptimizeFunction(MF, TII, MF.getSubtarget().getRegisterInfo(), - getAnalysisIfAvailable()); + BF.OptimizeFunction( + MF, TII, MF.getSubtarget().getRegisterInfo(), + &getAnalysisIfAvailable()->getMMI()); } MadeChange |= BFChange; diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -96,14 +96,15 @@ /// addPassesToX helper drives creation and initialization of TargetPassConfig. static TargetPassConfig * addPassesToGenerateCode(LLVMTargetMachine &TM, PassManagerBase &PM, - bool DisableVerify, MachineModuleInfo &MMI) { + bool DisableVerify, + MachineModuleInfoWrapperPass &MMIWP) { // Targets may override createPassConfig to provide a target-specific // subclass. TargetPassConfig *PassConfig = TM.createPassConfig(PM); // Set PassConfig options provided by TargetMachine. PassConfig->setDisableVerify(DisableVerify); PM.add(PassConfig); - PM.add(&MMI); + PM.add(&MMIWP); if (PassConfig->addISelPasses()) return nullptr; @@ -186,17 +187,15 @@ return false; } -bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, - raw_pwrite_stream &Out, - raw_pwrite_stream *DwoOut, - CodeGenFileType FileType, - bool DisableVerify, - MachineModuleInfo *MMI) { +bool LLVMTargetMachine::addPassesToEmitFile( + PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut, + CodeGenFileType FileType, bool DisableVerify, + MachineModuleInfoWrapperPass *MMIWP) { // Add common CodeGen passes. - if (!MMI) - MMI = new MachineModuleInfo(this); + if (!MMIWP) + MMIWP = new MachineModuleInfoWrapperPass(this); TargetPassConfig *PassConfig = - addPassesToGenerateCode(*this, PM, DisableVerify, *MMI); + addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP); if (!PassConfig) return true; @@ -206,12 +205,13 @@ // testing to be meaningful, we need to ensure that the symbols created // are MCSymbolXCOFF variants, which requires that // the TargetLoweringObjectFile instance has been initialized. - MCContext &Ctx = MMI->getContext(); + MCContext &Ctx = MMIWP->getMMI().getContext(); const_cast(*this->getObjFileLowering()) .Initialize(Ctx, *this); } PM.add(createPrintMIRPass(Out)); - } else if (addAsmPrinter(PM, Out, DwoOut, FileType, MMI->getContext())) + } else if (addAsmPrinter(PM, Out, DwoOut, FileType, + MMIWP->getMMI().getContext())) return true; PM.add(createFreeMachineFunctionPass()); @@ -227,15 +227,15 @@ raw_pwrite_stream &Out, bool DisableVerify) { // Add common CodeGen passes. - MachineModuleInfo *MMI = new MachineModuleInfo(this); + MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(this); TargetPassConfig *PassConfig = - addPassesToGenerateCode(*this, PM, DisableVerify, *MMI); + addPassesToGenerateCode(*this, PM, DisableVerify, *MMIWP); if (!PassConfig) return true; assert(TargetPassConfig::willCompleteCodeGenPipeline() && "Cannot emit MC with limited codegen pipeline"); - Ctx = &MMI->getContext(); + Ctx = &MMIWP->getMMI().getContext(); if (Options.MCOptions.MCSaveTempLabels) Ctx->setAllowTemporaryLabels(false); diff --git a/llvm/lib/CodeGen/MIRPrintingPass.cpp b/llvm/lib/CodeGen/MIRPrintingPass.cpp --- a/llvm/lib/CodeGen/MIRPrintingPass.cpp +++ b/llvm/lib/CodeGen/MIRPrintingPass.cpp @@ -11,7 +11,9 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/MIRPrintingPass.h" #include "llvm/CodeGen/MIRPrinter.h" +#include "llvm/CodeGen/PassManager.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Passes.h" @@ -20,17 +22,32 @@ using namespace llvm; +PreservedAnalyses MIRPrintingPass::run(Module &M, ModuleAnalysisManager &MAM) { + printMIR(OS, M); + // FIXME: Inefficient. Should only make this adaptor once. Put it in + // the class and construct it the first time. + return createModuleToFunctionPassAdaptor( + createFunctionToMachineFunctionPassAdaptor(*this)) + .run(M, MAM); +} + +PreservedAnalyses MIRPrintingPass::run(MachineFunction &MF, + MachineFunctionAnalysisManager &) { + printMIR(OS, MF); + return PreservedAnalyses::all(); +} + namespace { /// This pass prints out the LLVM IR to an output stream using the MIR /// serialization format. -struct MIRPrintingPass : public MachineFunctionPass { +struct MIRPrintingLegacyPass : public MachineFunctionPass { static char ID; raw_ostream &OS; std::string MachineFunctions; - MIRPrintingPass() : MachineFunctionPass(ID), OS(dbgs()) {} - MIRPrintingPass(raw_ostream &OS) : MachineFunctionPass(ID), OS(OS) {} + MIRPrintingLegacyPass() : MachineFunctionPass(ID), OS(dbgs()) {} + MIRPrintingLegacyPass(raw_ostream &OS) : MachineFunctionPass(ID), OS(OS) {} StringRef getPassName() const override { return "MIR Printing Pass"; } @@ -54,17 +71,18 @@ } }; -char MIRPrintingPass::ID = 0; +char MIRPrintingLegacyPass::ID = 0; } // end anonymous namespace -char &llvm::MIRPrintingPassID = MIRPrintingPass::ID; -INITIALIZE_PASS(MIRPrintingPass, "mir-printer", "MIR Printer", false, false) +char &llvm::MIRPrintingPassID = MIRPrintingLegacyPass::ID; +INITIALIZE_PASS(MIRPrintingLegacyPass, "mir-printer", "MIR Printer", false, + false) namespace llvm { MachineFunctionPass *createPrintMIRPass(raw_ostream &OS) { - return new MIRPrintingPass(OS); + return new MIRPrintingLegacyPass(OS); } } // end namespace llvm diff --git a/llvm/lib/CodeGen/MachineBlockPlacement.cpp b/llvm/lib/CodeGen/MachineBlockPlacement.cpp --- a/llvm/lib/CodeGen/MachineBlockPlacement.cpp +++ b/llvm/lib/CodeGen/MachineBlockPlacement.cpp @@ -2855,9 +2855,11 @@ BranchFolder BF(/*EnableTailMerge=*/true, /*CommonHoist=*/false, *MBFI, *MBPI, TailMergeSize); - if (BF.OptimizeFunction(MF, TII, MF.getSubtarget().getRegisterInfo(), - getAnalysisIfAvailable(), MLI, - /*AfterBlockPlacement=*/true)) { + if (BF.OptimizeFunction( + MF, TII, MF.getSubtarget().getRegisterInfo(), + &getAnalysisIfAvailable()->getMMI(), + MLI, + /*AfterBlockPlacement=*/true)) { // Redo the layout if tail merging creates/removes/moves blocks. BlockToChain.clear(); ComputedEdges.clear(); diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp --- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp +++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp @@ -59,6 +59,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/DebugCounter.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/CodeGen/MachineCopyPropagation.h" #include #include @@ -180,16 +181,11 @@ } }; -class MachineCopyPropagation : public MachineFunctionPass { - const TargetRegisterInfo *TRI; - const TargetInstrInfo *TII; - const MachineRegisterInfo *MRI; - +class MachineCopyPropagationLegacyPass : public MachineFunctionPass { public: static char ID; // Pass identification, replacement for typeid - - MachineCopyPropagation() : MachineFunctionPass(ID) { - initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry()); + MachineCopyPropagationLegacyPass() : MachineFunctionPass(ID) { + initializeMachineCopyPropagationLegacyPassPass(*PassRegistry::getPassRegistry()); } void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -203,11 +199,24 @@ return MachineFunctionProperties().set( MachineFunctionProperties::Property::NoVRegs); } +}; + +class MachineCopyPropagation { + const TargetRegisterInfo *TRI; + const TargetInstrInfo *TII; + const MachineRegisterInfo *MRI; + +public: + bool Changed; + MachineCopyPropagation(const TargetRegisterInfo *TRI, + const TargetInstrInfo *TII, + const MachineRegisterInfo *MRI) + : TRI(TRI), TII(TII), MRI(MRI), Changed(false) {} + void CopyPropagateBlock(MachineBasicBlock &MBB); private: void ClobberRegister(unsigned Reg); void ReadRegister(unsigned Reg); - void CopyPropagateBlock(MachineBasicBlock &MBB); bool eraseIfRedundant(MachineInstr &Copy, unsigned Src, unsigned Def); void forwardUses(MachineInstr &MI); bool isForwardableRegClassCopy(const MachineInstr &Copy, @@ -218,17 +227,15 @@ SmallSetVector MaybeDeadCopies; CopyTracker Tracker; - - bool Changed; }; } // end anonymous namespace -char MachineCopyPropagation::ID = 0; +char MachineCopyPropagationLegacyPass::ID = 0; -char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID; +char &llvm::MachineCopyPropagationID = MachineCopyPropagationLegacyPass::ID; -INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE, +INITIALIZE_PASS(MachineCopyPropagationLegacyPass, DEBUG_TYPE, "Machine Copy Propagation Pass", false, false) void MachineCopyPropagation::ReadRegister(unsigned Reg) { @@ -623,18 +630,23 @@ Tracker.clear(); } -bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) { - if (skipFunction(MF.getFunction())) - return false; +MachineCopyPropagation copyPropagate(MachineFunction &MF) { + MachineCopyPropagation info{MF.getSubtarget().getRegisterInfo(), + MF.getSubtarget().getInstrInfo(), + &MF.getRegInfo()}; - Changed = false; + for (MachineBasicBlock &MBB : MF) + info.CopyPropagateBlock(MBB); - TRI = MF.getSubtarget().getRegisterInfo(); - TII = MF.getSubtarget().getInstrInfo(); - MRI = &MF.getRegInfo(); + return info; +} - for (MachineBasicBlock &MBB : MF) - CopyPropagateBlock(MBB); +PreservedAnalyses MachineCopyPropagationPass::run(MachineFunction &MF, MachineFunctionAnalysisManager &AM) { + return copyPropagate(MF).Changed ? PreservedAnalyses::all() : PreservedAnalyses::none(); +} - return Changed; +bool MachineCopyPropagationLegacyPass::runOnMachineFunction(MachineFunction &MF) { + if (skipFunction(MF.getFunction())) + return false; + return copyPropagate(MF).Changed; } diff --git a/llvm/lib/CodeGen/MachineFunctionPass.cpp b/llvm/lib/CodeGen/MachineFunctionPass.cpp --- a/llvm/lib/CodeGen/MachineFunctionPass.cpp +++ b/llvm/lib/CodeGen/MachineFunctionPass.cpp @@ -41,7 +41,7 @@ if (F.hasAvailableExternallyLinkage()) return false; - MachineModuleInfo &MMI = getAnalysis(); + MachineModuleInfo &MMI = getAnalysis().getMMI(); MachineFunction &MF = MMI.getOrCreateMachineFunction(F); MachineFunctionProperties &MFProps = MF.getProperties(); @@ -101,8 +101,8 @@ } void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); // MachineFunctionPass preserves all LLVM IR passes, but there's no // high-level way to express this. Instead, just list a bunch of diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -36,11 +36,6 @@ using namespace llvm; using namespace llvm::dwarf; -// Handle the Pass registration stuff necessary to use DataLayout's. -INITIALIZE_PASS(MachineModuleInfo, "machinemoduleinfo", - "Machine Module Information", false, false) -char MachineModuleInfo::ID = 0; - // Out of line virtual method. MachineModuleInfoImpl::~MachineModuleInfoImpl() = default; @@ -193,27 +188,15 @@ Map->UpdateForRAUWBlock(cast(getValPtr()), cast(V2)); } -MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) - : ImmutablePass(ID), TM(*TM), - Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(), - TM->getObjFileLowering(), nullptr, false) { - initializeMachineModuleInfoPass(*PassRegistry::getPassRegistry()); -} - -MachineModuleInfo::~MachineModuleInfo() = default; - -bool MachineModuleInfo::doInitialization(Module &M) { +void MachineModuleInfo::initialize() { ObjFileMMI = nullptr; CurCallSite = 0; UsesMSVCFloatingPoint = UsesMorestackAddr = false; HasSplitStack = HasNosplitStack = false; AddrLabelSymbols = nullptr; - TheModule = &M; - DbgInfoAvailable = !llvm::empty(M.debug_compile_units()); - return false; } -bool MachineModuleInfo::doFinalization(Module &M) { +void MachineModuleInfo::finalize() { Personalities.clear(); delete AddrLabelSymbols; @@ -223,8 +206,28 @@ delete ObjFileMMI; ObjFileMMI = nullptr; +} - return false; +MachineModuleInfo::MachineModuleInfo(MachineModuleInfo &&MMI) + : TM(std::move(MMI.TM)), Context(MMI.TM.getMCAsmInfo(), MMI.TM.getMCRegisterInfo(), + MMI.TM.getObjFileLowering(), nullptr, false) { + ObjFileMMI = MMI.ObjFileMMI; + CurCallSite = MMI.CurCallSite; + UsesMSVCFloatingPoint = MMI.UsesMSVCFloatingPoint; + UsesMorestackAddr = MMI.UsesMorestackAddr; + HasSplitStack = MMI.HasSplitStack; + HasNosplitStack = MMI.HasNosplitStack; + AddrLabelSymbols = MMI.AddrLabelSymbols; +} + +MachineModuleInfo::MachineModuleInfo(const LLVMTargetMachine *TM) + : TM(*TM), Context(TM->getMCAsmInfo(), TM->getMCRegisterInfo(), + TM->getObjFileLowering(), nullptr, false) { + initialize(); +} + +MachineModuleInfo::~MachineModuleInfo() { + finalize(); } //===- Address of Block Management ----------------------------------------===// @@ -305,12 +308,13 @@ FreeMachineFunction() : FunctionPass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); } bool runOnFunction(Function &F) override { - MachineModuleInfo &MMI = getAnalysis(); + MachineModuleInfo &MMI = + getAnalysis().getMMI(); MMI.deleteMachineFunctionFor(F); return true; } @@ -327,3 +331,36 @@ FunctionPass *llvm::createFreeMachineFunctionPass() { return new FreeMachineFunction(); } + +MachineModuleInfoWrapperPass::MachineModuleInfoWrapperPass( + const LLVMTargetMachine *TM) + : ImmutablePass(ID), MMI(TM) { + initializeMachineModuleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); +} + +// Handle the Pass registration stuff necessary to use DataLayout's. +INITIALIZE_PASS(MachineModuleInfoWrapperPass, "machinemoduleinfo", + "Machine Module Information", false, false) +char MachineModuleInfoWrapperPass::ID = 0; + +bool MachineModuleInfoWrapperPass::doInitialization(Module &M) { + MMI.initialize(); + MMI.TheModule = &M; + MMI.DbgInfoAvailable = !llvm::empty(M.debug_compile_units()); + return false; +} + +bool MachineModuleInfoWrapperPass::doFinalization(Module &M) { + MMI.finalize(); + return false; +} + +AnalysisKey MachineModuleAnalysis::Key; + +MachineModuleInfo MachineModuleAnalysis::run(Module &M, + ModuleAnalysisManager &) { + MachineModuleInfo MMI(TM); + MMI.TheModule = &M; + MMI.DbgInfoAvailable = !llvm::empty(M.debug_compile_units()); + return MMI; +} diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp --- a/llvm/lib/CodeGen/MachineOutliner.cpp +++ b/llvm/lib/CodeGen/MachineOutliner.cpp @@ -846,8 +846,8 @@ StringRef getPassName() const override { return "Machine Outliner"; } void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); AU.setPreservesAll(); ModulePass::getAnalysisUsage(AU); } @@ -1128,7 +1128,7 @@ IRBuilder<> Builder(EntryBB); Builder.CreateRetVoid(); - MachineModuleInfo &MMI = getAnalysis(); + MachineModuleInfo &MMI = getAnalysis().getMMI(); MachineFunction &MF = MMI.getOrCreateMachineFunction(*F); MachineBasicBlock &MBB = *MF.CreateMachineBasicBlock(); const TargetSubtargetInfo &STI = MF.getSubtarget(); @@ -1417,7 +1417,7 @@ if (M.empty()) return false; - MachineModuleInfo &MMI = getAnalysis(); + MachineModuleInfo &MMI = getAnalysis().getMMI(); // If the user passed -enable-machine-outliner=always or // -enable-machine-outliner, the pass will run on all functions in the module. diff --git a/llvm/lib/CodeGen/PassManager.cpp b/llvm/lib/CodeGen/PassManager.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/CodeGen/PassManager.cpp @@ -0,0 +1,92 @@ +//===-- PassManager.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/PassManager.h" + +using namespace llvm; + +namespace llvm { +template class AllAnalysesOn; +template class AnalysisManager; +template class PassManager; +template class InnerAnalysisManagerProxy; +template class OuterAnalysisManagerProxy; + +template <> +bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate( + Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv) { + // If literally everything is preserved, we're done. + if (PA.areAllPreserved()) + return false; // This is still a valid proxy. + + // Just assume that all proxies are valid for the time being until we run into trouble. + + // // 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 FAM has been completely updated to handle the deletion of functions. + // // Specifically, any FAM-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; + // } + + // // Directly check if the relevant set is preserved. + // bool AreFunctionAnalysesPreserved = + // PA.allAnalysesInSetPreserved>(); + + // // Now walk all the functions to see if any inner analysis invalidation is + // // necessary. + // for (Function &F : M) { + // Optional FunctionPA; + + // // Check to see whether the preserved set needs to be pruned based on + // // module-level analysis invalidation that triggers deferred invalidation + // // registered with the outer analysis manager proxy for this function. + // if (auto *OuterProxy = + // InnerAM->getCachedResult(F)) + // for (const auto &OuterInvalidationPair : + // OuterProxy->getOuterInvalidations()) { + // AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first; + // const auto &InnerAnalysisIDs = OuterInvalidationPair.second; + // if (Inv.invalidate(OuterAnalysisID, M, PA)) { + // if (!FunctionPA) + // FunctionPA = PA; + // for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs) + // FunctionPA->abandon(InnerAnalysisID); + // } + // } + + // // Check if we needed a custom PA set, and if so we'll need to run the + // // inner invalidation. + // if (FunctionPA) { + // InnerAM->invalidate(F, *FunctionPA); + // continue; + // } + + // // Otherwise we only need to do invalidation if the original PA set didn't + // // preserve all function analyses. + // if (!AreFunctionAnalysesPreserved) + // InnerAM->invalidate(F, PA); + // } + + // Return false to indicate that this result is still a valid proxy. + return false; +} +} // namespace llvm diff --git a/llvm/lib/CodeGen/UnreachableBlockElim.cpp b/llvm/lib/CodeGen/UnreachableBlockElim.cpp --- a/llvm/lib/CodeGen/UnreachableBlockElim.cpp +++ b/llvm/lib/CodeGen/UnreachableBlockElim.cpp @@ -103,7 +103,7 @@ df_iterator_default_set Reachable; bool ModifiedPHI = false; - MMI = getAnalysisIfAvailable(); + MMI = &getAnalysisIfAvailable()->getMMI(); MachineDominatorTree *MDT = getAnalysisIfAvailable(); MachineLoopInfo *MLI = getAnalysisIfAvailable(); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -51,6 +51,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/CodeGen/UnreachableBlockElim.h" #include "llvm/IR/Dominators.h" @@ -142,8 +143,8 @@ #include "llvm/Transforms/Scalar/LowerWidenableCondition.h" #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h" #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" -#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" #include "llvm/Transforms/Scalar/MergeICmps.h" +#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" #include "llvm/Transforms/Scalar/NaryReassociate.h" #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -312,3 +312,9 @@ }, parseLoopUnswitchOptions) #undef LOOP_PASS_WITH_PARAMS + +#ifndef MACHINE_FUNCTION_PASS +#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) +#endif +MACHINE_FUNCTION_PASS("machine-cp", MachineCopyPropagationPass()) +#undef MACHINE_FUNCTION_PASS diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp @@ -29,13 +29,14 @@ // except reserved size is not correctly aligned. const Function &F = MF.getFunction(); - if (auto *Resolver = MF.getMMI().getResolver()) { - if (AMDGPUPerfHintAnalysis *PHA = static_cast( - Resolver->getAnalysisIfAvailable(&AMDGPUPerfHintAnalysisID, true))) { - MemoryBound = PHA->isMemoryBound(&F); - WaveLimiter = PHA->needsWaveLimiter(&F); - } - } + // FIXME. How do we resolve this with the new PM? + // if (auto *Resolver = MF.getMMI().getResolver()) { + // if (AMDGPUPerfHintAnalysis *PHA = static_cast( + // Resolver->getAnalysisIfAvailable(&AMDGPUPerfHintAnalysisID, true))) { + // MemoryBound = PHA->isMemoryBound(&F); + // WaveLimiter = PHA->needsWaveLimiter(&F); + // } + // } CallingConv::ID CC = F.getCallingConv(); if (CC == CallingConv::AMDGPU_KERNEL || CC == CallingConv::SPIR_KERNEL) diff --git a/llvm/lib/Target/X86/X86InsertPrefetch.cpp b/llvm/lib/Target/X86/X86InsertPrefetch.cpp --- a/llvm/lib/Target/X86/X86InsertPrefetch.cpp +++ b/llvm/lib/Target/X86/X86InsertPrefetch.cpp @@ -173,7 +173,7 @@ void X86InsertPrefetch::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); } bool X86InsertPrefetch::runOnMachineFunction(MachineFunction &MF) { diff --git a/llvm/lib/Target/X86/X86RetpolineThunks.cpp b/llvm/lib/Target/X86/X86RetpolineThunks.cpp --- a/llvm/lib/Target/X86/X86RetpolineThunks.cpp +++ b/llvm/lib/Target/X86/X86RetpolineThunks.cpp @@ -58,8 +58,8 @@ void getAnalysisUsage(AnalysisUsage &AU) const override { MachineFunctionPass::getAnalysisUsage(AU); - AU.addRequired(); - AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); } private: @@ -97,7 +97,7 @@ TII = STI->getInstrInfo(); Is64Bit = TM->getTargetTriple().getArch() == Triple::x86_64; - MMI = &getAnalysis(); + MMI = &getAnalysis().getMMI(); Module &M = const_cast(*MMI->getModule()); // If this function is not a thunk, check to see if we need to insert diff --git a/llvm/tools/llc/CMakeLists.txt b/llvm/tools/llc/CMakeLists.txt --- a/llvm/tools/llc/CMakeLists.txt +++ b/llvm/tools/llc/CMakeLists.txt @@ -17,6 +17,7 @@ Target TransformUtils Vectorize + Passes ) # Support plugins. diff --git a/llvm/tools/llc/LLVMBuild.txt b/llvm/tools/llc/LLVMBuild.txt --- a/llvm/tools/llc/LLVMBuild.txt +++ b/llvm/tools/llc/LLVMBuild.txt @@ -18,4 +18,4 @@ type = Tool name = llc parent = Tools -required_libraries = AsmParser BitReader IRReader MIRParser TransformUtils Scalar Vectorize all-targets +required_libraries = AsmParser BitReader IRReader MIRParser TransformUtils Scalar Vectorize Passes all-targets diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -21,6 +21,7 @@ #include "llvm/CodeGen/MIRParser/MIRParser.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/PassManager.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/AutoUpgrade.h" @@ -36,6 +37,7 @@ #include "llvm/IRReader/IRReader.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Pass.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -52,6 +54,10 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/Cloning.h" #include + +// NEW PM MARKER +#include +#include using namespace llvm; // General options for llc. Other pass-specific options are specified @@ -157,6 +163,8 @@ namespace { static ManagedStatic> RunPassNames; +static ManagedStatic> RunNewPassNames; + struct RunPassOption { void operator=(const std::string &Val) const { if (Val.empty()) @@ -167,6 +175,17 @@ RunPassNames->push_back(PassName); } }; + +struct RunNewPassOption { + void operator=(const std::string &Val) const { + if (Val.empty()) + return; + SmallVector PassNames; + StringRef(Val).split(PassNames, ',', -1, false); + for (auto PassName : PassNames) + RunNewPassNames->push_back(PassName); + } +}; } static RunPassOption RunPassOpt; @@ -176,6 +195,15 @@ cl::desc("Run compiler only for specified passes (comma separated list)"), cl::value_desc("pass-name"), cl::ZeroOrMore, cl::location(RunPassOpt)); +static RunNewPassOption RunNewPassOpt; + +static cl::opt> RunNewPass( + "run-new-pass", + cl::desc( + "Run compiler only for specified new passes (comma separated list)"), + cl::value_desc("new-pass-name"), cl::ZeroOrMore, + cl::location(RunNewPassOpt)); + static int compileModule(char **, LLVMContext &); static std::unique_ptr GetOutputStream(const char *TargetName, @@ -370,6 +398,18 @@ return 0; } +static bool addNewPass(ModulePassManager &PM, const char *argv0, + StringRef PassName, TargetPassConfig &TPC) { + if (PassName == "none") + return false; + if (PassName == "machine-cp") + PM.addPass(createModuleToFunctionPassAdaptor( + createFunctionToMachineFunctionPassAdaptor(MachineCopyPropagationPass()))); + std::string Banner = std::string("After ") + std::string("machine-cp"); + TPC.printAndVerify(Banner); + return false; +} + static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName, TargetPassConfig &TPC) { if (PassName == "none") @@ -500,6 +540,36 @@ // Build up all of the passes that we want to do to the module. legacy::PassManager PM; + LLVMTargetMachine &LLVMTM = static_cast(*Target); + + PassInstrumentationCallbacks PIC; + PassBuilder PB(TheTarget->createTargetMachine( + TheTriple.getTriple(), CPUStr, FeaturesStr, Options, getRelocModel(), + getCodeModel(), OLvl)); + MachineFunctionAnalysisManager MFAM; + FunctionAnalysisManager FAM; + ModuleAnalysisManager MAM; + + PB.registerModuleAnalyses(MAM); + PB.registerFunctionAnalyses(FAM); + MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); }); + FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); }); + FAM.registerPass([&] { return MachineFunctionAnalysisManagerFunctionProxy(MFAM); }); + // MFAM.registerPass([&] { return FunctionAnalysisManagerMachineFunctionProxy(FAM); }); +#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + MFAM.registerPass([&] { return CREATE_PASS; }); + +#define FUNCTION_ANALYSIS_CODEGEN(NAME, CREATE_PASS) \ + FAM.registerPass([&] { return CREATE_PASS; }); + +#define MODULE_ANALYSIS_CODEGEN(NAME, CREATE_PASS) \ + MAM.registerPass([&] { return CREATE_PASS; }); + +#include "../../lib/Passes/PassRegistry.def" + + ModulePassManager MPM; + MachineFunctionPassManager MFPM; + // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple())); @@ -508,6 +578,11 @@ TLII.disableAllFunctions(); PM.add(new TargetLibraryInfoWrapperPass(TLII)); + FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); + MAM.registerPass([&] { return TargetLibraryAnalysis(TLII); }); + + MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); }); + // Add the target data from the target machine, if it exists, or the module. M->setDataLayout(Target->createDataLayout()); @@ -548,8 +623,10 @@ } const char *argv0 = argv[0]; - LLVMTargetMachine &LLVMTM = static_cast(*Target); - MachineModuleInfo *MMI = new MachineModuleInfo(&LLVMTM); + MachineModuleInfoWrapperPass *MMIWP = + new MachineModuleInfoWrapperPass(&LLVMTM); + + const bool UsingNewPM = !RunNewPassNames->empty(); // Construct a custom pass pipeline that starts after instruction // selection. @@ -569,18 +646,26 @@ TPC.setDisableVerify(NoVerify); PM.add(&TPC); - PM.add(MMI); + PM.add(MMIWP); TPC.printAndVerify(""); for (const std::string &RunPassName : *RunPassNames) { if (addPass(PM, argv0, RunPassName, TPC)) return 1; } + for (const std::string &RunPassName : *RunNewPassNames) { + if (addNewPass(MPM, argv0, RunPassName, TPC)) + return 1; + } TPC.setInitialized(); - PM.add(createPrintMIRPass(*OS)); + + if (UsingNewPM) + MPM.addPass(MIRPrintingPass(*OS)); + else + PM.add(createPrintMIRPass(*OS)); PM.add(createFreeMachineFunctionPass()); } else if (Target->addPassesToEmitFile(PM, *OS, DwoOut ? &DwoOut->os() : nullptr, - FileType, NoVerify, MMI)) { + FileType, NoVerify, MMIWP)) { WithColor::warning(errs(), argv[0]) << "target does not support generation of this" << " file type!\n"; @@ -588,8 +673,13 @@ } if (MIR) { - assert(MMI && "Forgot to create MMI?"); - if (MIR->parseMachineFunctions(*M, *MMI)) + assert(MMIWP && "Forgot to create MMIWP?"); + if (UsingNewPM) { + if (MIR->parseMachineFunctions( + *M, MAM.getResult(*M))) + return 1; + } else + if (MIR->parseMachineFunctions(*M, MMIWP->getMMI())) return 1; } @@ -608,6 +698,12 @@ Buffer.clear(); } + // Now that we have all of the passes ready, run them. + { + PrettyStackTraceString CrashInfo("Optimizer"); + MPM.run(*M, MAM); + } + PM.run(*M); auto HasError = diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp --- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp +++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp @@ -143,10 +143,10 @@ createModule(Context, TM.createDataLayout()); // TODO: This only works for targets implementing LLVMTargetMachine. const LLVMTargetMachine &LLVMTM = static_cast(TM); - std::unique_ptr MMI = - llvm::make_unique(&LLVMTM); - llvm::MachineFunction &MF = - createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get()); + std::unique_ptr MMIWP = + llvm::make_unique(&LLVMTM); + llvm::MachineFunction &MF = createVoidVoidPtrMachineFunction( + FunctionID, Module.get(), &MMIWP.get()->getMMI()); // Saving reserved registers for client. return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF); } @@ -161,10 +161,10 @@ llvm::make_unique(); std::unique_ptr Module = createModule(Context, TM->createDataLayout()); - std::unique_ptr MMI = - llvm::make_unique(TM.get()); - llvm::MachineFunction &MF = - createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get()); + std::unique_ptr MMIWP = + llvm::make_unique(TM.get()); + llvm::MachineFunction &MF = createVoidVoidPtrMachineFunction( + FunctionID, Module.get(), &MMIWP.get()->getMMI()); // We need to instruct the passes that we're done with SSA and virtual // registers. @@ -195,7 +195,7 @@ fillMachineFunction(MF, LiveIns, Code); // We create the pass manager, run the passes to populate AsmBuffer. - llvm::MCContext &MCContext = MMI->getContext(); + llvm::MCContext &MCContext = MMIWP->getMMI().getContext(); llvm::legacy::PassManager PM; llvm::TargetLibraryInfoImpl TLII(llvm::Triple(Module->getTargetTriple())); @@ -203,7 +203,7 @@ llvm::TargetPassConfig *TPC = TM->createPassConfig(PM); PM.add(TPC); - PM.add(MMI.release()); + PM.add(MMIWP.release()); TPC->printAndVerify("MachineFunctionGenerator::assemble"); // Add target-specific passes. ET.addTargetSpecificPasses(PM); diff --git a/llvm/unittests/MI/LiveIntervalTest.cpp b/llvm/unittests/MI/LiveIntervalTest.cpp --- a/llvm/unittests/MI/LiveIntervalTest.cpp +++ b/llvm/unittests/MI/LiveIntervalTest.cpp @@ -63,10 +63,10 @@ M->setDataLayout(TM.createDataLayout()); - MachineModuleInfo *MMI = new MachineModuleInfo(&TM); - if (MIR->parseMachineFunctions(*M, *MMI)) + MachineModuleInfoWrapperPass *MMIWP = new MachineModuleInfoWrapperPass(&TM); + if (MIR->parseMachineFunctions(*M, MMIWP->getMMI())) return nullptr; - PM.add(MMI); + PM.add(MMIWP); return M; }