113 #include <unordered_set> 115 #define DEBUG_TYPE "sync-dependence" 124 : FuncRPOT(DT.getRoot()->
getParent()), DT(DT), PDT(PDT), LI(LI) {}
155 : FuncRPOT(FuncRPOT), DT(DT), PDT(PDT), LI(LI),
160 bool WasAdded = DefMap.emplace(&Block, &DefBlock).second;
162 PendingUpdates.insert(&Block);
166 Out <<
"Propagator::DefMap {\n";
167 for (
const auto *Block : FuncRPOT) {
168 auto It = DefMap.find(Block);
169 Out << Block->getName() <<
" : ";
170 if (It == DefMap.end()) {
173 const auto *DefBlock = It->second;
174 Out << (DefBlock ? DefBlock->getName() :
"<null>") <<
"\n";
186 if (ParentLoop && !ParentLoop->
contains(&SuccBlock)) {
187 DefMap.emplace(&SuccBlock, &DefBlock);
188 ReachedLoopExits.
insert(&SuccBlock);
193 auto ItLastDef = DefMap.find(&SuccBlock);
194 if (ItLastDef == DefMap.end()) {
195 addPending(SuccBlock, DefBlock);
200 if (ItLastDef->second != &DefBlock) {
202 if (!JoinBlocks->insert(&SuccBlock).second)
206 addPending(SuccBlock, SuccBlock);
219 template <
typename SuccessorIterable>
220 std::unique_ptr<ConstBlockSet>
222 SuccessorIterable NodeSuccessors,
const Loop *ParentLoop) {
226 const auto *PdNode = PDT.
getNode(const_cast<BasicBlock *>(&RootBlock));
227 const auto *IpdNode = PdNode->getIDom();
228 const auto *PdBoundBlock = IpdNode ? IpdNode->getBlock() :
nullptr;
231 for (
const auto *SuccBlock : NodeSuccessors) {
232 DefMap.emplace(SuccBlock, SuccBlock);
234 if (ParentLoop && !ParentLoop->
contains(SuccBlock)) {
236 ReachedLoopExits.
insert(SuccBlock);
240 PendingUpdates.insert(SuccBlock);
244 auto ItBeginRPO = FuncRPOT.
begin();
247 for (; *ItBeginRPO != &RootBlock; ++ItBeginRPO) {}
249 auto ItEndRPO = FuncRPOT.
end();
250 assert(ItBeginRPO != ItEndRPO);
253 auto ItBlockRPO = ItBeginRPO;
254 while (++ItBlockRPO != ItEndRPO && *ItBlockRPO != PdBoundBlock) {
255 const auto *Block = *ItBlockRPO;
258 auto ItPending = PendingUpdates.find(Block);
259 if (ItPending == PendingUpdates.end())
261 PendingUpdates.erase(ItPending);
264 auto ItDef = DefMap.find(Block);
265 const auto *DefBlock = ItDef->second;
270 (ParentLoop != BlockLoop && ParentLoop->
contains(BlockLoop))) {
274 BlockLoop->getExitBlocks(BlockLoopExits);
275 for (
const auto *BlockLoopExit : BlockLoopExits) {
276 visitSuccessor(*BlockLoopExit, ParentLoop, *DefBlock);
281 for (
const auto *SuccBlock :
successors(Block)) {
282 visitSuccessor(*SuccBlock, ParentLoop, *DefBlock);
308 ParentLoop ? ParentLoop->
getHeader() :
nullptr;
309 if (ParentLoop && ParentLoop->
contains(PdBoundBlock)) {
310 DefMap[ParentLoopHeader] = DefMap[PdBoundBlock];
314 if (!ReachedLoopExits.
empty()) {
316 const auto *HeaderDefBlock = DefMap[ParentLoopHeader];
318 assert(HeaderDefBlock &&
"no definition in header of carrying loop");
320 for (
const auto *ExitBlock : ReachedLoopExits) {
321 auto ItExitDef = DefMap.find(ExitBlock);
322 assert((ItExitDef != DefMap.end()) &&
323 "no reaching def at reachable loop exit");
324 if (ItExitDef->second != HeaderDefBlock) {
325 JoinBlocks->insert(ExitBlock);
330 return std::move(JoinBlocks);
336 LoopExitVec LoopExits;
338 if (LoopExits.size() < 1) {
339 return EmptyBlockSet;
343 auto ItCached = CachedLoopExitJoins.find(&Loop);
344 if (ItCached != CachedLoopExitJoins.end())
345 return *ItCached->second;
352 auto ItInserted = CachedLoopExitJoins.emplace(&
Loop, std::move(JoinBlocks));
353 assert(ItInserted.second);
354 return *ItInserted.first->second;
361 return EmptyBlockSet;
365 auto ItCached = CachedBranchJoins.
find(&Term);
366 if (ItCached != CachedBranchJoins.end())
367 return *ItCached->second;
371 const auto &TermBlock = *Term.getParent();
373 TermBlock,
successors(Term.getParent()), LI.getLoopFor(&TermBlock));
375 auto ItInserted = CachedBranchJoins.emplace(&Term, std::move(JoinBlocks));
376 assert(ItInserted.second);
377 return *ItInserted.first->second;
SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI)
This class represents lattice values for constants.
SmallPtrSet< const BasicBlock *, 4 > ConstBlockSet
~SyncDependenceAnalysis()
const ConstBlockSet & join_blocks(const Instruction &Term)
Computes divergent join points and loop exits caused by branch divergence in Term.
const PostDominatorTree & PDT
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
iterator find(ConstPtrType Ptr) const
SmallPtrSet< const BasicBlock *, 4 > ReachedLoopExits
BlockT * getHeader() const
void getExitBlocks(SmallVectorImpl< BlockT *> &ExitBlocks) const
Return all of the successor blocks of this loop.
void addPending(const BasicBlock &Block, const BasicBlock &DefBlock)
std::map< const BasicBlock *, const BasicBlock * > DefiningBlockMap
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
void printDefs(raw_ostream &Out)
unsigned getNumSuccessors() const
Return the number of successors that this instruction has.
const FunctionRPOT & FuncRPOT
void visitSuccessor(const BasicBlock &SuccBlock, const Loop *ParentLoop, const BasicBlock &DefBlock)
LLVM Basic Block Representation.
LLVM_NODISCARD bool empty() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
DivergencePropagator(const FunctionRPOT &FuncRPOT, const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI)
std::unordered_set< const BasicBlock * > PendingUpdates
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A range adaptor for a pair of iterators.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LoopT * getParentLoop() const
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
std::unique_ptr< ConstBlockSet > JoinBlocks
Represents a single loop in the control flow graph.
std::unique_ptr< ConstBlockSet > computeJoinPoints(const BasicBlock &RootBlock, SuccessorIterable NodeSuccessors, const Loop *ParentLoop)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
succ_range successors(Instruction *I)
static const Function * getParent(const Value *V)
This class implements an extremely fast bulk output stream that can only output to a stream...