summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Zarzycki <dave@znu.io>2018-02-26 18:41:26 +0000
committerDavid Zarzycki <dave@znu.io>2018-02-26 18:41:26 +0000
commitd15f31936a5987a06066a2d49fba388c69a027eb (patch)
tree93f8a9e578a4997c043cfc8c4024adc9d4d6ed47
parenta456db3ea3927f04f972942840c4062780129d83 (diff)
downloadbcm5719-llvm-d15f31936a5987a06066a2d49fba388c69a027eb.tar.gz
bcm5719-llvm-d15f31936a5987a06066a2d49fba388c69a027eb.zip
[ADT] Simplify and optimize StringSwitch
This change improves incremental rebuild performance on dual Xeon 8168 machines by 54%. This change also improves run time code gen by not forcing the case values to be lvalues. llvm-svn: 326109
-rw-r--r--llvm/include/llvm/ADT/StringRef.h10
-rw-r--r--llvm/include/llvm/ADT/StringSwitch.h173
-rw-r--r--llvm/unittests/ADT/StringSwitchTest.cpp6
3 files changed, 82 insertions, 107 deletions
diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index f6c93a858db..3d2417acead 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -855,6 +855,10 @@ namespace llvm {
/// constexpr StringLiteral S("test");
///
class StringLiteral : public StringRef {
+ private:
+ constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) {
+ }
+
public:
template <size_t N>
constexpr StringLiteral(const char (&Str)[N])
@@ -867,6 +871,12 @@ namespace llvm {
#endif
: StringRef(Str, N - 1) {
}
+
+ // Explicit construction for strings like "foo\0bar".
+ template <size_t N>
+ static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) {
+ return StringLiteral(Str, N - 1);
+ }
};
/// @name StringRef Comparison Operators
diff --git a/llvm/include/llvm/ADT/StringSwitch.h b/llvm/include/llvm/ADT/StringSwitch.h
index 75577b7738b..5fad2476181 100644
--- a/llvm/include/llvm/ADT/StringSwitch.h
+++ b/llvm/include/llvm/ADT/StringSwitch.h
@@ -42,16 +42,16 @@ namespace llvm {
template<typename T, typename R = T>
class StringSwitch {
/// \brief The string we are matching.
- StringRef Str;
+ const StringRef Str;
/// \brief The pointer to the result of this switch statement, once known,
/// null before that.
- const T *Result;
+ Optional<T> Result;
public:
LLVM_ATTRIBUTE_ALWAYS_INLINE
explicit StringSwitch(StringRef S)
- : Str(S), Result(nullptr) { }
+ : Str(S), Result() { }
// StringSwitch is not copyable.
StringSwitch(const StringSwitch &) = delete;
@@ -61,196 +61,159 @@ public:
*this = std::move(other);
}
StringSwitch &operator=(StringSwitch &&other) {
- Str = other.Str;
- Result = other.Result;
+ Str = std::move(other.Str);
+ Result = std::move(other.Result);
return *this;
}
~StringSwitch() = default;
// Case-sensitive case matchers
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& Case(const char (&S)[N], const T& Value) {
- assert(N);
- if (!Result && N-1 == Str.size() &&
- (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
- Result = &Value;
+ StringSwitch &Case(StringLiteral S, T Value) {
+ if (!Result && Str == S) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& EndsWith(const char (&S)[N], const T &Value) {
- assert(N);
- if (!Result && Str.size() >= N-1 &&
- (N == 1 || std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0)) {
- Result = &Value;
+ StringSwitch& EndsWith(StringLiteral S, T Value) {
+ if (!Result && Str.endswith(S)) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch& StartsWith(const char (&S)[N], const T &Value) {
- assert(N);
- if (!Result && Str.size() >= N-1 &&
- (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) {
- Result = &Value;
+ StringSwitch& StartsWith(StringLiteral S, T Value) {
+ if (!Result && Str.startswith(S)) {
+ Result = std::move(Value);
}
return *this;
}
- template<unsigned N0, unsigned N1>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) {
return Case(S0, Value).Case(S1, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, Value);
}
- template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const T& Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7, unsigned N8>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const char (&S8)[N8], const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4,
- unsigned N5, unsigned N6, unsigned N7, unsigned N8, unsigned N9>
LLVM_ATTRIBUTE_ALWAYS_INLINE
- StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1],
- const char (&S2)[N2], const char (&S3)[N3],
- const char (&S4)[N4], const char (&S5)[N5],
- const char (&S6)[N6], const char (&S7)[N7],
- const char (&S8)[N8], const char (&S9)[N9],
- const T &Value) {
+ StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, StringLiteral S5,
+ StringLiteral S6, StringLiteral S7, StringLiteral S8,
+ StringLiteral S9, T Value) {
return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value);
}
// Case-insensitive case matchers.
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.equals_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CaseLower(StringLiteral S, T Value) {
+ if (!Result && Str.equals_lower(S))
+ Result = std::move(Value);
return *this;
}
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.endswith_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &EndsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.endswith_lower(S))
+ Result = Value;
return *this;
}
- template <unsigned N>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(const char (&S)[N],
- const T &Value) {
- if (!Result && Str.startswith_lower(StringRef(S, N - 1)))
- Result = &Value;
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &StartsWithLower(StringLiteral S, T Value) {
+ if (!Result && Str.startswith_lower(S))
+ Result = std::move(Value);
return *this;
}
- template <unsigned N0, unsigned N1>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) {
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) {
return CaseLower(S0, Value).CaseLower(S1, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const char (&S3)[N3], const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value);
}
- template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
- LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &
- CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2],
- const char (&S3)[N3], const char (&S4)[N4], const T &Value) {
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2,
+ StringLiteral S3, StringLiteral S4, T Value) {
return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value);
}
+ LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
- R Default(const T &Value) const {
+ R Default(T Value) {
if (Result)
- return *Result;
+ return std::move(*Result);
return Value;
}
+ LLVM_NODISCARD
LLVM_ATTRIBUTE_ALWAYS_INLINE
- operator R() const {
+ operator R() {
assert(Result && "Fell off the end of a string-switch");
- return *Result;
+ return std::move(*Result);
}
};
diff --git a/llvm/unittests/ADT/StringSwitchTest.cpp b/llvm/unittests/ADT/StringSwitchTest.cpp
index 1a51629ca57..62d3a319e7a 100644
--- a/llvm/unittests/ADT/StringSwitchTest.cpp
+++ b/llvm/unittests/ADT/StringSwitchTest.cpp
@@ -158,7 +158,8 @@ TEST(StringSwitchTest, Cases) {
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
- .Cases("wind\0ws", "win32", "winnt", OSType::Windows)
+ .Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
.Cases("linux", "unix", "*nix", "posix", OSType::Linux)
.Default(OSType::Unknown);
};
@@ -184,7 +185,8 @@ TEST(StringSwitchTest, CasesLower) {
auto Translate = [](StringRef S) {
return llvm::StringSwitch<OSType>(S)
- .CasesLower("wind\0ws", "win32", "winnt", OSType::Windows)
+ .CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
.CasesLower("linux", "unix", "*nix", "posix", OSType::Linux)
.Default(OSType::Unknown);
};
OpenPOWER on IntegriCloud