27
27
// /
28
28
// / 2. Performing a post-order walk over the control flow graph, tracking any
29
29
// / LSLocations that are read from or stored into in each basic block. After
30
- // / eliminating any dead stores in single blocks, it computes a kill set for
31
- // / each block. The kill set tracks what LSLocations are stored into by this
32
- // / basic block and its successors .
30
+ // / eliminating any dead stores in single blocks, it computes a genset and
31
+ // / killset for each block. The genset keeps a list of upward visible stores
32
+ // / and the killset keeps a list of LSLocation this basic block reads (kills) .
33
33
// /
34
- // / 3. An optimistic iterative dataflow is performed on the gen sets and kill
35
- // / sets until convergence.
34
+ // / 3. An optimistic iterative dataflow is performed on the genset and killset
35
+ // / until convergence.
36
36
// /
37
37
// / At the core of DSE, there is the LSLocation class. a LSLocation is an
38
38
// / abstraction of an object field in program. It consists of a base and a
67
67
#include " swift/SILOptimizer/Analysis/ValueTracking.h"
68
68
#include " swift/SILOptimizer/PassManager/Passes.h"
69
69
#include " swift/SILOptimizer/PassManager/Transforms.h"
70
- #include " swift/SILOptimizer/Utils/Local.h"
71
70
#include " swift/SILOptimizer/Utils/CFG.h"
71
+ #include " swift/SILOptimizer/Utils/Local.h"
72
72
#include " llvm/ADT/Statistic.h"
73
73
#include " llvm/ADT/DenseSet.h"
74
74
#include " llvm/ADT/BitVector.h"
75
75
#include " llvm/Support/Allocator.h"
76
76
#include " llvm/Support/CommandLine.h"
77
77
#include " llvm/Support/Debug.h"
78
- #include < algorithm>
79
78
80
79
using namespace swift ;
81
- using swift::LSLocation;
82
80
83
81
STATISTIC (NumDeadStores, " Number of dead stores removed" );
84
82
STATISTIC (NumPartialDeadStores, " Number of partial dead stores removed" );
85
83
86
84
// / ComputeMaxStoreSet - If we ignore all reads, what is the max store set that
87
- // / can reach the beginning of a basic block. This helps generating the genset
88
- // / and killset. i.e. if there is no upward visible store that can reach the
89
- // / beginning of a basic block, then we know that the genset and killset for
90
- // / the stored location need not be set.
85
+ // / can reach a particular point in a basic block. This helps in generating
86
+ // / the genset and killset. i.e. if there is no upward visible store that can
87
+ // / reach the beginning of a basic block, then we know that the genset and
88
+ // / killset for the stored location need not be set for the basic block .
91
89
// /
92
90
// / BuildGenKillSet - Build the genset and killset of the basic block.
93
91
// /
@@ -114,8 +112,8 @@ static inline bool isPerformingDSE(DSEKind Kind) {
114
112
return Kind == DSEKind::PerformDSE;
115
113
}
116
114
117
- // / Return true if all basic blocks have their successors processed if
118
- // / they are iterated in post order.
115
+ // / Return true if all basic blocks will have their successors processed if
116
+ // / the basic blocks in the functions are iterated in post order.
119
117
static bool isOneIterationFunction (PostOrderFunctionInfo *PO) {
120
118
llvm::DenseSet<SILBasicBlock *> HandledBBs;
121
119
for (SILBasicBlock *B : PO->getPostOrder ()) {
@@ -165,9 +163,12 @@ class DSEContext;
165
163
// / is initialized to the intersection of BBWriteSetIns of all successors of the
166
164
// / basic block.
167
165
// /
166
+ // / BBWriteSetMid is initialized to BBWriteSetOut of the current basic block
167
+ // / before instructions in the basic block is processed.
168
+ // /
168
169
// / Initially BBWriteSetIn is set to true. After the basic block is processed,
169
170
// / if its BBWriteSetMid is different from BBWriteSetIn, BBWriteSetIn is
170
- // / initialized to the value of BBWriteSetMid and the data flow is rerun on the
171
+ // / assigned the value of BBWriteSetMid and the data flow is rerun on the
171
172
// / current basic block's predecessors.
172
173
// /
173
174
// / Instructions in each basic block are processed in post-order as follows:
@@ -214,10 +215,10 @@ class BlockState {
214
215
// / kills an upward visible store.
215
216
llvm::SmallBitVector BBKillSet;
216
217
217
- // / A bit vector to keep the maximum number of stores that can reach the
218
- // / beginning of the basic block. If a bit is set, that means there is
219
- // / potentially an upward visible store to the location at the beginning
220
- // / of the basic block.
218
+ // / A bit vector to keep the maximum number of stores that can reach a
219
+ // / certain point of the basic block. If a bit is set, that means there is
220
+ // / potentially an upward visible store to the location at the particular
221
+ // / point of the basic block.
221
222
llvm::SmallBitVector BBMaxStoreSet;
222
223
223
224
// / The dead stores in the current basic block.
@@ -231,7 +232,6 @@ class BlockState {
231
232
llvm::DenseMap<SILValue, SILValue> LiveStores;
232
233
233
234
// / Constructors.
234
- BlockState () : BB(nullptr ) {}
235
235
BlockState (SILBasicBlock *B) : BB(B) {}
236
236
237
237
// / Return the current basic block.
@@ -240,7 +240,7 @@ class BlockState {
240
240
// / Initialize the bitvectors for the return basic block.
241
241
void initReturnBlock (DSEContext &Ctx);
242
242
243
- // / Initialize the bitvectors for the basic block.
243
+ // / Initialize the bitvectors for the current basic block.
244
244
void init (DSEContext &Ctx, bool OneIterationFunction);
245
245
246
246
// / Check whether the BBWriteSetIn has changed. If it does, we need to rerun
@@ -256,11 +256,10 @@ class BlockState {
256
256
} // end anonymous namespace
257
257
258
258
bool BlockState::updateBBWriteSetIn (llvm::SmallBitVector &X) {
259
- bool Changed = (BBWriteSetIn != X);
260
- if (!Changed)
261
- return Changed;
259
+ if (BBWriteSetIn == X)
260
+ return false ;
262
261
BBWriteSetIn = X;
263
- return Changed ;
262
+ return true ;
264
263
}
265
264
266
265
void BlockState::startTrackingLocation (llvm::SmallBitVector &BV, unsigned i) {
@@ -294,7 +293,7 @@ class DSEContext {
294
293
// / Alias Analysis.
295
294
AliasAnalysis *AA;
296
295
297
- // / Escape analysis .
296
+ // / Escape Analysis .
298
297
EscapeAnalysis *EA;
299
298
300
299
// / Type Expansion Analysis.
@@ -344,20 +343,20 @@ class DSEContext {
344
343
void processWriteForGenKillSet (BlockState *S, unsigned bit);
345
344
bool processWriteForDSE (BlockState *S, unsigned bit);
346
345
347
- // / Process Instructions . Extract locations from SIL LoadInst.
346
+ // / Process instructions . Extract locations from SIL LoadInst.
348
347
void processLoadInst (SILInstruction *Inst, DSEKind Kind);
349
348
350
- // / Process Instructions . Extract locations from SIL StoreInst.
349
+ // / Process instructions . Extract locations from SIL StoreInst.
351
350
void processStoreInst (SILInstruction *Inst, DSEKind Kind);
352
351
353
- // / Process Instructions . Extract locations from SIL DebugValueAddrInst.
352
+ // / Process instructions . Extract locations from SIL DebugValueAddrInst.
354
353
// / DebugValueAddrInst maybe promoted to DebugValue, when this is done,
355
354
// / DebugValueAddrInst is effectively a read on the location.
356
355
void processDebugValueAddrInst (SILInstruction *I, DSEKind Kind);
357
356
void processDebugValueAddrInstForGenKillSet (SILInstruction *I);
358
357
void processDebugValueAddrInstForDSE (SILInstruction *I);
359
358
360
- // / Process Instructions . Extract locations from unknown memory inst.
359
+ // / Process instructions . Extract locations from unknown memory inst.
361
360
void processUnknownReadInst (SILInstruction *Inst, DSEKind Kind);
362
361
void processUnknownReadInstForGenKillSet (SILInstruction *Inst);
363
362
void processUnknownReadInstForDSE (SILInstruction *Inst);
@@ -388,8 +387,6 @@ class DSEContext {
388
387
void invalidateLSLocationBaseForDSE (SILInstruction *Inst);
389
388
390
389
// / Get the bit representing the location in the LocationVault.
391
- // /
392
- // / NOTE: Adds the location to the location vault if necessary.
393
390
unsigned getLocationBit (const LSLocation &L);
394
391
395
392
public:
@@ -402,7 +399,7 @@ class DSEContext {
402
399
bool run ();
403
400
404
401
// / Run the iterative DF to converge the BBWriteSetIn.
405
- void runIterativeDF ();
402
+ void runIterativeDSE ();
406
403
407
404
// / Returns the escape analysis we use.
408
405
EscapeAnalysis *getEA () { return EA; }
@@ -424,8 +421,8 @@ class DSEContext {
424
421
// / block with the generated gen and kill set.
425
422
bool processBasicBlockWithGenKillSet (SILBasicBlock *BB);
426
423
427
- // / Intersect the successor live-ins .
428
- void mergeSuccessorStates (SILBasicBlock *BB);
424
+ // / Intersect the successors' BBWriteSetIns .
425
+ void mergeSuccessorLiveIns (SILBasicBlock *BB);
429
426
430
427
// / Update the BlockState based on the given instruction.
431
428
void processInstruction (SILInstruction *I, DSEKind Kind);
@@ -450,10 +447,13 @@ void BlockState::initReturnBlock(DSEContext &Ctx) {
450
447
void BlockState::init (DSEContext &Ctx, bool OneIterationFunction) {
451
448
std::vector<LSLocation> &LV = Ctx.getLocationVault ();
452
449
LocationNum = LV.size ();
453
- // The initial state of BBWriteSetIn should be all 1's. Otherwise the
454
- // dataflow solution could be too conservative.
450
+ // For function that requires just 1 iteration of the data flow to converge
451
+ // we set the initiali state of BBWriteSetIn to 0.
452
+ //
453
+ // For other functions, the initial state of BBWriteSetIn should be all 1's.
454
+ // Otherwise the dataflow solution could be too conservative.
455
455
//
456
- // consider this case, the dead store by var a = 10 before the loop will not
456
+ // Consider this case, the dead store by var a = 10 before the loop will not
457
457
// be eliminated if the BBWriteSetIn is set to 0 initially.
458
458
//
459
459
// var a = 10
@@ -528,7 +528,7 @@ void DSEContext::processBasicBlockForGenKillSet(SILBasicBlock *BB) {
528
528
529
529
bool DSEContext::processBasicBlockWithGenKillSet (SILBasicBlock *BB) {
530
530
// Compute the BBWriteSetOut at the end of the basic block.
531
- mergeSuccessorStates (BB);
531
+ mergeSuccessorLiveIns (BB);
532
532
533
533
// Compute the BBWriteSet at the beginning of the basic block.
534
534
BlockState *S = getBlockState (BB);
@@ -543,7 +543,7 @@ bool DSEContext::processBasicBlockWithGenKillSet(SILBasicBlock *BB) {
543
543
void DSEContext::processBasicBlockForDSE (SILBasicBlock *BB) {
544
544
// Intersect in the successor WriteSetIns. A store is dead if it is not read
545
545
// from any path to the end of the program. Thus an intersection.
546
- mergeSuccessorStates (BB);
546
+ mergeSuccessorLiveIns (BB);
547
547
548
548
// Initialize the BBWriteSetMid to BBWriteSetOut to get started.
549
549
BlockState *S = getBlockState (BB);
@@ -557,7 +557,7 @@ void DSEContext::processBasicBlockForDSE(SILBasicBlock *BB) {
557
557
S->BBWriteSetIn = S->BBWriteSetMid ;
558
558
}
559
559
560
- void DSEContext::mergeSuccessorStates (SILBasicBlock *BB) {
560
+ void DSEContext::mergeSuccessorLiveIns (SILBasicBlock *BB) {
561
561
// If basic block has no successor, then all local writes can be considered
562
562
// dead for block with no successor.
563
563
if (BB->succ_empty ())
@@ -609,7 +609,7 @@ void DSEContext::invalidateLSLocationBaseForDSE(SILInstruction *I) {
609
609
void DSEContext::invalidateLSLocationBase (SILInstruction *I, DSEKind Kind) {
610
610
// If this instruction defines the base of a location, then we need to
611
611
// invalidate any locations with the same base.
612
-
612
+ //
613
613
// Are we building genset and killset.
614
614
if (isBuildingGenKillSet (Kind)) {
615
615
invalidateLSLocationBaseForGenKillSet (I);
@@ -711,7 +711,7 @@ void DSEContext::processRead(SILInstruction *I, BlockState *S, SILValue Mem,
711
711
712
712
bool DSEContext::processWriteForDSE (BlockState *S, unsigned bit) {
713
713
// If a tracked store must aliases with this store, then this store is dead.
714
- bool IsDead = false ;
714
+ bool StoreDead = false ;
715
715
LSLocation &R = LocationVault[bit];
716
716
for (unsigned i = 0 ; i < S->LocationNum ; ++i) {
717
717
if (!S->isTrackingLocation (S->BBWriteSetMid , i))
@@ -721,13 +721,13 @@ bool DSEContext::processWriteForDSE(BlockState *S, unsigned bit) {
721
721
if (!L.isMustAliasLSLocation (R, AA))
722
722
continue ;
723
723
// There is a must alias store. No need to check further.
724
- IsDead = true ;
724
+ StoreDead = true ;
725
725
break ;
726
726
}
727
727
728
728
// Track this new store.
729
729
S->startTrackingLocation (S->BBWriteSetMid , bit);
730
- return IsDead ;
730
+ return StoreDead ;
731
731
}
732
732
733
733
void DSEContext::processWriteForGenKillSet (BlockState *S, unsigned bit) {
@@ -967,20 +967,7 @@ void DSEContext::processInstruction(SILInstruction *I, DSEKind Kind) {
967
967
invalidateLSLocationBase (I, Kind);
968
968
}
969
969
970
- void DSEContext::runIterativeDF () {
971
- // We perform dead store elimination in the following phases.
972
- //
973
- // Phase 1. we compute the max store set at the beginning of the basic block.
974
- //
975
- // Phase 2. we compute the genset and killset for every basic block.
976
- //
977
- // Phase 3. we run the data flow with the genset and killset until
978
- // BBWriteSetIns stop changing.
979
- //
980
- // Phase 4. we run the data flow for the last iteration and perform the DSE.
981
- //
982
- // Phase 5. we remove the dead stores.
983
-
970
+ void DSEContext::runIterativeDSE () {
984
971
// Generate the genset and killset for each basic block. We can process the
985
972
// basic blocks in any order.
986
973
//
@@ -1045,9 +1032,26 @@ bool DSEContext::run() {
1045
1032
BBToLocState[S.getBB ()] = &S;
1046
1033
}
1047
1034
1035
+ // We perform dead store elimination in the following phases.
1036
+ //
1037
+ // Phase 1. we compute the max store set at the beginning of the basic block.
1038
+ //
1039
+ // Phase 2. we compute the genset and killset for every basic block.
1040
+ //
1041
+ // Phase 3. we run the data flow with the genset and killset until
1042
+ // BBWriteSetIns stop changing.
1043
+ //
1044
+ // Phase 4. we run the data flow for the last iteration and perform the DSE.
1045
+ //
1046
+ // Phase 5. we remove the dead stores.
1047
+ //
1048
+ // Phase 1 - 3 are only performed when we know the data flow will not
1049
+ // converge in a single iteration. Otherwise, we only run phase 4 and 5
1050
+ // on the function.
1051
+
1048
1052
// We need to run the iterative data flow on the function.
1049
1053
if (!OneIterationFunction) {
1050
- runIterativeDF ();
1054
+ runIterativeDSE ();
1051
1055
}
1052
1056
1053
1057
// The data flow has stabilized, run one last iteration over all the basic
0 commit comments