<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.25in 1.0in 1.25in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D">There is indeed a bug in my code because there’s an overloading of the “movsd” and “cmpsd” instructions, e.g. movsd can be either “Move Data from String to String”
 (the case I wanted to handle) or “Move or Merge Scalar Double-Precision Floating-Point Value” (the case that causes the unreachable).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D">Will have a fix soon.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D">BTW, you were right to change the asserts to llvm_unreachanbles.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D">Thanks,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D">Marina<o:p></o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;color:#1F497D"><o:p> </o:p></span></a></p>
<p class="MsoNormal"><a name="_____replyseparator"></a><b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif">From:</span></b><span style="font-size:11.0pt;font-family:"Calibri",sans-serif"> Diego Novillo [mailto:dnovillo@google.com]
<br>
<b>Sent:</b> Wednesday, January 20, 2016 03:56<br>
<b>To:</b> Yatsina, Marina<br>
<b>Cc:</b> llvm-commits@lists.llvm.org<br>
<b>Subject:</b> Re: [llvm] r258132 - [X86] Adding support for missing variations of X86 string related instructions<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">There seems to be something buggy with this patch.  In our internal builds, we enable -Wstring-conversion.  This picked up a couple of bad invocations of assert() in the patch:<o:p></o:p></p>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal">    lib/Target/X86/AsmParser/X86AsmParser.cpp:1010:12: error: implicit conversion turns string literal into bool: 'const char [39]' to 'bool' [-Werror,-Wstring-conversion]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    lib/Target/X86/AsmParser/X86AsmParser.cpp:1027:12: error: implicit conversion turns string literal into bool: 'const char [26]' to 'bool' [-Werror,-Wstring-conversion]<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I fixed them by turning the assertions into llvm_unreachable() calls:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal">-    assert("Only (R|E)SI and (R|E)DI are expected!");<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">+    llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal">-    assert("Unexpected register class");<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">+    llvm_unreachable("Unexpected register class");<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">It turns out, that we are hitting these assertions in a couple of tests which are now failing with my patch.  I believe this points to a problem with the original patch (r258132).   These tests are now failing:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal">Failing Tests (2):<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    LLVM :: CodeGen/X86/pr3154.ll<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">    LLVM :: MC/X86/x86-32-coverage.s<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">They are both hitting the llvm_unreachable("Unexpected register class") at lib/Target/X86/AsmParser/X86AsmParser.cpp:1027<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Could you take a look or revert?  Perhaps the intention was not to assert something else at that point?<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Thanks.  Diego.<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">On Tue, Jan 19, 2016 at 7:37 AM, Marina Yatsina via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<o:p></o:p></p>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal">Author: myatsina<br>
Date: Tue Jan 19 09:37:56 2016<br>
New Revision: 258132<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=258132&view=rev" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=258132&view=rev</a><br>
Log:<br>
[X86] Adding support for missing variations of X86 string related instructions<br>
<br>
The following are legal according to X86 spec:<br>
ins mem, DX<br>
outs DX, mem<br>
lods mem<br>
stos mem<br>
scas mem<br>
cmps mem, mem<br>
movs mem, mem<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D14827" target="_blank">http://reviews.llvm.org/D14827</a><br>
<br>
<br>
Modified:<br>
    llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp<br>
    llvm/trunk/lib/Target/X86/X86InstrInfo.td<br>
    llvm/trunk/test/MC/X86/index-operations.s<br>
    llvm/trunk/test/MC/X86/intel-syntax.s<br>
<br>
Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=258132&r1=258131&r2=258132&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=258132&r1=258131&r2=258132&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Tue Jan 19 09:37:56 2016<br>
@@ -683,9 +683,14 @@ private:<br>
<br>
   std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);<br>
   std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);<br>
