13
13
#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_ARCANALYSIS_H
14
14
#define SWIFT_SILOPTIMIZER_ANALYSIS_ARCANALYSIS_H
15
15
16
+ #include " swift/Basic/LLVM.h"
16
17
#include " swift/SIL/SILArgument.h"
17
- #include " swift/SIL/SILValue.h"
18
18
#include " swift/SIL/SILBasicBlock.h"
19
+ #include " swift/SIL/SILValue.h"
19
20
#include " swift/SILOptimizer/Analysis/AliasAnalysis.h"
20
21
#include " swift/SILOptimizer/Analysis/PostOrderAnalysis.h"
21
22
#include " swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
22
23
#include " llvm/ADT/BitVector.h"
23
- #include " llvm/ADT/SmallPtrSet.h"
24
24
#include " llvm/ADT/MapVector.h"
25
25
#include " llvm/ADT/SetVector.h"
26
+ #include " llvm/ADT/SmallPtrSet.h"
26
27
#include " llvm/ADT/TinyPtrVector.h"
27
28
28
29
namespace swift {
@@ -39,15 +40,13 @@ class SILFunction;
39
40
} // end namespace swift
40
41
41
42
namespace swift {
43
+
42
44
// / Return true if this is a retain instruction.
43
45
bool isRetainInstruction (SILInstruction *II);
44
46
45
47
// / Return true if this is a release instruction.
46
48
bool isReleaseInstruction (SILInstruction *II);
47
49
48
- using RetainList = TinyPtrVector<SILInstruction *>;
49
- using ReleaseList = TinyPtrVector<SILInstruction *>;
50
-
51
50
// / \returns True if the user \p User decrements the ref count of \p Ptr.
52
51
bool mayDecrementRefCount (SILInstruction *User, SILValue Ptr,
53
52
AliasAnalysis *AA);
@@ -141,16 +140,11 @@ class ConsumedResultToEpilogueRetainMatcher {
141
140
SILFunction *F;
142
141
RCIdentityFunctionInfo *RCFI;
143
142
AliasAnalysis *AA;
143
+
144
144
// We use a list of instructions for now so that we can keep the same interface
145
145
// and handle exploded retain_value later.
146
- RetainList EpilogueRetainInsts;
146
+ TinyPtrVector<SILInstruction *> EpilogueRetainInsts;
147
147
148
- // / Return true if all the successors of the EpilogueRetainInsts do not have
149
- // / a retain.
150
- bool isTransitiveSuccessorsRetainFree (llvm::DenseSet<SILBasicBlock *> BBs);
151
-
152
- // / Finds matching releases in the provided block \p BB.
153
- RetainKindValue findMatchingRetainsInBasicBlock (SILBasicBlock *BB, SILValue V);
154
148
public:
155
149
// / Finds matching releases in the return block of the function \p F.
156
150
ConsumedResultToEpilogueRetainMatcher (RCIdentityFunctionInfo *RCFI,
@@ -160,7 +154,9 @@ class ConsumedResultToEpilogueRetainMatcher {
160
154
// / Finds matching releases in the provided block \p BB.
161
155
void findMatchingRetains (SILBasicBlock *BB);
162
156
163
- RetainList getEpilogueRetains () { return EpilogueRetainInsts; }
157
+ ArrayRef<SILInstruction *> getEpilogueRetains () const {
158
+ return EpilogueRetainInsts;
159
+ }
164
160
165
161
// / Recompute the mapping from argument to consumed arg.
166
162
void recompute ();
@@ -182,6 +178,16 @@ class ConsumedResultToEpilogueRetainMatcher {
182
178
unsigned size () const { return EpilogueRetainInsts.size (); }
183
179
184
180
iterator_range<iterator> getRange () { return swift::make_range (begin (), end ()); }
181
+
182
+ private:
183
+ // / Return true if all the successors of the EpilogueRetainInsts do not have
184
+ // / a retain.
185
+ bool
186
+ isTransitiveSuccessorsRetainFree (const llvm::DenseSet<SILBasicBlock *> &BBs);
187
+
188
+ // / Finds matching releases in the provided block \p BB.
189
+ RetainKindValue findMatchingRetainsInBasicBlock (SILBasicBlock *BB,
190
+ SILValue V);
185
191
};
186
192
187
193
// / A class that attempts to match owned arguments and corresponding epilogue
@@ -197,40 +203,16 @@ class ConsumedArgToEpilogueReleaseMatcher {
197
203
RCIdentityFunctionInfo *RCFI;
198
204
ExitKind Kind;
199
205
ArrayRef<SILArgumentConvention> ArgumentConventions;
200
- llvm::SmallMapVector<SILArgument *, ReleaseList, 8 > ArgInstMap;
206
+
207
+ using InstListTy = TinyPtrVector<SILInstruction *>;
208
+ llvm::SmallMapVector<SILArgument *, InstListTy, 8 > ArgInstMap;
201
209
202
210
// / Set to true if we found some releases but not all for the argument.
203
211
llvm::DenseSet<SILArgument *> FoundSomeReleases;
204
212
205
213
// / Eventually this will be used in place of HasBlock.
206
214
SILBasicBlock *ProcessedBlock;
207
215
208
- // / Return true if we have seen releases to part or all of \p Derived in
209
- // / \p Insts.
210
- // /
211
- // / NOTE: This function relies on projections to analyze the relation
212
- // / between the releases values in \p Insts and \p Derived, it also bails
213
- // / out and return true if projection path can not be formed between Base
214
- // / and any one the released values.
215
- bool isRedundantRelease (ReleaseList Insts, SILValue Base, SILValue Derived);
216
-
217
- // / Return true if we have a release instruction for all the reference
218
- // / semantics part of \p Argument.
219
- bool releaseArgument (ReleaseList Insts, SILValue Argument);
220
-
221
- // / Walk the basic block and find all the releases that match to function
222
- // / arguments.
223
- void collectMatchingReleases (SILBasicBlock *BB);
224
-
225
- // / Walk the function and find all the destroy_addr instructions that match
226
- // / to function arguments.
227
- void collectMatchingDestroyAddresses (SILBasicBlock *BB);
228
-
229
- // / For every argument in the function, check to see whether all epilogue
230
- // / releases are found. Clear all releases for the argument if not all
231
- // / epilogue releases are found.
232
- void processMatchingReleases ();
233
-
234
216
public:
235
217
// / Finds matching releases in the return block of the function \p F.
236
218
ConsumedArgToEpilogueReleaseMatcher (
@@ -288,33 +270,32 @@ class ConsumedArgToEpilogueReleaseMatcher {
288
270
return getSingleReleaseForArgument (Arg);
289
271
}
290
272
291
- ReleaseList getReleasesForArgument (SILArgument *Arg) {
292
- ReleaseList Releases;
273
+ ArrayRef<SILInstruction *> getReleasesForArgument (SILArgument *Arg) {
293
274
auto I = ArgInstMap.find (Arg);
294
275
if (I == ArgInstMap.end ())
295
- return Releases ;
296
- return I->second ;
276
+ return {} ;
277
+ return I->second ;
297
278
}
298
279
299
- ReleaseList getReleasesForArgument (SILValue V) {
300
- ReleaseList Releases;
280
+ ArrayRef<SILInstruction *> getReleasesForArgument (SILValue V) {
301
281
auto *Arg = dyn_cast<SILArgument>(V);
302
282
if (!Arg)
303
- return Releases ;
283
+ return {} ;
304
284
return getReleasesForArgument (Arg);
305
285
}
306
286
307
287
// / Recompute the mapping from argument to consumed arg.
308
288
void recompute ();
309
289
310
290
bool isSingleReleaseMatchedToArgument (SILInstruction *Inst) {
311
- auto Pred = [&Inst](const std::pair<SILArgument *,
312
- ReleaseList> &P) -> bool {
313
- if (P.second .size () > 1 )
314
- return false ;
315
- return *P.second .begin () == Inst;
316
- };
317
- return count_if (ArgInstMap, Pred);
291
+ return count_if (
292
+ ArgInstMap,
293
+ [&Inst](const std::pair<SILArgument *, ArrayRef<SILInstruction *>> &P)
294
+ -> bool {
295
+ if (P.second .size () > 1 )
296
+ return false ;
297
+ return *P.second .begin () == Inst;
298
+ });
318
299
}
319
300
320
301
using iterator = decltype (ArgInstMap)::iterator;
@@ -334,6 +315,34 @@ class ConsumedArgToEpilogueReleaseMatcher {
334
315
unsigned size () const { return ArgInstMap.size (); }
335
316
336
317
iterator_range<iterator> getRange () { return swift::make_range (begin (), end ()); }
318
+
319
+ private:
320
+ // / Return true if we have seen releases to part or all of \p Derived in
321
+ // / \p Insts.
322
+ // /
323
+ // / NOTE: This function relies on projections to analyze the relation
324
+ // / between the releases values in \p Insts and \p Derived, it also bails
325
+ // / out and return true if projection path can not be formed between Base
326
+ // / and any one the released values.
327
+ bool isRedundantRelease (ArrayRef<SILInstruction *> Insts, SILValue Base,
328
+ SILValue Derived);
329
+
330
+ // / Return true if we have a release instruction for all the reference
331
+ // / semantics part of \p Argument.
332
+ bool releaseArgument (ArrayRef<SILInstruction *> Insts, SILValue Argument);
333
+
334
+ // / Walk the basic block and find all the releases that match to function
335
+ // / arguments.
336
+ void collectMatchingReleases (SILBasicBlock *BB);
337
+
338
+ // / Walk the function and find all the destroy_addr instructions that match
339
+ // / to function arguments.
340
+ void collectMatchingDestroyAddresses (SILBasicBlock *BB);
341
+
342
+ // / For every argument in the function, check to see whether all epilogue
343
+ // / releases are found. Clear all releases for the argument if not all
344
+ // / epilogue releases are found.
345
+ void processMatchingReleases ();
337
346
};
338
347
339
348
class ReleaseTracker {
0 commit comments