From d1d7ed63ff02c0c4ca68a2a143ce4341c576df97 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 26 May 2010 21:47:28 +0000 Subject: [PATCH] Add StringRef::compare_numeric and use it to sort TableGen register records. This means that our Registers are now ordered R7, R8, R9, R10, R12, ... Not R1, R10, R11, R12, R2, R3, ... llvm-svn: 104745 --- llvm/include/llvm/ADT/StringRef.h | 4 ++++ llvm/lib/Support/StringRef.cpp | 28 +++++++++++++++++++++++++++ llvm/lib/Target/X86/SSEDomainFix.cpp | 4 +--- llvm/unittests/ADT/StringRefTest.cpp | 11 +++++++++++ llvm/utils/TableGen/CodeGenTarget.cpp | 2 ++ llvm/utils/TableGen/Record.h | 2 +- 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h index ab6358bdfa6c..33756f605f01 100644 --- a/llvm/include/llvm/ADT/StringRef.h +++ b/llvm/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/llvm/lib/Support/StringRef.cpp b/llvm/lib/Support/StringRef.cpp index 2b262dcd3fa7..ca0f518a88b6 100644 --- a/llvm/lib/Support/StringRef.cpp +++ b/llvm/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/llvm/lib/Target/X86/SSEDomainFix.cpp b/llvm/lib/Target/X86/SSEDomainFix.cpp index 5e808450d1cd..dab070e1febd 100644 --- a/llvm/lib/Target/X86/SSEDomainFix.cpp +++ b/llvm/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/llvm/unittests/ADT/StringRefTest.cpp b/llvm/unittests/ADT/StringRefTest.cpp index b0dcb0a0abab..887ba5d1f9e6 100644 --- a/llvm/unittests/ADT/StringRefTest.cpp +++ b/llvm/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/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index 5d4548923013..3797992d9d3f 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/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/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h index 576d626e069c..8f9fd950bb0f 100644 --- a/llvm/utils/TableGen/Record.h +++ b/llvm/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; } };