Skip to content
This repository has been archived by the owner on Feb 5, 2019. It is now read-only.

Commit

Permalink
MIRParser: Allow regclass specification on operand
Browse files Browse the repository at this point in the history
You can now define the register class of a virtual register on the
operand itself avoiding the need to use a "registers:" block.

Example: "%0:gr64 = COPY %rax"

Differential Revision: https://reviews.llvm.org/D22398

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292321 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
MatzeB committed Jan 18, 2017
1 parent 13bc67e commit c1fa073
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 8 deletions.
71 changes: 69 additions & 2 deletions lib/CodeGen/MIRParser/MIParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -139,6 +142,7 @@ class MIParser {
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,
Expand Down Expand Up @@ -878,6 +882,62 @@ bool MIParser::parseRegister(unsigned &Reg, VRegInfo *&Info) {
}
}

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()) {
Expand Down Expand Up @@ -1004,6 +1064,13 @@ bool MIParser::parseRegisterOperand(MachineOperand &Dest,
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)) {
Expand Down
9 changes: 8 additions & 1 deletion lib/CodeGen/MIRParser/MIParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,16 @@ struct VRegInfo {
unsigned PreferredReg = 0;
};

typedef StringMap<const TargetRegisterClass*> Name2RegClassMap;
typedef StringMap<const RegisterBank*> Name2RegBankMap;

struct PerFunctionMIParsingState {
BumpPtrAllocator Allocator;
MachineFunction &MF;
SourceMgr *SM;
const SlotMapping &IRSlots;
const Name2RegClassMap &Names2RegClasses;
const Name2RegBankMap &Names2RegBanks;

DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
DenseMap<unsigned, VRegInfo*> VRegInfos;
Expand All @@ -59,7 +64,9 @@ struct PerFunctionMIParsingState {
DenseMap<unsigned, unsigned> JumpTableSlots;

PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM,
const SlotMapping &IRSlots);
const SlotMapping &IRSlots,
const Name2RegClassMap &Names2RegClasses,
const Name2RegBankMap &Names2RegBanks);

VRegInfo &getVRegInfo(unsigned VReg);
};
Expand Down
11 changes: 6 additions & 5 deletions lib/CodeGen/MIRParser/MIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class MIRParserImpl {
StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
SlotMapping IRSlots;
/// Maps from register class names to register classes.
StringMap<const TargetRegisterClass *> Names2RegClasses;
Name2RegClassMap Names2RegClasses;
/// Maps from register bank names to register banks.
StringMap<const RegisterBank *> Names2RegBanks;
Name2RegBankMap Names2RegBanks;

public:
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
Expand Down Expand Up @@ -325,6 +325,8 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
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);
Expand All @@ -338,7 +340,8 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
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()) {
Expand Down Expand Up @@ -818,7 +821,6 @@ void MIRParserImpl::initNames2RegBanks(const MachineFunction &MF) {

const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,
StringRef Name) {
initNames2RegClasses(MF);
auto RegClassInfo = Names2RegClasses.find(Name);
if (RegClassInfo == Names2RegClasses.end())
return nullptr;
Expand All @@ -827,7 +829,6 @@ const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,

const RegisterBank *MIRParserImpl::getRegBank(const MachineFunction &MF,
StringRef Name) {
initNames2RegBanks(MF);
auto RegBankInfo = Names2RegBanks.find(Name);
if (RegBankInfo == Names2RegBanks.end())
return nullptr;
Expand Down
20 changes: 20 additions & 0 deletions test/CodeGen/MIR/AArch64/register-operand-bank.mir
Original file line number Diff line number Diff line change
@@ -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
...
13 changes: 13 additions & 0 deletions test/CodeGen/MIR/X86/register-operand-class-invalid0.mir
Original file line number Diff line number Diff line change
@@ -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
...
14 changes: 14 additions & 0 deletions test/CodeGen/MIR/X86/register-operand-class-invalid1.mir
Original file line number Diff line number Diff line change
@@ -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
...
24 changes: 24 additions & 0 deletions test/CodeGen/MIR/X86/register-operand-class.mir
Original file line number Diff line number Diff line change
@@ -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
...

0 comments on commit c1fa073

Please sign in to comment.