[llvm] r368712 - [ARM] Fix detection of duplicates when parsing reg list operands

Momchil Velikov via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 13 09:13:00 PDT 2019


Author: chill
Date: Tue Aug 13 09:13:00 2019
New Revision: 368712

URL: http://llvm.org/viewvc/llvm-project?rev=368712&view=rev
Log:
[ARM] Fix detection of duplicates when parsing reg list operands

Differential Revision: https://reviews.llvm.org/D65957

Added:
    llvm/trunk/test/MC/ARM/register-list-dup.s
Modified:
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=368712&r1=368711&r2=368712&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Tue Aug 13 09:13:00 2019
@@ -3559,16 +3559,15 @@ public:
         Kind = k_SPRRegisterList;
     }
 
-    // Sort based on the register encoding values.
-    array_pod_sort(Regs.begin(), Regs.end());
-
     if (Kind == k_RegisterList && Regs.back().second == ARM::APSR)
       Kind = k_RegisterListWithAPSR;
 
+    assert(std::is_sorted(Regs.begin(), Regs.end()) &&
+           "Register list must be sorted by encoding");
+
     auto Op = make_unique<ARMOperand>(Kind);
-    for (SmallVectorImpl<std::pair<unsigned, unsigned>>::const_iterator
-           I = Regs.begin(), E = Regs.end(); I != E; ++I)
-      Op->Registers.push_back(I->second);
+    for (const auto &P : Regs)
+      Op->Registers.push_back(P.second);
 
     Op->StartLoc = StartLoc;
     Op->EndLoc = EndLoc;
@@ -4269,6 +4268,24 @@ static unsigned getNextRegister(unsigned
   }
 }
 
+// Insert an <Encoding, Register> pair in an ordered vector. Return true on
+// success, or false, if duplicate encoding found.
+static bool
+insertNoDuplicates(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
+                   unsigned Enc, unsigned Reg) {
+  Regs.emplace_back(Enc, Reg);
+  for (auto I = Regs.rbegin(), J = I + 1, E = Regs.rend(); J != E; ++I, ++J) {
+    if (J->first == Enc) {
+      Regs.erase(J.base());
+      return false;
+    }
+    if (J->first < Enc)
+      break;
+    std::swap(*I, *J);
+  }
+  return true;
+}
+
 /// Parse a register list.
 bool ARMAsmParser::parseRegisterList(OperandVector &Operands,
                                      bool EnforceOrder) {
@@ -4294,7 +4311,7 @@ bool ARMAsmParser::parseRegisterList(Ope
   if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
     Reg = getDRegFromQReg(Reg);
     EReg = MRI->getEncodingValue(Reg);
-    Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+    Registers.emplace_back(EReg, Reg);
     ++Reg;
   }
   const MCRegisterClass *RC;
@@ -4311,7 +4328,7 @@ bool ARMAsmParser::parseRegisterList(Ope
 
   // Store the register.
   EReg = MRI->getEncodingValue(Reg);
-  Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+  Registers.emplace_back(EReg, Reg);
 
   // This starts immediately after the first register token in the list,
   // so we can see either a comma or a minus (range separator) as a legal
@@ -4342,7 +4359,11 @@ bool ARMAsmParser::parseRegisterList(Ope
       while (Reg != EndReg) {
         Reg = getNextRegister(Reg);
         EReg = MRI->getEncodingValue(Reg);
-        Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+        if (!insertNoDuplicates(Registers, EReg, Reg)) {
+          Warning(AfterMinusLoc, StringRef("duplicated register (") +
+                                     ARMInstPrinter::getRegisterName(Reg) +
+                                     ") in register list");
+        }
       }
       continue;
     }
@@ -4366,11 +4387,16 @@ bool ARMAsmParser::parseRegisterList(Ope
       // subset of GPRRegClassId except it contains APSR as well.
       RC = &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID];
     }
-    if (Reg == ARM::VPR && (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
-                            RC == &ARMMCRegisterClasses[ARM::DPRRegClassID])) {
+    if (Reg == ARM::VPR &&
+        (RC == &ARMMCRegisterClasses[ARM::SPRRegClassID] ||
+         RC == &ARMMCRegisterClasses[ARM::DPRRegClassID] ||
+         RC == &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID])) {
       RC = &ARMMCRegisterClasses[ARM::FPWithVPRRegClassID];
       EReg = MRI->getEncodingValue(Reg);
-      Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+      if (!insertNoDuplicates(Registers, EReg, Reg)) {
+        Warning(RegLoc, "duplicated register (" + RegTok.getString() +
+                            ") in register list");
+      }
       continue;
     }
     // The register must be in the same register class as the first.
@@ -4387,21 +4413,19 @@ bool ARMAsmParser::parseRegisterList(Ope
       else if (!ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains(Reg))
         return Error(RegLoc, "register list not in ascending order");
     }
-    if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
-      Warning(RegLoc, "duplicated register (" + RegTok.getString() +
-              ") in register list");
-      continue;
-    }
     // VFP register lists must also be contiguous.
     if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
         RC != &ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID] &&
         Reg != OldReg + 1)
       return Error(RegLoc, "non-contiguous register range");
     EReg = MRI->getEncodingValue(Reg);
