@@ -98,8 +98,8 @@ enum class DSEKind : unsigned {
98
98
99
99
// / Return the deallocate stack instructions corresponding to the given
100
100
// / AllocStackInst.
101
- static llvm::SmallVector<SILInstruction *, 1 > findDeallocStackInst (
102
- AllocStackInst *ASI) {
101
+ static llvm::SmallVector<SILInstruction *, 1 >
102
+ findDeallocStackInst ( AllocStackInst *ASI) {
103
103
llvm::SmallVector<SILInstruction *, 1 > DSIs;
104
104
for (auto UI = ASI->use_begin (), E = ASI->use_end (); UI != E; ++UI) {
105
105
if (DeallocStackInst *D = dyn_cast<DeallocStackInst>(UI->getUser ())) {
@@ -249,13 +249,16 @@ class BlockState {
249
249
llvm::DenseMap<SILValue, SILValue> LiveStores;
250
250
251
251
// / Constructors.
252
- BlockState (SILBasicBlock *B) : BB(B) {}
252
+ BlockState (SILBasicBlock *B, unsigned LocationNum, bool Optimistic)
253
+ : BB(B), LocationNum(LocationNum) {
254
+ init (LocationNum, Optimistic);
255
+ }
253
256
254
257
// / Return the current basic block.
255
258
SILBasicBlock *getBB () const { return BB; }
256
259
257
260
// / Initialize the bitvectors for the current basic block.
258
- void init (DSEContext &Ctx , bool Optimistic);
261
+ void init (unsigned LocationNum , bool Optimistic);
259
262
260
263
// / Check whether the BBWriteSetIn has changed. If it does, we need to rerun
261
264
// / the data flow on this block's predecessors to reach fixed point.
@@ -298,11 +301,13 @@ bool BlockState::isTrackingLocation(llvm::SmallBitVector &BV, unsigned i) {
298
301
namespace {
299
302
300
303
class DSEContext {
301
- enum class ProcessKind {
302
- ProcessOptimistic = 0 ,
303
- ProcessPessimistic = 1 ,
304
- ProcessNone = 2 ,
305
- };
304
+ // / How to process the current function.
305
+ enum class ProcessKind {
306
+ ProcessOptimistic = 0 ,
307
+ ProcessPessimistic = 1 ,
308
+ ProcessNone = 2 ,
309
+ };
310
+
306
311
private:
307
312
// / The module we are currently processing.
308
313
SILModule *Mod;
@@ -322,17 +327,14 @@ class DSEContext {
322
327
// / Type Expansion Analysis.
323
328
TypeExpansionAnalysis *TE;
324
329
330
+ // / The allocator we are using.
331
+ llvm::BumpPtrAllocator &BPA;
332
+
325
333
// / The epilogue release matcher we are using.
326
334
ConsumedArgToEpilogueReleaseMatcher& ERM;
327
335
328
- // / Allocator.
329
- llvm::BumpPtrAllocator BPA;
330
-
331
336
// / Map every basic block to its location state.
332
- llvm::DenseMap<SILBasicBlock *, BlockState *> BBToLocState;
333
-
334
- // / Keeps the actual BlockStates.
335
- std::vector<BlockState> BlockStates;
337
+ llvm::SmallDenseMap<SILBasicBlock *, BlockState *> BBToLocState;
336
338
337
339
// / Keeps all the locations for the current function. The BitVector in each
338
340
// / BlockState is then laid on top of it to keep track of which LSLocation
@@ -371,14 +373,13 @@ class DSEContext {
371
373
372
374
// / There is a read to a location, expand the location into individual fields
373
375
// / before processing them.
374
- void processRead (SILInstruction *Inst, BlockState *S, SILValue M, DSEKind K);
376
+ void processRead (SILInstruction *Inst, SILValue M, DSEKind K);
375
377
void processReadForGenKillSet (BlockState *S, unsigned bit);
376
378
void processReadForDSE (BlockState *S, unsigned Bit);
377
379
378
380
// / There is a write to a location, expand the location into individual fields
379
381
// / before processing them.
380
- void processWrite (SILInstruction *Inst, BlockState *S, SILValue V, SILValue M,
381
- DSEKind K);
382
+ void processWrite (SILInstruction *Inst, SILValue V, SILValue M, DSEKind K);
382
383
void processWriteForGenKillSet (BlockState *S, unsigned bit);
383
384
bool processWriteForDSE (BlockState *S, unsigned bit);
384
385
@@ -395,7 +396,8 @@ class DSEContext {
395
396
void processDebugValueAddrInstForGenKillSet (SILInstruction *I);
396
397
void processDebugValueAddrInstForDSE (SILInstruction *I);
397
398
398
- // / Process instructions. Extract locations from unknown memory inst.
399
+ // / Process unknown read instructions. Extract locations from unknown memory
400
+ // / inst.
399
401
void processUnknownReadInst (SILInstruction *Inst, DSEKind Kind);
400
402
void processUnknownReadInstForGenKillSet (SILInstruction *Inst);
401
403
void processUnknownReadInstForDSE (SILInstruction *Inst);
@@ -421,9 +423,9 @@ class DSEContext {
421
423
// / If not, on the second iteration, the intersection of the successors of
422
424
// / the loop basic block will have store to x.a and therefore x.a = 13 can now
423
425
// / be considered dead.
424
- void invalidateLSLocationBase (SILInstruction *Inst , DSEKind Kind);
425
- void invalidateLSLocationBaseForGenKillSet (SILInstruction *Inst );
426
- void invalidateLSLocationBaseForDSE (SILInstruction *Inst );
426
+ void invalidateBase (SILValue B, BlockState *S , DSEKind Kind);
427
+ void invalidateBaseForGenKillSet (SILValue B, BlockState *S );
428
+ void invalidateBaseForDSE (SILValue B, BlockState *S );
427
429
428
430
// / Get the bit representing the location in the LocationVault.
429
431
unsigned getLocationBit (const LSLocation &L);
@@ -432,8 +434,9 @@ class DSEContext {
432
434
// / Constructor.
433
435
DSEContext (SILFunction *F, SILModule *M, SILPassManager *PM,
434
436
AliasAnalysis *AA, EscapeAnalysis *EA, TypeExpansionAnalysis *TE,
437
+ llvm::BumpPtrAllocator &BPA,
435
438
ConsumedArgToEpilogueReleaseMatcher &ERM)
436
- : Mod(M), F(F), PM(PM), AA(AA), EA(EA), TE(TE), ERM(ERM) {}
439
+ : Mod(M), F(F), PM(PM), AA(AA), EA(EA), TE(TE), BPA(BPA), ERM(ERM) {}
437
440
438
441
// / Entry point for dead store elimination.
439
442
bool run ();
@@ -444,12 +447,10 @@ class DSEContext {
444
447
// / Returns the escape analysis we use.
445
448
EscapeAnalysis *getEA () { return EA; }
446
449
447
- // / Returns the function currently being processing.
448
- SILFunction *getFn () { return F; }
449
-
450
450
// / Returns the location vault of the current function.
451
451
std::vector<LSLocation> &getLocationVault () { return LocationVault; }
452
452
453
+ // / Returns the epilogue release matcher we are using.
453
454
ConsumedArgToEpilogueReleaseMatcher &getERM () const { return ERM; };
454
455
455
456
// / Use a set of ad hoc rules to tell whether we should run a pessimistic
@@ -476,9 +477,7 @@ class DSEContext {
476
477
477
478
} // end anonymous namespace
478
479
479
- void BlockState::init (DSEContext &Ctx, bool Optimistic) {
480
- std::vector<LSLocation> &LV = Ctx.getLocationVault ();
481
- LocationNum = LV.size ();
480
+ void BlockState::init (unsigned LocationNum, bool Optimistic) {
482
481
// For function that requires just 1 iteration of the data flow to converge
483
482
// we set the initial state of BBWriteSetIn to 0.
484
483
//
@@ -506,7 +505,6 @@ void BlockState::init(DSEContext &Ctx, bool Optimistic) {
506
505
// MaxStoreSet is optimistically set to true initially.
507
506
BBMaxStoreSet.resize (LocationNum, true );
508
507
509
-
510
508
// DeallocateLocation initially empty.
511
509
BBDeallocateLocation.resize (LocationNum, false );
512
510
}
@@ -604,6 +602,12 @@ void DSEContext::processBasicBlockForGenKillSet(SILBasicBlock *BB) {
604
602
// Compute the genset and killset for this instruction.
605
603
processInstruction (&(*I), DSEKind::BuildGenKillSet);
606
604
}
605
+
606
+ // Handle SILArgument for base invalidation.
607
+ ArrayRef<SILArgument *> Args = BB->getBBArgs ();
608
+ for (auto &X : Args) {
609
+ invalidateBase (X, BBState, DSEKind::BuildGenKillSet);
610
+ }
607
611
}
608
612
609
613
bool DSEContext::processBasicBlockWithGenKillSet (SILBasicBlock *BB) {
@@ -620,8 +624,7 @@ bool DSEContext::processBasicBlockWithGenKillSet(SILBasicBlock *BB) {
620
624
return S->updateBBWriteSetIn (S->BBWriteSetMid );
621
625
}
622
626
623
- void DSEContext::processBasicBlockForDSE (SILBasicBlock *BB,
624
- bool Optimistic) {
627
+ void DSEContext::processBasicBlockForDSE (SILBasicBlock *BB, bool Optimistic) {
625
628
// If we know this is not a one iteration function which means its
626
629
// its BBWriteSetIn and BBWriteSetOut have been computed and converged,
627
630
// and this basic block does not even have StoreInsts, there is no point
@@ -643,6 +646,12 @@ void DSEContext::processBasicBlockForDSE(SILBasicBlock *BB,
643
646
processInstruction (&(*I), DSEKind::PerformDSE);
644
647
}
645
648
649
+ // Handle SILArgument for base invalidation.
650
+ ArrayRef<SILArgument *> Args = BB->getBBArgs ();
651
+ for (auto &X : Args) {
652
+ invalidateBase (X, S, DSEKind::BuildGenKillSet);
653
+ }
654
+
646
655
S->BBWriteSetIn = S->BBWriteSetMid ;
647
656
}
648
657
@@ -697,40 +706,38 @@ void DSEContext::mergeSuccessorLiveIns(SILBasicBlock *BB) {
697
706
C->BBWriteSetOut |= C->BBDeallocateLocation ;
698
707
}
699
708
700
- void DSEContext::invalidateLSLocationBaseForGenKillSet (SILInstruction *I) {
701
- BlockState *S = getBlockState (I);
709
+ void DSEContext::invalidateBaseForGenKillSet (SILValue B, BlockState *S) {
702
710
for (unsigned i = 0 ; i < S->LocationNum ; ++i) {
703
- if (LocationVault[i].getBase () != I )
711
+ if (LocationVault[i].getBase () != B )
704
712
continue ;
705
713
S->startTrackingLocation (S->BBKillSet , i);
706
714
S->stopTrackingLocation (S->BBGenSet , i);
707
715
}
708
716
}
709
717
710
- void DSEContext::invalidateLSLocationBaseForDSE (SILInstruction *I) {
711
- BlockState *S = getBlockState (I);
718
+ void DSEContext::invalidateBaseForDSE (SILValue B, BlockState *S) {
712
719
for (unsigned i = 0 ; i < S->LocationNum ; ++i) {
713
720
if (!S->BBWriteSetMid .test (i))
714
721
continue ;
715
- if (LocationVault[i].getBase () != I )
722
+ if (LocationVault[i].getBase () != B )
716
723
continue ;
717
724
S->stopTrackingLocation (S->BBWriteSetMid , i);
718
725
}
719
726
}
720
727
721
- void DSEContext::invalidateLSLocationBase (SILInstruction *I , DSEKind Kind) {
728
+ void DSEContext::invalidateBase (SILValue B, BlockState *S , DSEKind Kind) {
722
729
// If this instruction defines the base of a location, then we need to
723
730
// invalidate any locations with the same base.
724
731
//
725
732
// Are we building genset and killset.
726
733
if (isBuildingGenKillSet (Kind)) {
727
- invalidateLSLocationBaseForGenKillSet (I );
734
+ invalidateBaseForGenKillSet (B, S );
728
735
return ;
729
736
}
730
737
731
738
// Are we performing dead store elimination.
732
739
if (isPerformingDSE (Kind)) {
733
- invalidateLSLocationBaseForDSE (I );
740
+ invalidateBaseForDSE (B, S );
734
741
return ;
735
742
}
736
743
@@ -771,8 +778,8 @@ void DSEContext::processReadForGenKillSet(BlockState *S, unsigned bit) {
771
778
}
772
779
}
773
780
774
- void DSEContext::processRead (SILInstruction *I, BlockState *S, SILValue Mem,
775
- DSEKind Kind) {
781
+ void DSEContext::processRead (SILInstruction *I, SILValue Mem, DSEKind Kind) {
782
+ auto *S = getBlockState (I);
776
783
// Construct a LSLocation to represent the memory read by this instruction.
777
784
// NOTE: The base will point to the actual object this inst is accessing,
778
785
// not this particular field.
@@ -856,8 +863,9 @@ void DSEContext::processWriteForMaxStoreSet(BlockState *S, unsigned bit) {
856
863
S->startTrackingLocation (S->BBMaxStoreSet , bit);
857
864
}
858
865
859
- void DSEContext::processWrite (SILInstruction *I, BlockState *S, SILValue Val,
860
- SILValue Mem, DSEKind Kind) {
866
+ void DSEContext::processWrite (SILInstruction *I, SILValue Val, SILValue Mem,
867
+ DSEKind Kind) {
868
+ auto *S = getBlockState (I);
861
869
// Construct a LSLocation to represent the memory read by this instruction.
862
870
// NOTE: The base will point to the actual object this inst is accessing,
863
871
// not this particular field.
@@ -979,12 +987,12 @@ void DSEContext::processWrite(SILInstruction *I, BlockState *S, SILValue Val,
979
987
}
980
988
981
989
void DSEContext::processLoadInst (SILInstruction *I, DSEKind Kind) {
982
- processRead (I, getBlockState (I), cast<LoadInst>(I)->getOperand (), Kind);
990
+ processRead (I, cast<LoadInst>(I)->getOperand (), Kind);
983
991
}
984
992
985
993
void DSEContext::processStoreInst (SILInstruction *I, DSEKind Kind) {
986
994
auto *SI = cast<StoreInst>(I);
987
- processWrite (I, getBlockState (I), SI->getSrc (), SI->getDest (), Kind);
995
+ processWrite (I, SI->getSrc (), SI->getDest (), Kind);
988
996
}
989
997
990
998
void DSEContext::processDebugValueAddrInstForGenKillSet (SILInstruction *I) {
@@ -1091,7 +1099,7 @@ void DSEContext::processInstruction(SILInstruction *I, DSEKind Kind) {
1091
1099
}
1092
1100
1093
1101
// Check whether this instruction will invalidate any other locations.
1094
- invalidateLSLocationBase (I , Kind);
1102
+ invalidateBase (I, getBlockState (I) , Kind);
1095
1103
}
1096
1104
1097
1105
void DSEContext::runIterativeDSE () {
@@ -1132,46 +1140,30 @@ void DSEContext::runIterativeDSE() {
1132
1140
}
1133
1141
1134
1142
bool DSEContext::run () {
1135
- // Is this a one iteration function.
1136
- auto *PO = PM->getAnalysis <PostOrderAnalysis>()->get (F);
1137
-
1138
1143
std::pair<int , int > LSCount = std::make_pair (0 , 0 );
1139
1144
// Walk over the function and find all the locations accessed by
1140
1145
// this function.
1141
- LSLocation::enumerateLSLocations (*F, LocationVault,
1142
- LocToBitIndex,
1146
+ LSLocation::enumerateLSLocations (*F, LocationVault, LocToBitIndex,
1143
1147
BaseToLocIndex, TE, LSCount);
1144
1148
1145
1149
// Check how to optimize this function.
1146
1150
ProcessKind Kind = getProcessFunctionKind (LSCount.second );
1147
1151
1148
1152
// We do not optimize this function at all.
1149
1153
if (Kind == ProcessKind::ProcessNone)
1150
- return false ;
1154
+ return false ;
1151
1155
1152
1156
// Do we run a pessimistic data flow ?
1153
1157
bool Optimistic = Kind == ProcessKind::ProcessOptimistic ? true : false ;
1154
1158
1155
1159
// For all basic blocks in the function, initialize a BB state.
1156
1160
//
1157
- // DenseMap has a minimum size of 64, while many functions do not have more
1158
- // than 64 basic blocks. Therefore, allocate the BlockState in a vector and
1159
- // use pointer in BBToLocState to access them.
1160
- for (auto &B : *F) {
1161
- BlockStates.push_back (BlockState (&B));
1162
- // Since we know all the locations accessed in this function, we can resize
1163
- // the bit vector to the appropriate size.
1164
- BlockStates.back ().init (*this , Optimistic);
1165
- }
1166
-
1167
1161
// Initialize the BBToLocState mapping.
1168
- for (auto &S : BlockStates) {
1169
- BBToLocState[S.getBB ()] = &S;
1170
- }
1171
-
1172
- // Initialize the store bit state at the end of each basic block.
1173
- for (auto &X : BlockStates) {
1174
- X.initStoreSetAtEndOfBlock (*this );
1162
+ unsigned LocationNum = this ->getLocationVault ().size ();
1163
+ for (auto &B : *F) {
1164
+ auto *State = new (BPA) BlockState (&B, LocationNum, Optimistic);
1165
+ BBToLocState[&B] = State;
1166
+ State->initStoreSetAtEndOfBlock (*this );
1175
1167
}
1176
1168
1177
1169
// We perform dead store elimination in the following phases.
@@ -1198,6 +1190,8 @@ bool DSEContext::run() {
1198
1190
1199
1191
// The data flow has stabilized, run one last iteration over all the basic
1200
1192
// blocks and try to remove dead stores.
1193
+ // Is this a one iteration function.
1194
+ auto *PO = PM->getAnalysis <PostOrderAnalysis>()->get (F);
1201
1195
for (SILBasicBlock *B : PO->getPostOrder ()) {
1202
1196
processBasicBlockForDSE (B, Optimistic);
1203
1197
}
@@ -1245,9 +1239,13 @@ class DeadStoreElimination : public SILFunctionTransform {
1245
1239
auto *TE = PM->getAnalysis <TypeExpansionAnalysis>();
1246
1240
auto *RCFI = PM->getAnalysis <RCIdentityAnalysis>()->get (F);
1247
1241
1242
+ // The allocator we are using.
1243
+ llvm::BumpPtrAllocator BPA;
1244
+
1245
+ // The epilogue release matcher we are using.
1248
1246
ConsumedArgToEpilogueReleaseMatcher ERM (RCFI, F);
1249
1247
1250
- DSEContext DSE (F, &F->getModule (), PM, AA, EA, TE, ERM);
1248
+ DSEContext DSE (F, &F->getModule (), PM, AA, EA, TE, BPA, ERM);
1251
1249
if (DSE.run ()) {
1252
1250
invalidateAnalysis (SILAnalysis::InvalidationKind::Instructions);
1253
1251
}
0 commit comments