summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/CodeGen/MIRParser/MILexer.cpp13
-rw-r--r--llvm/lib/CodeGen/MIRParser/MILexer.h8
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIParser.cpp12
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIParser.h1
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIRParser.cpp23
-rw-r--r--llvm/lib/CodeGen/MIRPrinter.cpp3
-rw-r--r--llvm/test/CodeGen/MIR/X86/undefined-virtual-register.mir28
-rw-r--r--llvm/test/CodeGen/MIR/X86/virtual-registers.mir78
8 files changed, 149 insertions, 17 deletions
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 4baa3859461..1ba5725d1f8 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -115,9 +115,22 @@ static Cursor maybeLexMachineBasicBlock(
return C;
}
+static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
+ auto Range = C;
+ C.advance(); // Skip '%'
+ auto NumberRange = C;
+ while (isdigit(C.peek()))
+ C.advance();
+ Token = MIToken(MIToken::VirtualRegister, Range.upto(C),
+ APSInt(NumberRange.upto(C)));
+ return C;
+}
+
static Cursor maybeLexRegister(Cursor C, MIToken &Token) {
if (C.peek() != '%')
return None;
+ if (isdigit(C.peek(1)))
+ return lexVirtualRegister(C, Token);
auto Range = C;
C.advance(); // Skip '%'
while (isIdentifierChar(C.peek()))
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index ef471d250c2..187747c6dd3 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -51,7 +51,8 @@ struct MIToken {
GlobalValue,
// Other tokens
- IntegerLiteral
+ IntegerLiteral,
+ VirtualRegister
};
private:
@@ -73,7 +74,8 @@ public:
bool isError() const { return Kind == Error; }
bool isRegister() const {
- return Kind == NamedRegister || Kind == underscore;
+ return Kind == NamedRegister || Kind == underscore ||
+ Kind == VirtualRegister;
}
bool isRegisterFlag() const {
@@ -93,7 +95,7 @@ public:
bool hasIntegerValue() const {
return Kind == IntegerLiteral || Kind == MachineBasicBlock ||
- Kind == GlobalValue;
+ Kind == GlobalValue || Kind == VirtualRegister;
}
};
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 7fd794bd211..5a88a8d21a5 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -288,6 +288,17 @@ bool MIParser::parseRegister(unsigned &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;
+ }
// TODO: Parse other register kinds.
default:
llvm_unreachable("The current token should be a register");
@@ -425,6 +436,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
case MIToken::kw_undef:
case MIToken::underscore:
case MIToken::NamedRegister:
+ case MIToken::VirtualRegister:
return parseRegisterOperand(Dest);
case MIToken::IntegerLiteral:
return parseImmediateOperand(Dest);
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.h b/llvm/lib/CodeGen/MIRParser/MIParser.h
index e4c38004272..8a911b32a76 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.h
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.h
@@ -28,6 +28,7 @@ class SourceMgr;
struct PerFunctionMIParsingState {
DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
+ DenseMap<unsigned, unsigned> VirtualRegisterSlots;
};
bool parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, MachineFunction &MF,
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 0f7673eea07..612084c0b8d 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -102,9 +102,11 @@ public:
const yaml::MachineBasicBlock &YamlMBB,
const PerFunctionMIParsingState &PFS);
- bool initializeRegisterInfo(const MachineFunction &MF,
- MachineRegisterInfo &RegInfo,
- const yaml::MachineFunction &YamlMF);
+ bool
+ initializeRegisterInfo(const MachineFunction &MF,
+ MachineRegisterInfo &RegInfo,
+ const yaml::MachineFunction &YamlMF,
+ DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
bool initializeFrameInfo(MachineFrameInfo &MFI,
const yaml::MachineFunction &YamlMF);
@@ -258,12 +260,13 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
- if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
+ PerFunctionMIParsingState PFS;
+ if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
+ PFS.VirtualRegisterSlots))
return true;
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF))
return true;
- PerFunctionMIParsingState PFS;
const auto &F = *MF.getFunction();
for (const auto &YamlMBB : YamlMF.BasicBlocks) {
const BasicBlock *BB = nullptr;
@@ -330,7 +333,8 @@ bool MIRParserImpl::initializeMachineBasicBlock(
bool MIRParserImpl::initializeRegisterInfo(
const MachineFunction &MF, MachineRegisterInfo &RegInfo,
- const yaml::MachineFunction &YamlMF) {
+ const yaml::MachineFunction &YamlMF,
+ DenseMap<unsigned, unsigned> &VirtualRegisterSlots) {
assert(RegInfo.isSSA());
if (!YamlMF.IsSSA)
RegInfo.leaveSSA();
@@ -346,9 +350,10 @@ bool MIRParserImpl::initializeRegisterInfo(
return error(VReg.Class.SourceRange.Start,
Twine("use of undefined register class '") +
VReg.Class.Value + "'");
- // TODO: create the mapping from IDs to registers so that the virtual
- // register references can be parsed correctly.
- RegInfo.createVirtualRegister(RC);
+ unsigned Reg = RegInfo.createVirtualRegister(RC);
+ // TODO: Report an error when the same virtual register with the same ID is
+ // redefined.
+ VirtualRegisterSlots.insert(std::make_pair(VReg.ID, Reg));
}
return false;
}
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 8e97ce4dbf1..2ae3c4491a6 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -250,9 +250,10 @@ void MIPrinter::print(const MachineInstr &MI) {
static void printReg(unsigned Reg, raw_ostream &OS,
const TargetRegisterInfo *TRI) {
// TODO: Print Stack Slots.
- // TODO: Print virtual registers.
if (!Reg)
OS << '_';
+ else if (TargetRegisterInfo::isVirtualRegister(Reg))
+ OS << '%' << TargetRegisterInfo::virtReg2Index(Reg);
else if (Reg < TRI->getNumRegs())
OS << '%' << StringRef(TRI->getName(Reg)).lower();
else
diff --git a/llvm/test/CodeGen/MIR/X86/undefined-virtual-register.mir b/llvm/test/CodeGen/MIR/X86/undefined-virtual-register.mir
new file mode 100644
index 00000000000..12370c80caf
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/undefined-virtual-register.mir
@@ -0,0 +1,28 @@
+# RUN: not llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that the MIR parser reports an error when parsing a
+# reference to an undefined virtual register.
+
+--- |
+
+ define i32 @test(i32 %a) {
+ entry:
+ ret i32 %a
+ }
+
+...
+---
+name: test
+isSSA: true
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: gr32 }
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - '%0 = COPY %edi'
+ # CHECK: [[@LINE+1]]:22: use of undefined virtual register '%10'
+ - '%eax = COPY %10'
+ - 'RETQ %eax'
+...
+
diff --git a/llvm/test/CodeGen/MIR/X86/virtual-registers.mir b/llvm/test/CodeGen/MIR/X86/virtual-registers.mir
index 154c71335bb..c6d76e6a18c 100644
--- a/llvm/test/CodeGen/MIR/X86/virtual-registers.mir
+++ b/llvm/test/CodeGen/MIR/X86/virtual-registers.mir
@@ -1,6 +1,6 @@
# RUN: llc -march=x86-64 -start-after machine-sink -stop-after machine-sink -o /dev/null %s | FileCheck %s
-# This test ensures that the MIR parser parses virtual register definitions
-# correctly.
+# This test ensures that the MIR parser parses virtual register definitions and
+# references correctly.
--- |
@@ -16,6 +16,18 @@
ret i32 %a
}
+ define i32 @foo(i32 %a) {
+ entry:
+ %0 = icmp sle i32 %a, 10
+ br i1 %0, label %less, label %exit
+
+ less:
+ ret i32 0
+
+ exit:
+ ret i32 %a
+ }
+
...
---
name: bar
@@ -30,6 +42,64 @@ registers:
- { id: 1, class: gr32 }
- { id: 2, class: gr32 }
body:
- - id: 0
+ - id: 0
+ name: entry
+ # CHECK: %0 = COPY %edi
+ # CHECK-NEXT: %1 = SUB32ri8 %0, 10
+ instructions:
+ - '%0 = COPY %edi'
+ - '%1 = SUB32ri8 %0, 10, implicit-def %eflags'
+ - 'JG_1 %bb.2.exit, implicit %eflags'
+ - 'JMP_1 %bb.1.less'
+ - id: 1
+ name: less
+ # CHECK: %2 = MOV32r0
+ # CHECK-NEXT: %eax = COPY %2
+ instructions:
+ - '%2 = MOV32r0 implicit-def %eflags'
+ - '%eax = COPY %2'
+ - 'RETQ %eax'
+ - id: 2
+ name: exit
+ instructions:
+ - '%eax = COPY %0'
+ - 'RETQ %eax'
+...
+---
+name: foo
+isSSA: true
+tracksRegLiveness: true
+# CHECK: name: foo
+# CHECK: registers:
+# CHECK-NEXT: - { id: 0, class: gr32 }
+# CHECK-NEXT: - { id: 1, class: gr32 }
+# CHECK-NEXT: - { id: 2, class: gr32 }
+registers:
+ - { id: 2, class: gr32 }
+ - { id: 0, class: gr32 }
+ - { id: 10, class: gr32 }
+body:
+ - id: 0
+ name: entry
+ # CHECK: %0 = COPY %edi
+ # CHECK-NEXT: %1 = SUB32ri8 %0, 10
+ instructions:
+ - '%2 = COPY %edi'
+ - '%0 = SUB32ri8 %2, 10, implicit-def %eflags'
+ - 'JG_1 %bb.2.exit, implicit %eflags'
+ - 'JMP_1 %bb.1.less'
+ - id: 1
+ name: less
+ # CHECK: %2 = MOV32r0
+ # CHECK-NEXT: %eax = COPY %2
+ instructions:
+ - '%10 = MOV32r0 implicit-def %eflags'
+ - '%eax = COPY %10'
+ - 'RETQ %eax'
+ - id: 2
+ name: exit
+ # CHECK: %eax = COPY %0
+ instructions:
+ - '%eax = COPY %2'
+ - 'RETQ %eax'
...
-
OpenPOWER on IntegriCloud