Index: llvm/trunk/lib/CodeGen/MIRParser/MIParser.h =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIParser.h +++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.h @@ -45,11 +45,16 @@ unsigned PreferredReg = 0; }; +typedef StringMap Name2RegClassMap; +typedef StringMap Name2RegBankMap; + struct PerFunctionMIParsingState { BumpPtrAllocator Allocator; MachineFunction &MF; SourceMgr *SM; const SlotMapping &IRSlots; + const Name2RegClassMap &Names2RegClasses; + const Name2RegBankMap &Names2RegBanks; DenseMap MBBSlots; DenseMap VRegInfos; @@ -59,7 +64,9 @@ DenseMap JumpTableSlots; PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM, - const SlotMapping &IRSlots); + const SlotMapping &IRSlots, + const Name2RegClassMap &Names2RegClasses, + const Name2RegBankMap &Names2RegBanks); VRegInfo &getVRegInfo(unsigned VReg); }; Index: llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp +++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp @@ -41,8 +41,11 @@ using namespace llvm; PerFunctionMIParsingState::PerFunctionMIParsingState(MachineFunction &MF, - SourceMgr &SM, const SlotMapping &IRSlots) - : MF(MF), SM(&SM), IRSlots(IRSlots) { + SourceMgr &SM, const SlotMapping &IRSlots, + const Name2RegClassMap &Names2RegClasses, + const Name2RegBankMap &Names2RegBanks) + : MF(MF), SM(&SM), IRSlots(IRSlots), Names2RegClasses(Names2RegClasses), + Names2RegBanks(Names2RegBanks) { } VRegInfo &PerFunctionMIParsingState::getVRegInfo(unsigned Num) { @@ -139,6 +142,7 @@ bool parseVirtualRegister(VRegInfo *&Info); bool parseRegister(unsigned &Reg, VRegInfo *&VRegInfo); bool parseRegisterFlag(unsigned &Flags); + bool parseRegisterClassOrBank(VRegInfo &RegInfo); bool parseSubRegisterIndex(unsigned &SubReg); bool parseRegisterTiedDefIndex(unsigned &TiedDefIdx); bool parseRegisterOperand(MachineOperand &Dest, @@ -878,6 +882,62 @@ } } +bool MIParser::parseRegisterClassOrBank(VRegInfo &RegInfo) { + if (Token.isNot(MIToken::Identifier)) + return error("expected a register class or register bank name"); + StringRef::iterator Loc = Token.location(); + StringRef Name = Token.stringValue(); + + // Was it a register class? + auto RCNameI = PFS.Names2RegClasses.find(Name); + if (RCNameI != PFS.Names2RegClasses.end()) { + lex(); + const TargetRegisterClass &RC = *RCNameI->getValue(); + + switch (RegInfo.Kind) { + case VRegInfo::UNKNOWN: + case VRegInfo::NORMAL: + RegInfo.Kind = VRegInfo::NORMAL; + if (RegInfo.Explicit && RegInfo.D.RC != &RC) { + const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + return error(Loc, Twine("conflicting register classes, previously: ") + + Twine(TRI.getRegClassName(RegInfo.D.RC))); + } + RegInfo.D.RC = &RC; + RegInfo.Explicit = true; + return false; + + case VRegInfo::GENERIC: + case VRegInfo::REGBANK: + return error(Loc, "register class specification on generic register"); + } + llvm_unreachable("Unexpected register kind"); + } + + // Should be a register bank. + auto RBNameI = PFS.Names2RegBanks.find(Name); + lex(); + if (RBNameI == PFS.Names2RegBanks.end()) + return error(Loc, "expected a register class or register bank name"); + + const RegisterBank &RegBank = *RBNameI->getValue(); + switch (RegInfo.Kind) { + case VRegInfo::UNKNOWN: + case VRegInfo::GENERIC: + case VRegInfo::REGBANK: + RegInfo.Kind = VRegInfo::REGBANK; + if (RegInfo.Explicit && RegInfo.D.RegBank != &RegBank) + return error(Loc, "conflicting register banks"); + RegInfo.D.RegBank = &RegBank; + RegInfo.Explicit = true; + return false; + + case VRegInfo::NORMAL: + return error(Loc, "register class specification on normal register"); + } + llvm_unreachable("Unexpected register kind"); +} + bool MIParser::parseRegisterFlag(unsigned &Flags) { const unsigned OldFlags = Flags; switch (Token.kind()) { @@ -1004,6 +1064,13 @@ if (!TargetRegisterInfo::isVirtualRegister(Reg)) return error("subregister index expects a virtual register"); } + if (Token.is(MIToken::colon)) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return error("register class specification expects a virtual register"); + lex(); + if (parseRegisterClassOrBank(*RegInfo)) + return true; + } MachineRegisterInfo &MRI = MF.getRegInfo(); if ((Flags & RegState::Define) == 0) { if (consumeIfPresent(MIToken::lparen)) { Index: llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp +++ llvm/trunk/lib/CodeGen/MIRParser/MIRParser.cpp @@ -55,9 +55,9 @@ StringMap> Functions; SlotMapping IRSlots; /// Maps from register class names to register classes. - StringMap Names2RegClasses; + Name2RegClassMap Names2RegClasses; /// Maps from register bank names to register banks. - StringMap Names2RegBanks; + Name2RegBankMap Names2RegBanks; public: MIRParserImpl(std::unique_ptr Contents, StringRef Filename, @@ -325,6 +325,8 @@ return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. + initNames2RegClasses(MF); + initNames2RegBanks(MF); const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); @@ -338,7 +340,8 @@ if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); - PerFunctionMIParsingState PFS(MF, SM, IRSlots); + PerFunctionMIParsingState PFS(MF, SM, IRSlots, Names2RegClasses, + Names2RegBanks); if (parseRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { @@ -818,7 +821,6 @@ const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF, StringRef Name) { - initNames2RegClasses(MF); auto RegClassInfo = Names2RegClasses.find(Name); if (RegClassInfo == Names2RegClasses.end()) return nullptr; @@ -827,7 +829,6 @@ const RegisterBank *MIRParserImpl::getRegBank(const MachineFunction &MF, StringRef Name) { - initNames2RegBanks(MF); auto RegBankInfo = Names2RegBanks.find(Name); if (RegBankInfo == Names2RegBanks.end()) return nullptr; Index: llvm/trunk/test/CodeGen/MIR/AArch64/register-operand-bank.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/AArch64/register-operand-bank.mir +++ llvm/trunk/test/CodeGen/MIR/AArch64/register-operand-bank.mir @@ -0,0 +1,20 @@ +# RUN: llc -o - %s -mtriple=aarch64-- -run-pass=none | FileCheck %s +# REQUIRES: global-isel +# Test various aspects of register bank specification on machine operands. +--- | + define void @func() { ret void } +... +--- +# CHECK-LABEL: name: func +# CHECK: registers: +# CHECK: - { id: 0, class: gpr } +# CHECK: - { id: 1, class: fpr } +name: func +body: | + bb.0: + %0 : gpr(s64) = COPY %x9 + %x9 = COPY %0 + + %3 : fpr(s64) = COPY %d0 + %d1 = COPY %3 : fpr +... Index: llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid0.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid0.mir +++ llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid0.mir @@ -0,0 +1,13 @@ +# RUN: not llc -o /dev/null %s -march=x86-64 -run-pass none 2>&1 | FileCheck %s +# This test ensures that an error is reported for specifying the register class +# of a physical register. +--- | + define void @t() { ret void } +... +--- +name: t +body: | + bb.0: + ; CHECK: [[@LINE+1]]:10: register class specification expects a virtual register + %eax : gr32 = COPY %rdx +... Index: llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid1.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid1.mir +++ llvm/trunk/test/CodeGen/MIR/X86/register-operand-class-invalid1.mir @@ -0,0 +1,14 @@ +# RUN: not llc -o /dev/null %s -march=x86-64 -run-pass none 2>&1 | FileCheck %s +# This test ensures that an error is reported for specifying the register class +# of a physical register. +--- | + define void @t() { ret void } +... +--- +name: t +body: | + bb.0: + %0 : gr32 = COPY %rdx + ; CHECK: [[@LINE+1]]:24: conflicting register classes, previously: GR32 + NOOP implicit %0 : gr32_abcd +... Index: llvm/trunk/test/CodeGen/MIR/X86/register-operand-class.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/X86/register-operand-class.mir +++ llvm/trunk/test/CodeGen/MIR/X86/register-operand-class.mir @@ -0,0 +1,24 @@ +# RUN: llc -o - %s -march=x86-64 -run-pass none | FileCheck %s +# Test various aspects of register class specification on machine operands. +--- | + define void @func() { ret void } +... +--- +# CHECK-LABEL: name: func +# CHECK: registers: +# CHECK: - { id: 0, class: gr32 } +# CHECK: - { id: 1, class: gr64 } +# CHECK: - { id: 2, class: gr32 } +# CHECK: - { id: 3, class: gr16 } +name: func +body: | + bb.0: + %0 : gr32 = COPY %rax + %1.sub_32bit : gr64 = COPY %eax + %rdx = COPY %1 + %2 = COPY %ecx + %ecx = COPY %2 : gr32 + + %3 : gr16 = COPY %bx + %bx = COPY %3 : gr16 +...