@@ -226,12 +226,22 @@ class ModelledPHI {
226
226
public:
227
227
ModelledPHI () = default ;
228
228
229
- ModelledPHI (const PHINode *PN) {
230
- // BasicBlock comes first so we sort by basic block pointer order, then by value pointer order.
231
- SmallVector<std::pair<BasicBlock *, Value *>, 4 > Ops;
229
+ ModelledPHI (const PHINode *PN,
230
+ const DenseMap<const BasicBlock *, unsigned > &BlockOrder) {
231
+ // BasicBlock comes first so we sort by basic block pointer order,
232
+ // then by value pointer order. No need to call `verifyModelledPHI`
233
+ // As the Values and Blocks are populated in a deterministic order.
234
+ using OpsType = std::pair<BasicBlock *, Value *>;
235
+ SmallVector<OpsType, 4 > Ops;
232
236
for (unsigned I = 0 , E = PN->getNumIncomingValues (); I != E; ++I)
233
237
Ops.push_back ({PN->getIncomingBlock (I), PN->getIncomingValue (I)});
234
- llvm::sort (Ops);
238
+
239
+ auto ComesBefore = [BlockOrder](OpsType O1, OpsType O2) {
240
+ return BlockOrder.lookup (O1.first ) < BlockOrder.lookup (O2.first );
241
+ };
242
+ // Sort in a deterministic order.
243
+ llvm::sort (Ops, ComesBefore);
244
+
235
245
for (auto &P : Ops) {
236
246
Blocks.push_back (P.first );
237
247
Values.push_back (P.second );
@@ -247,16 +257,38 @@ class ModelledPHI {
247
257
return M;
248
258
}
249
259
260
+ void
261
+ verifyModelledPHI (const DenseMap<const BasicBlock *, unsigned > &BlockOrder) {
262
+ assert (Values.size () > 1 && Blocks.size () > 1 &&
263
+ " Modelling PHI with less than 2 values" );
264
+ auto ComesBefore = [BlockOrder](const BasicBlock *BB1,
265
+ const BasicBlock *BB2) {
266
+ return BlockOrder.lookup (BB1) < BlockOrder.lookup (BB2);
267
+ };
268
+ assert (llvm::is_sorted (Blocks, ComesBefore));
269
+ int C = 0 ;
270
+ llvm::for_each (Values, [&C, this ](const Value *V) {
271
+ if (!isa<UndefValue>(V)) {
272
+ const Instruction *I = cast<Instruction>(V);
273
+ assert (I->getParent () == this ->Blocks [C]);
274
+ }
275
+ C++;
276
+ });
277
+ }
250
278
// / 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) {
279
+ ModelledPHI (SmallVectorImpl<Instruction *> &V,
280
+ SmallSetVector<BasicBlock *, 4 > &B,
281
+ const DenseMap<const BasicBlock *, unsigned > &BlockOrder) {
282
+ // The order of Values and Blocks are already ordered by the caller.
253
283
llvm::copy (V, std::back_inserter (Values));
254
284
llvm::copy (B, std::back_inserter (Blocks));
285
+ verifyModelledPHI (BlockOrder);
255
286
}
256
287
257
288
// / Create a PHI from [I[OpNum] for I in Insts].
258
- template <typename BArray>
259
- ModelledPHI (ArrayRef<Instruction *> Insts, unsigned OpNum, const BArray &B) {
289
+ // / TODO: Figure out a way to verifyModelledPHI in this constructor.
290
+ ModelledPHI (ArrayRef<Instruction *> Insts, unsigned OpNum,
291
+ SmallSetVector<BasicBlock *, 4 > &B) {
260
292
llvm::copy (B, std::back_inserter (Blocks));
261
293
for (auto *I : Insts)
262
294
Values.push_back (I->getOperand (OpNum));
@@ -297,7 +329,8 @@ class ModelledPHI {
297
329
298
330
// Hash functor
299
331
unsigned hash () const {
300
- return (unsigned )hash_combine_range (Values.begin (), Values.end ());
332
+ // Is deterministic because Values are saved in a specific order.
333
+ return (unsigned )hash_combine_range (Values.begin (), Values.end ());
301
334
}
302
335
303
336
bool operator ==(const ModelledPHI &Other) const {
@@ -566,7 +599,7 @@ class ValueTable {
566
599
567
600
class GVNSink {
568
601
public:
569
- GVNSink () = default ;
602
+ GVNSink () {}
570
603
571
604
bool run (Function &F) {
572
605
LLVM_DEBUG (dbgs () << " GVNSink: running on function @" << F.getName ()
@@ -575,6 +608,16 @@ class GVNSink {
575
608
unsigned NumSunk = 0 ;
576
609
ReversePostOrderTraversal<Function*> RPOT (&F);
577
610
VN.setReachableBBs (BasicBlocksSet (RPOT.begin (), RPOT.end ()));
611
+ // Populate reverse post-order to order basic blocks in deterministic
612
+ // order. Any arbitrary ordering will work in this case as long as they are
613
+ // deterministic. The node ordering of newly created basic blocks
614
+ // are irrelevant because RPOT(for computing sinkable candidates) is also
615
+ // obtained ahead of time and only their order are relevant for this pass.
616
+ unsigned NodeOrdering = 0 ;
617
+ RPOTOrder[*RPOT.begin ()] = ++NodeOrdering;
618
+ for (auto *BB : RPOT)
619
+ if (!pred_empty (BB))
620
+ RPOTOrder[BB] = ++NodeOrdering;
578
621
for (auto *N : RPOT)
579
622
NumSunk += sinkBB (N);
580
623
@@ -583,6 +626,7 @@ class GVNSink {
583
626
584
627
private:
585
628
ValueTable VN;
629
+ DenseMap<const BasicBlock *, unsigned > RPOTOrder;
586
630
587
631
bool shouldAvoidSinkingInstruction (Instruction *I) {
588
632
// These instructions may change or break semantics if moved.
@@ -603,7 +647,7 @@ class GVNSink {
603
647
void analyzeInitialPHIs (BasicBlock *BB, ModelledPHISet &PHIs,
604
648
SmallPtrSetImpl<Value *> &PHIContents) {
605
649
for (PHINode &PN : BB->phis ()) {
606
- auto MPHI = ModelledPHI (&PN);
650
+ auto MPHI = ModelledPHI (&PN, RPOTOrder );
607
651
PHIs.insert (MPHI);
608
652
for (auto *V : MPHI.getValues ())
609
653
PHIContents.insert (V);
@@ -691,7 +735,7 @@ GVNSink::analyzeInstructionForSinking(LockstepReverseIterator &LRI,
691
735
}
692
736
693
737
// The sunk instruction's results.
694
- ModelledPHI NewPHI (NewInsts, ActivePreds);
738
+ ModelledPHI NewPHI (NewInsts, ActivePreds, RPOTOrder );
695
739
696
740
// Does sinking this instruction render previous PHIs redundant?
697
741
if (NeededPHIs.erase (NewPHI))
@@ -766,6 +810,9 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
766
810
BBEnd->printAsOperand (dbgs ()); dbgs () << " \n " );
767
811
SmallVector<BasicBlock *, 4 > Preds;
768
812
for (auto *B : predecessors (BBEnd)) {
813
+ // Bailout on basic blocks without predecessor(PR42346).
814
+ if (!RPOTOrder.count (B))
815
+ return 0 ;
769
816
auto *T = B->getTerminator ();
770
817
if (isa<BranchInst>(T) || isa<SwitchInst>(T))
771
818
Preds.push_back (B);
@@ -774,7 +821,11 @@ unsigned GVNSink::sinkBB(BasicBlock *BBEnd) {
774
821
}
775
822
if (Preds.size () < 2 )
776
823
return 0 ;
777
- llvm::sort (Preds);
824
+ auto ComesBefore = [this ](const BasicBlock *BB1, const BasicBlock *BB2) {
825
+ return RPOTOrder.lookup (BB1) < RPOTOrder.lookup (BB2);
826
+ };
827
+ // Sort in a deterministic order.
828
+ llvm::sort (Preds, ComesBefore);
778
829
779
830
unsigned NumOrigPreds = Preds.size ();
780
831
// We can only sink instructions through unconditional branches.
@@ -889,5 +940,6 @@ PreservedAnalyses GVNSinkPass::run(Function &F, FunctionAnalysisManager &AM) {
889
940
GVNSink G;
890
941
if (!G.run (F))
891
942
return PreservedAnalyses::all ();
943
+
892
944
return PreservedAnalyses::none ();
893
945
}
0 commit comments