[llvm] r245482 - MIR Serialization: Serialize instruction's register ties.

Alex Lorenz via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 12:05:35 PDT 2015


Author: arphaman
Date: Wed Aug 19 14:05:34 2015
New Revision: 245482

URL: http://llvm.org/viewvc/llvm-project?rev=245482&view=rev
Log:
MIR Serialization: Serialize instruction's register ties.

This commit serializes the machine instruction's register operand ties.
The ties are printed out only when the instructon has register ties that are
different from the ties that are specified in the instruction's description.

Added:
    llvm/trunk/test/CodeGen/MIR/X86/def-register-already-tied-error.mir
    llvm/trunk/test/CodeGen/MIR/X86/expected-integer-after-tied-def.mir
    llvm/trunk/test/CodeGen/MIR/X86/expected-tied-def-after-lparen.mir
    llvm/trunk/test/CodeGen/MIR/X86/invalid-tied-def-index-error.mir
    llvm/trunk/test/CodeGen/MIR/X86/tied-def-operand-invalid.mir
Modified:
    llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp
    llvm/trunk/lib/CodeGen/MIRParser/MILexer.h
    llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
    llvm/trunk/lib/CodeGen/MIRPrinter.cpp
    llvm/trunk/test/CodeGen/MIR/X86/inline-asm-registers.mir

Modified: llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp?rev=245482&r1=245481&r2=245482&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRParser/MILexer.cpp Wed Aug 19 14:05:34 2015
@@ -195,6 +195,7 @@ static MIToken::TokenKind getIdentifierK
       .Case("internal", MIToken::kw_internal)
       .Case("early-clobber", MIToken::kw_early_clobber)
       .Case("debug-use", MIToken::kw_debug_use)
+      .Case("tied-def", MIToken::kw_tied_def)
       .Case("frame-setup", MIToken::kw_frame_setup)
       .Case("debug-location", MIToken::kw_debug_location)
       .Case(".cfi_same_value", MIToken::kw_cfi_same_value)

Modified: llvm/trunk/lib/CodeGen/MIRParser/MILexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MILexer.h?rev=245482&r1=245481&r2=245482&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRParser/MILexer.h (original)
+++ llvm/trunk/lib/CodeGen/MIRParser/MILexer.h Wed Aug 19 14:05:34 2015
@@ -56,6 +56,7 @@ struct MIToken {
     kw_internal,
     kw_early_clobber,
     kw_debug_use,
+    kw_tied_def,
     kw_frame_setup,
     kw_debug_location,
     kw_cfi_same_value,

Modified: llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp?rev=245482&r1=245481&r2=245482&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp Wed Aug 19 14:05:34 2015
@@ -43,10 +43,16 @@ struct MachineOperandWithLocation {
   MachineOperand Operand;
   StringRef::iterator Begin;
   StringRef::iterator End;
+  Optional<unsigned> TiedDefIdx;
 
   MachineOperandWithLocation(const MachineOperand &Operand,
-                             StringRef::iterator Begin, StringRef::iterator End)
-      : Operand(Operand), Begin(Begin), End(End) {}
+                             StringRef::iterator Begin, StringRef::iterator End,
+                             Optional<unsigned> &TiedDefIdx)
+      : Operand(Operand), Begin(Begin), End(End), TiedDefIdx(TiedDefIdx) {
+    if (TiedDefIdx)
+      assert(Operand.isReg() && Operand.isUse() &&
+             "Only used register operands can be tied");
+  }
 };
 
 class MIParser {
@@ -111,7 +117,9 @@ public:
   bool parseRegister(unsigned &Reg);
   bool parseRegisterFlag(unsigned &Flags);
   bool parseSubRegisterIndex(unsigned &SubReg);
-  bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false);
+  bool parseRegisterTiedDefIndex(unsigned &TiedDefIdx);
+  bool parseRegisterOperand(MachineOperand &Dest,
+                            Optional<unsigned> &TiedDefIdx, bool IsDef = false);
   bool parseImmediateOperand(MachineOperand &Dest);
   bool parseIRConstant(StringRef::iterator Loc, const Constant *&C);
   bool parseTypedImmediateOperand(MachineOperand &Dest);
@@ -136,8 +144,10 @@ public:
   bool parseBlockAddressOperand(MachineOperand &Dest);
   bool parseTargetIndexOperand(MachineOperand &Dest);
   bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest);
