@@ -223,12 +223,12 @@ raw_ostream &operator<<(raw_ostream &OS, const SinkingInstructionCandidate &C) {
223
223
class ModelledPHI {
224
224
SmallVector<Value *, 4 > Values;
225
225
SmallVector<BasicBlock *, 4 > Blocks;
226
- DominatorTree *DT;
227
226
228
227
public:
229
228
ModelledPHI () = default ;
230
229
231
- ModelledPHI (const PHINode *PN, DominatorTree *DT) : DT(DT) {
230
+ ModelledPHI (const PHINode *PN,
231
+ const DenseMap<const BasicBlock *, unsigned > &DFS) {
232
232
// BasicBlock comes first so we sort by basic block pointer order,
233
233
// then by value pointer order. No need to call `verifyModelledPHI`
234
234
// As the Values and Blocks are populated in DFSOrder already.
@@ -237,9 +237,8 @@ class ModelledPHI {
237
237
for (unsigned I = 0 , E = PN->getNumIncomingValues (); I != E; ++I)
238
238
Ops.push_back ({PN->getIncomingBlock (I), PN->getIncomingValue (I)});
239
239
240
- auto DFSOrder = [DT](OpsType O1, OpsType O2) {
241
- return DT->getNode (O1.first )->getDFSNumIn () <
242
- DT->getNode (O2.first )->getDFSNumIn ();
240
+ auto DFSOrder = [DFS](OpsType O1, OpsType O2) {
241
+ return DFS.lookup (O1.first ) < DFS.lookup (O2.first );
243
242
};
244
243
// Sort by DFSNumber to have a deterministic order.
245
244
llvm::sort (Ops, DFSOrder);
@@ -259,11 +258,11 @@ class ModelledPHI {
259
258
return M;
260
259
}
261
260
262
- void verifyModelledPHI () {
261
+ void verifyModelledPHI (const DenseMap< const BasicBlock *, unsigned > &DFS ) {
263
262
assert (Values.size () > 1 && Blocks.size () > 1 &&
264
263
" Modelling PHI with less than 2 values" );
265
- auto DFSOrder = [this ](const BasicBlock *BB1, const BasicBlock *BB2) {
266
- return DT-> getNode (BB1)-> getDFSNumIn () < DT-> getNode (BB2)-> getDFSNumIn ( );
264
+ auto DFSOrder = [DFS ](const BasicBlock *BB1, const BasicBlock *BB2) {
265
+ return DFS. lookup (BB1) < DFS. lookup (BB2);
267
266
};
268
267
assert (llvm::is_sorted (Blocks, DFSOrder));
269
268
int C = 0 ;
@@ -277,19 +276,18 @@ class ModelledPHI {
277
276
}
278
277
// / Create a PHI from an array of incoming values and incoming blocks.
279
278
ModelledPHI (SmallVectorImpl<Instruction *> &V,
280
- SmallSetVector<BasicBlock *, 4 > &B, DominatorTree *DT)
281
- : DT(DT ) {
279
+ SmallSetVector<BasicBlock *, 4 > &B,
280
+ const DenseMap< const BasicBlock *, unsigned > &DFS ) {
282
281
// The order of Values and Blocks are already as per their DFSNumbers.
283
282
llvm::copy (V, std::back_inserter (Values));
284
283
llvm::copy (B, std::back_inserter (Blocks));
285
- verifyModelledPHI ();
284
+ verifyModelledPHI (DFS );
286
285
}
287
286
288
287
// / Create a PHI from [I[OpNum] for I in Insts].
289
288
// / TODO: Figure out a way to verifyModelledPHI in this constructor.
290
289
ModelledPHI (ArrayRef<Instruction *> Insts, unsigned OpNum,
291
- SmallSetVector<BasicBlock *, 4 > &B, DominatorTree *DT)
292
- : DT(DT) {
290
+ SmallSetVector<BasicBlock *, 4 > &B) {
293
291
llvm::copy (B, std::back_inserter (Blocks));
294
292
for (auto *I : Insts)
295
293
Values.push_back (I->getOperand (OpNum));
@@ -609,6 +607,13 @@ class GVNSink {
609
607
unsigned NumSunk = 0 ;
610
608
ReversePostOrderTraversal<Function*> RPOT (&F);
611
609
VN.setReachableBBs (BasicBlocksSet (RPOT.begin (), RPOT.end ()));
610
+ // Populated DFSNumbers ahead of time to avoid updating dominator tree
611
+ // when CFG is modified. The DFSNumbers of newly created basic blocks
612
+ // are irrelevant because RPOT is also obtained ahead of time and only
613
+ // DFSNumbers of original CFG are relevant for sinkable candidates.
614
+ for (auto *BB : RPOT)
615
+ if (DT->getNode (BB))
616
+ DFSNumbers[BB] = DT->getNode (BB)->getDFSNumIn ();
612
617
for (auto *N : RPOT)
613
618
NumSunk += sinkBB (N);
614
619
@@ -618,6 +623,7 @@ class GVNSink {
618
623
private:
619
624
ValueTable VN;
620
625
DominatorTree *DT;
626
+ DenseMap<const BasicBlock *, unsigned > DFSNumbers;
621
627
622
628
bool shouldAvoidSinkingInstruction (Instruction *I) {
623
629
// These instructions may change or break semantics if moved.
@@ -638,7 +644,7 @@ class GVNSink {
638
644
void analyzeInitialPHIs (BasicBlock *BB, ModelledPHISet &PHIs,
639
645
SmallPtrSetImpl<Value *> &PHIContents) {
640
646
for (PHINode &PN : BB->phis ()) {
641
- auto MPHI = ModelledPHI (&PN, DT );
647
+ auto MPHI = ModelledPHI (&PN, DFSNumbers );
642
648
PHIs.insert (MPHI);
643
649
for (auto *V : MPHI.getValues ())
644
650
PHIContents.insert (V);
@@ -726,7 +732,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
726
732
}
727
733
728
734
// The sunk instruction's results.
729
- ModelledPHI NewPHI (NewInsts, ActivePreds, DT );
735
+ ModelledPHI NewPHI (NewInsts, ActivePreds, DFSNumbers );
730
736
731
737
// Does sinking this instruction render previous PHIs redundant?
732
738
if (NeededPHIs.erase (NewPHI))
@@ -763,7 +769,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
763
769
return std::nullopt;
764
770
765
771
for (unsigned OpNum = 0 , E = I0->getNumOperands (); OpNum != E; ++OpNum) {
766
- ModelledPHI PHI (NewInsts, OpNum, ActivePreds, DT );
772
+ ModelledPHI PHI (NewInsts, OpNum, ActivePreds);
767
773
if (PHI.areAllIncomingValuesSame ())
768
774
continue ;
769
775
if (!canReplaceOperandWithVariable (I0, OpNum))
@@ -802,7 +808,7 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
802
808
SmallVector<BasicBlock *, 4 > Preds;
803
809
for (auto *B : predecessors (BBEnd)) {
804
810
// Bailout on malformed CFG where BasicBlock has no predecessor(PR42346).
805
- if (!DT-> getNode (B))
811
+ if (!DFSNumbers. count (B))
806
812
return 0 ;
807
813
auto *T = B->getTerminator ();
808
814
if (isa<BranchInst>(T) || isa<SwitchInst>(T))
@@ -813,7 +819,7 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
813
819
if (Preds.size () < 2 )
814
820
return 0 ;
815
821
auto DFSOrder = [this ](const BasicBlock *BB1, const BasicBlock *BB2) {
816
- return DT-> getNode (BB1)-> getDFSNumIn () < DT-> getNode (BB2)-> getDFSNumIn ( );
822
+ return DFSNumbers. lookup (BB1) < DFSNumbers. lookup (BB2);
817
823
};
818
824
// Sort by DFSNumber to have a deterministic order.
819
825
llvm::sort (Preds, DFSOrder);
0 commit comments