diff options
author | 2023-12-14 23:41:15 -0800 | |
---|---|---|
committer | 2023-12-14 23:41:53 -0800 | |
commit | a7e3dafd035024803b80676ab8ed02b4acb9b111 (patch) | |
tree | ba96a98b6fad60770721aa98b4190ba876ffb118 /absl | |
parent | cee0d5b4c38d6a3488e6dae2d7674ecbcff3f6c1 (diff) |
Roll back changes to AsciiStrToUpper() and AsciiStrToLower() due to bug report.
PiperOrigin-RevId: 591161019
Change-Id: Iae2477a24819e20288fbb83b4a343031af71f1bb
Diffstat (limited to 'absl')
-rw-r--r-- | absl/strings/ascii.cc | 62 | ||||
-rw-r--r-- | absl/strings/ascii_benchmark.cc | 4 |
2 files changed, 5 insertions, 61 deletions
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc index c696a5b1..df905e05 100644 --- a/absl/strings/ascii.cc +++ b/absl/strings/ascii.cc @@ -15,10 +15,8 @@ #include "absl/strings/ascii.h" #include <climits> -#include <cstdint> #include <cstring> #include <string> -#include <type_traits> #include "absl/base/config.h" #include "absl/base/nullability.h" @@ -162,19 +160,6 @@ ABSL_DLL const char kToUpper[256] = { }; // clang-format on -template <class T> -static constexpr T BroadcastByte(unsigned char value) { - static_assert(std::is_integral<T>::value && sizeof(T) <= sizeof(uint64_t) && - std::is_unsigned<T>::value, - "only unsigned integers up to 64-bit allowed"); - T result = value; - constexpr size_t result_bit_width = sizeof(result) * CHAR_BIT; - result |= result << ((CHAR_BIT << 0) & (result_bit_width - 1)); - result |= result << ((CHAR_BIT << 1) & (result_bit_width - 1)); - result |= result << ((CHAR_BIT << 2) & (result_bit_width - 1)); - return result; -} - // Returns whether `c` is in the a-z/A-Z range (w.r.t. `ToUpper`). // Implemented by: // 1. Pushing the a-z/A-Z range to [SCHAR_MIN, SCHAR_MIN + 26). @@ -190,42 +175,8 @@ constexpr bool AsciiInAZRange(unsigned char c) { } template <bool ToUpper> -static constexpr char* PartialAsciiStrCaseFold(absl::Nonnull<char*> p, - absl::Nonnull<char*> end) { - using vec_t = size_t; - const size_t n = static_cast<size_t>(end - p); - - // SWAR algorithm: http://0x80.pl/notesen/2016-01-06-swar-swap-case.html - constexpr char ch_a = ToUpper ? 'a' : 'A', ch_z = ToUpper ? 'z' : 'Z'; - char* const swar_end = p + (n / sizeof(vec_t)) * sizeof(vec_t); - while (p < swar_end) { - vec_t v = vec_t(); - - // memcpy the vector, but constexpr - for (size_t i = 0; i < sizeof(vec_t); ++i) { - v |= static_cast<vec_t>(static_cast<unsigned char>(p[i])) - << (i * CHAR_BIT); - } - - constexpr unsigned int msb = 1u << 7; - vec_t a = v + ascii_internal::BroadcastByte<vec_t>(msb - ch_a - 0), - z = v + ascii_internal::BroadcastByte<vec_t>(msb - ch_z - 1); - v ^= ((a & ~z) & ascii_internal::BroadcastByte<vec_t>(msb)) >> 2; - - // memcpy the vector, but constexpr - for (size_t i = 0; i < sizeof(vec_t); ++i) { - p[i] = static_cast<char>(v >> (i * CHAR_BIT)); - } - - p += sizeof(v); - } - - return p; -} - -template <bool ToUpper> -static constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, - absl::Nonnull<char*> end) { +constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, + absl::Nonnull<char*> end) { // The upper- and lowercase versions of ASCII characters differ by only 1 bit. // When we need to flip the case, we can xor with this bit to achieve the // desired result. Note that the choice of 'a' and 'A' here is arbitrary. We @@ -233,17 +184,10 @@ static constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, // have the same single bit difference. constexpr unsigned char kAsciiCaseBitFlip = 'a' ^ 'A'; - using vec_t = size_t; - // TODO(b/316380338): When FDO becomes able to vectorize these, - // revert this manual optimization and just leave the naive loop. - if (static_cast<size_t>(end - p) >= sizeof(vec_t)) { - p = ascii_internal::PartialAsciiStrCaseFold<ToUpper>(p, end); - } - while (p < end) { + for (; p < end; ++p) { unsigned char v = static_cast<unsigned char>(*p); v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0; *p = static_cast<char>(v); - ++p; } } diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc index 4ae73174..3aecdb8b 100644 --- a/absl/strings/ascii_benchmark.cc +++ b/absl/strings/ascii_benchmark.cc @@ -113,7 +113,7 @@ static void BM_StrToLower(benchmark::State& state) { BENCHMARK(BM_StrToLower) ->DenseRange(0, 32) ->RangeMultiplier(2) - ->Range(64, 1 << 26); + ->Range(64, 1 << 20); static void BM_StrToUpper(benchmark::State& state) { const int size = state.range(0); @@ -127,6 +127,6 @@ static void BM_StrToUpper(benchmark::State& state) { BENCHMARK(BM_StrToUpper) ->DenseRange(0, 32) ->RangeMultiplier(2) - ->Range(64, 1 << 26); + ->Range(64, 1 << 20); } // namespace |