Skip to content

Commit d4a38c8

Browse files
authored
[DFAJumpThreading] Handle select unfolding when user phi is not a dir… (#109511)
…ect successor Previously the code assumed that the select instruction is defined in a block that is a direct predecessor of the block where the PHINode uses it. So, we were hitting an assertion when we tried to access the def block as an incoming block for the user phi node. This patch handles that case by using the correct end block and creating a new phi node that aggregates both the values of the select in that end block, and then using that new unfolded phi to overwrite the original user phi node. Fixes #106083 Change-Id: Ie471994cca232318f74a6e6438efa21e561c2dc0
1 parent d075deb commit d4a38c8

File tree

2 files changed

+152
-17
lines changed

2 files changed

+152
-17
lines changed

llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,14 @@ void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
194194
SelectInst *SI = SIToUnfold.getInst();
195195
PHINode *SIUse = SIToUnfold.getUse();
196196
BasicBlock *StartBlock = SI->getParent();
197-
BasicBlock *EndBlock = SIUse->getParent();
198197
BranchInst *StartBlockTerm =
199198
dyn_cast<BranchInst>(StartBlock->getTerminator());
200199

201200
assert(StartBlockTerm);
202201
assert(SI->hasOneUse());
203202

204203
if (StartBlockTerm->isUnconditional()) {
204+
BasicBlock *EndBlock = StartBlock->getUniqueSuccessor();
205205
// Arbitrarily choose the 'false' side for a new input value to the PHI.
206206
BasicBlock *NewBlock = BasicBlock::Create(
207207
SI->getContext(), Twine(SI->getName(), ".si.unfold.false"),
@@ -223,32 +223,44 @@ void unfold(DomTreeUpdater *DTU, LoopInfo *LI, SelectInstToUnfold SIToUnfold,
223223
NewBlock->getFirstInsertionPt());
224224
NewPhi->addIncoming(SIOp2, StartBlock);
225225

226-
if (auto *OpSi = dyn_cast<SelectInst>(SIOp1))
227-
NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
228-
if (auto *OpSi = dyn_cast<SelectInst>(SIOp2))
229-
NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
230-
231-
// Update the phi node of SI.
232-
for (unsigned Idx = 0; Idx < SIUse->getNumIncomingValues(); ++Idx) {
233-
if (SIUse->getIncomingBlock(Idx) == StartBlock)
234-
SIUse->setIncomingValue(Idx, SIOp1);
226+
// Update any other PHI nodes in EndBlock.
227+
for (PHINode &Phi : EndBlock->phis()) {
228+
if (SIUse == &Phi)
229+
continue;
230+
Phi.addIncoming(Phi.getIncomingValueForBlock(StartBlock), NewBlock);
235231
}
236-
SIUse->addIncoming(NewPhi, NewBlock);
237232

238-
// Update any other PHI nodes in EndBlock.
239-
for (auto II = EndBlock->begin(); PHINode *Phi = dyn_cast<PHINode>(II);
240-
++II) {
241-
if (Phi != SIUse)
242-
Phi->addIncoming(Phi->getIncomingValueForBlock(StartBlock), NewBlock);
233+
// Update the phi node of SI, which is its only use.
234+
if (EndBlock == SIUse->getParent()) {
235+
SIUse->addIncoming(NewPhi, NewBlock);
236+
SIUse->replaceUsesOfWith(SI, SIOp1);
237+
} else {
238+
PHINode *EndPhi = PHINode::Create(SIUse->getType(), pred_size(EndBlock),
239+
Twine(SI->getName(), ".si.unfold.phi"),
240+
EndBlock->getFirstInsertionPt());
241+
for (BasicBlock *Pred : predecessors(EndBlock)) {
242+
if (Pred != StartBlock && Pred != NewBlock)
243+
EndPhi->addIncoming(EndPhi, Pred);
244+
}
245+
246+
EndPhi->addIncoming(SIOp1, StartBlock);
247+
EndPhi->addIncoming(NewPhi, NewBlock);
248+
SIUse->replaceUsesOfWith(SI, EndPhi);
249+
SIUse = EndPhi;
243250
}
244251

245-
StartBlockTerm->eraseFromParent();
252+
if (auto *OpSi = dyn_cast<SelectInst>(SIOp1))
253+
NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, SIUse));
254+
if (auto *OpSi = dyn_cast<SelectInst>(SIOp2))
255+
NewSIsToUnfold->push_back(SelectInstToUnfold(OpSi, NewPhi));
246256

247257
// Insert the real conditional branch based on the original condition.
258+
StartBlockTerm->eraseFromParent();
248259
BranchInst::Create(EndBlock, NewBlock, SI->getCondition(), StartBlock);
249260
DTU->applyUpdates({{DominatorTree::Insert, StartBlock, EndBlock},
250261
{DominatorTree::Insert, StartBlock, NewBlock}});
251262
} else {
263+
BasicBlock *EndBlock = SIUse->getParent();
252264
BasicBlock *NewBlockT = BasicBlock::Create(
253265
SI->getContext(), Twine(SI->getName(), ".si.unfold.true"),
254266
EndBlock->getParent(), EndBlock);

llvm/test/Transforms/DFAJumpThreading/dfa-jump-threading-transform.ll

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,126 @@ define void @self-reference() {
300300
end:
301301
ret void
302302
}
303+
304+
define void @pr106083_invalidBBarg_fold(i1 %cmp1, i1 %cmp2, i1 %not, ptr %d) {
305+
; CHECK-LABEL: @pr106083_invalidBBarg_fold(
306+
; CHECK-NEXT: bb:
307+
; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[BB1:%.*]], label [[SEL_SI_UNFOLD_FALSE:%.*]]
308+
; CHECK: sel.si.unfold.false:
309+
; CHECK-NEXT: [[DOTSI_UNFOLD_PHI1:%.*]] = phi i32 [ 1, [[BB:%.*]] ]
310+
; CHECK-NEXT: br label [[BB1]]
311+
; CHECK: BB1:
312+
; CHECK-NEXT: [[I:%.*]] = phi i16 [ 0, [[BB1_BACKEDGE:%.*]] ], [ 0, [[BB]] ], [ 1, [[BB7:%.*]] ], [ 0, [[SEL_SI_UNFOLD_FALSE]] ], [ 1, [[BB7_JT0:%.*]] ]
313+
; CHECK-NEXT: [[SEL_SI_UNFOLD_PHI:%.*]] = phi i32 [ [[SEL_SI_UNFOLD_PHI]], [[BB1_BACKEDGE]] ], [ [[SEL_SI_UNFOLD_PHI]], [[BB7]] ], [ 0, [[BB]] ], [ [[DOTSI_UNFOLD_PHI1]], [[SEL_SI_UNFOLD_FALSE]] ], [ [[SEL_SI_UNFOLD_PHI]], [[BB7_JT0]] ]
314+
; CHECK-NEXT: br i1 [[NOT:%.*]], label [[BB7_JT0]], label [[BB2:%.*]]
315+
; CHECK: BB2:
316+
; CHECK-NEXT: store i16 0, ptr [[D:%.*]], align 2
317+
; CHECK-NEXT: br i1 [[CMP2:%.*]], label [[BB7]], label [[SPEC_SELECT_SI_UNFOLD_FALSE_JT0:%.*]]
318+
; CHECK: spec.select.si.unfold.false:
319+
; CHECK-NEXT: br label [[BB7]]
320+
; CHECK: spec.select.si.unfold.false.jt0:
321+
; CHECK-NEXT: [[DOTSI_UNFOLD_PHI_JT0:%.*]] = phi i32 [ 0, [[BB2]] ]
322+
; CHECK-NEXT: br label [[BB7_JT0]]
323+
; CHECK: BB7:
324+
; CHECK-NEXT: [[D_PROMOTED4:%.*]] = phi i16 [ 1, [[BB2]] ], [ 1, [[SPEC_SELECT_SI_UNFOLD_FALSE:%.*]] ]
325+
; CHECK-NEXT: [[_3:%.*]] = phi i32 [ [[SEL_SI_UNFOLD_PHI]], [[BB2]] ], [ poison, [[SPEC_SELECT_SI_UNFOLD_FALSE]] ]
326+
; CHECK-NEXT: switch i32 [[_3]], label [[BB1_BACKEDGE]] [
327+
; CHECK-NEXT: i32 0, label [[BB1]]
328+
; CHECK-NEXT: i32 1, label [[BB8:%.*]]
329+
; CHECK-NEXT: ]
330+
; CHECK: BB7.jt0:
331+
; CHECK-NEXT: [[D_PROMOTED4_JT0:%.*]] = phi i16 [ 0, [[BB1]] ], [ 1, [[SPEC_SELECT_SI_UNFOLD_FALSE_JT0]] ]
332+
; CHECK-NEXT: [[_3_JT0:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[DOTSI_UNFOLD_PHI_JT0]], [[SPEC_SELECT_SI_UNFOLD_FALSE_JT0]] ]
333+
; CHECK-NEXT: br label [[BB1]]
334+
; CHECK: BB1.backedge:
335+
; CHECK-NEXT: br label [[BB1]]
336+
; CHECK: BB8:
337+
; CHECK-NEXT: ret void
338+
;
339+
bb:
340+
%sel = select i1 %cmp1, i32 0, i32 1
341+
br label %BB1
342+
343+
BB1: ; preds = %BB1.backedge, %BB7, %bb
344+
%i = phi i16 [ 0, %BB1.backedge ], [ 0, %bb ], [ 1, %BB7 ]
345+
br i1 %not, label %BB7, label %BB2
346+
347+
BB2: ; preds = %BB1
348+
store i16 0, ptr %d, align 2
349+
%spec.select = select i1 %cmp2, i32 %sel, i32 0
350+
br label %BB7
351+
352+
BB7: ; preds = %BB2, %BB1
353+
%d.promoted4 = phi i16 [ 0, %BB1 ], [ 1, %BB2 ]
354+
%_3 = phi i32 [ 0, %BB1 ], [ %spec.select, %BB2 ]
355+
switch i32 %_3, label %BB1.backedge [
356+
i32 0, label %BB1
357+
i32 1, label %BB8
358+
]
359+
360+
BB1.backedge: ; preds = %BB7
361+
br label %BB1
362+
363+
BB8: ; preds = %BB7
364+
ret void
365+
}
366+
367+
define void @pr106083_select_dead_uses(i1 %cmp1, i1 %not, ptr %p) {
368+
; CHECK-LABEL: @pr106083_select_dead_uses(
369+
; CHECK-NEXT: bb:
370+
; CHECK-NEXT: br i1 [[CMP1:%.*]], label [[DOTLOOPEXIT6:%.*]], label [[SPEC_SELECT_SI_UNFOLD_FALSE:%.*]]
371+
; CHECK: spec.select.si.unfold.false:
372+
; CHECK-NEXT: [[DOTSI_UNFOLD_PHI1:%.*]] = phi i32 [ 1, [[BB:%.*]] ]
373+
; CHECK-NEXT: br label [[DOTLOOPEXIT6]]
374+
; CHECK: .loopexit6:
375+
; CHECK-NEXT: [[SPEC_SELECT_SI_UNFOLD_PHI:%.*]] = phi i32 [ [[SPEC_SELECT_SI_UNFOLD_PHI]], [[SELECT_UNFOLD:%.*]] ], [ 0, [[BB]] ], [ [[DOTSI_UNFOLD_PHI1]], [[SPEC_SELECT_SI_UNFOLD_FALSE]] ]
376+
; CHECK-NEXT: br i1 [[NOT:%.*]], label [[SELECT_UNFOLD_JT0:%.*]], label [[BB1:%.*]]
377+
; CHECK: bb1:
378+
; CHECK-NEXT: [[I:%.*]] = load i32, ptr [[P:%.*]], align 4
379+
; CHECK-NEXT: [[NOT2:%.*]] = icmp eq i32 0, 0
380+
; CHECK-NEXT: br i1 [[NOT2]], label [[SELECT_UNFOLD]], label [[SPEC_SELECT7_SI_UNFOLD_FALSE_JT0:%.*]]
381+
; CHECK: spec.select7.si.unfold.false:
382+
; CHECK-NEXT: br label [[SELECT_UNFOLD]]
383+
; CHECK: spec.select7.si.unfold.false.jt0:
384+
; CHECK-NEXT: [[DOTSI_UNFOLD_PHI_JT0:%.*]] = phi i32 [ 0, [[BB1]] ]
385+
; CHECK-NEXT: br label [[SELECT_UNFOLD_JT0]]
386+
; CHECK: select.unfold:
387+
; CHECK-NEXT: [[_2:%.*]] = phi i32 [ [[SPEC_SELECT_SI_UNFOLD_PHI]], [[BB1]] ], [ poison, [[SPEC_SELECT7_SI_UNFOLD_FALSE:%.*]] ]
388+
; CHECK-NEXT: switch i32 [[_2]], label [[BB2:%.*]] [
389+
; CHECK-NEXT: i32 0, label [[DOTPREHEADER_PREHEADER:%.*]]
390+
; CHECK-NEXT: i32 1, label [[DOTLOOPEXIT6]]
391+
; CHECK-NEXT: ]
392+
; CHECK: select.unfold.jt0:
393+
; CHECK-NEXT: [[_2_JT0:%.*]] = phi i32 [ 0, [[DOTLOOPEXIT6]] ], [ [[DOTSI_UNFOLD_PHI_JT0]], [[SPEC_SELECT7_SI_UNFOLD_FALSE_JT0]] ]
394+
; CHECK-NEXT: br label [[DOTPREHEADER_PREHEADER]]
395+
; CHECK: .preheader.preheader:
396+
; CHECK-NEXT: ret void
397+
; CHECK: bb2:
398+
; CHECK-NEXT: unreachable
399+
;
400+
bb:
401+
%spec.select = select i1 %cmp1, i32 0, i32 1
402+
br label %.loopexit6
403+
404+
.loopexit6: ; preds = %select.unfold, %bb
405+
br i1 %not, label %select.unfold, label %bb1
406+
407+
bb1: ; preds = %.loopexit6
408+
%i = load i32, ptr %p, align 4
409+
%not2 = icmp eq i32 0, 0
410+
%spec.select7 = select i1 %not2, i32 %spec.select, i32 0
411+
br label %select.unfold
412+
413+
select.unfold: ; preds = %bb1, %.loopexit6
414+
%_2 = phi i32 [ 0, %.loopexit6 ], [ %spec.select7, %bb1 ]
415+
switch i32 %_2, label %bb2 [
416+
i32 0, label %.preheader.preheader
417+
i32 1, label %.loopexit6
418+
]
419+
420+
.preheader.preheader: ; preds = %select.unfold
421+
ret void
422+
423+
bb2: ; preds = %select.unfold
424+
unreachable
425+
}

0 commit comments

Comments
 (0)