@@ -181,14 +181,52 @@ BasicBlock *AMDGPUUnifyDivergentExitNodesImpl::unifyReturnBlockSet(
181181 return NewRetBlock;
182182}
183183
184+ static BasicBlock *
185+ createDummyReturnBlock (Function &F,
186+ SmallVector<BasicBlock *, 4 > &ReturningBlocks) {
187+ BasicBlock *DummyReturnBB =
188+ BasicBlock::Create (F.getContext (), " DummyReturnBlock" , &F);
189+ Type *RetTy = F.getReturnType ();
190+ Value *RetVal = RetTy->isVoidTy () ? nullptr : PoisonValue::get (RetTy);
191+ ReturnInst::Create (F.getContext (), RetVal, DummyReturnBB);
192+ ReturningBlocks.push_back (DummyReturnBB);
193+ return DummyReturnBB;
194+ }
195+
196+ // / Handle conditional branch instructions (-> 2 targets) and callbr
197+ // / instructions with N targets.
198+ static void handleNBranch (Function &F, BasicBlock *BB, Instruction *BI,
199+ BasicBlock *DummyReturnBB,
200+ std::vector<DominatorTree::UpdateType> &Updates) {
201+ SmallVector<BasicBlock *, 2 > Successors (successors (BB));
202+
203+ // Create a new transition block to hold the conditional branch.
204+ BasicBlock *TransitionBB = BB->splitBasicBlock (BI, " TransitionBlock" );
205+
206+ Updates.reserve (Updates.size () + 2 * Successors.size () + 2 );
207+
208+ // 'Successors' become successors of TransitionBB instead of BB,
209+ // and TransitionBB becomes a single successor of BB.
210+ Updates.emplace_back (DominatorTree::Insert, BB, TransitionBB);
211+ for (BasicBlock *Successor : Successors) {
212+ Updates.emplace_back (DominatorTree::Insert, TransitionBB, Successor);
213+ Updates.emplace_back (DominatorTree::Delete, BB, Successor);
214+ }
215+
216+ // Create a branch that will always branch to the transition block and
217+ // references DummyReturnBB.
218+ BB->getTerminator ()->eraseFromParent ();
219+ BranchInst::Create (TransitionBB, DummyReturnBB,
220+ ConstantInt::getTrue (F.getContext ()), BB);
221+ Updates.emplace_back (DominatorTree::Insert, BB, DummyReturnBB);
222+ }
223+
184224bool AMDGPUUnifyDivergentExitNodesImpl::run (Function &F, DominatorTree *DT,
185225 const PostDominatorTree &PDT,
186226 const UniformityInfo &UA) {
187- assert (hasOnlySimpleTerminator (F) && " Unsupported block terminator." );
188-
189227 if (PDT.root_size () == 0 ||
190228 (PDT.root_size () == 1 &&
191- !isa<BranchInst>(PDT.getRoot ()->getTerminator ())))
229+ !isa<BranchInst, CallBrInst >(PDT.getRoot ()->getTerminator ())))
192230 return false ;
193231
194232 // Loop over all of the blocks in a function, tracking all of the blocks that
@@ -222,46 +260,27 @@ bool AMDGPUUnifyDivergentExitNodesImpl::run(Function &F, DominatorTree *DT,
222260 if (HasDivergentExitBlock)
223261 UnreachableBlocks.push_back (BB);
224262 } else if (BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator ())) {
225-
226- ConstantInt *BoolTrue = ConstantInt::getTrue (F.getContext ());
227- if (DummyReturnBB == nullptr ) {
228- DummyReturnBB = BasicBlock::Create (F.getContext (),
229- " DummyReturnBlock" , &F);
230- Type *RetTy = F.getReturnType ();
231- Value *RetVal = RetTy->isVoidTy () ? nullptr : PoisonValue::get (RetTy);
232- ReturnInst::Create (F.getContext (), RetVal, DummyReturnBB);
233- ReturningBlocks.push_back (DummyReturnBB);
234- }
263+ if (!DummyReturnBB)
264+ DummyReturnBB = createDummyReturnBlock (F, ReturningBlocks);
235265
236266 if (BI->isUnconditional ()) {
237267 BasicBlock *LoopHeaderBB = BI->getSuccessor (0 );
238268 BI->eraseFromParent (); // Delete the unconditional branch.
239269 // Add a new conditional branch with a dummy edge to the return block.
240- BranchInst::Create (LoopHeaderBB, DummyReturnBB, BoolTrue, BB);
241- Updates.emplace_back (DominatorTree::Insert, BB, DummyReturnBB);
242- } else { // Conditional branch.
243- SmallVector<BasicBlock *, 2 > Successors (successors (BB));
244-
245- // Create a new transition block to hold the conditional branch.
246- BasicBlock *TransitionBB = BB->splitBasicBlock (BI, " TransitionBlock" );
247-
248- Updates.reserve (Updates.size () + 2 * Successors.size () + 2 );
249-
250- // 'Successors' become successors of TransitionBB instead of BB,
251- // and TransitionBB becomes a single successor of BB.
252- Updates.emplace_back (DominatorTree::Insert, BB, TransitionBB);
253- for (BasicBlock *Successor : Successors) {
254- Updates.emplace_back (DominatorTree::Insert, TransitionBB, Successor);
255- Updates.emplace_back (DominatorTree::Delete, BB, Successor);
256- }
257-
258- // Create a branch that will always branch to the transition block and
259- // references DummyReturnBB.
260- BB->getTerminator ()->eraseFromParent ();
261- BranchInst::Create (TransitionBB, DummyReturnBB, BoolTrue, BB);
270+ BranchInst::Create (LoopHeaderBB, DummyReturnBB,
271+ ConstantInt::getTrue (F.getContext ()), BB);
262272 Updates.emplace_back (DominatorTree::Insert, BB, DummyReturnBB);
273+ } else {
274+ handleNBranch (F, BB, BI, DummyReturnBB, Updates);
263275 }
264276 Changed = true ;
277+ } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(BB->getTerminator ())) {
278+ if (!DummyReturnBB)
279+ DummyReturnBB = createDummyReturnBlock (F, ReturningBlocks);
280+
281+ handleNBranch (F, BB, CBI, DummyReturnBB, Updates);
282+ } else {
283+ llvm_unreachable (" unsupported block terminator" );
265284 }
266285 }
267286
0 commit comments