diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index ab6358bdfa6..33756f605f0 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -128,6 +128,10 @@ namespace llvm { /// compare_lower - Compare two strings, ignoring case. int compare_lower(StringRef RHS) const; + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const; + /// \brief Determine the edit distance between this string and another /// string. /// diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index 2b262dcd3fa..ca0f518a88b 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -23,6 +23,10 @@ static char ascii_tolower(char x) { return x; } +static bool ascii_isdigit(char x) { + return x >= '0' && x <= '9'; +} + /// compare_lower - Compare strings, ignoring case. int StringRef::compare_lower(StringRef RHS) const { for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { @@ -37,6 +41,30 @@ int StringRef::compare_lower(StringRef RHS) const { return Length < RHS.Length ? -1 : 1; } +/// compare_numeric - Compare strings, handle embedded numbers. +int StringRef::compare_numeric(StringRef RHS) const { + for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) { + if (Data[I] == RHS.Data[I]) + continue; + if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) { + // The longer sequence of numbers is larger. This doesn't really handle + // prefixed zeros well. + for (size_t J = I+1; J != E+1; ++J) { + bool ld = J < Length && ascii_isdigit(Data[J]); + bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]); + if (ld != rd) + return rd ? -1 : 1; + if (!rd) + break; + } + } + return Data[I] < RHS.Data[I] ? -1 : 1; + } + if (Length == RHS.Length) + return 0; + return Length < RHS.Length ? -1 : 1; +} + // Compute the edit distance between the two given strings. unsigned StringRef::edit_distance(llvm::StringRef Other, bool AllowReplacements) { diff --git a/lib/Target/X86/SSEDomainFix.cpp b/lib/Target/X86/SSEDomainFix.cpp index 5e808450d1c..dab070e1feb 100644 --- a/lib/Target/X86/SSEDomainFix.cpp +++ b/lib/Target/X86/SSEDomainFix.cpp @@ -155,9 +155,7 @@ char SSEDomainFixPass::ID = 0; /// Translate TRI register number to an index into our smaller tables of /// interesting registers. Return -1 for boring registers. int SSEDomainFixPass::RegIndex(unsigned reg) { - // Registers are sorted lexicographically. - // We just need them to be consecutive, ordering doesn't matter. - assert(X86::XMM9 == X86::XMM0+NumRegs-1 && "Unexpected sort"); + assert(X86::XMM15 == X86::XMM0+NumRegs-1 && "Unexpected sort"); reg -= X86::XMM0; return reg < NumRegs ? (int) reg : -1; } diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index b0dcb0a0aba..887ba5d1f9e 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -53,6 +53,17 @@ TEST(StringRefTest, StringOps) { EXPECT_EQ( 1, StringRef("aab").compare("aaa")); EXPECT_EQ(-1, StringRef("aab").compare("aabb")); EXPECT_EQ( 1, StringRef("aab").compare("aa")); + + EXPECT_EQ(-1, StringRef("aab").compare_numeric("aad")); + EXPECT_EQ( 0, StringRef("aab").compare_numeric("aab")); + EXPECT_EQ( 1, StringRef("aab").compare_numeric("aaa")); + EXPECT_EQ(-1, StringRef("aab").compare_numeric("aabb")); + EXPECT_EQ( 1, StringRef("aab").compare_numeric("aa")); + EXPECT_EQ(-1, StringRef("1").compare_numeric("10")); + EXPECT_EQ( 0, StringRef("10").compare_numeric("10")); + EXPECT_EQ( 0, StringRef("10a").compare_numeric("10a")); + EXPECT_EQ( 1, StringRef("2").compare_numeric("1")); + EXPECT_EQ( 0, StringRef("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty")); } TEST(StringRefTest, Operators) { diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 5d454892301..3797992d9d3 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -159,6 +159,7 @@ void CodeGenTarget::ReadRegisters() const { std::vector Regs = Records.getAllDerivedDefinitions("Register"); if (Regs.empty()) throw std::string("No 'Register' subclasses defined!"); + std::sort(Regs.begin(), Regs.end(), LessRecord()); Registers.reserve(Regs.size()); Registers.assign(Regs.begin(), Regs.end()); @@ -175,6 +176,7 @@ const std::string &CodeGenRegister::getName() const { void CodeGenTarget::ReadSubRegIndices() const { SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); + std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord()); } void CodeGenTarget::ReadRegisterClasses() const { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 576d626e069..8f9fd950bb0 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -1461,7 +1461,7 @@ public: /// struct LessRecord { bool operator()(const Record *Rec1, const Record *Rec2) const { - return Rec1->getName() < Rec2->getName(); + return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0; } };