summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/CodeGen/MIRYamlMapping.h19
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIRParser.cpp50
-rw-r--r--llvm/lib/CodeGen/MIRPrinter.cpp18
-rw-r--r--llvm/test/CodeGen/MIR/X86/undefined-register-class.mir26
-rw-r--r--llvm/test/CodeGen/MIR/X86/virtual-registers.mir35
5 files changed, 141 insertions, 7 deletions
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index f7f64d10912..ea6d1874f3a 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -81,6 +81,21 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue)
namespace llvm {
namespace yaml {
+struct VirtualRegisterDefinition {
+ unsigned ID;
+ StringValue Class;
+ // TODO: Serialize the virtual register hints.
+};
+
+template <> struct MappingTraits<VirtualRegisterDefinition> {
+ static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
+ YamlIO.mapRequired("id", Reg.ID);
+ YamlIO.mapRequired("class", Reg.Class);
+ }
+
+ static const bool flow = true;
+};
+
struct MachineBasicBlock {
unsigned ID;
StringValue Name;
@@ -109,6 +124,7 @@ template <> struct MappingTraits<MachineBasicBlock> {
} // end namespace yaml
} // end namespace llvm
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock)
namespace llvm {
@@ -169,7 +185,7 @@ struct MachineFunction {
bool IsSSA = false;
bool TracksRegLiveness = false;
bool TracksSubRegLiveness = false;
- // TODO: Serialize virtual register definitions.
+ std::vector<VirtualRegisterDefinition> VirtualRegisters;
// TODO: Serialize the various register masks.
// TODO: Serialize live in registers.
// Frame information
@@ -187,6 +203,7 @@ template <> struct MappingTraits<MachineFunction> {
YamlIO.mapOptional("isSSA", MF.IsSSA);
YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness);
YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness);
+ YamlIO.mapOptional("registers", MF.VirtualRegisters);
YamlIO.mapOptional("frameInfo", MF.FrameInfo);
YamlIO.mapOptional("body", MF.BasicBlocks);
}
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index e5ba0322235..d9fd3861d44 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -49,6 +49,8 @@ class MIRParserImpl {
LLVMContext &Context;
StringMap<std::unique_ptr<yaml::MachineFunction>> Functions;
SlotMapping IRSlots;
+ /// Maps from register class names to register classes.
+ StringMap<const TargetRegisterClass *> Names2RegClasses;
public:
MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
@@ -100,7 +102,8 @@ public:
const yaml::MachineBasicBlock &YamlMBB,
const PerFunctionMIParsingState &PFS);
- bool initializeRegisterInfo(MachineRegisterInfo &RegInfo,
+ bool initializeRegisterInfo(const MachineFunction &MF,
+ MachineRegisterInfo &RegInfo,
const yaml::MachineFunction &YamlMF);
bool initializeFrameInfo(MachineFrameInfo &MFI,
@@ -117,6 +120,14 @@ private:
/// Create an empty function with the given name.
void createDummyFunction(StringRef Name, Module &M);
+
+ void initNames2RegClasses(const MachineFunction &MF);
+
+ /// Check if the given identifier is a name of a register class.
+ ///
+ /// Return null if the name isn't a register class.
+ const TargetRegisterClass *getRegClass(const MachineFunction &MF,
+ StringRef Name);
};
} // end namespace llvm
@@ -247,7 +258,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
MF.setAlignment(YamlMF.Alignment);
MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
MF.setHasInlineAsm(YamlMF.HasInlineAsm);
- if (initializeRegisterInfo(MF.getRegInfo(), YamlMF))
+ if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF))
return true;
if (initializeFrameInfo(*MF.getFrameInfo(), YamlMF.FrameInfo))
return true;
@@ -318,7 +329,8 @@ bool MIRParserImpl::initializeMachineBasicBlock(
}
bool MIRParserImpl::initializeRegisterInfo(
- MachineRegisterInfo &RegInfo, const yaml::MachineFunction &YamlMF) {
+ const MachineFunction &MF, MachineRegisterInfo &RegInfo,
+ const yaml::MachineFunction &YamlMF) {
assert(RegInfo.isSSA());
if (!YamlMF.IsSSA)
RegInfo.leaveSSA();
@@ -326,6 +338,18 @@ bool MIRParserImpl::initializeRegisterInfo(
if (!YamlMF.TracksRegLiveness)
RegInfo.invalidateLiveness();
RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness);
+
+ // Parse the virtual register information.
+ for (const auto &VReg : YamlMF.VirtualRegisters) {
+ const auto *RC = getRegClass(MF, VReg.Class.Value);
+ if (!RC)
+ 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);
+ }
return false;
}
@@ -395,6 +419,26 @@ SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
Error.getFixIts());
}
+void MIRParserImpl::initNames2RegClasses(const MachineFunction &MF) {
+ if (!Names2RegClasses.empty())
+ return;
+ const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+ for (unsigned I = 0, E = TRI->getNumRegClasses(); I < E; ++I) {
+ const auto *RC = TRI->getRegClass(I);
+ Names2RegClasses.insert(
+ std::make_pair(StringRef(TRI->getRegClassName(RC)).lower(), RC));
+ }
+}
+
+const TargetRegisterClass *MIRParserImpl::getRegClass(const MachineFunction &MF,
+ StringRef Name) {
+ initNames2RegClasses(MF);
+ auto RegClassInfo = Names2RegClasses.find(Name);
+ if (RegClassInfo == Names2RegClasses.end())
+ return nullptr;
+ return RegClassInfo->getValue();
+}
+
MIRParser::MIRParser(std::unique_ptr<MIRParserImpl> Impl)
: Impl(std::move(Impl)) {}
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index b4e47232ec2..3ca98240d94 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -42,7 +42,8 @@ public:
void print(const MachineFunction &MF);
- void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo);
+ void convert(yaml::MachineFunction &MF, const MachineRegisterInfo &RegInfo,
+ const TargetRegisterInfo *TRI);
void convert(yaml::MachineFrameInfo &YamlMFI, const MachineFrameInfo &MFI);
void convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB,
const MachineBasicBlock &MBB);
@@ -95,7 +96,7 @@ void MIRPrinter::print(const MachineFunction &MF) {
YamlMF.Alignment = MF.getAlignment();
YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();
YamlMF.HasInlineAsm = MF.hasInlineAsm();
- convert(YamlMF, MF.getRegInfo());
+ convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
convert(YamlMF.FrameInfo, *MF.getFrameInfo());
int I = 0;
@@ -117,10 +118,21 @@ void MIRPrinter::print(const MachineFunction &MF) {
}
void MIRPrinter::convert(yaml::MachineFunction &MF,
- const MachineRegisterInfo &RegInfo) {
+ const MachineRegisterInfo &RegInfo,
+ const TargetRegisterInfo *TRI) {
MF.IsSSA = RegInfo.isSSA();
MF.TracksRegLiveness = RegInfo.tracksLiveness();
MF.TracksSubRegLiveness = RegInfo.subRegLivenessEnabled();
+
+ // Print the virtual register definitions.
+ for (unsigned I = 0, E = RegInfo.getNumVirtRegs(); I < E; ++I) {
+ unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
+ yaml::VirtualRegisterDefinition VReg;
+ VReg.ID = I;
+ VReg.Class =
+ StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
+ MF.VirtualRegisters.push_back(VReg);
+ }
}
void MIRPrinter::convert(yaml::MachineFrameInfo &YamlMFI,
diff --git a/llvm/test/CodeGen/MIR/X86/undefined-register-class.mir b/llvm/test/CodeGen/MIR/X86/undefined-register-class.mir
new file mode 100644
index 00000000000..a14d2303a7d
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/undefined-register-class.mir
@@ -0,0 +1,26 @@
+# 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 it encounters an
+# unknown register class.
+
+--- |
+
+ define i32 @test(i32 %a) {
+ entry:
+ ret i32 %a
+ }
+
+...
+---
+name: test
+isSSA: true
+tracksRegLiveness: true
+registers:
+ # CHECK: [[@LINE+1]]:20: use of undefined register class 'gr3200'
+ - {id: 0, class: 'gr3200'}
+body:
+ - id: 0
+ name: entry
+ instructions:
+ - 'RETQ %eax'
+...
+
diff --git a/llvm/test/CodeGen/MIR/X86/virtual-registers.mir b/llvm/test/CodeGen/MIR/X86/virtual-registers.mir
new file mode 100644
index 00000000000..154c71335bb
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/virtual-registers.mir
@@ -0,0 +1,35 @@
+# 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.
+
+--- |
+
+ define i32 @bar(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
+isSSA: true
+tracksRegLiveness: true
+# CHECK: registers:
+# CHECK-NEXT: - { id: 0, class: gr32 }
+# CHECK-NEXT: - { id: 1, class: gr32 }
+# CHECK-NEXT: - { id: 2, class: gr32 }
+registers:
+ - { id: 0, class: gr32 }
+ - { id: 1, class: gr32 }
+ - { id: 2, class: gr32 }
+body:
+ - id: 0
+...
+
OpenPOWER on IntegriCloud