Index: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -3559,16 +3559,15 @@ 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(Kind); - for (SmallVectorImpl>::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 @@ } } +// Insert an pair in an ordered vector. Return true on +// success, or false, if duplicate encoding found. +static bool +insertNoDuplicates(SmallVectorImpl> &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 @@ if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) { Reg = getDRegFromQReg(Reg); EReg = MRI->getEncodingValue(Reg); - Registers.push_back(std::pair(EReg, Reg)); + Registers.emplace_back(EReg, Reg); ++Reg; } const MCRegisterClass *RC; @@ -4311,7 +4328,7 @@ // Store the register. EReg = MRI->getEncodingValue(Reg); - Registers.push_back(std::pair(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 @@ while (Reg != EndReg) { Reg = getNextRegister(Reg); EReg = MRI->getEncodingValue(Reg); - Registers.push_back(std::pair(EReg, Reg)); + if (!insertNoDuplicates(Registers, EReg, Reg)) { + Warning(AfterMinusLoc, StringRef("duplicated register (") + + ARMInstPrinter::getRegisterName(Reg) + + ") in register list"); + } } continue; } @@ -4366,11 +4387,16 @@ // 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(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 @@ 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(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(EReg, Reg)); + Registers.emplace_back(EReg, Reg); } } Index: llvm/trunk/test/MC/ARM/register-list-dup.s =================================================================== --- llvm/trunk/test/MC/ARM/register-list-dup.s +++ llvm/trunk/test/MC/ARM/register-list-dup.s @@ -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: {{^ \^}}