OSDN Git Service

MIR Serialization: Serialize the liveout register mask machine operands.
authorAlex Lorenz <arphaman@gmail.com>
Mon, 10 Aug 2015 23:24:42 +0000 (23:24 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Mon, 10 Aug 2015 23:24:42 +0000 (23:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244529 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MIRParser/MILexer.cpp
lib/CodeGen/MIRParser/MILexer.h
lib/CodeGen/MIRParser/MIParser.cpp
lib/CodeGen/MIRPrinter.cpp
test/CodeGen/MIR/X86/liveout-register-mask.mir [new file with mode: 0644]

index f8640de..c59d780 100644 (file)
@@ -201,6 +201,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("non-temporal", MIToken::kw_non_temporal)
       .Case("invariant", MIToken::kw_invariant)
       .Case("align", MIToken::kw_align)
+      .Case("liveout", MIToken::kw_liveout)
       .Default(MIToken::Identifier);
 }
 
index 8448c22..831a21b 100644 (file)
@@ -70,6 +70,7 @@ struct MIToken {
     kw_non_temporal,
     kw_invariant,
     kw_align,
+    kw_liveout,
 
     // Identifier tokens
     Identifier,
index fe39d15..cfdd588 100644 (file)
@@ -121,6 +121,7 @@ public:
   bool parseIRBlock(BasicBlock *&BB, const Function &F);
   bool parseBlockAddressOperand(MachineOperand &Dest);
   bool parseTargetIndexOperand(MachineOperand &Dest);
+  bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest);
   bool parseMachineOperand(MachineOperand &Dest);
   bool parseMachineOperandAndTargetFlags(MachineOperand &Dest);
   bool parseOffset(int64_t &Offset);
@@ -920,6 +921,33 @@ bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) {
   return false;
 }
 
+bool MIParser::parseLiveoutRegisterMaskOperand(MachineOperand &Dest) {
+  assert(Token.is(MIToken::kw_liveout));
+  const auto *TRI = MF.getSubtarget().getRegisterInfo();
+  assert(TRI && "Expected target register info");
+  uint32_t *Mask = MF.allocateRegisterMask(TRI->getNumRegs());
+  lex();
+  if (expectAndConsume(MIToken::lparen))
+    return true;
+  while (true) {
+    if (Token.isNot(MIToken::NamedRegister))
+      return error("expected a named register");
+    unsigned Reg = 0;
+    if (parseRegister(Reg))
+      return true;
+    lex();
+    Mask[Reg / 32] |= 1U << (Reg % 32);
+    // TODO: Report an error if the same register is used more than once.
+    if (Token.isNot(MIToken::comma))
+      break;
+    lex();
+  }
+  if (expectAndConsume(MIToken::rparen))
+    return true;
+  Dest = MachineOperand::CreateRegLiveOut(Mask);
+  return false;
+}
+
 bool MIParser::parseMachineOperand(MachineOperand &Dest) {
   switch (Token.kind()) {
   case MIToken::kw_implicit:
@@ -970,6 +998,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
     return parseBlockAddressOperand(Dest);
   case MIToken::kw_target_index:
     return parseTargetIndexOperand(Dest);
+  case MIToken::kw_liveout:
+    return parseLiveoutRegisterMaskOperand(Dest);
   case MIToken::Error:
     return true;
   case MIToken::Identifier:
index 6327ff2..c12b2cf 100644 (file)
@@ -645,6 +645,21 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
       llvm_unreachable("Can't print this machine register mask yet.");
     break;
   }
+  case MachineOperand::MO_RegisterLiveOut: {
+    const uint32_t *RegMask = Op.getRegLiveOut();
+    OS << "liveout(";
+    bool IsCommaNeeded = false;
+    for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) {
+      if (RegMask[Reg / 32] & (1U << (Reg % 32))) {
+        if (IsCommaNeeded)
+          OS << ", ";
+        printReg(Reg, OS, TRI);
+        IsCommaNeeded = true;
+      }
+    }
+    OS << ")";
+    break;
+  }
   case MachineOperand::MO_Metadata:
     Op.getMetadata()->printAsOperand(OS, MST);
     break;
diff --git a/test/CodeGen/MIR/X86/liveout-register-mask.mir b/test/CodeGen/MIR/X86/liveout-register-mask.mir
new file mode 100644 (file)
index 0000000..5f193ab
--- /dev/null
@@ -0,0 +1,43 @@
+# RUN: llc -march=x86-64 -start-after stackmap-liveness -stop-after stackmap-liveness -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser parses the liveout register mask
+# machine operands correctly.
+
+--- |
+
+  define void @small_patchpoint_codegen(i64 %p1, i64 %p2, i64 %p3, i64 %p4) {
+  entry:
+    %result = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 5, i32 5, i8* null, i32 2, i64 %p1, i64 %p2)
+    ret void
+  }
+
+  declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
+
+...
+---
+name:            small_patchpoint_codegen
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+  - { reg: '%rsi' }
+frameInfo:
+  hasPatchPoint: true
+  stackSize:     8
+  adjustsStack:  true
+  hasCalls:      true
+fixedStack:
+  - { id: 0, type: spill-slot, offset: -16, size: 8, alignment: 16 }
+body:
+  - id:          0
+    name:        entry
+    liveins:     [ '%rdi', '%rsi', '%rbp' ]
+    instructions:
+      - 'frame-setup PUSH64r killed %rbp, implicit-def %rsp, implicit %rsp'
+      - CFI_INSTRUCTION .cfi_def_cfa_offset 16
+      - 'CFI_INSTRUCTION .cfi_offset %rbp, -16'
+      - '%rbp = frame-setup MOV64rr %rsp'
+      - 'CFI_INSTRUCTION .cfi_def_cfa_register %rbp'
+# CHECK: PATCHPOINT 5, 5, 0, 2, 0, %rdi, %rsi, csr_64, liveout(%esp, %rsp, %sp, %spl),
+      - 'PATCHPOINT 5, 5, 0, 2, 0, %rdi, %rsi, csr_64, liveout(%esp, %rsp, %sp, %spl), implicit-def dead early-clobber %r11, implicit-def %rsp, implicit-def dead %rax'
+      - '%rbp = POP64r implicit-def %rsp, implicit %rsp'
+      - RETQ
+...