@@ -146,6 +146,57 @@ static bool mayWriteTo(AliasAnalysis *AA, SideEffectAnalysis *SEA,
146
146
return false ;
147
147
}
148
148
149
+ // / Returns true if \p sideEffectInst cannot be reordered with a call to a
150
+ // / global initialier.
151
+ static bool mayConflictWithGlobalInit (AliasAnalysis *AA,
152
+ SILInstruction *sideEffectInst, ApplyInst *globalInitCall) {
153
+ if (auto *SI = dyn_cast<StoreInst>(sideEffectInst)) {
154
+ return AA->mayReadOrWriteMemory (globalInitCall, SI->getDest ());
155
+ }
156
+ if (auto *LI = dyn_cast<LoadInst>(sideEffectInst)) {
157
+ return AA->mayWriteToMemory (globalInitCall, LI->getOperand ());
158
+ }
159
+ return true ;
160
+ }
161
+
162
+ // / Returns true if any of the instructions in \p sideEffectInsts which are
163
+ // / post-dominated by a call to a global initialier cannot be reordered with
164
+ // / the call.
165
+ static bool mayConflictWithGlobalInit (AliasAnalysis *AA,
166
+ InstSet &sideEffectInsts,
167
+ ApplyInst *globalInitCall,
168
+ SILBasicBlock *preHeader, PostDominanceInfo *PD) {
169
+ if (!PD->dominates (globalInitCall->getParent (), preHeader))
170
+ return true ;
171
+
172
+ SILBasicBlock *globalInitBlock = globalInitCall->getParent ();
173
+ for (auto *seInst : sideEffectInsts) {
174
+ // Only check instructions in blocks which are "before" (i.e. post-dominated
175
+ // by) the block which contains the init-call.
176
+ // Instructions which are before the call in the same block have already
177
+ // been checked.
178
+ if (PD->properlyDominates (globalInitBlock, seInst->getParent ())) {
179
+ if (mayConflictWithGlobalInit (AA, seInst, globalInitCall))
180
+ return true ;
181
+ }
182
+ }
183
+ return false ;
184
+ }
185
+
186
+ // / Returns true if any of the instructions in \p sideEffectInsts cannot be
187
+ // / reordered with a call to a global initialier (which is in the same basic
188
+ // / block).
189
+ static bool mayConflictWithGlobalInit (AliasAnalysis *AA,
190
+ ArrayRef<SILInstruction *> sideEffectInsts,
191
+ ApplyInst *globalInitCall) {
192
+ for (auto *seInst : sideEffectInsts) {
193
+ assert (seInst->getParent () == globalInitCall->getParent ());
194
+ if (mayConflictWithGlobalInit (AA, seInst, globalInitCall))
195
+ return true ;
196
+ }
197
+ return false ;
198
+ }
199
+
149
200
// When Hoisting / Sinking,
150
201
// Don't descend into control-dependent code.
151
202
// Only traverse into basic blocks that dominate all exits.
@@ -409,6 +460,8 @@ class LoopTreeOptimization {
409
460
AliasAnalysis *AA;
410
461
SideEffectAnalysis *SEA;
411
462
DominanceInfo *DomTree;
463
+ PostDominanceAnalysis *PDA;
464
+ PostDominanceInfo *postDomTree = nullptr ;
412
465
AccessedStorageAnalysis *ASA;
413
466
bool Changed;
414
467
@@ -435,10 +488,11 @@ class LoopTreeOptimization {
435
488
public:
436
489
LoopTreeOptimization (SILLoop *TopLevelLoop, SILLoopInfo *LI,
437
490
AliasAnalysis *AA, SideEffectAnalysis *SEA,
438
- DominanceInfo *DT, AccessedStorageAnalysis *ASA,
491
+ DominanceInfo *DT, PostDominanceAnalysis *PDA,
492
+ AccessedStorageAnalysis *ASA,
439
493
bool RunsOnHighLevelSil)
440
- : LoopInfo(LI), AA(AA), SEA(SEA), DomTree(DT), ASA(ASA ), Changed( false ),
441
- RunsOnHighLevelSIL (RunsOnHighLevelSil) {
494
+ : LoopInfo(LI), AA(AA), SEA(SEA), DomTree(DT), PDA(PDA ), ASA(ASA ),
495
+ Changed ( false ), RunsOnHighLevelSIL(RunsOnHighLevelSil) {
442
496
// Collect loops for a recursive bottom-up traversal in the loop tree.
443
497
BotUpWorkList.push_back (TopLevelLoop);
444
498
for (unsigned i = 0 ; i < BotUpWorkList.size (); ++i) {
@@ -556,9 +610,11 @@ static bool isSafeReadOnlyApply(SideEffectAnalysis *SEA, ApplyInst *AI) {
556
610
}
557
611
558
612
static void checkSideEffects (swift::SILInstruction &Inst,
559
- InstSet &SideEffectInsts) {
613
+ InstSet &SideEffectInsts,
614
+ SmallVectorImpl<SILInstruction *> &sideEffectsInBlock) {
560
615
if (Inst.mayHaveSideEffects ()) {
561
616
SideEffectInsts.insert (&Inst);
617
+ sideEffectsInBlock.push_back (&Inst);
562
618
}
563
619
}
564
620
@@ -708,13 +764,15 @@ void LoopTreeOptimization::analyzeCurrentLoop(
708
764
709
765
// Interesting instructions in the loop:
710
766
SmallVector<ApplyInst *, 8 > ReadOnlyApplies;
767
+ SmallVector<ApplyInst *, 8 > globalInitCalls;
711
768
SmallVector<LoadInst *, 8 > Loads;
712
769
SmallVector<StoreInst *, 8 > Stores;
713
770
SmallVector<FixLifetimeInst *, 8 > FixLifetimes;
714
771
SmallVector<BeginAccessInst *, 8 > BeginAccesses;
715
772
SmallVector<FullApplySite, 8 > fullApplies;
716
773
717
774
for (auto *BB : Loop->getBlocks ()) {
775
+ SmallVector<SILInstruction *, 8 > sideEffectsInBlock;
718
776
for (auto &Inst : *BB) {
719
777
switch (Inst.getKind ()) {
720
778
case SILInstructionKind::FixLifetimeInst: {
@@ -731,12 +789,12 @@ void LoopTreeOptimization::analyzeCurrentLoop(
731
789
case SILInstructionKind::StoreInst: {
732
790
Stores.push_back (cast<StoreInst>(&Inst));
733
791
LoadsAndStores.push_back (&Inst);
734
- checkSideEffects (Inst, sideEffects);
792
+ checkSideEffects (Inst, sideEffects, sideEffectsInBlock );
735
793
break ;
736
794
}
737
795
case SILInstructionKind::BeginAccessInst:
738
796
BeginAccesses.push_back (cast<BeginAccessInst>(&Inst));
739
- checkSideEffects (Inst, sideEffects);
797
+ checkSideEffects (Inst, sideEffects, sideEffectsInBlock );
740
798
break ;
741
799
case SILInstructionKind::RefElementAddrInst:
742
800
SpecialHoist.push_back (cast<RefElementAddrInst>(&Inst));
@@ -747,12 +805,21 @@ void LoopTreeOptimization::analyzeCurrentLoop(
747
805
// cond_fail that would have protected (executed before) a memory access
748
806
// must - after hoisting - also be executed before said access.
749
807
HoistUp.insert (&Inst);
750
- checkSideEffects (Inst, sideEffects);
808
+ checkSideEffects (Inst, sideEffects, sideEffectsInBlock );
751
809
break ;
752
810
case SILInstructionKind::ApplyInst: {
753
811
auto *AI = cast<ApplyInst>(&Inst);
754
812
if (isSafeReadOnlyApply (SEA, AI)) {
755
813
ReadOnlyApplies.push_back (AI);
814
+ } else if (SILFunction *callee = AI->getReferencedFunctionOrNull ()) {
815
+ // Calls to global inits are different because we don't care about
816
+ // side effects which are "after" the call in the loop.
817
+ if (callee->isGlobalInit () &&
818
+ // Check against side-effects within the same block.
819
+ // Side-effects in other blocks are checked later (after we
820
+ // scanned all blocks of the loop).
821
+ !mayConflictWithGlobalInit (AA, sideEffectsInBlock, AI))
822
+ globalInitCalls.push_back (AI);
756
823
}
757
824
// check for array semantics and side effects - same as default
758
825
LLVM_FALLTHROUGH;
@@ -761,7 +828,7 @@ void LoopTreeOptimization::analyzeCurrentLoop(
761
828
if (auto fullApply = FullApplySite::isa (&Inst)) {
762
829
fullApplies.push_back (fullApply);
763
830
}
764
- checkSideEffects (Inst, sideEffects);
831
+ checkSideEffects (Inst, sideEffects, sideEffectsInBlock );
765
832
if (canHoistUpDefault (&Inst, Loop, DomTree, RunsOnHighLevelSIL)) {
766
833
HoistUp.insert (&Inst);
767
834
}
@@ -780,6 +847,23 @@ void LoopTreeOptimization::analyzeCurrentLoop(
780
847
HoistUp.insert (LI);
781
848
}
782
849
}
850
+
851
+ if (!globalInitCalls.empty ()) {
852
+ if (!postDomTree) {
853
+ postDomTree = PDA->get (Preheader->getParent ());
854
+ }
855
+ if (postDomTree->getRootNode ()) {
856
+ for (ApplyInst *ginitCall : globalInitCalls) {
857
+ // Check against side effects which are "before" (i.e. post-dominated
858
+ // by) the global initializer call.
859
+ if (!mayConflictWithGlobalInit (AA, sideEffects, ginitCall, Preheader,
860
+ postDomTree)) {
861
+ HoistUp.insert (ginitCall);
862
+ }
863
+ }
864
+ }
865
+ }
866
+
783
867
// Collect memory locations for which we can move all loads and stores out
784
868
// of the loop.
785
869
for (StoreInst *SI : Stores) {
@@ -1041,6 +1125,7 @@ class LICM : public SILFunctionTransform {
1041
1125
}
1042
1126
1043
1127
DominanceAnalysis *DA = PM->getAnalysis <DominanceAnalysis>();
1128
+ PostDominanceAnalysis *PDA = PM->getAnalysis <PostDominanceAnalysis>();
1044
1129
AliasAnalysis *AA = PM->getAnalysis <AliasAnalysis>();
1045
1130
SideEffectAnalysis *SEA = PM->getAnalysis <SideEffectAnalysis>();
1046
1131
AccessedStorageAnalysis *ASA = getAnalysis<AccessedStorageAnalysis>();
@@ -1051,8 +1136,8 @@ class LICM : public SILFunctionTransform {
1051
1136
1052
1137
for (auto *TopLevelLoop : *LoopInfo) {
1053
1138
if (!DomTree) DomTree = DA->get (F);
1054
- LoopTreeOptimization Opt (TopLevelLoop, LoopInfo, AA, SEA, DomTree, ASA ,
1055
- RunsOnHighLevelSil);
1139
+ LoopTreeOptimization Opt (TopLevelLoop, LoopInfo, AA, SEA, DomTree, PDA ,
1140
+ ASA, RunsOnHighLevelSil);
1056
1141
Changed |= Opt.optimize ();
1057
1142
}
1058
1143
0 commit comments