-  void AddDefaultSrcDestOperands(<br>
-      OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,<br>
-      std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);<br>
+  bool IsSIReg(unsigned Reg);<br>
+  unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg);<br>
+  void<br>
+  AddDefaultSrcDestOperands(OperandVector &Operands,<br>
+                            std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,<br>
+                            std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);<br>
+  bool VerifyAndAdjustOperands(OperandVector &OrigOperands,<br>
+                               OperandVector &FinalOperands);<br>
   std::unique_ptr<X86Operand> ParseOperand();<br>
   std::unique_ptr<X86Operand> ParseATTOperand();<br>
   std::unique_ptr<X86Operand> ParseIntelOperand();<br>
@@ -747,11 +752,6 @@ private:<br>
<br>
   bool OmitRegisterFromClobberLists(unsigned RegNo) override;<br>
<br>
-  /// doSrcDstMatch - Returns true if operands are matching in their<br>
-  /// word size (%si and %di, %esi and %edi, etc.). Order depends on<br>
-  /// the parsing mode (Intel vs. AT&T).<br>
-  bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2);<br>
-<br>
   /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})<br>
   /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.<br>
   /// \return \c true if no parsing errors occurred, \c false otherwise.<br>
@@ -867,27 +867,6 @@ static bool CheckBaseRegAndIndexReg(unsi<br>
   return false;<br>
 }<br>
<br>
-bool X86AsmParser::doSrcDstMatch(X86Operand &Op1, X86Operand &Op2)<br>
-{<br>
-  // Return true and let a normal complaint about bogus operands happen.<br>
-  if (!Op1.isMem() || !Op2.isMem())<br>
-    return true;<br>
-<br>
-  // Actually these might be the other way round if Intel syntax is<br>
-  // being used. It doesn't matter.<br>
-  unsigned diReg = Op1.Mem.BaseReg;<br>
-  unsigned siReg = Op2.Mem.BaseReg;<br>
-<br>
-  if (X86MCRegisterClasses[X86::GR16RegClassID].contains(siReg))<br>
-    return X86MCRegisterClasses[X86::GR16RegClassID].contains(diReg);<br>
-  if (X86MCRegisterClasses[X86::GR32RegClassID].contains(siReg))<br>
-    return X86MCRegisterClasses[X86::GR32RegClassID].contains(diReg);<br>
-  if (X86MCRegisterClasses[X86::GR64RegClassID].contains(siReg))<br>
-    return X86MCRegisterClasses[X86::GR64RegClassID].contains(diReg);<br>
-  // Again, return true and let another error happen.<br>
-  return true;<br>
-}<br>
-<br>
 bool X86AsmParser::ParseRegister(unsigned &RegNo,<br>
                                  SMLoc &StartLoc, SMLoc &EndLoc) {<br>
   MCAsmParser &Parser = getParser();<br>
@@ -1025,6 +1004,37 @@ std::unique_ptr<X86Operand> X86AsmParser<br>
                                Loc, Loc, 0);<br>
 }<br>
<br>
+bool X86AsmParser::IsSIReg(unsigned Reg) {<br>
+  switch (Reg) {<br>
+  default:<br>
+    assert("Only (R|E)SI and (R|E)DI are expected!");<br>
+    return false;<br>
+  case X86::RSI:<br>
+  case X86::ESI:<br>
+  case X86::SI:<br>
+    return true;<br>
+  case X86::RDI:<br>
+  case X86::EDI:<br>
+  case X86::DI:<br>
+    return false;<br>
+  }<br>
+}<br>
+<br>
+unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg,<br>
+                                          bool IsSIReg) {<br>
+  switch (RegClassID) {<br>
+  default:<br>
+    assert("Unexpected register class");<br>
+    return Reg;<br>
+  case X86::GR64RegClassID:<br>
+    return IsSIReg ? X86::RSI : X86::RDI;<br>
+  case X86::GR32RegClassID:<br>
+    return IsSIReg ? X86::ESI : X86::EDI;<br>
+  case X86::GR16RegClassID:<br>
+    return IsSIReg ? X86::SI : X86::DI;<br>
+  }<br>
+}<br>
+<br>
 void X86AsmParser::AddDefaultSrcDestOperands(<br>
     OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,<br>
     std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {<br>
@@ -1038,6 +1048,76 @@ void X86AsmParser::AddDefaultSrcDestOper<br>
   }<br>
 }<br>
