Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -2646,6 +2646,12 @@ return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F); } + /// Return if the edge from \p From BB to \p To BB is assumed dead. + /// This is specifically useful in AAReachability. + virtual bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const { + return false; + } + /// See AbstractAttribute::getName() const std::string getName() const override { return "AAIsDead"; } Index: llvm/lib/Transforms/IPO/AttributorAttributes.cpp =================================================================== --- llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -3093,6 +3093,10 @@ /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override; + bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override { + return !AssumedLiveEdges.count(std::make_pair(From, To)); + } + /// See AbstractAttribute::trackStatistics() void trackStatistics() const override {} @@ -3170,6 +3174,9 @@ /// Collection of instructions that are known to not transfer control. SmallSetVector KnownDeadEnds; + /// Collection of all assumed live edges + DenseSet> AssumedLiveEdges; + /// Collection of all assumed live BasicBlocks. DenseSet AssumedLiveBlocks; }; @@ -3335,6 +3342,10 @@ << UsedAssumedInformation << "\n"); for (const Instruction *AliveSuccessor : AliveSuccessors) { + // if successor belongs to different basic block, record the edge. + if (I->getParent() != AliveSuccessor->getParent()) + AssumedLiveEdges.insert( + std::make_pair(I->getParent(), AliveSuccessor->getParent())); if (!I->isTerminator()) { assert(AliveSuccessors.size() == 1 && "Non-terminator expected to have a single successor!");