-  bool parseMachineOperand(MachineOperand &Dest);
-  bool parseMachineOperandAndTargetFlags(MachineOperand &Dest);
+  bool parseMachineOperand(MachineOperand &Dest,
+                           Optional<unsigned> &TiedDefIdx);
+  bool parseMachineOperandAndTargetFlags(MachineOperand &Dest,
+                                         Optional<unsigned> &TiedDefIdx);
   bool parseOffset(int64_t &Offset);
   bool parseAlignment(unsigned &Alignment);
   bool parseOperandsOffset(MachineOperand &Op);
@@ -174,6 +184,9 @@ private:
 
   bool parseInstruction(unsigned &OpCode, unsigned &Flags);
 
+  bool assignRegisterTies(MachineInstr &MI,
+                          ArrayRef<MachineOperandWithLocation> Operands);
+
   bool verifyImplicitOperands(ArrayRef<MachineOperandWithLocation> Operands,
                               const MCInstrDesc &MCID);
 
@@ -552,9 +565,11 @@ bool MIParser::parse(MachineInstr *&MI)
   SmallVector<MachineOperandWithLocation, 8> Operands;
   while (Token.isRegister() || Token.isRegisterFlag()) {
     auto Loc = Token.location();
-    if (parseRegisterOperand(MO, /*IsDef=*/true))
+    Optional<unsigned> TiedDefIdx;
+    if (parseRegisterOperand(MO, TiedDefIdx, /*IsDef=*/true))
       return true;
-    Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
+    Operands.push_back(
+        MachineOperandWithLocation(MO, Loc, Token.location(), TiedDefIdx));
     if (Token.isNot(MIToken::comma))
       break;
     lex();
@@ -570,9 +585,11 @@ bool MIParser::parse(MachineInstr *&MI)
   while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_debug_location) &&
          Token.isNot(MIToken::coloncolon) && Token.isNot(MIToken::lbrace)) {
     auto Loc = Token.location();
-    if (parseMachineOperandAndTargetFlags(MO))
+    Optional<unsigned> TiedDefIdx;
+    if (parseMachineOperandAndTargetFlags(MO, TiedDefIdx))
       return true;
-    Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
+    Operands.push_back(
+        MachineOperandWithLocation(MO, Loc, Token.location(), TiedDefIdx));
     if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon) ||
         Token.is(MIToken::lbrace))
       break;
@@ -621,6 +638,8 @@ bool MIParser::parse(MachineInstr *&MI)
   MI->setFlags(Flags);
   for (const auto &Operand : Operands)
     MI->addOperand(MF, Operand.Operand);
+  if (assignRegisterTies(*MI, Operands))
+    return true;
   if (MemOperands.empty())
     return false;
   MachineInstr::mmo_iterator MemRefs =
@@ -861,7 +880,59 @@ bool MIParser::parseSubRegisterIndex(uns
   return false;
 }
 
