@@ -437,6 +437,10 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
437
437
SmallVector<StringRef, 16 > DebugVars;
438
438
const SILInstruction *CurInstruction = nullptr ;
439
439
DominanceInfo *Dominance = nullptr ;
440
+
441
+ // Used for dominance checking within a basic block.
442
+ llvm::DenseMap<const SILInstruction *, unsigned > InstNumbers;
443
+
440
444
DeadEndBlocks DEBlocks;
441
445
bool SingleFunction = true ;
442
446
@@ -615,20 +619,32 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
615
619
}
616
620
}
617
621
622
+ static unsigned numInstsInFunction (const SILFunction &F) {
623
+ unsigned numInsts = 0 ;
624
+ for (auto &BB : F) {
625
+ numInsts += std::distance (BB.begin (), BB.end ());
626
+ }
627
+ return numInsts;
628
+ }
629
+
618
630
SILVerifier (const SILFunction &F, bool SingleFunction = true )
619
631
: M(F.getModule().getSwiftModule()), F(F),
620
632
fnConv (F.getLoweredFunctionType(), F.getModule()),
621
633
TC(F.getModule().Types), OpenedArchetypes(&F), Dominance(nullptr ),
634
+ InstNumbers(numInstsInFunction(F)),
622
635
DEBlocks(&F), SingleFunction(SingleFunction) {
623
636
if (F.isExternalDeclaration ())
624
637
return ;
625
638
626
639
// Check to make sure that all blocks are well formed. If not, the
627
640
// SILVerifier object will explode trying to compute dominance info.
641
+ unsigned InstIdx = 0 ;
628
642
for (auto &BB : F) {
629
643
require (!BB.empty (), " Basic blocks cannot be empty" );
630
644
require (isa<TermInst>(BB.back ()),
631
645
" Basic blocks must end with a terminator instruction" );
646
+ for (auto &I : BB)
647
+ InstNumbers[&I] = InstIdx++;
632
648
}
633
649
634
650
Dominance = new DominanceInfo (const_cast <SILFunction *>(&F));
@@ -644,6 +660,20 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
644
660
delete Dominance;
645
661
}
646
662
663
+ // Checks dominance between two instructions.
664
+ // This does not use DominanceInfo.properlyDominates, because for large basic
665
+ // blocks it would result in quadratic behavior.
666
+ bool properlyDominates (SILInstruction *a, SILInstruction *b) {
667
+ auto aBlock = a->getParent (), bBlock = b->getParent ();
668
+
669
+ // If the blocks are different, it's as easy as whether A's block
670
+ // dominates B's block.
671
+ if (aBlock != bBlock)
672
+ return Dominance->properlyDominates (aBlock, bBlock);
673
+
674
+ return InstNumbers[a] < InstNumbers[b];
675
+ }
676
+
647
677
// FIXME: For sanity, address-type block args should be prohibited at all SIL
648
678
// stages. However, the optimizer currently breaks the invariant in three
649
679
// places:
@@ -775,7 +805,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
775
805
} else {
776
806
require (valueI->getFunction () == &F,
777
807
" instruction uses value of instruction from another function" );
778
- require (Dominance-> properlyDominates (valueI, I),
808
+ require (properlyDominates (valueI, I),
779
809
" instruction isn't dominated by its operand" );
780
810
}
781
811
}
@@ -939,7 +969,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
939
969
auto Def = OpenedArchetypes.getOpenedArchetypeDef (OpenedA);
940
970
require (Def, " Opened archetype should be registered in SILFunction" );
941
971
require (I == nullptr || Def == I ||
942
- Dominance-> properlyDominates (cast<SILInstruction>(Def), I),
972
+ properlyDominates (cast<SILInstruction>(Def), I),
943
973
" Use of an opened archetype should be dominated by a "
944
974
" definition of this opened archetype" );
945
975
}
@@ -1071,7 +1101,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
1071
1101
auto Def = OpenedArchetypes.getOpenedArchetypeDef (A);
1072
1102
require (Def, " Opened archetype should be registered in SILFunction" );
1073
1103
require (Def == AI ||
1074
- Dominance-> properlyDominates (cast<SILInstruction>(Def), AI),
1104
+ properlyDominates (cast<SILInstruction>(Def), AI),
1075
1105
" Use of an opened archetype should be dominated by a "
1076
1106
" definition of this opened archetype" );
1077
1107
}
0 commit comments