diff options
author | Abseil Team <absl-team@google.com> | 2018-11-01 14:00:22 -0700 |
---|---|---|
committer | Matt Calabrese <calabrese@x.team> | 2018-11-02 12:35:09 -0400 |
commit | f95179062eb65ce40895cc76f1398cce25394369 (patch) | |
tree | 9506d0c91321ddc6c4d487d130676b444fe5b88f | |
parent | cc8dcd307b76a575d2e3e0958a4fe4c7193c2f68 (diff) |
Export of internal Abseil changes.
--
4e224c85c3730398919fc5195cb1fc7a752e6e4f by Mark Barolak <mbar@google.com>:
Update some references to "StringPiece" to say "string_view" instead.
PiperOrigin-RevId: 219693697
--
6bdc925a3db5e97f1f8a404bdfda2e47e48f7b9a by Abseil Team <absl-team@google.com>:
Disable weak symbols for the Windows backend of LLVM, since they are currently buggy. See https://bugs.llvm.org/show_bug.cgi?id=37598 for more information.
PiperOrigin-RevId: 219676493
--
5823f495036181191f435efa4c45d60ca3160145 by Derek Mauro <dmauro@google.com>:
Don't use the SSE2 implementation of container_internal::Group
with -funsigned-char under GCC.
This is a workaround for https://github.com/abseil/abseil-cpp/issues/209.
_mm_cmpgt_epi8 is broken under GCC with -funsigned-char.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
PiperOrigin-RevId: 219666066
GitOrigin-RevId: 4e224c85c3730398919fc5195cb1fc7a752e6e4f
Change-Id: I2f115d0256576cf476ae73a9464c21d4106a2a56
-rw-r--r-- | absl/base/attributes.h | 13 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set.h | 28 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set_test.cc | 67 | ||||
-rw-r--r-- | absl/strings/str_cat.cc | 2 | ||||
-rw-r--r-- | absl/strings/str_split_benchmark.cc | 8 |
5 files changed, 71 insertions, 47 deletions
diff --git a/absl/base/attributes.h b/absl/base/attributes.h index e8500224..c44b8828 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -155,7 +155,12 @@ // ABSL_ATTRIBUTE_WEAK // // Tags a function as weak for the purposes of compilation and linking. -#if ABSL_HAVE_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__)) +// Weak attributes currently do not work properly in LLVM's Windows backend, +// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for futher information. +#if (ABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !(defined(__llvm__) && defined(_WIN32)) #undef ABSL_ATTRIBUTE_WEAK #define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) #define ABSL_HAVE_ATTRIBUTE_WEAK 1 @@ -296,13 +301,13 @@ // ABSL_HAVE_ATTRIBUTE_SECTION // -// Indicates whether labeled sections are supported. Labeled sections are not -// supported on Darwin/iOS. +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. #ifdef ABSL_HAVE_ATTRIBUTE_SECTION #error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set #elif (ABSL_HAVE_ATTRIBUTE(section) || \ (defined(__GNUC__) && !defined(__clang__))) && \ - !defined(__APPLE__) + !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK #define ABSL_HAVE_ATTRIBUTE_SECTION 1 // ABSL_ATTRIBUTE_SECTION diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index aa423b25..78382a35 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -337,10 +337,10 @@ inline bool IsDeleted(ctrl_t c) { return c == kDeleted; } inline bool IsEmptyOrDeleted(ctrl_t c) { return c < kSentinel; } #if SWISSTABLE_HAVE_SSE2 -struct Group { +struct GroupSse2Impl { static constexpr size_t kWidth = 16; // the number of slots per group - explicit Group(const ctrl_t* pos) { + explicit GroupSse2Impl(const ctrl_t* pos) { ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos)); } @@ -390,11 +390,13 @@ struct Group { __m128i ctrl; }; -#else -struct Group { +#endif // SWISSTABLE_HAVE_SSE2 + +struct GroupPortableImpl { static constexpr size_t kWidth = 8; - explicit Group(const ctrl_t* pos) : ctrl(little_endian::Load64(pos)) {} + explicit GroupPortableImpl(const ctrl_t* pos) + : ctrl(little_endian::Load64(pos)) {} BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const { // For the technique, see: @@ -441,12 +443,24 @@ struct Group { uint64_t ctrl; }; -#endif // SWISSTABLE_HAVE_SSE2 + +#if SWISSTABLE_HAVE_SSE2 && defined(__GNUC__) && !defined(__clang__) +// https://github.com/abseil/abseil-cpp/issues/209 +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853 +// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char +// Work around this by using the portable implementation of Group +// when using -funsigned-char under GCC. +using Group = std::conditional<std::is_signed<char>::value, GroupSse2Impl, + GroupPortableImpl>::type; +#elif SWISSTABLE_HAVE_SSE2 +using Group = GroupSse2Impl; +#else +using Group = GroupPortableImpl; +#endif template <class Policy, class Hash, class Eq, class Alloc> class raw_hash_set; - inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n >= Group::kWidth - 1; } diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index f48578eb..b66a8f16 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -130,45 +130,50 @@ TEST(Group, EmptyGroup) { for (h2_t h = 0; h != 128; ++h) EXPECT_FALSE(Group{EmptyGroup()}.Match(h)); } -#if SWISSTABLE_HAVE_SSE2 TEST(Group, Match) { - ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, - 7, 5, 3, 1, 1, 1, 1, 1}; - EXPECT_THAT(Group{group}.Match(0), ElementsAre()); - EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15)); - EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10)); - EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9)); - EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8)); + if (Group::kWidth == 16) { + ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, + 7, 5, 3, 1, 1, 1, 1, 1}; + EXPECT_THAT(Group{group}.Match(0), ElementsAre()); + EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15)); + EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10)); + EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9)); + EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8)); + } else if (Group::kWidth == 8) { + ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; + EXPECT_THAT(Group{group}.Match(0), ElementsAre()); + EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7)); + EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4)); + } else { + FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth; + } } TEST(Group, MatchEmpty) { - ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, - 7, 5, 3, 1, 1, 1, 1, 1}; - EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4)); -} - -TEST(Group, MatchEmptyOrDeleted) { - ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, - 7, 5, 3, 1, 1, 1, 1, 1}; - EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4)); -} -#else -TEST(Group, Match) { - ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; - EXPECT_THAT(Group{group}.Match(0), ElementsAre()); - EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7)); - EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4)); -} -TEST(Group, MatchEmpty) { - ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; - EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0)); + if (Group::kWidth == 16) { + ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, + 7, 5, 3, 1, 1, 1, 1, 1}; + EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4)); + } else if (Group::kWidth == 8) { + ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; + EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0)); + } else { + FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth; + } } TEST(Group, MatchEmptyOrDeleted) { - ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; - EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3)); + if (Group::kWidth == 16) { + ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7, + 7, 5, 3, 1, 1, 1, 1, 1}; + EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4)); + } else if (Group::kWidth == 8) { + ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1}; + EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3)); + } else { + FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth; + } } -#endif TEST(Batch, DropDeletes) { constexpr size_t kCapacity = 63; diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index efa4fd73..b14d571f 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -80,7 +80,7 @@ AlphaNum::AlphaNum(Dec dec) { // StrCat() // This merges the given strings or integers, with no delimiter. This // is designed to be the fastest possible way to construct a string out -// of a mix of raw C strings, StringPieces, strings, and integer values. +// of a mix of raw C strings, string_views, strings, and integer values. // ---------------------------------------------------------------------- // Append is merely a version of memcpy that returns the address of the byte diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc index 326ff744..0ac297c8 100644 --- a/absl/strings/str_split_benchmark.cc +++ b/absl/strings/str_split_benchmark.cc @@ -35,16 +35,16 @@ std::string MakeTestString(int desired_length) { return test; } -void BM_Split2StringPiece(benchmark::State& state) { +void BM_Split2StringView(benchmark::State& state) { std::string test = MakeTestString(state.range(0)); for (auto _ : state) { std::vector<absl::string_view> result = absl::StrSplit(test, ';'); benchmark::DoNotOptimize(result); } } -BENCHMARK_RANGE(BM_Split2StringPiece, 0, 1 << 20); +BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20); -void BM_Split2StringPieceLifted(benchmark::State& state) { +void BM_Split2StringViewLifted(benchmark::State& state) { std::string test = MakeTestString(state.range(0)); std::vector<absl::string_view> result; for (auto _ : state) { @@ -52,7 +52,7 @@ void BM_Split2StringPieceLifted(benchmark::State& state) { } benchmark::DoNotOptimize(result); } -BENCHMARK_RANGE(BM_Split2StringPieceLifted, 0, 1 << 20); +BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20); void BM_Split2String(benchmark::State& state) { std::string test = MakeTestString(state.range(0)); |