diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index c209c4aede9bb..4a93ee55e76dc 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -195,6 +195,12 @@ void adl_swap(T &&lhs, T &&rhs) noexcept( adl_detail::adl_swap(std::forward(lhs), std::forward(rhs)); } +/// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. +template +constexpr bool empty(const T &RangeOrContainer) { + return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); +} + // mapped_iterator - This is a simple iterator adapter that causes a function to // be applied whenever operator* is invoked on the iterator. diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp index b1d585bfc683f..3f22ada803c9f 100644 --- a/llvm/lib/Analysis/LazyCallGraph.cpp +++ b/llvm/lib/Analysis/LazyCallGraph.cpp @@ -619,7 +619,7 @@ LazyCallGraph::RefSCC::switchInternalEdgeToCall( // If the merge range is empty, then adding the edge didn't actually form any // new cycles. We're done. - if (MergeRange.begin() == MergeRange.end()) { + if (empty(MergeRange)) { // Now that the SCC structure is finalized, flip the kind to call. SourceN->setEdgeKind(TargetN, Edge::Call); return false; // No new cycle. diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp index 5e77fcbb0ed93..38913e4afcba3 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -80,5 +80,5 @@ bool InstructionSelector::isObviouslySafeToFold(MachineInstr &MI, return true; return !MI.mayLoadOrStore() && !MI.hasUnmodeledSideEffects() && - MI.implicit_operands().begin() == MI.implicit_operands().end(); + empty(MI.implicit_operands()); } diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp index b6ed2654bd04d..ca776de0a0fe0 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerInfo.cpp @@ -298,8 +298,7 @@ LegalizeRuleSet &LegalizerInfo::getActionDefinitionsBuilder( std::initializer_list Opcodes) { unsigned Representative = *Opcodes.begin(); - assert(Opcodes.begin() != Opcodes.end() && - Opcodes.begin() + 1 != Opcodes.end() && + assert(!empty(Opcodes) && Opcodes.begin() + 1 != Opcodes.end() && "Initializer list must have at least two opcodes"); for (auto I = Opcodes.begin() + 1, E = Opcodes.end(); I != E; ++I) diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp index 9e2d48d1dc424..6bb48dc2e8aac 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -140,7 +140,7 @@ bool RegBankSelect::repairReg( return false; assert(ValMapping.NumBreakDowns == 1 && "Not yet implemented"); // An empty range of new register means no repairing. - assert(NewVRegs.begin() != NewVRegs.end() && "We should not have to repair"); + assert(!empty(NewVRegs) && "We should not have to repair"); // Assume we are repairing a use and thus, the original reg will be // the source of the repairing. diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index dd15567ef1c1b..28404e52d6ea9 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -426,7 +426,7 @@ void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) { "This mapping is too complex for this function"); iterator_range::const_iterator> NewRegs = OpdMapper.getVRegs(OpIdx); - if (NewRegs.begin() == NewRegs.end()) { + if (empty(NewRegs)) { LLVM_DEBUG(dbgs() << " has not been repaired, nothing to be done\n"); continue; } diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index d9ff07efbe904..7c3c50b4d6e53 100644 --- a/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -88,7 +88,7 @@ iterator_range getDestructors(const Module &M) { } void CtorDtorRunner::add(iterator_range CtorDtors) { - if (CtorDtors.begin() == CtorDtors.end()) + if (empty(CtorDtors)) return; MangleAndInterner Mangle( diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index e5fb765f778fb..02b7953cb5bbe 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -280,7 +280,7 @@ bool DebugInfoFinder::addScope(DIScope *Scope) { } static MDNode *stripDebugLocFromLoopID(MDNode *N) { - assert(N->op_begin() != N->op_end() && "Missing self reference?"); + assert(!empty(N->operands()) && "Missing self reference?"); // if there is no debug location, we do not have to rewrite this MDNode. if (std::none_of(N->op_begin() + 1, N->op_end(), [](const MDOperand &Op) { diff --git a/llvm/lib/Transforms/IPO/PartialInlining.cpp b/llvm/lib/Transforms/IPO/PartialInlining.cpp index 11c4bbc437c10..bcb19af85b29b 100644 --- a/llvm/lib/Transforms/IPO/PartialInlining.cpp +++ b/llvm/lib/Transforms/IPO/PartialInlining.cpp @@ -1251,7 +1251,7 @@ std::pair PartialInlinerImpl::unswitchFunction(Function *F) { if (PSI->isFunctionEntryCold(F)) return {false, nullptr}; - if (F->user_begin() == F->user_end()) + if (empty(F->users())) return {false, nullptr}; OptimizationRemarkEmitter ORE(F); @@ -1357,7 +1357,7 @@ bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) { return false; } - assert(Cloner.OrigFunc->user_begin() == Cloner.OrigFunc->user_end() && + assert(empty(Cloner.OrigFunc->users()) && "F's users should all be replaced!"); std::vector Users(Cloner.ClonedFunc->user_begin(), diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index f5c1493781dbf..cd57ebd0c6f4b 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1751,7 +1751,7 @@ NewGVN::performSymbolicPHIEvaluation(ArrayRef PHIOps, return true; }); // If we are left with no operands, it's dead. - if (Filtered.begin() == Filtered.end()) { + if (empty(Filtered)) { // If it has undef at this point, it means there are no-non-undef arguments, // and thus, the value of the phi node must be undef. if (HasUndef) { diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp index 9d9624850fbd8..585ce6b4c1188 100644 --- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp +++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp @@ -522,7 +522,7 @@ Value *PredicateInfo::materializeStack(unsigned int &Counter, if (isa(ValInfo)) { IRBuilder<> B(getBranchTerminator(ValInfo)); Function *IF = getCopyDeclaration(F.getParent(), Op->getType()); - if (IF->user_begin() == IF->user_end()) + if (empty(IF->users())) CreatedDeclarations.insert(IF); CallInst *PIC = B.CreateCall(IF, Op, Op->getName() + "." + Twine(Counter++)); @@ -534,7 +534,7 @@ Value *PredicateInfo::materializeStack(unsigned int &Counter, "Should not have gotten here without it being an assume"); IRBuilder<> B(PAssume->AssumeInst); Function *IF = getCopyDeclaration(F.getParent(), Op->getType()); - if (IF->user_begin() == IF->user_end()) + if (empty(IF->users())) CreatedDeclarations.insert(IF); CallInst *PIC = B.CreateCall(IF, Op); PredicateMap.insert({PIC, ValInfo}); diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index dd0d441a4da6b..849f9ee1d19dd 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -5260,7 +5260,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder, // Figure out the corresponding result for each case value and phi node in the // common destination, as well as the min and max case values. - assert(SI->case_begin() != SI->case_end()); + assert(!empty(SI->cases())); SwitchInst::CaseIt CI = SI->case_begin(); ConstantInt *MinCaseVal = CI->getCaseValue(); ConstantInt *MaxCaseVal = CI->getCaseValue(); diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 427d470b61d41..80e10d071ab56 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -364,6 +364,23 @@ TEST(STLExtrasTest, ADLTest) { EXPECT_EQ(5, count); } +TEST(STLExtrasTest, EmptyTest) { + std::vector V; + EXPECT_TRUE(empty(V)); + V.push_back(nullptr); + EXPECT_FALSE(empty(V)); + + std::initializer_list E = {}; + std::initializer_list NotE = {7, 13, 42}; + EXPECT_TRUE(empty(E)); + EXPECT_FALSE(empty(NotE)); + + auto R0 = make_range(V.begin(), V.begin()); + EXPECT_TRUE(empty(R0)); + auto R1 = make_range(V.begin(), V.end()); + EXPECT_FALSE(empty(R1)); +} + TEST(STLExtrasTest, EarlyIncrementTest) { std::list L = {1, 2, 3, 4};