Skip to content

Commit 8ae1830

Browse files
Store OptTable::Info::Name as a StringRef
This avoids implicit conversion to StringRef at several points, which in turns avoid redundant calls to strlen. As a side effect, this greatly simplifies the implementation of StrCmpOptionNameIgnoreCase. It also eventually gives a consistent, humble speedup in compilation time. https://llvm-compile-time-tracker.com/compare.php?from=5f5b942823474e98e43a27d515a87ce140396c53&to=60e13b778119fc32d50dc38ff1a564a87146e9c6&stat=instructions:u Differential Revision: https://reviews.llvm.org/D139274
1 parent ba5c26d commit 8ae1830

File tree

5 files changed

+28
-37
lines changed

5 files changed

+28
-37
lines changed

clang/lib/Driver/ToolChains/Gnu.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ static bool getStaticPIE(const ArgList &Args, const ToolChain &TC) {
331331
if (HasStaticPIE && Args.hasArg(options::OPT_nopie)) {
332332
const Driver &D = TC.getDriver();
333333
const llvm::opt::OptTable &Opts = D.getOpts();
334-
const char *StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
335-
const char *NoPIEName = Opts.getOptionName(options::OPT_nopie);
334+
StringRef StaticPIEName = Opts.getOptionName(options::OPT_static_pie);
335+
StringRef NoPIEName = Opts.getOptionName(options::OPT_nopie);
336336
D.Diag(diag::err_drv_cannot_mix_options) << StaticPIEName << NoPIEName;
337337
}
338338
return HasStaticPIE;

llvm/include/llvm/Option/OptTable.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class OptTable {
4444
/// A null terminated array of prefix strings to apply to name while
4545
/// matching.
4646
const char *const *Prefixes;
47-
const char *Name;
47+
StringRef Name;
4848
const char *HelpText;
4949
const char *MetaVar;
5050
unsigned ID;
@@ -102,9 +102,7 @@ class OptTable {
102102
const Option getOption(OptSpecifier Opt) const;
103103

104104
/// Lookup the name of the given option.
105-
const char *getOptionName(OptSpecifier id) const {
106-
return getInfo(id).Name;
107-
}
105+
StringRef getOptionName(OptSpecifier id) const { return getInfo(id).Name; }
108106

109107
/// Get the kind of the given option.
110108
unsigned getOptionKind(OptSpecifier id) const {
@@ -184,7 +182,7 @@ class OptTable {
184182
/// takes
185183
///
186184
/// \return true in success, and false in fail.
187-
bool addValues(const char *Option, const char *Values);
185+
bool addValues(StringRef Option, const char *Values);
188186

189187
/// Parse a single argument; returning the new argument and
190188
/// updating Index.

llvm/lib/Option/OptTable.cpp

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,23 @@ namespace opt {
3636
// Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
3737
// with an exception. '\0' comes at the end of the alphabet instead of the
3838
// beginning (thus options precede any other options which prefix them).
39-
static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
40-
const char *X = A, *Y = B;
41-
char a = tolower(*A), b = tolower(*B);
42-
while (a == b) {
43-
if (a == '\0')
44-
return 0;
45-
46-
a = tolower(*++X);
47-
b = tolower(*++Y);
48-
}
39+
static int StrCmpOptionNameIgnoreCase(StringRef A, StringRef B) {
40+
size_t MinSize = std::min(A.size(), B.size());
41+
if (int Res = A.substr(0, MinSize).compare_insensitive(B.substr(0, MinSize)))
42+
return Res;
4943

50-
if (a == '\0') // A is a prefix of B.
51-
return 1;
52-
if (b == '\0') // B is a prefix of A.
53-
return -1;
44+
if (A.size() == B.size())
45+
return 0;
5446

55-
// Otherwise lexicographic.
56-
return (a < b) ? -1 : 1;
47+
return (A.size() == MinSize) ? 1 /* A is a prefix of B. */
48+
: -1 /* B is a prefix of A */;
5749
}
5850

5951
#ifndef NDEBUG
60-
static int StrCmpOptionName(const char *A, const char *B) {
52+
static int StrCmpOptionName(StringRef A, StringRef B) {
6153
if (int N = StrCmpOptionNameIgnoreCase(A, B))
6254
return N;
63-
return strcmp(A, B);
55+
return A.compare(B);
6456
}
6557

6658
static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
@@ -86,7 +78,7 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
8678
#endif
8779

8880
// Support lower_bound between info and an option name.
89-
static inline bool operator<(const OptTable::Info &I, const char *Name) {
81+
static inline bool operator<(const OptTable::Info &I, StringRef Name) {
9082
return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
9183
}
9284

@@ -321,7 +313,7 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
321313
return BestDistance;
322314
}
323315

324-
bool OptTable::addValues(const char *Option, const char *Values) {
316+
bool OptTable::addValues(StringRef Option, const char *Values) {
325317
for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
326318
Info &In = OptionInfos[I];
327319
if (optionMatches(In, Option)) {
@@ -347,8 +339,8 @@ std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
347339

348340
const Info *End = OptionInfos.data() + OptionInfos.size();
349341
StringRef Name = Str.ltrim(PrefixChars);
350-
const Info *Start = std::lower_bound(
351-
OptionInfos.data() + FirstSearchableIndex, End, Name.data());
342+
const Info *Start =
343+
std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name);
352344
const Info *Fallback = nullptr;
353345
unsigned Prev = Index;
354346

@@ -415,7 +407,7 @@ std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
415407
StringRef Name = StringRef(Str).ltrim(PrefixChars);
416408

417409
// Search for the first next option which could be a prefix.
418-
Start = std::lower_bound(Start, End, Name.data());
410+
Start = std::lower_bound(Start, End, Name);
419411

420412
// Options are stored in sorted order, with '\0' at the end of the
421413
// alphabet. Since the only options which can accept a string must

llvm/unittests/Option/OptionMarshallingTest.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/ADT/StringRef.h"
910
#include "gtest/gtest.h"
1011

1112
struct OptionWithMarshallingInfo {
12-
const char *Name;
13+
llvm::StringRef Name;
1314
const char *KeyPath;
1415
const char *ImpliedCheck;
1516
const char *ImpliedValue;
@@ -27,10 +28,10 @@ static const OptionWithMarshallingInfo MarshallingTable[] = {
2728
};
2829

2930
TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) {
30-
ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-d");
31-
ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-c");
32-
ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-b");
33-
ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-a");
31+
ASSERT_STREQ(MarshallingTable[0].Name.data(), "marshalled-flag-d");
32+
ASSERT_STREQ(MarshallingTable[1].Name.data(), "marshalled-flag-c");
33+
ASSERT_STREQ(MarshallingTable[2].Name.data(), "marshalled-flag-b");
34+
ASSERT_STREQ(MarshallingTable[3].Name.data(), "marshalled-flag-a");
3435
}
3536

3637
TEST(OptionMarshalling, EmittedSpecifiedKeyPath) {

llvm/utils/TableGen/OptParserEmitter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ static std::string getOptionSpelling(const Record &R) {
5454

5555
static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
5656
size_t PrefixLength;
57-
OS << "&";
57+
OS << "llvm::StringRef(";
5858
write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
59-
OS << "[" << PrefixLength << "]";
59+
OS << ").substr(" << PrefixLength << ")";
6060
}
6161

6262
class MarshallingInfo {

0 commit comments

Comments
 (0)