<br>
+bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,<br>
+                                           OperandVector &FinalOperands) {<br>
+<br>
+  if (OrigOperands.size() > 1) {<br>
+    // Check if sizes match, OrigOpernads also contains the instruction name<br>
+    assert(OrigOperands.size() == FinalOperands.size() + 1 &&<br>
+           "Opernand size mismatch");<br>
+<br>
+    // Verify types match<br>
+    int RegClassID = -1;<br>
+    for (unsigned int i = 0; i < FinalOperands.size(); ++i) {<br>
+      X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);<br>
+      X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);<br>
+<br>
+      if (FinalOp.isReg() &&<br>
+          (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))<br>
+        // Return false and let a normal complaint about bogus operands happen<br>
+        return false;<br>
+<br>
+      if (FinalOp.isMem()) {<br>
+<br>
+        if (!OrigOp.isMem())<br>
+          // Return false and let a normal complaint about bogus operands happen<br>
+          return false;<br>
+<br>
+        unsigned OrigReg = OrigOp.Mem.BaseReg;<br>
+        unsigned FinalReg = FinalOp.Mem.BaseReg;<br>
+<br>
+        // If we've already encounterd a register class, make sure all register<br>
+        // bases are of the same register class<br>
+        if (RegClassID != -1 &&<br>
+            !X86MCRegisterClasses[RegClassID].contains(OrigReg)) {<br>
+          return Error(OrigOp.getStartLoc(),<br>
+                       "mismatching source and destination index registers");<br>
+        }<br>
+<br>
+        if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg))<br>
+          RegClassID = X86::GR64RegClassID;<br>
+        else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg))<br>
+          RegClassID = X86::GR32RegClassID;<br>
+        else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg))<br>
+          RegClassID = X86::GR16RegClassID;<br>
+<br>
+        bool IsSI = IsSIReg(FinalReg);<br>
+        FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);<br>
+<br>
+        if (FinalReg != OrigReg) {<br>
+          std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";<br>
+          Warning(OrigOp.getStartLoc(),<br>
+                  "memory operand is only for determining the size, " +<br>
+                      RegName + " will be used for the location");<br>
+        }<br>
+<br>
+        FinalOp.Mem.Size = OrigOp.Mem.Size;<br>
+        FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;<br>
+        FinalOp.Mem.BaseReg = FinalReg;<br>
+      }<br>
+    }<br>
+<br>
+    // Remove old operandss<br>
+    for (unsigned int i = 0; i < FinalOperands.size(); ++i)<br>
+      OrigOperands.pop_back();<br>
+  }<br>
+  // OrigOperands.append(FinalOperands.begin(), FinalOperands.end());<br>
+  for (unsigned int i = 0; i < FinalOperands.size(); ++i)<br>
+    OrigOperands.push_back(std::move(FinalOperands[i]));<br>
+<br>
+  return false;<br>
+}<br>
+<br>
 std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() {<br>
   if (isParsingIntelSyntax())<br>
     return ParseIntelOperand();<br>
@@ -2274,84 +2354,92 @@ bool X86AsmParser::ParseInstruction(Pars<br>
     }<br>
   }<br>
<br>
+  SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;<br>
+  bool HadVerifyError = false;<br>
+<br>
   // Append default arguments to "ins[bwld]"<br>