-bool MIParser::parseRegisterOperand(MachineOperand &Dest, bool IsDef) {
+bool MIParser::parseRegisterTiedDefIndex(unsigned &TiedDefIdx) {
+  if (!consumeIfPresent(MIToken::kw_tied_def))
+    return error("expected 'tied-def' after '('");
+  if (Token.isNot(MIToken::IntegerLiteral))
+    return error("expected an integer literal after 'tied-def'");
+  if (getUnsigned(TiedDefIdx))
+    return true;
+  lex();
+  if (expectAndConsume(MIToken::rparen))
+    return true;
+  return false;
+}
+
+bool MIParser::assignRegisterTies(
+    MachineInstr &MI, ArrayRef<MachineOperandWithLocation> Operands) {
+  SmallVector<std::pair<unsigned, unsigned>, 4> TiedRegisterPairs;
+  for (unsigned I = 0, E = Operands.size(); I != E; ++I) {
+    if (!Operands[I].TiedDefIdx)
+      continue;
+    // The parser ensures that this operand is a register use, so we just have
+    // to check the tied-def operand.
+    unsigned DefIdx = Operands[I].TiedDefIdx.getValue();
+    if (DefIdx >= E)
+      return error(Operands[I].Begin,
+                   Twine("use of invalid tied-def operand index '" +
+                         Twine(DefIdx) + "'; instruction has only ") +
+                       Twine(E) + " operands");
+    const auto &DefOperand = Operands[DefIdx].Operand;
+    if (!DefOperand.isReg() || !DefOperand.isDef())
+      // FIXME: add note with the def operand.
+      return error(Operands[I].Begin,
+                   Twine("use of invalid tied-def operand index '") +
+                       Twine(DefIdx) + "'; the operand #" + Twine(DefIdx) +
+                       " isn't a defined register");
+    // Check that the tied-def operand wasn't tied elsewhere.
+    for (const auto &TiedPair : TiedRegisterPairs) {
+      if (TiedPair.first == DefIdx)
+        return error(Operands[I].Begin,
+                     Twine("the tied-def operand #") + Twine(DefIdx) +
+                         " is already tied with another register operand");
+    }
+    TiedRegisterPairs.push_back(std::make_pair(DefIdx, I));
+  }
+  // FIXME: Verify that for non INLINEASM instructions, the def and use tied
+  // indices must be less than tied max.
+  for (const auto &TiedPair : TiedRegisterPairs)
+    MI.tieOperands(TiedPair.first, TiedPair.second);
+  return false;
+}
+
+bool MIParser::parseRegisterOperand(MachineOperand &Dest,
+                                    Optional<unsigned> &TiedDefIdx,
+                                    bool IsDef) {
   unsigned Reg;
   unsigned Flags = IsDef ? RegState::Define : 0;
   while (Token.isRegisterFlag()) {
@@ -878,6 +949,12 @@ bool MIParser::parseRegisterOperand(Mach
     if (parseSubRegisterIndex(SubReg))
       return true;
   }
+  if ((Flags & RegState::Define) == 0 && consumeIfPresent(MIToken::lparen)) {
+    unsigned Idx;
+    if (parseRegisterTiedDefIndex(Idx))
+      return true;
+    TiedDefIdx = Idx;
+  }
   Dest = MachineOperand::CreateReg(
       Reg, Flags & RegState::Define, Flags & RegState::Implicit,
       Flags & RegState::Kill, Flags & RegState::Dead, Flags & RegState::Undef,
@@ -1296,7 +1373,8 @@ bool MIParser::parseLiveoutRegisterMaskO
   return false;
 }
 
-bool MIParser::parseMachineOperand(MachineOperand &Dest) {
+bool MIParser::parseMachineOperand(MachineOperand &Dest,
+                                   Optional<unsigned> &TiedDefIdx) {
   switch (Token.kind()) {
   case MIToken::kw_implicit:
   case MIToken::kw_implicit_define:
@@ -1310,7 +1388,7 @@ bool MIParser::parseMachineOperand(Machi
   case MIToken::underscore:
   case MIToken::NamedRegister:
   case MIToken::VirtualRegister:
-    return parseRegisterOperand(Dest);
+    return parseRegisterOperand(Dest, TiedDefIdx);
   case MIToken::IntegerLiteral:
     return parseImmediateOperand(Dest);
   case MIToken::IntegerType:
@@ -1367,7 +1445,8 @@ bool MIParser::parseMachineOperand(Machi
   return false;
 }
 
-bool MIParser::parseMachineOperandAndTargetFlags(MachineOperand &Dest) {
+bool MIParser::parseMachineOperandAndTargetFlags(
+    MachineOperand &Dest, Optional<unsigned> &TiedDefIdx) {
   unsigned TF = 0;
   bool HasTargetFlags = false;
   if (Token.is(MIToken::kw_target_flags)) {
@@ -1399,7 +1478,7 @@ bool MIParser::parseMachineOperandAndTar
       return true;
   }
   auto Loc = Token.location();
-  if (parseMachineOperand(Dest))
+  if (parseMachineOperand(Dest, TiedDefIdx))
     return true;
   if (!HasTargetFlags)
     return false;

Modified: llvm/trunk/lib/CodeGen/MIRPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRPrinter.cpp?rev=245482&r1=245481&r2=245482&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp Wed Aug 19 14:05:34 2015
@@ -117,7 +117,7 @@ public:
   void printOffset(int64_t Offset);
   void printTargetFlags(const MachineOperand &Op);
   void print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
-             bool IsDef = false);
+             unsigned I, bool ShouldPrintRegisterTies, bool IsDef = false);
   void print(const MachineMemOperand &Op);
 
   void print(const MCCFIInstruction &CFI, const TargetRegisterInfo *TRI);
@@ -502,6 +502,23 @@ void MIPrinter::print(const MachineBasic
     OS.indent(2) << "}\n";
 }
 
+/// Return true when an instruction has tied register that can't be determined
+/// by the instruction's descriptor.
+static bool hasComplexRegisterTies(const MachineInstr &MI) {
+  const MCInstrDesc &MCID = MI.getDesc();
+  for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
+    const auto &Operand = MI.getOperand(I);
+    if (!Operand.isReg() || Operand.isDef())
+      // Ignore the defined registers as MCID marks only the uses as tied.
+      continue;
+    int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO);
+    int TiedIdx = Operand.isTied() ? int(MI.findTiedOperandIdx(I)) : -1;
+    if (ExpectedTiedIdx != TiedIdx)
+      return true;
+  }
+  return false;
+}
+
 void MIPrinter::print(const MachineInstr &MI) {
   const auto &SubTarget = MI.getParent()->getParent()->getSubtarget();
   const auto *TRI = SubTarget.getRegisterInfo();
@@ -511,13 +528,14 @@ void MIPrinter::print(const MachineInstr
   if (MI.isCFIInstruction())
     assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
 
+  bool ShouldPrintRegisterTies = hasComplexRegisterTies(MI);
   unsigned I = 0, E = MI.getNumOperands();
   for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
          !MI.getOperand(I).isImplicit();
        ++I) {
     if (I)
       OS << ", ";
-    print(MI.getOperand(I), TRI, /*IsDef=*/true);
+    print(MI.getOperand(I), TRI, I, ShouldPrintRegisterTies, /*IsDef=*/true);
   }
 
   if (I)
@@ -532,7 +550,7 @@ void MIPrinter::print(const MachineInstr
   for (; I < E; ++I) {
     if (NeedComma)
       OS << ", ";
-    print(MI.getOperand(I), TRI);
+    print(MI.getOperand(I), TRI, I, ShouldPrintRegisterTies);
     NeedComma = true;
   }
 
@@ -690,11 +708,10 @@ static const char *getTargetIndexName(co
 }
 
 void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
-                      bool IsDef) {
+                      unsigned I, bool ShouldPrintRegisterTies, 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())
@@ -716,6 +733,8 @@ void MIPrinter::print(const MachineOpera
     // Print the sub register.
     if (Op.getSubReg() != 0)
       OS << ':' << TRI->getSubRegIndexName(Op.getSubReg());
+    if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef())
+      OS << "(tied-def " << Op.getParent()->findTiedOperandIdx(I) << ")";
     break;
   case MachineOperand::MO_Immediate:
     OS << Op.getImm();

Added: llvm/trunk/test/CodeGen/MIR/X86/def-register-already-tied-error.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/def-register-already-tied-error.mir?rev=245482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/def-register-already-tied-error.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/def-register-already-tied-error.mir Wed Aug 19 14:05:34 2015
@@ -0,0 +1,25 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define i64 @test(i64 %x) #0 {
+  entry:
+    %asm = tail call i64 asm sideeffect "$foo", "=r,0"(i64 %x) nounwind
+    ret i64 %asm
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi
+
+  ; CHECK: [[@LINE+1]]:83: the tied-def operand #3 is already tied with another register operand
+    INLINEASM $"$foo", 1, 2818058, def %rdi, 2147483657, killed %rdi(tied-def 3), killed %rdi(tied-def 3)
+    %rax = COPY killed %rdi
+    RETQ killed %rax
+...

Added: llvm/trunk/test/CodeGen/MIR/X86/expected-integer-after-tied-def.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-integer-after-tied-def.mir?rev=245482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/expected-integer-after-tied-def.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/expected-integer-after-tied-def.mir Wed Aug 19 14:05:34 2015
@@ -0,0 +1,25 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define i64 @test(i64 %x) #0 {
+  entry:
+    %asm = tail call i64 asm sideeffect "$foo", "=r,0"(i64 %x) nounwind
+    ret i64 %asm
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi
+
+  ; CHECK: [[@LINE+1]]:78: expected an integer literal after 'tied-def'
+    INLINEASM $"$foo", 1, 2818058, def %rdi, 2147483657, killed %rdi(tied-def)
+    %rax = COPY killed %rdi
+    RETQ killed %rax
+...

Added: llvm/trunk/test/CodeGen/MIR/X86/expected-tied-def-after-lparen.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-tied-def-after-lparen.mir?rev=245482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/expected-tied-def-after-lparen.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/expected-tied-def-after-lparen.mir Wed Aug 19 14:05:34 2015
@@ -0,0 +1,25 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define i64 @test(i64 %x) #0 {
+  entry:
+    %asm = tail call i64 asm sideeffect "$foo", "=r,0"(i64 %x) nounwind
+    ret i64 %asm
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi
+
+  ; CHECK: [[@LINE+1]]:70: expected 'tied-def' after '('
+    INLINEASM $"$foo", 1, 2818058, def %rdi, 2147483657, killed %rdi(3)
+    %rax = COPY killed %rdi
+    RETQ killed %rax
+...

Modified: llvm/trunk/test/CodeGen/MIR/X86/inline-asm-registers.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/inline-asm-registers.mir?rev=245482&r1=245481&r2=245482&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/inline-asm-registers.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/inline-asm-registers.mir Wed Aug 19 14:05:34 2015
@@ -8,6 +8,13 @@
     ret i64 %x1
   }
 
+  define i64 @test2(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 }
 ...
 ---
@@ -27,3 +34,21 @@ body: |
     %rax = MOV64rr killed %rsi
     RETQ killed %rax
 ...
+---
+name:            test2
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+  - { reg: '%rsi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi, %rsi
+
+  ; Verify that the register ties are preserved.
+  ; CHECK-LABEL: name: test2
+  ; CHECK: INLINEASM $foo, 0, 2818058, def %rsi, 2818058, def dead %rdi, 2147549193, killed %rdi(tied-def 5), 2147483657, killed %rsi(tied-def 3), 12, implicit-def dead early-clobber %eflags
+    INLINEASM $foo, 0, 2818058, def %rsi, 2818058, def dead %rdi, 2147549193, killed %rdi(tied-def 5), 2147483657, killed %rsi(tied-def 3), 12, implicit-def dead early-clobber %eflags
+    %rax = MOV64rr killed %rsi
+    RETQ killed %rax
+...

Added: llvm/trunk/test/CodeGen/MIR/X86/invalid-tied-def-index-error.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/invalid-tied-def-index-error.mir?rev=245482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/invalid-tied-def-index-error.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/invalid-tied-def-index-error.mir Wed Aug 19 14:05:34 2015
@@ -0,0 +1,25 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define i64 @test(i64 %x) #0 {
+  entry:
+    %asm = tail call i64 asm sideeffect "$foo", "=r,0"(i64 %x) nounwind
+    ret i64 %asm
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi
+
+  ; CHECK: [[@LINE+1]]:58: use of invalid tied-def operand index '300'; instruction has only 6 operands
+    INLINEASM $"$foo", 1, 2818058, def %rdi, 2147483657, killed %rdi(tied-def 300)
+    %rax = COPY killed %rdi
+    RETQ killed %rax
+...

Added: llvm/trunk/test/CodeGen/MIR/X86/tied-def-operand-invalid.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/tied-def-operand-invalid.mir?rev=245482&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/tied-def-operand-invalid.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/tied-def-operand-invalid.mir Wed Aug 19 14:05:34 2015
@@ -0,0 +1,25 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+--- |
+  define i64 @test(i64 %x) #0 {
+  entry:
+    %asm = tail call i64 asm sideeffect "$foo", "=r,0"(i64 %x) nounwind
+    ret i64 %asm
+  }
+
+  attributes #0 = { nounwind }
+...
+---
+name:            test
+hasInlineAsm:    true
+tracksRegLiveness: true
+liveins:
+  - { reg: '%rdi' }
+body: |
+  bb.0.entry:
+    liveins: %rdi
+
+  ; CHECK: [[@LINE+1]]:58: use of invalid tied-def operand index '0'; the operand #0 isn't a defined register
+    INLINEASM $"$foo", 1, 2818058, def %rdi, 2147483657, killed %rdi(tied-def 0)
+    %rax = COPY killed %rdi
+    RETQ killed %rax
+...




More information about the llvm-commits mailing list