-    Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+    if (!insertNoDuplicates(Registers, EReg, Reg)) {
+      Warning(RegLoc, "duplicated register (" + RegTok.getString() +
+                          ") in register list");
+    }
     if (isQReg) {
       EReg = MRI->getEncodingValue(++Reg);
-      Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
+      Registers.emplace_back(EReg, Reg);
     }
   }
 

Added: llvm/trunk/test/MC/ARM/register-list-dup.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/register-list-dup.s?rev=368712&view=auto
==============================================================================
--- llvm/trunk/test/MC/ARM/register-list-dup.s (added)
+++ llvm/trunk/test/MC/ARM/register-list-dup.s Tue Aug 13 09:13:00 2019
@@ -0,0 +1,66 @@
+// RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -show-encoding < %s 2>&1 | FileCheck -strict-whitespace %s
+
+clrm {r0, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r0}}}
+// CHECK-NEXT: {{^          \^}}
+
+clrm {r0, r0, r1}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r0, r1}}}
+// CHECK-NEXT: {{^          \^}}
+
+clrm {r0, r1, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0, r1, r0}}}
+// CHECK-NEXT: {{^              \^}}
+
+clrm {r0, r1, r1}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r0, r1, r1}}}
+// CHECK-NEXT: {{^              \^}}
+
+clrm {r1, r0, r1}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r1, r0, r1}}}
+// CHECK-NEXT: {{^              \^}}
+
+clrm {r1, r1, r0}
+// CHECK: warning: duplicated register (r1) in register list
+// CHECK-NEXT: {{^clrm {r1, r1, r0}}}
+// CHECK-NEXT: {{^          \^}}
+
+clrm {r0-r3, r0}
+// CHECK: warning: duplicated register (r0) in register list
+// CHECK-NEXT: {{^clrm {r0-r3, r0}}}
+// CHECK-NEXT: {{^             \^}}
+
+clrm {r2, r0-r3}
+// CHECK: warning: duplicated register (r2) in register list
+// CHECK-NEXT: {{^clrm {r2, r0-r3}}}
+// CHECK-NEXT: {{^             \^}}
+
+vscclrm {s0, s0, s1, vpr}
+// CHECK: error: non-contiguous register range
+// CHECK: {{^vscclrm {s0, s0, s1, vpr}}}
+// CHECK: {{^             \^}}
+
+vscclrm {s0-s3, vpr, s4}
+// CHECK: error: register list not in ascending order
+// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, s4}}}
+// CHECK-NEXT: {{^                     \^}}
+
+vscclrm {s0-s3, vpr, vpr}
+// CHECK: warning: duplicated register (vpr) in register list
+// CHECK-NEXT: {{^vscclrm {s0-s3, vpr, vpr}}}
+// CHECK-NEXT: {{^                     \^}}
+
+vscclrm {q2, d4, vpr}
+// CHECK: error: register list not in ascending order
+// CHECK-NEXT: {{^vscclrm {q2, d4, vpr}}}
+// CHECK-NEXT: {{^             \^}}
+
+vscclrm {q2, d5, vpr}
+// CHECK: error: non-contiguous register range
+// CHECK-NEXT: {{^vscclrm {q2, d5, vpr}}}
+// CHECK-NEXT: {{^             \^}}




More information about the llvm-commits mailing list