-  if (Name.startswith("ins") && Operands.size() == 1 &&<br>
-      (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd")) {<br>
-    AddDefaultSrcDestOperands(Operands,<br>
+  if (Name.startswith("ins") &&<br>
+      (Operands.size() == 1 || Operands.size() == 3) &&<br>
+      (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||<br>
+       Name == "ins")) {<br>
+<br>
+    AddDefaultSrcDestOperands(TmpOperands,<br>
                               X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),<br>
                               DefaultMemDIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
   }<br>
<br>
   // Append default arguments to "outs[bwld]"<br>
-  if (Name.startswith("outs") && Operands.size() == 1 &&<br>
+  if (Name.startswith("outs") &&<br>
+      (Operands.size() == 1 || Operands.size() == 3) &&<br>
       (Name == "outsb" || Name == "outsw" || Name == "outsl" ||<br>
-       Name == "outsd" )) {<br>
-    AddDefaultSrcDestOperands(Operands,<br>
-                              DefaultMemSIOperand(NameLoc),<br>
+       Name == "outsd" || Name == "outs")) {<br>
+    AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),<br>
                               X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
   }<br>
<br>
   // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate<br>
   // values of $SIREG according to the mode. It would be nice if this<br>
   // could be achieved with InstAlias in the tables.<br>
-  if (Name.startswith("lods") && Operands.size() == 1 &&<br>
+  if (Name.startswith("lods") &&<br>
+      (Operands.size() == 1 || Operands.size() == 2) &&<br>
       (Name == "lods" || Name == "lodsb" || Name == "lodsw" ||<br>
-       Name == "lodsl" || Name == "lodsd" || Name == "lodsq"))<br>
-    Operands.push_back(DefaultMemSIOperand(NameLoc));<br>
+       Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {<br>
+    TmpOperands.push_back(DefaultMemSIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
+  }<br>
<br>
   // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate<br>
   // values of $DIREG according to the mode. It would be nice if this<br>
   // could be achieved with InstAlias in the tables.<br>
-  if (Name.startswith("stos") && Operands.size() == 1 &&<br>
+  if (Name.startswith("stos") &&<br>
+      (Operands.size() == 1 || Operands.size() == 2) &&<br>
       (Name == "stos" || Name == "stosb" || Name == "stosw" ||<br>
-       Name == "stosl" || Name == "stosd" || Name == "stosq"))<br>
-    Operands.push_back(DefaultMemDIOperand(NameLoc));<br>
+       Name == "stosl" || Name == "stosd" || Name == "stosq")) {<br>
+    TmpOperands.push_back(DefaultMemDIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
+  }<br>
<br>
   // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate<br>
   // values of $DIREG according to the mode. It would be nice if this<br>
   // could be achieved with InstAlias in the tables.<br>
-  if (Name.startswith("scas") && Operands.size() == 1 &&<br>
+  if (Name.startswith("scas") &&<br>
+      (Operands.size() == 1 || Operands.size() == 2) &&<br>
       (Name == "scas" || Name == "scasb" || Name == "scasw" ||<br>
-       Name == "scasl" || Name == "scasd" || Name == "scasq"))<br>
-    Operands.push_back(DefaultMemDIOperand(NameLoc));<br>
+       Name == "scasl" || Name == "scasd" || Name == "scasq")) {<br>
+    TmpOperands.push_back(DefaultMemDIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
+  }<br>
<br>
   // Add default SI and DI operands to "cmps[bwlq]".<br>
   if (Name.startswith("cmps") &&<br>
+      (Operands.size() == 1 || Operands.size() == 3) &&<br>
       (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||<br>
        Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {<br>
-    if (Operands.size() == 1) {<br>
-      AddDefaultSrcDestOperands(Operands,<br>
-                                DefaultMemDIOperand(NameLoc),<br>
-                                DefaultMemSIOperand(NameLoc));<br>
-    } else if (Operands.size() == 3) {<br>
-      X86Operand &Op = (X86Operand &)*Operands[1];<br>
-      X86Operand &Op2 = (X86Operand &)*Operands[2];<br>
-      if (!doSrcDstMatch(Op, Op2))<br>
-        return Error(Op.getStartLoc(),<br>
-                     "mismatching source and destination index registers");<br>
-    }<br>
+    AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),<br>
+                              DefaultMemSIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
   }<br>
<br>
   // Add default SI and DI operands to "movs[bwlq]".<br>
-  if ((Name.startswith("movs") &&<br>
-      (Name == "movs" || Name == "movsb" || Name == "movsw" ||<br>
-       Name == "movsl" || Name == "movsd" || Name == "movsq")) ||<br>
-      (Name.startswith("smov") &&<br>
-      (Name == "smov" || Name == "smovb" || Name == "smovw" ||<br>
-       Name == "smovl" || Name == "smovd" || Name == "smovq"))) {<br>
-    if (Operands.size() == 1) {<br>
-      if (Name == "movsd")<br>
-        Operands.back() = X86Operand::CreateToken("movsl", NameLoc);<br>
-      AddDefaultSrcDestOperands(Operands,<br>
-                                DefaultMemSIOperand(NameLoc),<br>
-                                DefaultMemDIOperand(NameLoc));<br>
-    } else if (Operands.size() == 3) {<br>
-      X86Operand &Op = (X86Operand &)*Operands[1];<br>
-      X86Operand &Op2 = (X86Operand &)*Operands[2];<br>
-      if (!doSrcDstMatch(Op, Op2))<br>
-        return Error(Op.getStartLoc(),<br>
-                     "mismatching source and destination index registers");<br>
-    }<br>
+  if (((Name.startswith("movs") &&<br>
+        (Name == "movs" || Name == "movsb" || Name == "movsw" ||<br>
+         Name == "movsl" || Name == "movsd" || Name == "movsq")) ||<br>
+       (Name.startswith("smov") &&<br>
+        (Name == "smov" || Name == "smovb" || Name == "smovw" ||<br>
+         Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&<br>
+      (Operands.size() == 1 || Operands.size() == 3)) {<br>
+    if (Name == "movsd" && Operands.size() == 1)<br>
+      Operands.back() = X86Operand::CreateToken("movsl", NameLoc);<br>
+    AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),<br>
+                              DefaultMemDIOperand(NameLoc));<br>
+    HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);<br>
+  }<br>
+<br>
+  // Check if we encountered an error for one the string insturctions<br>
+  if (HadVerifyError) {<br>
+    return HadVerifyError;<br>
   }<br>
<br>
   // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>.  Canonicalize to<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=258132&r1=258131&r2=258132&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=258132&r1=258131&r2=258132&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)<br>
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Tue Jan 19 09:37:56 2016<br>
@@ -2782,6 +2782,11 @@ def : InstAlias<"lods\t{$src, %al|al, $s<br>
 def : InstAlias<"lods\t{$src, %ax|ax, $src}", (LODSW srcidx16:$src), 0>;<br>
 def : InstAlias<"lods\t{$src, %eax|eax, $src}", (LODSL srcidx32:$src), 0>;<br>
 def : InstAlias<"lods\t{$src, %rax|rax, $src}", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
+def : InstAlias<"lods\t$src", (LODSB srcidx8:$src),  0>;<br>
+def : InstAlias<"lods\t$src", (LODSW srcidx16:$src), 0>;<br>
+def : InstAlias<"lods\t$src", (LODSL srcidx32:$src), 0>;<br>
+def : InstAlias<"lods\t$src", (LODSQ srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
+<br>
<br>
 // stos aliases. Accept the source being omitted because it's implicit in<br>
 // the mnemonic, or the mnemonic suffix being omitted because it's implicit<br>
@@ -2794,6 +2799,11 @@ def : InstAlias<"stos\t{%al, $dst|$dst,<br>
 def : InstAlias<"stos\t{%ax, $dst|$dst, ax}", (STOSW dstidx16:$dst), 0>;<br>
 def : InstAlias<"stos\t{%eax, $dst|$dst, eax}", (STOSL dstidx32:$dst), 0>;<br>
 def : InstAlias<"stos\t{%rax, $dst|$dst, rax}", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;<br>
+def : InstAlias<"stos\t$dst", (STOSB dstidx8:$dst),  0>;<br>
+def : InstAlias<"stos\t$dst", (STOSW dstidx16:$dst), 0>;<br>
+def : InstAlias<"stos\t$dst", (STOSL dstidx32:$dst), 0>;<br>
+def : InstAlias<"stos\t$dst", (STOSQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;<br>
+<br>
<br>
 // scas aliases. Accept the destination being omitted because it's implicit<br>
 // in the mnemonic, or the mnemonic suffix being omitted because it's implicit<br>
@@ -2806,6 +2816,24 @@ def : InstAlias<"scas\t{$dst, %al|al, $d<br>
 def : InstAlias<"scas\t{$dst, %ax|ax, $dst}", (SCASW dstidx16:$dst), 0>;<br>
 def : InstAlias<"scas\t{$dst, %eax|eax, $dst}", (SCASL dstidx32:$dst), 0>;<br>
 def : InstAlias<"scas\t{$dst, %rax|rax, $dst}", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;<br>
+def : InstAlias<"scas\t$dst", (SCASB dstidx8:$dst),  0>;<br>
+def : InstAlias<"scas\t$dst", (SCASW dstidx16:$dst), 0>;<br>
+def : InstAlias<"scas\t$dst", (SCASL dstidx32:$dst), 0>;<br>
+def : InstAlias<"scas\t$dst", (SCASQ dstidx64:$dst), 0>, Requires<[In64BitMode]>;<br>
+<br>
+// cmps aliases. Mnemonic suffix being omitted because it's implicit<br>
+// in the destination.<br>
+def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSB dstidx8:$dst, srcidx8:$src),  0>;<br>
+def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSW dstidx16:$dst, srcidx16:$src), 0>;<br>
+def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSL dstidx32:$dst, srcidx32:$src), 0>;<br>
+def : InstAlias<"cmps\t{$dst, $src|$src, $dst}", (CMPSQ dstidx64:$dst, srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
+<br>
+// movs aliases. Mnemonic suffix being omitted because it's implicit<br>
+// in the destination.<br>
+def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSB dstidx8:$dst, srcidx8:$src),  0>;<br>
+def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSW dstidx16:$dst, srcidx16:$src), 0>;<br>
+def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSL dstidx32:$dst, srcidx32:$src), 0>;<br>
+def : InstAlias<"movs\t{$src, $dst|$dst, $src}", (MOVSQ dstidx64:$dst, srcidx64:$src), 0>, Requires<[In64BitMode]>;<br>
<br>
 // div and idiv aliases for explicit A register.<br>
 def : InstAlias<"div{b}\t{$src, %al|al, $src}", (DIV8r  GR8 :$src)>;<br>
@@ -2918,6 +2946,18 @@ def : InstAlias<"imul{l}\t{$imm, $r|$r,<br>
 def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri32 GR64:$r, GR64:$r, i64i32imm:$imm), 0>;<br>
 def : InstAlias<"imul{q}\t{$imm, $r|$r, $imm}", (IMUL64rri8 GR64:$r, GR64:$r, i64i8imm:$imm), 0>;<br>
<br>
+// ins aliases. Accept the mnemonic suffix being omitted because it's implicit<br>
+// in the destination.<br>
+def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSB dstidx8:$dst),  0>;<br>
+def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSW dstidx16:$dst),  0>;<br>
+def : InstAlias<"ins\t{%dx, $dst|$dst, dx}", (INSL dstidx32:$dst),  0>;<br>
+<br>
+// outs aliases. Accept the mnemonic suffix being omitted because it's implicit<br>
+// in the source.<br>
+def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSB srcidx8:$src),  0>;<br>
+def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSW srcidx16:$src),  0>;<br>
+def : InstAlias<"outs\t{$src, %dx|dx, $src}", (OUTSL srcidx32:$src),  0>;<br>
+<br>
 // inb %dx -> inb %al, %dx<br>
 def : InstAlias<"inb\t{%dx|dx}", (IN8rr), 0>;<br>
 def : InstAlias<"inw\t{%dx|dx}", (IN16rr), 0>;<br>
