Index: llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h +++ llvm/trunk/include/llvm/CodeGen/MIRYamlMapping.h @@ -385,6 +385,8 @@ unsigned Alignment = 0; bool ExposesReturnsTwice = false; bool HasInlineAsm = false; + // MachineFunctionProperties + bool AllVRegsAllocated = false; // Register information bool IsSSA = false; bool TracksRegLiveness = false; @@ -408,6 +410,7 @@ YamlIO.mapOptional("alignment", MF.Alignment); YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice); YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm); + YamlIO.mapOptional("allVRegsAllocated", MF.AllVRegsAllocated); YamlIO.mapOptional("isSSA", MF.IsSSA); YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness); YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness); Index: llvm/trunk/include/llvm/CodeGen/MachineFunction.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineFunction.h +++ llvm/trunk/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,63 @@ } }; +/// Properties which a MachineFunction may have at a given point in time. +/// Each of these has checking code in the MachineVerifier, and passes can +/// require that a property be set. +class MachineFunctionProperties { + // TODO: Add MachineVerifier checks for AllVRegsAllocated + // TODO: Add a way to print the properties and make more useful error messages + // Possible TODO: Allow targets to extend this (perhaps by allowing the + // constructor to specify the size of the bit vector) + // Possible TODO: Allow requiring the negative (e.g. VRegsAllocated could be + // stated as the negative of "has vregs" + + // Stated in "positive" form; i.e. a pass could require that the property + // hold, but not that it does not hold. + BitVector Properties = + BitVector(static_cast(Property::LastProperty)); + + 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 +212,10 @@ /// True if the function includes any inline assembly. bool HasInlineAsm = false; + /// Current high-level properties of the IR of the function (e.g. is in SSA + /// form or whether registers have been allocated) + MachineFunctionProperties Properties; + // Allocation management for pseudo source values. std::unique_ptr PSVManager; @@ -271,6 +333,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: llvm/trunk/include/llvm/CodeGen/MachineFunctionPass.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineFunctionPass.h +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/FuncletLayout.cpp =================================================================== --- llvm/trunk/lib/CodeGen/FuncletLayout.cpp +++ llvm/trunk/lib/CodeGen/FuncletLayout.cpp @@ -28,6 +28,10 @@ } bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } }; } Index: llvm/trunk/lib/CodeGen/ImplicitNullChecks.cpp =================================================================== --- llvm/trunk/lib/CodeGen/ImplicitNullChecks.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/LiveDebugValues.cpp =================================================================== --- llvm/trunk/lib/CodeGen/LiveDebugValues.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp +++ llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp @@ -285,6 +285,8 @@ MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); MF.setHasInlineAsm(YamlMF.HasInlineAsm); + if (YamlMF.AllVRegsAllocated) + MF.getProperties().set(MachineFunctionProperties::Property::AllVRegsAllocated); PerFunctionMIParsingState PFS; if (initializeRegisterInfo(MF, YamlMF, PFS)) return true; Index: llvm/trunk/lib/CodeGen/MIRPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRPrinter.cpp +++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp @@ -171,6 +171,9 @@ YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.HasInlineAsm = MF.hasInlineAsm(); + YamlMF.AllVRegsAllocated = MF.getProperties().hasProperty( + MachineFunctionProperties::Property::AllVRegsAllocated); + convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction()->getParent()); MST.incorporateFunction(*MF.getFunction()); Index: llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/MachineFunctionPass.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineFunctionPass.cpp +++ llvm/trunk/lib/CodeGen/MachineFunctionPass.cpp @@ -21,11 +21,13 @@ #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" + using namespace llvm; Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O, @@ -40,7 +42,16 @@ return false; MachineFunction &MF = getAnalysis().getMF(); - return runOnMachineFunction(MF); + MachineFunctionProperties &MFProps = MF.getProperties(); + + assert(MFProps.verifyRequiredProperties(RequiredProperties) && + "Properties required by the pass are not met by the function"); + + bool RV = runOnMachineFunction(MF); + + MFProps.set(SetProperties); + MFProps.clear(ClearedProperties); + return RV; } void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const { Index: llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp =================================================================== --- llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/RegAllocFast.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp =================================================================== --- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp +++ llvm/trunk/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: llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp =================================================================== --- llvm/trunk/lib/CodeGen/StackMapLivenessAnalysis.cpp +++ llvm/trunk/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: llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp +++ llvm/trunk/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: llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ llvm/trunk/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()); Index: llvm/trunk/test/CodeGen/MIR/AArch64/machine-dead-copy.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/AArch64/machine-dead-copy.mir +++ llvm/trunk/test/CodeGen/MIR/AArch64/machine-dead-copy.mir @@ -14,6 +14,7 @@ # CHECK: bb.0: # CHECK-NOT: %w20 = COPY name: copyprop1 +allVRegsAllocated: true body: | bb.0: liveins: %w0, %w1 @@ -28,6 +29,7 @@ # CHECK: bb.0: # CHECK: %w20 = COPY name: copyprop2 +allVRegsAllocated: true body: | bb.0: liveins: %w0, %w1 @@ -42,6 +44,7 @@ # CHECK: bb.0: # CHECK-NOT: COPY name: copyprop3 +allVRegsAllocated: true body: | bb.0: liveins: %w0, %w1 @@ -56,6 +59,7 @@ # CHECK: bb.0: # CHECK-NOT: COPY name: copyprop4 +allVRegsAllocated: true body: | bb.0: liveins: %w0, %w1 Index: llvm/trunk/test/CodeGen/MIR/ARM/sched-it-debug-nodes.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/ARM/sched-it-debug-nodes.mir +++ llvm/trunk/test/CodeGen/MIR/ARM/sched-it-debug-nodes.mir @@ -92,6 +92,7 @@ alignment: 1 exposesReturnsTwice: false hasInlineAsm: false +allVRegsAllocated: true isSSA: false tracksRegLiveness: true tracksSubRegLiveness: false Index: llvm/trunk/test/CodeGen/X86/machine-copy-prop.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/machine-copy-prop.mir +++ llvm/trunk/test/CodeGen/X86/machine-copy-prop.mir @@ -25,6 +25,7 @@ # CHECK-NOT: COPY # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop_remove_kill0 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rdi @@ -42,6 +43,7 @@ # CHECK-NOT: COPY # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop_remove_kill1 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rdi @@ -59,6 +61,7 @@ # CHECK-NOT: COPY # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop_remove_kill2 +allVRegsAllocated: true body: | bb.0: %ax = COPY %di @@ -76,6 +79,7 @@ # CHECK-NOT: COPY # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop0 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rdi @@ -92,6 +96,7 @@ # CHECK-NEXT: NOOP implicit %rax # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop1 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rdi @@ -108,6 +113,7 @@ # CHECK-NOT: %rax = COPY %rdi # CHECK-NEXT: NOOP implicit %rax, implicit %rdi name: copyprop2 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rdi @@ -126,6 +132,7 @@ # CHECK-NEXT: %rbp = COPY %rax # CHECK-NEXT: NOOP implicit %rax, implicit %rbp name: nocopyprop0 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rbp @@ -143,6 +150,7 @@ # CHECK-NEXT: %rax = COPY %rbp # CHECK-NEXT: NOOP implicit %rax, implicit %rbp name: nocopyprop1 +allVRegsAllocated: true body: | bb.0: %rbp = COPY %rax @@ -160,6 +168,7 @@ # CHECK-NEXT: %rax = COPY %rbp # CHECK-NEXT: NOOP implicit %rax, implicit %rbp name: nocopyprop2 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rbp @@ -177,6 +186,7 @@ # CHECK-NEXT: %rbp = COPY %rax # CHECK-NEXT: NOOP implicit %rax, implicit %rbp name: nocopyprop3 +allVRegsAllocated: true body: | bb.0: %rbp = COPY %rax @@ -193,6 +203,7 @@ # CHECK-NEXT: %rax = COPY %rip # CHECK-NEXT: NOOP implicit %rax name: nocopyprop4 +allVRegsAllocated: true body: | bb.0: %rax = COPY %rip @@ -208,6 +219,7 @@ # CHECK-NEXT: %rip = COPY %rax # CHECK-NEXT: %rip = COPY %rax name: nocopyprop5 +allVRegsAllocated: true body: | bb.0: %rip = COPY %rax Index: llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir =================================================================== --- llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir +++ llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values-3preds.mir @@ -159,6 +159,7 @@ alignment: 4 exposesReturnsTwice: false hasInlineAsm: false +allVRegsAllocated: true isSSA: false tracksRegLiveness: true tracksSubRegLiveness: false Index: llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values.mir =================================================================== --- llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values.mir +++ llvm/trunk/test/DebugInfo/MIR/X86/live-debug-values.mir @@ -161,6 +161,7 @@ alignment: 4 exposesReturnsTwice: false hasInlineAsm: false +allVRegsAllocated: true isSSA: false tracksRegLiveness: true tracksSubRegLiveness: false