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,58 @@ } }; +// 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::LastProperty)); + // 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: + // Property descriptions: + // IsSSA (currently unused, intended to eventually replace + // MachineRegisterInfo::isSSA()) + // TracksLiveness: (currently unsued, intended to eventually replace + // MachineRegisterInfo::tracksLiveness()) + // AllVRegsAllocated: All virtual registers have been allocated; i.e. all + // register operands are physical registers. + enum class Property : unsigned { + IsSSA, + TracksLiveness, + AllVRegsAllocated, + LastProperty, + }; + + 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 +207,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 +326,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 @@ -20,16 +20,24 @@ #define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H #include "llvm/Pass.h" +#include "llvm/CodeGen/MachineFunction.h" namespace llvm { -class MachineFunction; - /// MachineFunctionPass - This class adapts the FunctionPass interface to /// allow convenient creation of passes that operate on the MachineFunction /// representation. Instead of overriding runOnFunction, subclasses /// override runOnMachineFunction. class MachineFunctionPass : public FunctionPass { +public: + bool doInitialization(Module&) override { + // Cache the properties info at module-init time so we don't have to + // construct them for every function. + RequiredProperties = getRequiredProperties(); + SetProperties = getSetProperties(); + ClearedProperties = getClearedProperties(); + return false; + } protected: explicit MachineFunctionPass(char &ID) : FunctionPass(ID) {} @@ -46,7 +54,21 @@ /// void getAnalysisUsage(AnalysisUsage &AU) const override; + virtual MachineFunctionProperties getRequiredProperties() const { + return MachineFunctionProperties(); + } + virtual MachineFunctionProperties getSetProperties() const { + return MachineFunctionProperties(); + } + virtual MachineFunctionProperties getClearedProperties() const { + return MachineFunctionProperties(); + } + private: + MachineFunctionProperties RequiredProperties; + MachineFunctionProperties SetProperties; + MachineFunctionProperties ClearedProperties; + /// createPrinterPass - Get a machine function printer pass. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const override; Index: lib/CodeGen/FuncletLayout.cpp =================================================================== --- lib/CodeGen/FuncletLayout.cpp +++ lib/CodeGen/FuncletLayout.cpp @@ -28,6 +28,10 @@ } bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } }; } Index: lib/CodeGen/ImplicitNullChecks.cpp =================================================================== --- lib/CodeGen/ImplicitNullChecks.cpp +++ lib/CodeGen/ImplicitNullChecks.cpp @@ -106,6 +106,11 @@ } bool runOnMachineFunction(MachineFunction &MF) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } }; /// \brief Detect re-ordering hazards and dependencies. Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -99,6 +99,11 @@ /// information we preserve. void getAnalysisUsage(AnalysisUsage &AU) const override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + /// Print to ostream with a message. void printVarLocInMBB(const VarLocInMBB &V, const char *msg, raw_ostream &Out) const; Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -49,6 +49,11 @@ bool runOnMachineFunction(MachineFunction &MF) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + private: void ClobberRegister(unsigned Reg); void CopyPropagateBlock(MachineBasicBlock &MBB); Index: lib/CodeGen/MachineFunctionPass.cpp =================================================================== --- lib/CodeGen/MachineFunctionPass.cpp +++ lib/CodeGen/MachineFunctionPass.cpp @@ -21,11 +21,16 @@ #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" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "machine-function-pass" + using namespace llvm; Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, @@ -40,7 +45,15 @@ return false; MachineFunction &MF = getAnalysis().getMF(); - return runOnMachineFunction(MF); + MachineFunctionProperties &MFProps = MF.getProperties(); + + assert(MFProps.verifyRequiredProperties(RequiredProperties)); + + 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 @@ -96,6 +96,11 @@ MachineFunctionPass::getAnalysisUsage(AU); } + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + bool runOnMachineFunction(MachineFunction &Fn) override; bool enablePostRAScheduler( Index: lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- lib/CodeGen/PrologEpilogInserter.cpp +++ lib/CodeGen/PrologEpilogInserter.cpp @@ -59,6 +59,11 @@ void getAnalysisUsage(AnalysisUsage &AU) const override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + /// runOnMachineFunction - Insert prolog/epilog code and replace abstract /// frame indexes with appropriate references. /// Index: lib/CodeGen/RegAllocBasic.cpp =================================================================== --- lib/CodeGen/RegAllocBasic.cpp +++ lib/CodeGen/RegAllocBasic.cpp @@ -83,6 +83,11 @@ /// RABasic analysis usage. void getAnalysisUsage(AnalysisUsage &AU) const override; + MachineFunctionProperties getSetProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + void releaseMemory() override; Spiller &spiller() override { return *SpillerInstance; } Index: lib/CodeGen/RegAllocFast.cpp =================================================================== --- lib/CodeGen/RegAllocFast.cpp +++ lib/CodeGen/RegAllocFast.cpp @@ -52,6 +52,7 @@ static char ID; RAFast() : MachineFunctionPass(ID), StackSlotForVirtReg(-1), isBulkSpilling(false) {} + private: MachineFunction *MF; MachineRegisterInfo *MRI; @@ -159,6 +160,11 @@ MachineFunctionPass::getAnalysisUsage(AU); } + MachineFunctionProperties getSetProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + private: bool runOnMachineFunction(MachineFunction &Fn) override; void AllocateBasicBlock(); Index: lib/CodeGen/RegAllocGreedy.cpp =================================================================== --- lib/CodeGen/RegAllocGreedy.cpp +++ lib/CodeGen/RegAllocGreedy.cpp @@ -322,6 +322,10 @@ /// RAGreedy analysis usage. void getAnalysisUsage(AnalysisUsage &AU) const override; + MachineFunctionProperties getSetProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } void releaseMemory() override; Spiller &spiller() override { return *SpillerInstance; } void enqueue(LiveInterval *LI) override; Index: lib/CodeGen/RegAllocPBQP.cpp =================================================================== --- lib/CodeGen/RegAllocPBQP.cpp +++ lib/CodeGen/RegAllocPBQP.cpp @@ -106,6 +106,11 @@ /// PBQP analysis usage. void getAnalysisUsage(AnalysisUsage &au) const override; + MachineFunctionProperties getSetProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + /// Perform register allocation bool runOnMachineFunction(MachineFunction &MF) override; Index: lib/CodeGen/StackMapLivenessAnalysis.cpp =================================================================== --- lib/CodeGen/StackMapLivenessAnalysis.cpp +++ lib/CodeGen/StackMapLivenessAnalysis.cpp @@ -62,6 +62,11 @@ /// information we preserve. void getAnalysisUsage(AnalysisUsage &AU) const override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + /// \brief Calculate the liveness information for the given machine function. bool runOnMachineFunction(MachineFunction &MF) override; 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());