Index: include/llvm/CodeGen/MachineRegisterInfo.h =================================================================== --- include/llvm/CodeGen/MachineRegisterInfo.h +++ include/llvm/CodeGen/MachineRegisterInfo.h @@ -20,6 +20,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/LowLevelType.h" @@ -75,6 +76,13 @@ VirtReg2IndexFunctor> VRegInfo; + /// Map for recovering vreg name from vreg number. + /// This map is used by the MIR Printer. + IndexedMap VReg2Name; + + /// StringSet that is used to unique vreg names. + StringSet<> VRegNames; + /// The flag is true upon \p UpdatedCSRs initialization /// and false otherwise. bool IsUpdatedCSRsInitialized; @@ -418,6 +426,10 @@ /// specified register (it may be live-in). bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } + StringRef getVRegName(unsigned Reg) const { + return VReg2Name.inBounds(Reg) ? VReg2Name[Reg].c_str() : ""; + } + /// Return true if there is exactly one operand defining the specified /// register. bool hasOneDef(unsigned RegNo) const { @@ -691,8 +703,9 @@ bool recomputeRegClass(unsigned Reg); /// createVirtualRegister - Create and return a new virtual register in the - /// function with the specified register class. - unsigned createVirtualRegister(const TargetRegisterClass *RegClass); + /// function with the specified register class. Optionally provide a name. + unsigned createVirtualRegister(const TargetRegisterClass *RegClass, + StringRef Name = ""); /// Accessor for VRegToType. This accessor should only be used /// by global-isel related work. Index: include/llvm/CodeGen/TargetRegisterInfo.h =================================================================== --- include/llvm/CodeGen/TargetRegisterInfo.h +++ include/llvm/CodeGen/TargetRegisterInfo.h @@ -1154,7 +1154,8 @@ /// /// Usage: OS << printReg(Reg, TRI, SubRegIdx) << '\n'; Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr, - unsigned SubRegIdx = 0); + unsigned SubRegIdx = 0, + const MachineRegisterInfo *MRI = nullptr); /// Create Printable object to print register units on a \ref raw_ostream. /// Index: lib/CodeGen/MIRParser/MILexer.h =================================================================== --- lib/CodeGen/MIRParser/MILexer.h +++ lib/CodeGen/MIRParser/MILexer.h @@ -118,6 +118,7 @@ Identifier, IntegerType, NamedRegister, + NamedVirtualRegister, MachineBasicBlockLabel, MachineBasicBlock, PointerType, @@ -170,7 +171,7 @@ bool isRegister() const { return Kind == NamedRegister || Kind == underscore || - Kind == VirtualRegister; + Kind == NamedVirtualRegister || Kind == VirtualRegister; } bool isRegisterFlag() const { Index: lib/CodeGen/MIRParser/MILexer.cpp =================================================================== --- lib/CodeGen/MIRParser/MILexer.cpp +++ lib/CodeGen/MIRParser/MILexer.cpp @@ -410,6 +410,16 @@ return isIdentifierChar(C) && C != '.'; } +static Cursor lexNamedVirtualRegister(Cursor C, MIToken &Token) { + Cursor Range = C; + C.advance(); // Skip '%' + while (isRegisterChar(C.peek())) + C.advance(); + Token.reset(MIToken::NamedVirtualRegister, Range.upto(C)) + .setStringValue(Range.upto(C).drop_front(1)); // Drop the '%' + return C; +} + static Cursor maybeLexRegister(Cursor C, MIToken &Token, ErrorCallbackType ErrorCallback) { if (C.peek() != '%' && C.peek() != '$') @@ -419,7 +429,9 @@ if (isdigit(C.peek(1))) return lexVirtualRegister(C, Token); - // ErrorCallback(Token.location(), "Named vregs are not yet supported."); + if (isRegisterChar(C.peek(1))) + return lexNamedVirtualRegister(C, Token); + return None; } Index: lib/CodeGen/MIRParser/MIParser.h =================================================================== --- lib/CodeGen/MIRParser/MIParser.h +++ lib/CodeGen/MIRParser/MIParser.h @@ -67,6 +67,9 @@ const Name2RegBankMap &Names2RegBanks); VRegInfo &getVRegInfo(unsigned VReg); + VRegInfo *makeVRegInfo(); + void populateVRegInfo(unsigned VReg, VRegInfo *Info); + VRegInfo *lookupVRegInfo(unsigned VReg); }; /// Parse the machine basic block definitions, and skip the machine Index: lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIParser.cpp +++ lib/CodeGen/MIRParser/MIParser.cpp @@ -98,6 +98,21 @@ return *I.first->second; } +VRegInfo *PerFunctionMIParsingState::makeVRegInfo() { + return new (Allocator) VRegInfo; +} + +VRegInfo *PerFunctionMIParsingState::lookupVRegInfo(unsigned Reg) { + auto I = VRegInfos.find(Reg); + return (I == VRegInfos.end()) ? nullptr : I->second; +} + +void PerFunctionMIParsingState::populateVRegInfo(unsigned VReg, VRegInfo *Info) { + auto I = VRegInfos.insert(std::make_pair(VReg, Info)); + if (I.second) + Info->VReg = VReg; +} + namespace { /// A wrapper struct around the 'MachineOperand' struct that includes a source @@ -127,6 +142,8 @@ StringMap Names2InstrOpCodes; /// Maps from register names to registers. StringMap Names2Regs; + /// Maps from virtual register names to virtual registers. + StringMap Names2VRegs; /// Maps from register mask names to register masks. StringMap Names2RegMasks; /// Maps from subregister names to subregister indices. @@ -182,6 +199,7 @@ bool parseNamedRegister(unsigned &Reg); bool parseVirtualRegister(VRegInfo *&Info); + bool parseNamedVirtualRegister(unsigned &Reg, VRegInfo *&Info); bool parseRegister(unsigned &Reg, VRegInfo *&VRegInfo); bool parseRegisterFlag(unsigned &Flags); bool parseRegisterClassOrBank(VRegInfo &RegInfo); @@ -283,6 +301,10 @@ /// register name is invalid. bool getRegisterByName(StringRef RegName, unsigned &Reg); + /// Try to convert a virtual register name to a virtual register number. + /// Return true if the register name is invalid. + bool getVirtualRegisterByName(StringRef RegName, unsigned &Reg); + void initNames2RegMasks(); /// Check if the given identifier is a name of a register mask. @@ -949,6 +971,33 @@ return false; } +bool MIParser::parseNamedVirtualRegister(unsigned &Reg, VRegInfo *&Info) { + assert(Token.is(MIToken::NamedVirtualRegister) && "Needs NamedRegister token"); + StringRef Name = Token.stringValue(); + if (!getVirtualRegisterByName(Name, Reg)) { + lex(); + Info = PFS.lookupVRegInfo(Reg); + return false; + } + + lex(); + if (!Token.is(MIToken::colon)) + return error(Twine("unknown register name '") + Name + "'"); + + lex(); + Info = PFS.makeVRegInfo(); + if (parseRegisterClassOrBank(*Info)) + return true; + + Reg = MF.getRegInfo().createVirtualRegister(Info->D.RC, Name.str()); + PFS.populateVRegInfo(Reg, Info); + + if (!Names2VRegs.insert(std::make_pair(Name, Reg)).second) + return error(Twine("Invalid register name '") + Name + "'"); + + return false; +} + bool MIParser::parseVirtualRegister(VRegInfo *&Info) { assert(Token.is(MIToken::VirtualRegister) && "Needs VirtualRegister token"); unsigned ID; @@ -965,6 +1014,8 @@ return false; case MIToken::NamedRegister: return parseNamedRegister(Reg); + case MIToken::NamedVirtualRegister: + return parseNamedVirtualRegister(Reg, Info); case MIToken::VirtualRegister: if (parseVirtualRegister(Info)) return true; @@ -1155,9 +1206,11 @@ return error("expected a register after register flags"); unsigned Reg; VRegInfo *RegInfo; + const bool IsNamedVreg = Token.is(MIToken::NamedVirtualRegister); if (parseRegister(Reg, RegInfo)) return true; - lex(); + if (!IsNamedVreg) + lex(); unsigned SubReg = 0; if (Token.is(MIToken::dot)) { if (parseSubRegisterIndex(SubReg)) @@ -1952,6 +2005,7 @@ case MIToken::underscore: case MIToken::NamedRegister: case MIToken::VirtualRegister: + case MIToken::NamedVirtualRegister: return parseRegisterOperand(Dest, TiedDefIdx); case MIToken::IntegerLiteral: return parseImmediateOperand(Dest); @@ -2499,6 +2553,14 @@ return false; } +bool MIParser::getVirtualRegisterByName(StringRef RegName, unsigned &Reg) { + auto RegInfo = Names2VRegs.find(RegName); + if (RegInfo == Names2VRegs.end()) + return true; + Reg = RegInfo->getValue(); + return false; +} + void MIParser::initNames2RegMasks() { if (!Names2RegMasks.empty()) return; Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -272,6 +272,8 @@ unsigned Reg = TargetRegisterInfo::index2VirtReg(I); yaml::VirtualRegisterDefinition VReg; VReg.ID = I; + if (RegInfo.getVRegName(Reg) != "") + continue; ::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI); unsigned PreferredReg = RegInfo.getSimpleHint(Reg); if (PreferredReg) Index: lib/CodeGen/MachineOperand.cpp =================================================================== --- lib/CodeGen/MachineOperand.cpp +++ lib/CodeGen/MachineOperand.cpp @@ -675,7 +675,15 @@ OS << "debug-use "; if (TargetRegisterInfo::isPhysicalRegister(getReg()) && isRenamable()) OS << "renamable "; - OS << printReg(Reg, TRI); + + const MachineRegisterInfo *MRI = nullptr; + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + if (const MachineFunction *MF = getMFIfAvailable(*this)) { + MRI = &MF->getRegInfo(); + } + } + + OS << printReg(Reg, TRI, 0, MRI); // Print the sub register. if (unsigned SubReg = getSubReg()) { if (TRI) Index: lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- lib/CodeGen/MachineRegisterInfo.cpp +++ lib/CodeGen/MachineRegisterInfo.cpp @@ -161,16 +161,25 @@ /// function with the specified register class. /// unsigned -MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){ +MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass, + StringRef Name) { assert(RegClass && "Cannot create register without RegClass!"); assert(RegClass->isAllocatable() && "Virtual register RegClass must be allocatable."); + assert((Name.empty() || VRegNames.find(Name) == VRegNames.end()) && + "Named VRegs Must be Unique."); // New virtual register number. unsigned Reg = createIncompleteVirtualRegister(); VRegInfo[Reg].first = RegClass; if (TheDelegate) TheDelegate->MRI_NoteNewVirtualRegister(Reg); + + if (!Name.empty()) { + VRegNames.insert(Name); + VReg2Name.grow(Reg); + VReg2Name[Reg] = Name.str(); + } return Reg; } Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -86,14 +86,20 @@ namespace llvm { Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI, - unsigned SubIdx) { - return Printable([Reg, TRI, SubIdx](raw_ostream &OS) { + unsigned SubIdx, const MachineRegisterInfo *MRI) { + return Printable([Reg, TRI, SubIdx, MRI](raw_ostream &OS) { if (!Reg) OS << "$noreg"; else if (TargetRegisterInfo::isStackSlot(Reg)) OS << "SS#" << TargetRegisterInfo::stackSlot2Index(Reg); - else if (TargetRegisterInfo::isVirtualRegister(Reg)) - OS << '%' << TargetRegisterInfo::virtReg2Index(Reg); + else if (TargetRegisterInfo::isVirtualRegister(Reg)) { + StringRef Name = MRI ? MRI->getVRegName(Reg) : ""; + if (Name != "") { + OS << '%' << Name; + } else { + OS << '%' << TargetRegisterInfo::virtReg2Index(Reg); + } + } else if (!TRI) OS << '$' << "physreg" << Reg; else if (Reg < TRI->getNumRegs()) { Index: test/CodeGen/MIR/AArch64/namedvregs.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/AArch64/namedvregs.mir @@ -0,0 +1,27 @@ +# RUN: llc -mtriple=arm64-apple-ios11.0.0 -o - -run-pass none %s | FileCheck %s +... +--- +name: namedVRegFunc +body: | + bb.0: + liveins: $x0, $d0, $d1 + %0:fpr64 = COPY $d1 + %1:fpr64 = COPY $d0 + $w0 = COPY %0 + + ;CHECK: %foo:gpr32 = COPY $w0 + ;CHECK: %bar:gpr32 = COPY $x0 + ;CHECK: COPY %bar + ;CHECK: %foobar:gpr32 = COPY %bar + ;CHECK: COPY %foobar + ;CHECK: %foobar:gpr32 = COPY %bar + + %foo:gpr32 = COPY $w0 + %bar:gpr32 = COPY $x0 + $w0 = COPY %bar + %foobar:gpr32 = COPY %bar + $w0 = COPY %foobar + %foobar:gpr32 = COPY %bar + RET_ReallyLR implicit $w0 + +...