@@ -222,20 +222,29 @@ raw_ostream &operator<<(raw_ostream &OS, const SinkingInstructionCandidate &C) {
222
222
class ModelledPHI {
223
223
SmallVector<Value *, 4 > Values;
224
224
SmallVector<BasicBlock *, 4 > Blocks;
225
+ DominatorTree *DT;
225
226
226
227
public:
227
228
ModelledPHI () = default ;
228
229
229
- ModelledPHI (const PHINode *PN) {
230
+ ModelledPHI (const PHINode *PN, DominatorTree *DT) : DT(DT ) {
230
231
// BasicBlock comes first so we sort by basic block pointer order, then by value pointer order.
231
- SmallVector<std::pair<BasicBlock *, Value *>, 4 > Ops;
232
+ using OpsType = std::pair<BasicBlock *, Value *>;
233
+ SmallVector<OpsType, 4 > Ops;
232
234
for (unsigned I = 0 , E = PN->getNumIncomingValues (); I != E; ++I)
233
235
Ops.push_back ({PN->getIncomingBlock (I), PN->getIncomingValue (I)});
234
- llvm::sort (Ops);
236
+
237
+ auto DFSOrder = [DT](OpsType O1, OpsType O2) {
238
+ return DT->getNode (O1.first ) < DT->getNode (O2.first );
239
+ };
240
+ // Sort by DFSNumber to have a deterministic order.
241
+ llvm::sort (Ops, DFSOrder);
242
+
235
243
for (auto &P : Ops) {
236
244
Blocks.push_back (P.first );
237
245
Values.push_back (P.second );
238
246
}
247
+ verifyModelledPHI ();
239
248
}
240
249
241
250
// / Create a dummy ModelledPHI that will compare unequal to any other ModelledPHI
@@ -247,19 +256,37 @@ class ModelledPHI {
247
256
return M;
248
257
}
249
258
259
+ void verifyModelledPHI () {
260
+ assert (Values.size () > 1 && Blocks.size () > 1 &&
261
+ " Modelling PHI with less than 2 values" );
262
+ auto DFSOrder = [this ](const BasicBlock *BB1, const BasicBlock *BB2) {
263
+ return this ->DT ->getNode (BB1) < this ->DT ->getNode (BB2);
264
+ };
265
+ assert (llvm::is_sorted (Blocks, DFSOrder));
266
+ int C = 0 ;
267
+ llvm::for_each (Values, [&C, this ](const Value* V) {
268
+ const Instruction *I = cast<Instruction>(V);
269
+ assert (I->getParent () == this ->Blocks [C++]);
270
+ });
271
+ }
250
272
// / Create a PHI from an array of incoming values and incoming blocks.
251
- template <typename VArray, typename BArray>
252
- ModelledPHI (const VArray &V, const BArray &B) {
273
+ ModelledPHI (SmallVectorImpl<Instruction *> &V,
274
+ SmallSetVector<BasicBlock *, 4 > &B, DominatorTree *DT)
275
+ : DT(DT) {
276
+ // The order of Values and Blocks are already as per their DFSNumbers.
253
277
llvm::copy (V, std::back_inserter (Values));
254
278
llvm::copy (B, std::back_inserter (Blocks));
279
+ verifyModelledPHI ();
255
280
}
256
281
257
282
// / Create a PHI from [I[OpNum] for I in Insts].
258
- template <typename BArray>
259
- ModelledPHI (ArrayRef<Instruction *> Insts, unsigned OpNum, const BArray &B) {
283
+ ModelledPHI (ArrayRef<Instruction *> Insts, unsigned OpNum,
284
+ SmallSetVector<BasicBlock *, 4 > &B, DominatorTree *DT)
285
+ : DT(DT) {
260
286
llvm::copy (B, std::back_inserter (Blocks));
261
287
for (auto *I : Insts)
262
288
Values.push_back (I->getOperand (OpNum));
289
+ verifyModelledPHI ();
263
290
}
264
291
265
292
// / Restrict the PHI's contents down to only \c NewBlocks.
@@ -297,7 +324,8 @@ class ModelledPHI {
297
324
298
325
// Hash functor
299
326
unsigned hash () const {
300
- return (unsigned )hash_combine_range (Values.begin (), Values.end ());
327
+ // Is deterministic because Values are saved in DFSOrder.
328
+ return (unsigned )hash_combine_range (Values.begin (), Values.end ());
301
329
}
302
330
303
331
bool operator ==(const ModelledPHI &Other) const {
@@ -566,7 +594,7 @@ class ValueTable {
566
594
567
595
class GVNSink {
568
596
public:
569
- GVNSink () = default ;
597
+ GVNSink (DominatorTree *DT) : DT(DT) {}
570
598
571
599
bool run (Function &F) {
572
600
LLVM_DEBUG (dbgs () << " GVNSink: running on function @" << F.getName ()
@@ -583,6 +611,7 @@ class GVNSink {
583
611
584
612
private:
585
613
ValueTable VN;
614
+ DominatorTree *DT;
586
615
587
616
bool shouldAvoidSinkingInstruction (Instruction *I) {
588
617
// These instructions may change or break semantics if moved.
@@ -603,7 +632,7 @@ class GVNSink {
603
632
void analyzeInitialPHIs (BasicBlock *BB, ModelledPHISet &PHIs,
604
633
SmallPtrSetImpl<Value *> &PHIContents) {
605
634
for (PHINode &PN : BB->phis ()) {
606
- auto MPHI = ModelledPHI (&PN);
635
+ auto MPHI = ModelledPHI (&PN, DT );
607
636
PHIs.insert (MPHI);
608
637
for (auto *V : MPHI.getValues ())
609
638
PHIContents.insert (V);
@@ -691,7 +720,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
691
720
}
692
721
693
722
// The sunk instruction's results.
694
- ModelledPHI NewPHI (NewInsts, ActivePreds);
723
+ ModelledPHI NewPHI (NewInsts, ActivePreds, DT );
695
724
696
725
// Does sinking this instruction render previous PHIs redundant?
697
726
if (NeededPHIs.erase (NewPHI))
@@ -728,7 +757,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
728
757
return std::nullopt;
729
758
730
759
for (unsigned OpNum = 0 , E = I0->getNumOperands (); OpNum != E; ++OpNum) {
731
- ModelledPHI PHI (NewInsts, OpNum, ActivePreds);
760
+ ModelledPHI PHI (NewInsts, OpNum, ActivePreds, DT );
732
761
if (PHI.areAllIncomingValuesSame ())
733
762
continue ;
734
763
if (!canReplaceOperandWithVariable (I0, OpNum))
@@ -774,7 +803,11 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
774
803
}
775
804
if (Preds.size () < 2 )
776
805
return 0 ;
777
- llvm::sort (Preds);
806
+ auto DFSOrder = [this ](const BasicBlock *BB1, const BasicBlock *BB2) {
807
+ return this ->DT ->getNode (BB1) < this ->DT ->getNode (BB2);
808
+ };
809
+ // Sort by DFSNumber to have a deterministic order.
810
+ llvm::sort (Preds, DFSOrder);
778
811
779
812
unsigned NumOrigPreds = Preds.size ();
780
813
// We can only sink instructions through unconditional branches.
@@ -886,8 +919,12 @@ void GVNSink::sinkLastInstruction(ArrayRef<BasicBlock *> Blocks,
886
919
} // end anonymous namespace
887
920
888
921
PreservedAnalyses GVNSinkPass::run (Function &F, FunctionAnalysisManager &AM) {
889
- GVNSink G;
922
+ auto &DT = AM.getResult <DominatorTreeAnalysis>(F);
923
+ GVNSink G (&DT);
890
924
if (!G.run (F))
891
925
return PreservedAnalyses::all ();
926
+
927
+ // PHI nodes get inserted which haven't been added to the Dominator Tree.
928
+ // FIXME: Update DominatorTree to account for sunk instructions.
892
929
return PreservedAnalyses::none ();
893
930
}
0 commit comments