<br>
Modified: llvm/trunk/test/MC/X86/index-operations.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/index-operations.s?rev=258132&r1=258131&r2=258132&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/index-operations.s?rev=258132&r1=258131&r2=258132&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/MC/X86/index-operations.s (original)<br>
+++ llvm/trunk/test/MC/X86/index-operations.s Tue Jan 19 09:37:56 2016<br>
@@ -144,3 +144,19 @@ insw %dx, (%edi)<br>
 // 64: insw %dx, %es:(%edi) # encoding: [0x66,0x67,0x6d]<br>
 // 32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d]<br>
 // 16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d]<br>
+<br>
+insw %dx, (%bx)<br>
+// ERR64: invalid 16-bit base register<br>
+// 32: insw %dx, %es:(%di) # encoding: [0x66,0x67,0x6d]<br>
+// 16: insw %dx, %es:(%di) # encoding: [0x6d]<br>
+<br>
+insw %dx, (%ebx)<br>
+// 64: insw %dx, %es:(%edi) # encoding: [0x66,0x67,0x6d]<br>
+// 32: insw %dx, %es:(%edi) # encoding: [0x66,0x6d]<br>
+// 16: insw %dx, %es:(%edi) # encoding: [0x67,0x6d]<br>
+<br>
+insw %dx, (%rbx)<br>
+// 64: insw %dx, %es:(%rdi) # encoding: [0x66,0x6d]<br>
+// ERR32: 64-bit<br>
+// ERR16: 64-bit<br>
+<br>
<br>
Modified: llvm/trunk/test/MC/X86/intel-syntax.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/intel-syntax.s?rev=258132&r1=258131&r2=258132&view=diff" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/intel-syntax.s?rev=258132&r1=258131&r2=258132&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/MC/X86/intel-syntax.s (original)<br>
+++ llvm/trunk/test/MC/X86/intel-syntax.s Tue Jan 19 09:37:56 2016<br>
@@ -751,3 +751,27 @@ loopnz _foo<br>
<br>
 sidt fword ptr [eax]<br>
 // CHECK: sidtq (%eax)<br>
