130#define DEBUG_TYPE "sync-dependence"
150using POCB = std::function<void(
const BasicBlock &)>;
151using VisitedSet = std::set<const BasicBlock *>;
152using BlockStack = std::vector<const BasicBlock *>;
156 VisitedSet &Finalized);
159static void computeStackPO(BlockStack &Stack,
const LoopInfo &LI,
Loop *
Loop,
160 POCB CallBack, VisitedSet &Finalized) {
162 while (!Stack.empty()) {
163 const auto *NextBB = Stack.back();
166 bool IsNestedLoop = NestedLoop !=
Loop;
171 NestedLoop->getUniqueExitBlocks(NestedExits);
172 bool PushedNodes =
false;
173 for (
const auto *NestedExitBB : NestedExits) {
174 if (NestedExitBB == LoopHeader)
178 if (Finalized.count(NestedExitBB))
181 Stack.push_back(NestedExitBB);
186 computeLoopPO(LI, *NestedLoop, CallBack, Finalized);
192 bool PushedNodes =
false;
193 for (
const auto *SuccBB :
successors(NextBB)) {
194 if (SuccBB == LoopHeader)
198 if (Finalized.count(SuccBB))
201 Stack.push_back(SuccBB);
206 if (!Finalized.insert(NextBB).second)
214 VisitedSet Finalized;
217 Stack.push_back(&
F.getEntryBlock());
218 computeStackPO(Stack, LI,
nullptr, CallBack, Finalized);
222 VisitedSet &Finalized) {
224 std::vector<const BasicBlock *> Stack;
228 Finalized.insert(LoopHeader);
229 CallBack(*LoopHeader);
232 for (
const auto *BB :
successors(LoopHeader)) {
235 if (BB == LoopHeader)
241 computeStackPO(Stack, LI, &
Loop, CallBack, Finalized);
253 : DT(DT), PDT(PDT), LI(LI) {
255 [&](
const BasicBlock &BB) { LoopPO.appendBlock(BB); });
274 using BlockLabelVec = std::vector<const BasicBlock *>;
277 std::unique_ptr<ControlDivergenceDesc>
DivDesc;
287 Out <<
"Propagator::BlockLabels {\n";
288 for (
int BlockIdx = (
int)
BlockLabels.size() - 1; BlockIdx > 0; --BlockIdx) {
295 Out <<
Label->getName() <<
"\n";
308 if (!OldLabel || (OldLabel == &PushedLabel)) {
320 bool visitLoopExitEdge(
const BasicBlock &ExitBlock,
321 const BasicBlock &DefBlock,
bool FromParentLoop) {
330 DivDesc->LoopDivBlocks.insert(&ExitBlock);
342 DivDesc->JoinDivBlocks.insert(&SuccBlock);
356 int FloorIdx = LoopPOT.
size() - 1;
363 auto SuccIdx = LoopPOT.
getIndexOf(*SuccBlock);
367 BlockIdx = std::max<int>(BlockIdx, SuccIdx);
368 FloorIdx = std::min<int>(FloorIdx, SuccIdx);
374 const auto *BlockLoop = LI.
getLoopFor(SuccBlock);
375 if (BlockLoop && DivBlockLoop->contains(BlockLoop))
377 DivDesc->LoopDivBlocks.insert(SuccBlock);
379 << SuccBlock->
getName() <<
"\n");
383 for (; BlockIdx >= FloorIdx; --BlockIdx) {
397 bool CausedJoin =
false;
398 int LoweredFloorIdx = FloorIdx;
403 BlockLoop->getExitBlocks(BlockLoopExits);
406 for (
const auto *BlockLoopExit : BlockLoopExits) {
407 CausedJoin |= visitLoopExitEdge(*BlockLoopExit, *Label, IsParentLoop);
408 LoweredFloorIdx = std::min<int>(LoweredFloorIdx,
414 CausedJoin |=
visitEdge(*SuccBlock, *Label);
416 std::min<int>(LoweredFloorIdx, LoopPOT.
getIndexOf(*SuccBlock));
423 FloorIdx = LoweredFloorIdx;
424 }
else if (FloorLabel != Label) {
427 FloorIdx = LoweredFloorIdx;
443 for (
const auto *BB : Blocks)
444 Out << LS << BB->getName();
452 if (Term.getNumSuccessors() <= 1) {
453 return EmptyDivergenceDesc;
457 auto ItCached = CachedControlDivDescs.find(&Term);
458 if (ItCached != CachedControlDivDescs.end())
459 return *ItCached->second;
463 const auto &TermBlock = *Term.getParent();
467 LLVM_DEBUG(
dbgs() <<
"Result (" << Term.getParent()->getName() <<
"):\n";
468 dbgs() <<
"JoinDivBlocks: ";
470 dbgs() <<
"\nLoopDivBlocks: ";
473 auto ItInserted = CachedControlDivDescs.emplace(&Term, std::move(DivDesc));
474 assert(ItInserted.second);
475 return *ItInserted.first->second;
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
Compute divergence starting with a divergent branch.
bool computeJoin(const BlockT &SuccBlock, const BlockT &PushedLabel)
const BlockT & DivTermBlock
std::unique_ptr< DivergenceDescriptorT > DivDesc
void printDefs(raw_ostream &Out)
const DominatorTreeT & DT
std::unique_ptr< DivergenceDescriptorT > computeJoinPoints()
BlockLabelMapT & BlockLabels
bool visitEdge(const BlockT &SuccBlock, const BlockT &Label)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
BlockT * getHeader() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::string str() const
str - Get the contents as an std::string.
~SyncDependenceAnalysis()
SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI)
const ControlDivergenceDesc & getJoinBlocks(const Instruction &Term)
Computes divergent join points and loop exits caused by branch divergence in Term.
StringRef getName() const
Return a constant reference to the value's name.
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto successors(const MachineBasicBlock *BB)
static void printBlockSet(ConstBlockSet &Blocks, raw_ostream &Out)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const BasicBlock * getBlockAt(unsigned Idx) const
unsigned getIndexOf(const BasicBlock &BB) const