From e2d47dd1bb0dcae478db891273635672c3dc969e Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Fri, 17 Aug 2018 07:51:01 +0000 Subject: [PATCH] [MISC]Fix wrong usage of std::equal() Differential Revision: https://reviews.llvm.org/D49958 llvm-svn: 340000 --- llvm/include/llvm/ADT/STLExtras.h | 33 ++++++++++++++-------- .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 2 +- llvm/lib/Transforms/Scalar/NewGVN.cpp | 8 ++---- llvm/unittests/ADT/STLExtrasTest.cpp | 15 ++++++++++ 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 03109a0..3d6d7a6 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1005,6 +1005,18 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Get the size of a range. This is a wrapper function around std::distance +/// which is only enabled when the operation is O(1). +template +auto size(R &&Range, typename std::enable_if< + std::is_same::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) + -> decltype(std::distance(Range.begin(), Range.end())) { + return std::distance(Range.begin(), Range.end()); +} + /// Provide wrappers to std::for_each which take ranges instead of having to /// pass begin/end explicitly. template @@ -1115,6 +1127,15 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { return std::lower_bound(adl_begin(Range), adl_end(Range), I); } +/// 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))); +} + /// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. @@ -1136,18 +1157,6 @@ void erase_if(Container &C, UnaryPredicate P) { C.erase(remove_if(C, P), C.end()); } -/// Get the size of a range. This is a wrapper function around std::distance -/// which is only enabled when the operation is O(1). -template -auto size(R &&Range, typename std::enable_if< - std::is_same::iterator_category, - std::random_access_iterator_tag>::value, - void>::type * = nullptr) - -> decltype(std::distance(Range.begin(), Range.end())) { - return std::distance(Range.begin(), Range.end()); -} - //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index f0efe4d..9ae5b3c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2931,7 +2931,7 @@ void SelectionDAGBuilder::visitSelect(const User &I) { ISD::VSELECT : ISD::SELECT; // Min/max matching is only viable if all output VTs are the same. - if (std::equal(ValueVTs.begin(), ValueVTs.end(), ValueVTs.begin())) { + if (is_splat(ValueVTs)) { EVT VT = ValueVTs[0]; LLVMContext &Ctx = *DAG.getContext(); auto &TLI = DAG.getTargetLoweringInfo(); diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 4dfde3a..bfb7d3d 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -3174,10 +3174,7 @@ bool NewGVN::singleReachablePHIPath( SmallVector OperandList; std::copy(FilteredPhiArgs.begin(), FilteredPhiArgs.end(), std::back_inserter(OperandList)); - bool Okay = OperandList.size() == 1; - if (!Okay) - Okay = - std::equal(OperandList.begin(), OperandList.end(), OperandList.begin()); + bool Okay = is_splat(OperandList); if (Okay) return singleReachablePHIPath(Visited, cast(OperandList[0]), Second); @@ -3272,8 +3269,7 @@ void NewGVN::verifyMemoryCongruency() const { const MemoryDef *MD = cast(U); return ValueToClass.lookup(MD->getMemoryInst()); }); - assert(std::equal(PhiOpClasses.begin(), PhiOpClasses.end(), - PhiOpClasses.begin()) && + assert(is_splat(PhiOpClasses) && "All MemoryPhi arguments should be in the same class"); } } diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 1e1e9c3..427d470 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -415,4 +415,19 @@ TEST(STLExtrasTest, EarlyIncrementTest) { EXPECT_EQ(EIR.end(), I); } +TEST(STLExtrasTest, splat) { + std::vector V; + EXPECT_FALSE(is_splat(V)); + + V.push_back(1); + EXPECT_TRUE(is_splat(V)); + + V.push_back(1); + V.push_back(1); + EXPECT_TRUE(is_splat(V)); + + V.push_back(2); + EXPECT_FALSE(is_splat(V)); +} + } // namespace -- 2.7.4