+<br>
+ins byte ptr [eax], dx<br>
+// CHECK: insb %dx, %es:(%edi)<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)DI will be used for the location<br>
+outs dx, word ptr [eax]<br>
+// CHECK: outsw (%esi), %dx<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)SI will be used for the location<br>
+lods dword ptr [eax]<br>
+// CHECK: lodsl (%esi), %eax<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)SI will be used for the location<br>
+stos qword ptr [eax]<br>
+// CHECK: stosq %rax, %es:(%edi)<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)DI will be used for the location<br>
+scas byte ptr [eax]<br>
+// CHECK: scasb %es:(%edi), %al<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)DI will be used for the location<br>
+cmps word ptr [eax], word ptr [ebx]<br>
+// CHECK: cmpsw %es:(%edi), (%esi)<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)SI will be used for the location<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)DI will be used for the location<br>
+movs dword ptr [eax], dword ptr [ebx]<br>
+// CHECK: movsl (%esi), %es:(%edi)<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)DI will be used for the location<br>
+// CHECK-STDERR: memory operand is only for determining the size, ES:(R|E)SI will be used for the location<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><o:p></o:p></p>
</blockquote>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</div>
<p>---------------------------------------------------------------------<br>
Intel Israel (74) Limited</p>

<p>This e-mail and any attachments may contain confidential material for<br>
the sole use of the intended recipient(s). Any review or distribution<br>
by others is strictly prohibited. If you are not the intended<br>
recipient, please contact the sender and delete all copies.</p></body>
</html>