From c9e52fbe4d4fa37a87b2855ad7e118dcdee2db68 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Mon, 22 Aug 2022 23:55:05 -0400 Subject: [PATCH] [ADT] Add all_equal predicate `llvm::all_equal` checks if all values in the given range are equal, i.e., there are no two elements that are not equal. Similar to `llvm::all_of`, it returns `true` when the range is empty. `llvm::all_equal` is intended to supersede `llvm::is_splat`, which will be deprecated and removed in future patches. See the discussion thread for more details: https://discourse.llvm.org/t/adt-is-splat-and-empty-ranges/64692. Reviewed By: dblaikie, shchenz Differential Revision: https://reviews.llvm.org/D132334 --- llvm/include/llvm/ADT/STLExtras.h | 25 +++++++++++++++++-------- llvm/unittests/ADT/STLExtrasTest.cpp | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 9173719..44f86e4 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1763,16 +1763,25 @@ template bool equal(L &&LRange, R &&RRange) { adl_end(RRange)); } -/// Wrapper function around std::equal to detect if all elements -/// in a container are same. -template -bool is_splat(R &&Range) { - size_t range_size = size(Range); - return range_size != 0 && (range_size == 1 || - std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); +/// Returns true if all elements in Range are equal or when the Range is empty. +template bool all_equal(R &&Range) { + auto Begin = adl_begin(Range); + auto End = adl_end(Range); + return Begin == End || std::equal(Begin + 1, End, Begin); +} + +/// Returns true if all Values in the initializer lists are equal or the list +// is empty. +template bool all_equal(std::initializer_list Values) { + return all_equal>(std::move(Values)); +} + +/// Returns true if Range consists of the same value repeated multiple times. +template bool is_splat(R &&Range) { + return !llvm::empty(Range) && all_equal(Range); } -/// Returns true iff all Values in the initializer lists are same. +/// Returns true if Values consists of the same value repeated multiple times. template bool is_splat(std::initializer_list Values) { return is_splat>(std::move(Values)); } diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 8ae5020..9b0af51 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -588,6 +588,29 @@ TEST(STLExtrasTest, EarlyIncrementTestCustomPointerIterator) { EXPECT_EQ(EIR.end(), I); } +TEST(STLExtrasTest, AllEqual) { + std::vector V; + EXPECT_TRUE(all_equal(V)); + + V.push_back(1); + EXPECT_TRUE(all_equal(V)); + + V.push_back(1); + V.push_back(1); + EXPECT_TRUE(all_equal(V)); + + V.push_back(2); + EXPECT_FALSE(all_equal(V)); +} + +TEST(STLExtrasTest, AllEqualInitializerList) { + EXPECT_TRUE(all_equal({1})); + EXPECT_TRUE(all_equal({1, 1})); + EXPECT_FALSE(all_equal({1, 2})); + EXPECT_FALSE(all_equal({2, 1})); + EXPECT_TRUE(all_equal({1, 1, 1})); +} + TEST(STLExtrasTest, IsSplat) { std::vector V; EXPECT_FALSE(is_splat(V)); -- 2.7.4