MIR Serialization: Serialize defined registers that require 'def' register flag.
authorAlex Lorenz <arphaman@gmail.com>
Wed, 19 Aug 2015 18:55:47 +0000 (18:55 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Wed, 19 Aug 2015 18:55:47 +0000 (18:55 +0000)
The defined registers are already serialized - they are represented by placing
them before the '=' in a machine instruction. However, certain instructions like
INLINEASM can have defined register operands after the '=', so this commit
introduces the 'def' register flag for such operands.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245480 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/inline-asm-registers.mir [new file with mode: 0644]

index 68c5e8af1a60bbc9e94eec531ae8cfbf8196ebeb..034a7d6e980801089c361264bc65115fedee942a 100644 (file)
@@ -188,6 +188,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
       .Case("_", MIToken::underscore)
       .Case("implicit", MIToken::kw_implicit)
       .Case("implicit-def", MIToken::kw_implicit_define)
+      .Case("def", MIToken::kw_def)
       .Case("dead", MIToken::kw_dead)
       .Case("killed", MIToken::kw_killed)
       .Case("undef", MIToken::kw_undef)
index fe8fc091b44c4632b9b9d8267df9e1f18dcc85bb..f0702fa01afb8fb1c6253b8aed1a33a46218c6db 100644 (file)
@@ -49,6 +49,7 @@ struct MIToken {
     // Keywords
     kw_implicit,
     kw_implicit_define,
+    kw_def,
     kw_dead,
     kw_killed,
     kw_undef,
@@ -145,9 +146,9 @@ public:
 
   bool isRegisterFlag() const {
     return Kind == kw_implicit || Kind == kw_implicit_define ||
-           Kind == kw_dead || Kind == kw_killed || Kind == kw_undef ||
-           Kind == kw_internal || Kind == kw_early_clobber ||
-           Kind == kw_debug_use;
+           Kind == kw_def || Kind == kw_dead || Kind == kw_killed ||
+           Kind == kw_undef || Kind == kw_internal ||
+           Kind == kw_early_clobber || Kind == kw_debug_use;
   }
 
   bool isMemoryOperandFlag() const {
index edfca5f88a423f96f804d1a53098f1a1bd72f30c..481bc1da981e8614c31bb38f2ef05dba7658512e 100644 (file)
@@ -816,6 +816,9 @@ bool MIParser::parseRegisterFlag(unsigned &Flags) {
   case MIToken::kw_implicit_define:
     Flags |= RegState::ImplicitDefine;
     break;
+  case MIToken::kw_def:
+    Flags |= RegState::Define;
+    break;
   case MIToken::kw_dead:
     Flags |= RegState::Dead;
     break;
@@ -1297,6 +1300,7 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest) {
   switch (Token.kind()) {
   case MIToken::kw_implicit:
   case MIToken::kw_implicit_define:
+  case MIToken::kw_def:
   case MIToken::kw_dead:
   case MIToken::kw_killed:
   case MIToken::kw_undef:
index faeb9055c2381d8581ed2cdc968a69afc2156f79..5d3c2999a11aa0ea3f4d388e1d455df382c1d1a1 100644 (file)
@@ -116,7 +116,8 @@ public:
   void printStackObjectReference(int FrameIndex);
   void printOffset(int64_t Offset);
   void printTargetFlags(const MachineOperand &Op);
-  void print(const MachineOperand &Op, const TargetRegisterInfo *TRI);
+  void print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
+             bool IsDef = false);
   void print(const MachineMemOperand &Op);
 
   void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI);
@@ -516,7 +517,7 @@ void MIPrinter::print(const MachineInstr &MI) {
        ++I) {
     if (I)
       OS << ", ";
-    print(MI.getOperand(I), TRI);
+    print(MI.getOperand(I), TRI, /*IsDef=*/true);
   }
 
   if (I)
@@ -688,13 +689,17 @@ static const char *getTargetIndexName(const MachineFunction &MF, int Index) {
   return nullptr;
 }
 
-void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) {
+void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
+                      bool IsDef) {
   printTargetFlags(Op);
   switch (Op.getType()) {
   case MachineOperand::MO_Register:
     // FIXME: Serialize the tied register.
     if (Op.isImplicit())
       OS << (Op.isDef() ? "implicit-def " : "implicit ");
+    else if (!IsDef && Op.isDef())
+      // Print the 'def' flag only when the operand is defined after '='.
+      OS << "def ";
     if (Op.isInternalRead())
       OS << "internal ";
     if (Op.isDead())
diff --git a/test/CodeGen/MIR/X86/inline-asm-registers.mir b/test/CodeGen/MIR/X86/inline-asm-registers.mir
new file mode 100644 (file)
index 0000000..cad1d22
--- /dev/null
@@ -0,0 +1,29 @@
+# RUN: llc -march=x86-64 -start-after block-placement -stop-after block-placement -o /dev/null %s | FileCheck %s
+
+--- |
+  define i64 @test(i64 %x, i64 %y) #0 {
+  entry:
+    %x0 = call { i64, i64 } asm "foo", "=r,=r,1,0,~{dirflag},~{fpsr},~{flags}"(i64 %x, i64 %y) #0
+    %x1 = extractvalue { i64, i64 } %x0, 0
+    ret i64 %x1
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+  - { reg: '%rsi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi, %rsi
+
+  ; CHECK-LABEL: name: test
+  ; CHECK: INLINEASM $foo, 0, 2818058, def %rsi, 2818058, def dead %rdi,
+    INLINEASM $foo, 0, 2818058, def %rsi, 2818058, def dead %rdi, 2147549193, killed %rdi, 2147483657, killed %rsi, 12, implicit-def dead early-clobber %eflags
+    %rax = MOV64rr killed %rsi
+    RETQ killed %rax
+...