Index: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h +++ llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h @@ -657,6 +657,13 @@ /// selection and constraining of all generic virtual registers). void clearVirtRegTypes(); + /// Creates a new virtual register that has no register class, register bank + /// or size assigned yet. This is only allowed to be used + /// temporarily while constructing machine instructions. Most operations are + /// undefined on an incomplete register until one of setRegClass(), + /// setRegBank() or setSize() has been called on it. + unsigned createIncompleteVirtualRegister(); + /// getNumVirtRegs - Return the number of virtual registers created. /// unsigned getNumVirtRegs() const { return VRegInfo.size(); } Index: llvm/trunk/lib/CodeGen/MIRParser/MIParser.h =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIParser.h +++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.h @@ -26,26 +26,42 @@ class MachineInstr; class MachineRegisterInfo; class MDNode; +class RegisterBank; struct SlotMapping; class SMDiagnostic; class SourceMgr; +class TargetRegisterClass; + +struct VRegInfo { + enum uint8_t { + UNKNOWN, NORMAL, GENERIC, REGBANK + } Kind = UNKNOWN; + bool Explicit = false; ///< VReg was explicitly specified in the .mir file. + union { + const TargetRegisterClass *RC; + const RegisterBank *RegBank; + } D; + unsigned VReg; + unsigned PreferredReg = 0; +}; struct PerFunctionMIParsingState { + BumpPtrAllocator Allocator; MachineFunction &MF; SourceMgr *SM; const SlotMapping &IRSlots; DenseMap MBBSlots; - DenseMap VirtualRegisterSlots; + DenseMap VRegInfos; DenseMap FixedStackObjectSlots; DenseMap StackObjectSlots; DenseMap ConstantPoolSlots; DenseMap JumpTableSlots; - /// Hold the generic virtual registers. - SmallSet GenericVRegs; PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, const SlotMapping &IRSlots); + + VRegInfo &getVRegInfo(unsigned VReg); }; /// Parse the machine basic block definitions, and skip the machine @@ -73,26 +89,25 @@ /// on the given source string. /// /// Return true if an error occurred. -bool parseMachineInstructions(const PerFunctionMIParsingState &PFS, - StringRef Src, SMDiagnostic &Error); +bool parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src, + SMDiagnostic &Error); -bool parseMBBReference(const PerFunctionMIParsingState &PFS, +bool parseMBBReference(PerFunctionMIParsingState &PFS, MachineBasicBlock *&MBB, StringRef Src, SMDiagnostic &Error); -bool parseNamedRegisterReference(const PerFunctionMIParsingState &PFS, - unsigned &Reg, StringRef Src, - SMDiagnostic &Error); +bool parseNamedRegisterReference(PerFunctionMIParsingState &PFS, unsigned &Reg, + StringRef Src, SMDiagnostic &Error); -bool parseVirtualRegisterReference(const PerFunctionMIParsingState &PFS, - unsigned &Reg, StringRef Src, +bool parseVirtualRegisterReference(PerFunctionMIParsingState &PFS, + VRegInfo *&Info, StringRef Src, SMDiagnostic &Error); -bool parseStackObjectReference(const PerFunctionMIParsingState &PFS, - int &FI, StringRef Src, SMDiagnostic &Error); +bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI, + StringRef Src, SMDiagnostic &Error); -bool parseMDNode(const PerFunctionMIParsingState &PFS, MDNode *&Node, - StringRef Src, SMDiagnostic &Error); +bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, + SMDiagnostic &Error); } // end namespace llvm Index: llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp +++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp @@ -44,6 +44,17 @@ : MF(MF), SM(&SM), IRSlots(IRSlots) { } +VRegInfo &PerFunctionMIParsingState::getVRegInfo(unsigned Num) { + auto I = VRegInfos.insert(std::make_pair(Num, nullptr)); + if (I.second) { + MachineRegisterInfo &MRI = MF.getRegInfo(); + VRegInfo *Info = new (Allocator) VRegInfo; + Info->VReg = MRI.createIncompleteVirtualRegister(); + I.first->second = Info; + } + return *I.first->second; +} + namespace { /// A wrapper struct around the 'MachineOperand' struct that includes a source @@ -68,7 +79,7 @@ SMDiagnostic &Error; StringRef Source, CurrentSource; MIToken Token; - const PerFunctionMIParsingState &PFS; + PerFunctionMIParsingState &PFS; /// Maps from instruction names to op codes. StringMap Names2InstrOpCodes; /// Maps from register names to registers. @@ -89,7 +100,7 @@ StringMap Names2BitmaskTargetFlags; public: - MIParser(const PerFunctionMIParsingState &PFS, SMDiagnostic &Error, + MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error, StringRef Source); /// \p SkipChar gives the number of characters to skip before looking @@ -112,7 +123,7 @@ bool parse(MachineInstr *&MI); bool parseStandaloneMBB(MachineBasicBlock *&MBB); bool parseStandaloneNamedRegister(unsigned &Reg); - bool parseStandaloneVirtualRegister(unsigned &Reg); + bool parseStandaloneVirtualRegister(VRegInfo *&Info); bool parseStandaloneStackObject(int &FI); bool parseStandaloneMDNode(MDNode *&Node); @@ -122,7 +133,9 @@ bool parseBasicBlockLiveins(MachineBasicBlock &MBB); bool parseBasicBlockSuccessors(MachineBasicBlock &MBB); - bool parseRegister(unsigned &Reg); + bool parseNamedRegister(unsigned &Reg); + bool parseVirtualRegister(VRegInfo *&Info); + bool parseRegister(unsigned &Reg, VRegInfo *&VRegInfo); bool parseRegisterFlag(unsigned &Flags); bool parseSubRegisterIndex(unsigned &SubReg); bool parseRegisterTiedDefIndex(unsigned &TiedDefIdx); @@ -255,7 +268,7 @@ } // end anonymous namespace -MIParser::MIParser(const PerFunctionMIParsingState &PFS, SMDiagnostic &Error, +MIParser::MIParser(PerFunctionMIParsingState &PFS, SMDiagnostic &Error, StringRef Source) : MF(PFS.MF), Error(Error), Source(Source), CurrentSource(Source), PFS(PFS) {} @@ -438,7 +451,7 @@ if (Token.isNot(MIToken::NamedRegister)) return error("expected a named register"); unsigned Reg = 0; - if (parseRegister(Reg)) + if (parseNamedRegister(Reg)) return true; MBB.addLiveIn(Reg); lex(); @@ -683,7 +696,7 @@ lex(); if (Token.isNot(MIToken::NamedRegister)) return error("expected a named register"); - if (parseRegister(Reg)) + if (parseNamedRegister(Reg)) return true; lex(); if (Token.isNot(MIToken::Eof)) @@ -691,11 +704,11 @@ return false; } -bool MIParser::parseStandaloneVirtualRegister(unsigned &Reg) { +bool MIParser::parseStandaloneVirtualRegister(VRegInfo *&Info) { lex(); if (Token.isNot(MIToken::VirtualRegister)) return error("expected a virtual register"); - if (parseRegister(Reg)) + if (parseVirtualRegister(Info)) return true; lex(); if (Token.isNot(MIToken::Eof)) @@ -791,33 +804,39 @@ return false; } -bool MIParser::parseRegister(unsigned &Reg) { +bool MIParser::parseNamedRegister(unsigned &Reg) { + assert(Token.is(MIToken::NamedRegister) && "Needs NamedRegister token"); + StringRef Name = Token.stringValue(); + if (getRegisterByName(Name, Reg)) + return error(Twine("unknown register name '") + Name + "'"); + return false; +} + +bool MIParser::parseVirtualRegister(VRegInfo *&Info) { + assert(Token.is(MIToken::VirtualRegister) && "Needs VirtualRegister token"); + unsigned ID; + if (getUnsigned(ID)) + return true; + Info = &PFS.getVRegInfo(ID); + return false; +} + +bool MIParser::parseRegister(unsigned &Reg, VRegInfo *&Info) { switch (Token.kind()) { case MIToken::underscore: Reg = 0; - break; - case MIToken::NamedRegister: { - StringRef Name = Token.stringValue(); - if (getRegisterByName(Name, Reg)) - return error(Twine("unknown register name '") + Name + "'"); - break; - } - case MIToken::VirtualRegister: { - unsigned ID; - if (getUnsigned(ID)) - return true; - const auto RegInfo = PFS.VirtualRegisterSlots.find(ID); - if (RegInfo == PFS.VirtualRegisterSlots.end()) - return error(Twine("use of undefined virtual register '%") + Twine(ID) + - "'"); - Reg = RegInfo->second; - break; - } + return false; + case MIToken::NamedRegister: + return parseNamedRegister(Reg); + case MIToken::VirtualRegister: + if (parseVirtualRegister(Info)) + return true; + Reg = Info->VReg; + return false; // TODO: Parse other register kinds. default: llvm_unreachable("The current token should be a register"); } - return false; } bool MIParser::parseRegisterFlag(unsigned &Flags) { @@ -927,7 +946,6 @@ bool MIParser::parseRegisterOperand(MachineOperand &Dest, Optional &TiedDefIdx, bool IsDef) { - unsigned Reg; unsigned Flags = IsDef ? RegState::Define : 0; while (Token.isRegisterFlag()) { if (parseRegisterFlag(Flags)) @@ -935,7 +953,9 @@ } if (!Token.isRegister()) return error("expected a register after register flags"); - if (parseRegister(Reg)) + unsigned Reg; + VRegInfo *RegInfo; + if (parseRegister(Reg, RegInfo)) return true; lex(); unsigned SubReg = 0; @@ -984,11 +1004,13 @@ return error("inconsistent type for generic virtual register"); MRI.setType(Reg, Ty); - } else if (PFS.GenericVRegs.count(Reg)) { + } else if (TargetRegisterInfo::isVirtualRegister(Reg)) { // Generic virtual registers must have a size. // If we end up here this means the size hasn't been specified and // this is bad! - return error("generic virtual registers must have a size"); + if (RegInfo->Kind == VRegInfo::GENERIC || + RegInfo->Kind == VRegInfo::REGBANK) + return error("generic virtual registers must have a size"); } Dest = MachineOperand::CreateReg( Reg, Flags & RegState::Define, Flags & RegState::Implicit, @@ -1305,7 +1327,7 @@ if (Token.isNot(MIToken::NamedRegister)) return error("expected a cfi register"); unsigned LLVMReg; - if (parseRegister(LLVMReg)) + if (parseNamedRegister(LLVMReg)) return true; const auto *TRI = MF.getSubtarget().getRegisterInfo(); assert(TRI && "Expected target register info"); @@ -1540,8 +1562,8 @@ while (true) { if (Token.isNot(MIToken::NamedRegister)) return error("expected a named register"); - unsigned Reg = 0; - if (parseRegister(Reg)) + unsigned Reg; + if (parseNamedRegister(Reg)) return true; lex(); Mask[Reg / 32] |= 1U << (Reg % 32); @@ -2166,36 +2188,36 @@ return MIParser(PFS, Error, Src).parseBasicBlockDefinitions(PFS.MBBSlots); } -bool llvm::parseMachineInstructions(const PerFunctionMIParsingState &PFS, +bool llvm::parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseBasicBlocks(); } -bool llvm::parseMBBReference(const PerFunctionMIParsingState &PFS, +bool llvm::parseMBBReference(PerFunctionMIParsingState &PFS, MachineBasicBlock *&MBB, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseStandaloneMBB(MBB); } -bool llvm::parseNamedRegisterReference(const PerFunctionMIParsingState &PFS, +bool llvm::parseNamedRegisterReference(PerFunctionMIParsingState &PFS, unsigned &Reg, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseStandaloneNamedRegister(Reg); } -bool llvm::parseVirtualRegisterReference(const PerFunctionMIParsingState &PFS, - unsigned &Reg, StringRef Src, +bool llvm::parseVirtualRegisterReference(PerFunctionMIParsingState &PFS, + VRegInfo *&Info, StringRef Src, SMDiagnostic &Error) { - return MIParser(PFS, Error, Src).parseStandaloneVirtualRegister(Reg); + return MIParser(PFS, Error, Src).parseStandaloneVirtualRegister(Info); } -bool llvm::parseStackObjectReference(const PerFunctionMIParsingState &PFS, +bool llvm::parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseStandaloneStackObject(FI); } -bool llvm::parseMDNode(const PerFunctionMIParsingState &PFS, +bool llvm::parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src, SMDiagnostic &Error) { return MIParser(PFS, Error, Src).parseStandaloneMDNode(Node); } Index: llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp +++ llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp @@ -102,10 +102,10 @@ /// Return true if error occurred. bool initializeMachineFunction(MachineFunction &MF); - bool initializeRegisterInfo(PerFunctionMIParsingState &PFS, - const yaml::MachineFunction &YamlMF); + bool parseRegisterInfo(PerFunctionMIParsingState &PFS, + const yaml::MachineFunction &YamlMF); - void inferRegisterInfo(const PerFunctionMIParsingState &PFS, + bool setupRegisterInfo(const PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF); bool initializeFrameInfo(PerFunctionMIParsingState &PFS, @@ -128,10 +128,10 @@ const yaml::MachineJumpTable &YamlJTI); private: - bool parseMDNode(const PerFunctionMIParsingState &PFS, MDNode *&Node, + bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, const yaml::StringValue &Source); - bool parseMBBReference(const PerFunctionMIParsingState &PFS, + bool parseMBBReference(PerFunctionMIParsingState &PFS, MachineBasicBlock *&MBB, const yaml::StringValue &Source); @@ -339,7 +339,7 @@ MF.getProperties().set(MachineFunctionProperties::Property::Selected); PerFunctionMIParsingState PFS(MF, SM, IRSlots); - if (initializeRegisterInfo(PFS, YamlMF)) + if (parseRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); @@ -389,19 +389,17 @@ } PFS.SM = &SM; - inferRegisterInfo(PFS, YamlMF); + if (setupRegisterInfo(PFS, YamlMF)) + return true; computeFunctionProperties(MF); - // FIXME: This is a temporary workaround until the reserved registers can be - // serialized. - MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; } -bool MIRParserImpl::initializeRegisterInfo(PerFunctionMIParsingState &PFS, - const yaml::MachineFunction &YamlMF) { +bool MIRParserImpl::parseRegisterInfo(PerFunctionMIParsingState &PFS, + const yaml::MachineFunction &YamlMF) { MachineFunction &MF = PFS.MF; MachineRegisterInfo &RegInfo = MF.getRegInfo(); assert(RegInfo.tracksLiveness()); @@ -411,39 +409,39 @@ SMDiagnostic Error; // Parse the virtual register information. for (const auto &VReg : YamlMF.VirtualRegisters) { - unsigned Reg; + VRegInfo &Info = PFS.getVRegInfo(VReg.ID.Value); + if (Info.Explicit) + return error(VReg.ID.SourceRange.Start, + Twine("redefinition of virtual register '%") + + Twine(VReg.ID.Value) + "'"); + Info.Explicit = true; + if (StringRef(VReg.Class.Value).equals("_")) { - // This is a generic virtual register. - // The size will be set appropriately when we reach the definition. - Reg = RegInfo.createGenericVirtualRegister(LLT{}); - PFS.GenericVRegs.insert(Reg); + Info.Kind = VRegInfo::GENERIC; } else { const auto *RC = getRegClass(MF, VReg.Class.Value); if (RC) { - Reg = RegInfo.createVirtualRegister(RC); + Info.Kind = VRegInfo::NORMAL; + Info.D.RC = RC; } else { - const auto *RegBank = getRegBank(MF, VReg.Class.Value); + const RegisterBank *RegBank = getRegBank(MF, VReg.Class.Value); if (!RegBank) return error( VReg.Class.SourceRange.Start, Twine("use of undefined register class or register bank '") + VReg.Class.Value + "'"); - Reg = RegInfo.createGenericVirtualRegister(LLT{}); - RegInfo.setRegBank(Reg, *RegBank); - PFS.GenericVRegs.insert(Reg); + Info.Kind = VRegInfo::REGBANK; + Info.D.RegBank = RegBank; } } - if (!PFS.VirtualRegisterSlots.insert(std::make_pair(VReg.ID.Value, Reg)) - .second) - return error(VReg.ID.SourceRange.Start, - Twine("redefinition of virtual register '%") + - Twine(VReg.ID.Value) + "'"); + if (!VReg.PreferredRegister.Value.empty()) { - unsigned PreferredReg = 0; - if (parseNamedRegisterReference(PFS, PreferredReg, + if (Info.Kind != VRegInfo::NORMAL) + return error(VReg.Class.SourceRange.Start, + Twine("preferred register can only be set for normal vregs")); + if (parseNamedRegisterReference(PFS, Info.PreferredReg, VReg.PreferredRegister.Value, Error)) return error(Error, VReg.PreferredRegister.SourceRange); - RegInfo.setSimpleHint(Reg, PreferredReg); } } @@ -454,9 +452,11 @@ return error(Error, LiveIn.Register.SourceRange); unsigned VReg = 0; if (!LiveIn.VirtualRegister.Value.empty()) { - if (parseVirtualRegisterReference(PFS, VReg, LiveIn.VirtualRegister.Value, + VRegInfo *Info; + if (parseVirtualRegisterReference(PFS, Info, LiveIn.VirtualRegister.Value, Error)) return error(Error, LiveIn.VirtualRegister.SourceRange); + VReg = Info->VReg; } RegInfo.addLiveIn(Reg, VReg); } @@ -475,20 +475,51 @@ return false; } -void MIRParserImpl::inferRegisterInfo(const PerFunctionMIParsingState &PFS, +bool MIRParserImpl::setupRegisterInfo(const PerFunctionMIParsingState &PFS, const yaml::MachineFunction &YamlMF) { - if (YamlMF.CalleeSavedRegisters) - return; - MachineRegisterInfo &MRI = PFS.MF.getRegInfo(); - for (const MachineBasicBlock &MBB : PFS.MF) { - for (const MachineInstr &MI : MBB) { - for (const MachineOperand &MO : MI.operands()) { - if (!MO.isRegMask()) - continue; - MRI.addPhysRegsUsedFromRegMask(MO.getRegMask()); + MachineFunction &MF = PFS.MF; + MachineRegisterInfo &MRI = MF.getRegInfo(); + bool Error = false; + // Create VRegs + for (auto P : PFS.VRegInfos) { + const VRegInfo &Info = *P.second; + unsigned Reg = Info.VReg; + switch (Info.Kind) { + case VRegInfo::UNKNOWN: + error(Twine("Cannot determine class/bank of virtual register ") + + Twine(P.first) + " in function '" + MF.getName() + "'"); + Error = true; + break; + case VRegInfo::NORMAL: + MRI.setRegClass(Reg, Info.D.RC); + if (Info.PreferredReg != 0) + MRI.setSimpleHint(Reg, Info.PreferredReg); + break; + case VRegInfo::GENERIC: + break; + case VRegInfo::REGBANK: + MRI.setRegBank(Reg, *Info.D.RegBank); + break; + } + } + + // Compute MachineRegisterInfo::UsedPhysRegMask + if (!YamlMF.CalleeSavedRegisters) { + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB) { + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isRegMask()) + continue; + MRI.addPhysRegsUsedFromRegMask(MO.getRegMask()); + } } } } + + // FIXME: This is a temporary workaround until the reserved registers can be + // serialized. + MRI.freezeReservedRegs(MF); + return Error; } bool MIRParserImpl::initializeFrameInfo(PerFunctionMIParsingState &PFS, @@ -646,7 +677,7 @@ return false; } -bool MIRParserImpl::parseMDNode(const PerFunctionMIParsingState &PFS, +bool MIRParserImpl::parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, const yaml::StringValue &Source) { if (Source.Value.empty()) return false; @@ -702,7 +733,7 @@ return false; } -bool MIRParserImpl::parseMBBReference(const PerFunctionMIParsingState &PFS, +bool MIRParserImpl::parseMBBReference(PerFunctionMIParsingState &PFS, MachineBasicBlock *&MBB, const yaml::StringValue &Source) { SMDiagnostic Error; Index: llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp +++ llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp @@ -93,6 +93,13 @@ return true; } +unsigned MachineRegisterInfo::createIncompleteVirtualRegister() { + unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs()); + VRegInfo.grow(Reg); + RegAllocHints.grow(Reg); + return Reg; +} + /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. /// @@ -103,10 +110,8 @@ "Virtual register RegClass must be allocatable."); // New virtual register number. - unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs()); - VRegInfo.grow(Reg); + unsigned Reg = createIncompleteVirtualRegister(); VRegInfo[Reg].first = RegClass; - RegAllocHints.grow(Reg); if (TheDelegate) TheDelegate->MRI_NoteNewVirtualRegister(Reg); return Reg; @@ -127,12 +132,10 @@ unsigned MachineRegisterInfo::createGenericVirtualRegister(LLT Ty) { // New virtual register number. - unsigned Reg = TargetRegisterInfo::index2VirtReg(getNumVirtRegs()); - VRegInfo.grow(Reg); - // FIXME: Should we use a dummy register bank? + unsigned Reg = createIncompleteVirtualRegister(); + // FIXME: Should we use a dummy register class? VRegInfo[Reg].first = static_cast(nullptr); getVRegToType()[Reg] = Ty; - RegAllocHints.grow(Reg); if (TheDelegate) TheDelegate->MRI_NoteNewVirtualRegister(Reg); return Reg; Index: llvm/trunk/test/CodeGen/MIR/X86/undefined-virtual-register.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/X86/undefined-virtual-register.mir +++ llvm/trunk/test/CodeGen/MIR/X86/undefined-virtual-register.mir @@ -18,8 +18,8 @@ body: | bb.0.entry: %0 = COPY %edi - ; CHECK: [[@LINE+1]]:17: use of undefined virtual register '%10' - %eax = COPY %10 + ; CHECK: Cannot determine class/bank of virtual register 1 in function 'test' + %eax = COPY %1 RETQ %eax ...