Index: include/llvm/CodeGen/MachineFunction.h =================================================================== --- include/llvm/CodeGen/MachineFunction.h +++ include/llvm/CodeGen/MachineFunction.h @@ -18,6 +18,7 @@ #ifndef LLVM_CODEGEN_MACHINEFUNCTION_H #define LLVM_CODEGEN_MACHINEFUNCTION_H +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/DebugLoc.h" @@ -88,6 +89,51 @@ } }; +// Properties which a MachineFunction may have at a given point in time +// TODO: Allow targets to extend this? Or is MachineFunctionInfo enough? +// Each of these has checking code in the MachineVerifier, and passes can +// require that a property be set. +class MachineFunctionProperties { + BitVector Properties = + BitVector(static_cast(Property::kLastProperty)); + // Stated in "positive" form; i.e. a pass could require that the property + // hold, but not that it does not hold. + // TODO: does it make sense to allow requiring the negative? kVRegsAllocated + // could be stated as the negative of "has vregs" + public: + enum class Property : unsigned { + kIsSSA, + kTracksLiveness, + kAllVRegsAllocated, + kLastProperty, + }; + + bool hasProperty(Property P) const { + return Properties[static_cast(P)]; + } + MachineFunctionProperties &set(Property P) { + Properties.set(static_cast(P)); + return *this; + } + MachineFunctionProperties &clear(Property P) { + Properties.reset(static_cast(P)); + return *this; + } + MachineFunctionProperties &set(const MachineFunctionProperties &MFP) { + Properties |= MFP.Properties; + return *this; + } + MachineFunctionProperties &clear(const MachineFunctionProperties &MFP) { + Properties.reset(MFP.Properties); + return *this; + } + // Returns true if all properties set in V (i.e. required by a pass) are set + // in this. + bool verifyRequiredProperties(const MachineFunctionProperties &V) const { + return !V.Properties.test(Properties); + } +}; + class MachineFunction { const Function *Fn; const TargetMachine &Target; @@ -154,6 +200,8 @@ /// True if the function includes any inline assembly. bool HasInlineAsm = false; + MachineFunctionProperties Properties; + // Allocation management for pseudo source values. std::unique_ptr PSVManager; @@ -271,6 +319,10 @@ HasInlineAsm = B; } + /// Get the function properties + const MachineFunctionProperties &getProperties() const { return Properties; } + MachineFunctionProperties &getProperties() { return Properties; } + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// Index: include/llvm/CodeGen/MachineFunctionPass.h =================================================================== --- include/llvm/CodeGen/MachineFunctionPass.h +++ include/llvm/CodeGen/MachineFunctionPass.h @@ -24,6 +24,7 @@ namespace llvm { class MachineFunction; +class MachineFunctionProperties; /// MachineFunctionPass - This class adapts the FunctionPass interface to /// allow convenient creation of passes that operate on the MachineFunction @@ -31,27 +32,43 @@ /// override runOnMachineFunction. class MachineFunctionPass : public FunctionPass { protected: - explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {} + explicit MachineFunctionPass(char &ID); + virtual ~MachineFunctionPass(); - /// runOnMachineFunction - This method must be overloaded to perform the - /// desired machine code transformation or analysis. - /// - virtual bool runOnMachineFunction(MachineFunction &MF) = 0; + /// runOnMachineFunction - This method must be overloaded to perform the + /// desired machine code transformation or analysis. + /// + virtual bool runOnMachineFunction(MachineFunction &MF) = 0; - /// getAnalysisUsage - Subclasses that override getAnalysisUsage - /// must call this. - /// - /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that - /// the pass does not modify the MachineBasicBlock CFG. - /// - void getAnalysisUsage(AnalysisUsage &AU) const override; + /// getAnalysisUsage - Subclasses that override getAnalysisUsage + /// must call this. + /// + /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that + /// the pass does not modify the MachineBasicBlock CFG. + /// + void getAnalysisUsage(AnalysisUsage &AU) const override; + + // Properties are stored as pointers here and implemented in the cpp file to + // avoid including all of MachineFunction.h + // XXX: if this is too ugly, move MFP to its own header. + MachineFunctionProperties &getRequiredProperties() { + return *RequiredProperties; + } + MachineFunctionProperties &getSetProperties() { return *SetProperties; } + MachineFunctionProperties &getClearedProperties() { + return *ClearedProperties; + } private: - /// createPrinterPass - Get a machine function printer pass. - Pass *createPrinterPass(raw_ostream &O, - const std::string &Banner) const override; + MachineFunctionProperties *RequiredProperties = nullptr; + MachineFunctionProperties *SetProperties = nullptr; + MachineFunctionProperties *ClearedProperties = nullptr; + + /// createPrinterPass - Get a machine function printer pass. + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; - bool runOnFunction(Function &F) override; + bool runOnFunction(Function &F) override; }; } // End llvm namespace Index: lib/CodeGen/FuncletLayout.cpp =================================================================== --- lib/CodeGen/FuncletLayout.cpp +++ lib/CodeGen/FuncletLayout.cpp @@ -25,6 +25,8 @@ static char ID; // Pass identification, replacement for typeid FuncletLayout() : MachineFunctionPass(ID) { initializeFuncletLayoutPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } bool runOnMachineFunction(MachineFunction &F) override; Index: lib/CodeGen/ImplicitNullChecks.cpp =================================================================== --- lib/CodeGen/ImplicitNullChecks.cpp +++ lib/CodeGen/ImplicitNullChecks.cpp @@ -103,6 +103,8 @@ ImplicitNullChecks() : MachineFunctionPass(ID) { initializeImplicitNullChecksPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } bool runOnMachineFunction(MachineFunction &MF) override; Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -119,6 +119,8 @@ /// Default construct and initialize the pass. LiveDebugValues::LiveDebugValues() : MachineFunctionPass(ID) { initializeLiveDebugValuesPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } /// Tell the pass manager which passes we depend on and what information we Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -45,6 +45,8 @@ static char ID; // Pass identification, replacement for typeid MachineCopyPropagation() : MachineFunctionPass(ID) { initializeMachineCopyPropagationPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } bool runOnMachineFunction(MachineFunction &MF) override; Index: lib/CodeGen/MachineFunctionPass.cpp =================================================================== --- lib/CodeGen/MachineFunctionPass.cpp +++ lib/CodeGen/MachineFunctionPass.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionAnalysis.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/StackProtector.h" @@ -28,6 +29,18 @@ #include "llvm/IR/Function.h" using namespace llvm; +MachineFunctionPass::MachineFunctionPass(char &ID) + : FunctionPass(ID), + RequiredProperties(new MachineFunctionProperties()), + SetProperties(new MachineFunctionProperties), + ClearedProperties(new MachineFunctionProperties) {} + +MachineFunctionPass::~MachineFunctionPass() { + delete RequiredProperties; + delete SetProperties; + delete ClearedProperties; +} + Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, const std::string &Banner) const { return createMachineFunctionPrinterPass(O, Banner); @@ -40,7 +53,14 @@ return false; MachineFunction &MF = getAnalysis().getMF(); - return runOnMachineFunction(MF); + MachineFunctionProperties &MFProps = MF.getProperties(); + assert(MFProps.verifyRequiredProperties(getRequiredProperties())); + + bool rv = runOnMachineFunction(MF); + + MFProps.set(*SetProperties); + MFProps.clear(*ClearedProperties); + return rv; } void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { Index: lib/CodeGen/PostRASchedulerList.cpp =================================================================== --- lib/CodeGen/PostRASchedulerList.cpp +++ lib/CodeGen/PostRASchedulerList.cpp @@ -83,7 +83,10 @@ public: static char ID; - PostRAScheduler() : MachineFunctionPass(ID) {} + PostRAScheduler() : MachineFunctionPass(ID) { + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); + } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -55,6 +55,8 @@ static char ID; PEI() : MachineFunctionPass(ID) { initializePEIPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } void getAnalysisUsage(AnalysisUsage &AU) const override; Index: lib/CodeGen/RegAllocBasic.cpp =================================================================== --- lib/CodeGen/RegAllocBasic.cpp +++ lib/CodeGen/RegAllocBasic.cpp @@ -129,6 +129,8 @@ initializeMachineLoopInfoPass(*PassRegistry::getPassRegistry()); initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry()); + getSetProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } void RABasic::getAnalysisUsage(AnalysisUsage &AU) const { Index: lib/CodeGen/RegAllocFast.cpp =================================================================== --- lib/CodeGen/RegAllocFast.cpp +++ lib/CodeGen/RegAllocFast.cpp @@ -50,9 +50,15 @@ class RAFast : public MachineFunctionPass { public: static char ID; - RAFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1), - isBulkSpilling(false) {} - private: + RAFast() + : MachineFunctionPass(ID), + StackSlotForVirtReg(-1), + isBulkSpilling(false) { + getSetProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); + } + + private: MachineFunction *MF; MachineRegisterInfo *MRI; const TargetRegisterInfo *TRI; Index: lib/CodeGen/RegAllocGreedy.cpp =================================================================== --- lib/CodeGen/RegAllocGreedy.cpp +++ lib/CodeGen/RegAllocGreedy.cpp @@ -455,6 +455,8 @@ initializeLiveRegMatrixPass(*PassRegistry::getPassRegistry()); initializeEdgeBundlesPass(*PassRegistry::getPassRegistry()); initializeSpillPlacementPass(*PassRegistry::getPassRegistry()); + getSetProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const { Index: lib/CodeGen/RegAllocPBQP.cpp =================================================================== --- lib/CodeGen/RegAllocPBQP.cpp +++ lib/CodeGen/RegAllocPBQP.cpp @@ -96,6 +96,8 @@ initializeLiveIntervalsPass(*PassRegistry::getPassRegistry()); initializeLiveStacksPass(*PassRegistry::getPassRegistry()); initializeVirtRegMapPass(*PassRegistry::getPassRegistry()); + getSetProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } /// Return the pass name. Index: lib/CodeGen/StackMapLivenessAnalysis.cpp =================================================================== --- lib/CodeGen/StackMapLivenessAnalysis.cpp +++ lib/CodeGen/StackMapLivenessAnalysis.cpp @@ -86,6 +86,8 @@ /// Default construct and initialize the pass. StackMapLiveness::StackMapLiveness() : MachineFunctionPass(ID) { initializeStackMapLivenessPass(*PassRegistry::getPassRegistry()); + getRequiredProperties().set( + MachineFunctionProperties::Property::kAllVRegsAllocated); } /// Tell the pass manager which passes we depend on and what information we Index: lib/Target/NVPTX/NVPTXTargetMachine.cpp =================================================================== --- lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ lib/Target/NVPTX/NVPTXTargetMachine.cpp @@ -223,6 +223,10 @@ disablePass(&PrologEpilogCodeInserterID); disablePass(&MachineCopyPropagationID); disablePass(&TailDuplicateID); + disablePass(&StackMapLivenessID); + disablePass(&LiveDebugValuesID); + disablePass(&PostRASchedulerID); + disablePass(&FuncletLayoutID); addPass(createNVVMReflectPass()); if (getOptLevel() != CodeGenOpt::None) Index: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -106,6 +106,8 @@ bool addILPOpts() override; void addPreRegAlloc() override; void addPostRegAlloc() override; + void addMachineLateOptimization() override; + bool addGCPasses() override { return false; } void addPreEmitPass() override; }; } // end anonymous namespace @@ -179,6 +181,9 @@ // virtual registers. Consider removing their restrictions and re-enabling // them. // + + // Has no asserts of its own, but was not written to handle virtual regs. + disablePass(&ShrinkWrapID); // We use our own PrologEpilogInserter which is very slightly modified to // tolerate virtual registers. disablePass(&PrologEpilogCodeInserterID); @@ -201,11 +206,20 @@ addPass(createWebAssemblyPEI()); } +void WebAssemblyPassConfig::addMachineLateOptimization() { + disablePass(&MachineCopyPropagationID); + disablePass(&PostRASchedulerID); + TargetPassConfig::addMachineLateOptimization(); +} + void WebAssemblyPassConfig::addPreEmitPass() { TargetPassConfig::addPreEmitPass(); // Eliminate multiple-entry loops. addPass(createWebAssemblyFixIrreducibleControlFlow()); + disablePass(&FuncletLayoutID); + disablePass(&StackMapLivenessID); + disablePass(&LiveDebugValuesID); // Put the CFG in structured form; insert BLOCK and LOOP markers. addPass(createWebAssemblyCFGStackify());