Index: llvm/trunk/include/llvm/ADT/STLExtras.h =================================================================== --- llvm/trunk/include/llvm/ADT/STLExtras.h +++ llvm/trunk/include/llvm/ADT/STLExtras.h @@ -1005,6 +1005,18 @@ 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 @@ 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 @@ 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 //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2931,7 +2931,7 @@ 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(); Index: llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp +++ llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp @@ -3174,10 +3174,7 @@ 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 @@ 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"); } } Index: llvm/trunk/unittests/ADT/STLExtrasTest.cpp =================================================================== --- llvm/trunk/unittests/ADT/STLExtrasTest.cpp +++ llvm/trunk/unittests/ADT/STLExtrasTest.cpp @@ -415,4 +415,19 @@ 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