93
93
#ifndef SWIFT_SILOPTIMIZER_UTILS_CANONICALOSSALIFETIME_H
94
94
#define SWIFT_SILOPTIMIZER_UTILS_CANONICALOSSALIFETIME_H
95
95
96
+ #include " swift/Basic/SmallPtrSetVector.h"
96
97
#include " swift/SIL/SILInstruction.h"
97
98
#include " swift/SILOptimizer/Analysis/DominanceAnalysis.h"
98
99
#include " swift/SILOptimizer/Analysis/NonLocalAccessBlockAnalysis.h"
@@ -123,13 +124,33 @@ class CanonicalOSSAConsumeInfo {
123
124
// / that should be canonicalized separately.
124
125
llvm::SmallDenseMap<SILBasicBlock *, CopyValueInst *, 4 > persistentCopies;
125
126
127
+ // / The set of non-destroy consumes that need to be poisoned. This is
128
+ // / determined in two steps. First findOrInsertDestroyInBlock() checks if the
129
+ // / lifetime shrank within the block. Second rewriteCopies() checks if the
130
+ // / consume is in remnantLiveOutBlock(). Finally injectPoison() inserts new
131
+ // / copies and poison destroys for everything in this set.
132
+ SmallPtrSetVector<SILInstruction *, 4 > needsPoisonConsumes;
133
+
126
134
public:
127
135
bool hasUnclaimedConsumes () const { return !finalBlockConsumes.empty (); }
128
136
129
137
void clear () {
130
138
finalBlockConsumes.clear ();
131
139
debugAfterConsume.clear ();
132
140
persistentCopies.clear ();
141
+ needsPoisonConsumes.clear ();
142
+ }
143
+
144
+ void recordNeedsPoison (SILInstruction *consume) {
145
+ needsPoisonConsumes.insert (consume);
146
+ }
147
+
148
+ bool needsPoison (SILInstruction *consume) const {
149
+ return needsPoisonConsumes.count (consume);
150
+ }
151
+
152
+ ArrayRef<SILInstruction *> getNeedsPoisonConsumes () const {
153
+ return needsPoisonConsumes.getArrayRef ();
133
154
}
134
155
135
156
bool hasFinalConsumes () const { return !finalBlockConsumes.empty (); }
@@ -158,6 +179,11 @@ class CanonicalOSSAConsumeInfo {
158
179
debugAfterConsume.push_back (dvi);
159
180
}
160
181
182
+ void popDebugAfterConsume (DebugValueInst *dvi) {
183
+ if (!debugAfterConsume.empty () && debugAfterConsume.back () == dvi)
184
+ debugAfterConsume.pop_back ();
185
+ }
186
+
161
187
ArrayRef<DebugValueInst *> getDebugInstsAfterConsume () const {
162
188
return debugAfterConsume;
163
189
}
@@ -189,6 +215,9 @@ class CanonicalizeOSSALifetime {
189
215
// / liveness may be pruned during canonicalization.
190
216
bool pruneDebugMode;
191
217
218
+ // / If true, then new destroy_value instructions will be poison.
219
+ bool poisonRefsMode;
220
+
192
221
NonLocalAccessBlockAnalysis *accessBlockAnalysis;
193
222
// Lazily initialize accessBlocks only when
194
223
// extendLivenessThroughOverlappingAccess is invoked.
@@ -232,16 +261,26 @@ class CanonicalizeOSSALifetime {
232
261
// / ending". end_borrows do not end a liverange that may include owned copies.
233
262
PrunedLiveness liveness;
234
263
264
+ // / remnantLiveOutBlocks are part of the original extended lifetime that are
265
+ // / not in canonical pruned liveness. There is a path from a PrunedLiveness
266
+ // / boundary to an original destroy that passes through this block.
267
+ // /
268
+ // / These blocks would be equivalent to PrunedLiveness::LiveOut if
269
+ // / PrunedLiveness were recomputed using all original destroys as interesting
270
+ // / uses, minus blocks already marked PrunedLiveness::LiveOut. (These blocks
271
+ // / may be in PrunedLiveness::LiveWithin).
272
+ SmallSetVector<SILBasicBlock *, 8 > remnantLiveOutBlocks;
273
+
235
274
// / Information about consuming instructions discovered in this caonical OSSA
236
275
// / lifetime.
237
276
CanonicalOSSAConsumeInfo consumes;
238
277
239
278
public:
240
- CanonicalizeOSSALifetime (bool pruneDebugMode,
279
+ CanonicalizeOSSALifetime (bool pruneDebugMode, bool poisonRefsMode,
241
280
NonLocalAccessBlockAnalysis *accessBlockAnalysis,
242
281
DominanceAnalysis *dominanceAnalysis,
243
282
DeadEndBlocks *deBlocks)
244
- : pruneDebugMode(pruneDebugMode),
283
+ : pruneDebugMode(pruneDebugMode), poisonRefsMode(poisonRefsMode),
245
284
accessBlockAnalysis (accessBlockAnalysis),
246
285
dominanceAnalysis(dominanceAnalysis), deBlocks(deBlocks) {}
247
286
@@ -263,6 +302,7 @@ class CanonicalizeOSSALifetime {
263
302
consumingBlocks.clear ();
264
303
debugValues.clear ();
265
304
liveness.clear ();
305
+ remnantLiveOutBlocks.clear ();
266
306
}
267
307
268
308
bool hasChanged () const { return changed; }
@@ -309,7 +349,12 @@ class CanonicalizeOSSALifetime {
309
349
310
350
void findOrInsertDestroys ();
311
351
352
+ void insertDestroyOnCFGEdge (SILBasicBlock *predBB, SILBasicBlock *succBB,
353
+ bool needsPoison);
354
+
312
355
void rewriteCopies ();
356
+
357
+ void injectPoison ();
313
358
};
314
359
315
360
} // end namespace swift
0 commit comments