1515#include " GCNSubtarget.h"
1616#include " llvm/Analysis/LoopInfo.h"
1717#include " llvm/Analysis/UniformityAnalysis.h"
18+ #include " llvm/Analysis/DomTreeUpdater.h"
1819#include " llvm/CodeGen/TargetPassConfig.h"
1920#include " llvm/IR/BasicBlock.h"
2021#include " llvm/IR/Constants.h"
@@ -86,7 +87,7 @@ class SIAnnotateControlFlow : public FunctionPass {
8687
8788 bool handleLoop (BranchInst *Term);
8889
89- bool insertWaveReconverge (BasicBlock *BB);
90+ bool tryWaveReconverge (BasicBlock *BB);
9091
9192public:
9293 static char ID;
@@ -203,8 +204,6 @@ bool SIAnnotateControlFlow::eraseIfUnused(PHINode *Phi) {
203204
204205// / Open a new "If" block
205206bool SIAnnotateControlFlow::openIf (BranchInst *Term) {
206- if (isUniform (Term))
207- return false ;
208207
209208 IRBuilder<> IRB (Term);
210209 Value *IfCall = IRB.CreateCall (If, {Term->getCondition ()});
@@ -305,20 +304,44 @@ bool SIAnnotateControlFlow::handleLoop(BranchInst *Term) {
305304}
306305
307306// / Close the last opened control flow
308- bool SIAnnotateControlFlow::insertWaveReconverge (BasicBlock *BB) {
309- assert (succ_empty (BB) || succ_size (BB) == 1 );
310-
311- if (succ_empty (BB))
312- return false ;
307+ bool SIAnnotateControlFlow::tryWaveReconverge (BasicBlock *BB) {
308+
309+ if (succ_empty (BB))
310+ return false ;
313311
314- BasicBlock *SingleSucc = *succ_begin (BB);
315- BranchInst *Term = dyn_cast<BranchInst>(BB->getTerminator ());
316- BasicBlock::iterator InsPt = Term ? BasicBlock::iterator (Term) : BB->end ();
312+ BranchInst *Term = dyn_cast<BranchInst>(BB->getTerminator ());
313+ if (Term->getNumSuccessors () == 1 ) {
314+ // The current BBs single successor is a top of the stack. We need to
315+ // reconverge over thaqt path.
316+ BasicBlock *SingleSucc = *succ_begin (BB);
317+ BasicBlock::iterator InsPt = Term ? BasicBlock::iterator (Term) : BB->end ();
317318
318- if (isTopOfStack (SingleSucc)) {
319- Value *Exec = Stack.back ().second ;
320- IRBuilder<>(BB, InsPt).CreateCall (WaveReconverge, {Exec});
319+ if (isTopOfStack (SingleSucc)) {
320+ Value *Exec = Stack.back ().second ;
321+ IRBuilder<>(BB, InsPt).CreateCall (WaveReconverge, {Exec});
322+ }
323+ } else {
324+ // We have a uniform conditional branch terminating the block.
325+ // THis block may be the last in the Then path of the enclosing divergent
326+ // IF.
327+ if (!isUniform (Term))
328+ // Divergent loop is going to be further processed in another place
329+ return false ;
330+
331+ for (auto Succ : Term->successors ()) {
332+ if (isTopOfStack (Succ)) {
333+ // Just split to make a room for further WAVE_RECONVERGE insertion
334+ SmallVector<BasicBlock*, 2 > Preds;
335+ for (auto P : predecessors (Succ)) {
336+ if (DT->dominates (BB, P))
337+ Preds.push_back (P);
338+ }
339+ DomTreeUpdater DTU (DT, DomTreeUpdater::UpdateStrategy::Eager);
340+ SplitBlockPredecessors (Succ, Preds, " .reconverge" , &DTU, LI,
341+ nullptr , false );
321342 }
343+ }
344+ }
322345
323346 return true ;
324347}
@@ -342,8 +365,8 @@ bool SIAnnotateControlFlow::runOnFunction(Function &F) {
342365 if (!Term || Term->isUnconditional ()) {
343366 if (isTopOfStack (BB))
344367 Stack.pop_back ();
345-
346- insertWaveReconverge (BB);
368+
369+ Changed |= tryWaveReconverge (BB);
347370
348371 continue ;
349372 }
@@ -352,6 +375,10 @@ bool SIAnnotateControlFlow::runOnFunction(Function &F) {
352375 if (isTopOfStack (BB))
353376 Stack.pop_back ();
354377
378+ // Let's take care of uniform loop latch that may be closing the Then
379+ // path of the enclosing divergent branch.
380+ Changed |= tryWaveReconverge (BB);
381+
355382 if (DT->dominates (Term->getSuccessor (1 ), BB))
356383 Changed |= handleLoop (Term);
357384 continue ;
@@ -368,7 +395,12 @@ bool SIAnnotateControlFlow::runOnFunction(Function &F) {
368395 Stack.pop_back ();
369396 }
370397
371- Changed |= openIf (Term);
398+ if (isUniform (Term))
399+ // Uniform conditional branch may be in the block that closes the Then
400+ // path of the divergent conditional branch.
401+ Changed |= tryWaveReconverge (BB);
402+ else
403+ Changed |= openIf (Term);
372404 }
373405
374406 if (!Stack.empty ()) {
0 commit comments