diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1636,6 +1636,57 @@ return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); } +/// Return the single value in \p Range that satisfies +/// \p P( *, AllowRepeats)->T * returning nullptr +/// when no values or multiple values were found. +/// When \p AllowRepeats is true, multiple values that compare equal +/// are allowed. +template +T *find_singleton(R &&Range, Predicate P, bool AllowRepeats = false) { + T *RC = nullptr; + for (auto *A : Range) { + if (T *PRC = P(A, AllowRepeats)) { + if (RC) { + if (!AllowRepeats || PRC != RC) + return nullptr; + } else + RC = PRC; + } + } + return RC; +} + +/// Return a pair consisting of the single value in \p Range that satisfies +/// \p P( *, AllowRepeats)->std::pair returning +/// nullptr when no values or multiple values were found, and a bool indicating +/// whether multiple values were found to cause the nullptr. +/// When \p AllowRepeats is true, multiple values that compare equal are +/// allowed. The predicate \p P returns a pair where T is the +/// singleton while the bool indicates whether multiples have already been +/// found. It is expected that first will be nullptr when second is true. +/// This allows using find_singleton_nested within the predicate \P. +template +std::pair find_singleton_nested(R &&Range, Predicate P, + bool AllowRepeats = false) { + T *RC = nullptr; + for (auto *A : Range) { + std::pair PRC = P(A, AllowRepeats); + if (PRC.second) { + assert(PRC.first == nullptr && + "Inconsistent return values in find_singleton_nested."); + return PRC; + } + if (PRC.first) { + if (RC) { + if (!AllowRepeats || PRC.first != RC) + return {nullptr, true}; + } else + RC = PRC.first; + } + } + return {RC, false}; +} + template OutputIt copy(R &&Range, OutputIt Out) { return std::copy(adl_begin(Range), adl_end(Range), Out); diff --git a/llvm/include/llvm/Analysis/LoopInfoImpl.h b/llvm/include/llvm/Analysis/LoopInfoImpl.h --- a/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -47,11 +47,14 @@ template BlockT *LoopBase::getExitingBlock() const { assert(!isInvalid() && "Loop not in a valid state!"); - SmallVector ExitingBlocks; - getExitingBlocks(ExitingBlocks); - if (ExitingBlocks.size() == 1) - return ExitingBlocks[0]; - return nullptr; + auto notInLoop = [&](BlockT *BB) { return !contains(BB); }; + auto isExitBlock = [&](BlockT *BB, bool AllowRepeats) -> BlockT * { + assert(!AllowRepeats && "Unexpected parameter value."); + // Child not in current loop? It must be an exit block. + return any_of(children(BB), notInLoop) ? BB : nullptr; + }; + + return find_singleton(blocks(), isExitBlock); } /// getExitBlocks - Return all of the successor blocks of this loop. These @@ -68,23 +71,41 @@ ExitBlocks.push_back(Succ); } +/// getExitBlock - If getExitBlocks would return exactly one block, +/// return that block. Otherwise return null. +template +std::pair getExitBlockHelper(const LoopBase *L, + bool Unique) { + assert(!L->isInvalid() && "Loop not in a valid state!"); + auto notInLoop = [&](BlockT *BB, + bool AllowRepeats) -> std::pair { + assert(AllowRepeats == Unique && "Unexpected parameter value."); + return {!L->contains(BB) ? BB : nullptr, false}; + }; + auto singleExitBlock = [&](BlockT *BB, + bool AllowRepeats) -> std::pair { + assert(AllowRepeats == Unique && "Unexpected parameter value."); + return find_singleton_nested(children(BB), notInLoop, + AllowRepeats); + }; + return find_singleton_nested(L->blocks(), singleExitBlock, Unique); +} + template bool LoopBase::hasNoExitBlocks() const { - SmallVector ExitBlocks; - getExitBlocks(ExitBlocks); - return ExitBlocks.empty(); + auto RC = getExitBlockHelper(this, false); + if (RC.second) + // found multiple exit blocks + return false; + // return true if there is no exit block + return !RC.first; } /// getExitBlock - If getExitBlocks would return exactly one block, /// return that block. Otherwise return null. template BlockT *LoopBase::getExitBlock() const { - assert(!isInvalid() && "Loop not in a valid state!"); - SmallVector ExitBlocks; - getExitBlocks(ExitBlocks); - if (ExitBlocks.size() == 1) - return ExitBlocks[0]; - return nullptr; + return getExitBlockHelper(this, false).first; } template @@ -135,11 +156,7 @@ template BlockT *LoopBase::getUniqueExitBlock() const { - SmallVector UniqueExitBlocks; - getUniqueExitBlocks(UniqueExitBlocks); - if (UniqueExitBlocks.size() == 1) - return UniqueExitBlocks[0]; - return nullptr; + return getExitBlockHelper(this, true).first; } /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). diff --git a/llvm/include/llvm/Analysis/RegionInfoImpl.h b/llvm/include/llvm/Analysis/RegionInfoImpl.h --- a/llvm/include/llvm/Analysis/RegionInfoImpl.h +++ b/llvm/include/llvm/Analysis/RegionInfoImpl.h @@ -159,20 +159,14 @@ template typename RegionBase::BlockT *RegionBase::getEnteringBlock() const { + auto isEnteringBlock = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * { + assert(!AllowRepeats && "Unexpected parameter value."); + return DT->getNode(Pred) && !contains(Pred) ? Pred : nullptr; + }; BlockT *entry = getEntry(); - BlockT *enteringBlock = nullptr; - - for (BlockT *Pred : make_range(InvBlockTraits::child_begin(entry), - InvBlockTraits::child_end(entry))) { - if (DT->getNode(Pred) && !contains(Pred)) { - if (enteringBlock) - return nullptr; - - enteringBlock = Pred; - } - } - - return enteringBlock; + return find_singleton(make_range(InvBlockTraits::child_begin(entry), + InvBlockTraits::child_end(entry)), + isEnteringBlock); } template @@ -201,22 +195,16 @@ template typename RegionBase::BlockT *RegionBase::getExitingBlock() const { BlockT *exit = getExit(); - BlockT *exitingBlock = nullptr; - if (!exit) return nullptr; - for (BlockT *Pred : make_range(InvBlockTraits::child_begin(exit), - InvBlockTraits::child_end(exit))) { - if (contains(Pred)) { - if (exitingBlock) - return nullptr; - - exitingBlock = Pred; - } - } - - return exitingBlock; + auto isContained = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * { + assert(!AllowRepeats && "Unexpected parameter value."); + return contains(Pred) ? Pred : nullptr; + }; + return find_singleton(make_range(InvBlockTraits::child_begin(exit), + InvBlockTraits::child_end(exit)), + isContained); } template