@@ -181,14 +181,52 @@ BasicBlock *AMDGPUUnifyDivergentExitNodesImpl::unifyReturnBlockSet(
181
181
return NewRetBlock;
182
182
}
183
183
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
+
184
224
bool AMDGPUUnifyDivergentExitNodesImpl::run (Function &F, DominatorTree *DT,
185
225
const PostDominatorTree &PDT,
186
226
const UniformityInfo &UA) {
187
- assert (hasOnlySimpleTerminator (F) && " Unsupported block terminator." );
188
-
189
227
if (PDT.root_size () == 0 ||
190
228
(PDT.root_size () == 1 &&
191
- !isa<BranchInst>(PDT.getRoot ()->getTerminator ())))
229
+ !isa<BranchInst, CallBrInst >(PDT.getRoot ()->getTerminator ())))
192
230
return false ;
193
231
194
232
// 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,
222
260
if (HasDivergentExitBlock)
223
261
UnreachableBlocks.push_back (BB);
224
262
} 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 == nullptr )
264
+ DummyReturnBB = createDummyReturnBlock (F, ReturningBlocks);
235
265
236
266
if (BI->isUnconditional ()) {
237
267
BasicBlock *LoopHeaderBB = BI->getSuccessor (0 );
238
268
BI->eraseFromParent (); // Delete the unconditional branch.
239
269
// 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);
262
272
Updates.emplace_back (DominatorTree::Insert, BB, DummyReturnBB);
273
+ } else {
274
+ handleNBranch (F, BB, BI, DummyReturnBB, Updates);
263
275
}
264
276
Changed = true ;
277
+ } else if (CallBrInst *CBI = dyn_cast<CallBrInst>(BB->getTerminator ())) {
278
+ if (DummyReturnBB == nullptr )
279
+ DummyReturnBB = createDummyReturnBlock (F, ReturningBlocks);
280
+
281
+ handleNBranch (F, BB, CBI, DummyReturnBB, Updates);
282
+ } else {
283
+ llvm_unreachable (" unsupported block terminator" );
265
284
}
266
285
}
267
286
0 commit comments