28
28
29
29
namespace swift {
30
30
31
+ using ReleaseSet = llvm::DenseSet<SILInstruction *>;
32
+
31
33
// / A structure that maintains all of the information about a specific
32
34
// / SILArgument that we are tracking.
33
35
struct ArgumentDescriptor {
36
+
34
37
// / The argument that we are tracking original data for.
35
38
SILArgument *Arg;
36
39
@@ -45,9 +48,6 @@ struct ArgumentDescriptor {
45
48
46
49
// / Should the argument be exploded ?
47
50
bool Explode;
48
-
49
- // / This parameter is owned to guaranteed.
50
- bool OwnedToGuaranteed;
51
51
52
52
// / Is this parameter an indirect result?
53
53
bool IsIndirectResult;
@@ -73,13 +73,17 @@ struct ArgumentDescriptor {
73
73
// / to the original argument. The reason why we do this is to make sure we
74
74
// / have access to the original argument's state if we modify the argument
75
75
// / when optimizing.
76
- ArgumentDescriptor (llvm::BumpPtrAllocator &BPA, SILArgument *A)
76
+ ArgumentDescriptor (llvm::BumpPtrAllocator &BPA, SILArgument *A,
77
+ ReleaseSet Releases)
77
78
: Arg(A), Index(A->getIndex ()),
78
79
Decl(A->getDecl ()), IsEntirelyDead(false ), Explode(false ),
79
- OwnedToGuaranteed(false ),
80
80
IsIndirectResult(A->isIndirectResult ()),
81
81
CalleeRelease(), CalleeReleaseInThrowBlock(),
82
- ProjTree(A->getModule (), BPA, A->getType()) {}
82
+ ProjTree(A->getModule (), BPA, A->getType(),
83
+ ProjectionTreeNode::LivenessKind::IgnoreEpilogueReleases,
84
+ Releases) {
85
+ ProjTree.computeUsesAndLiveness (A);
86
+ }
83
87
84
88
ArgumentDescriptor (const ArgumentDescriptor &) = delete;
85
89
ArgumentDescriptor (ArgumentDescriptor &&) = default;
@@ -91,6 +95,29 @@ struct ArgumentDescriptor {
91
95
return Arg->hasConvention (P);
92
96
}
93
97
98
+ // / Convert the potentially multiple interface params associated with this
99
+ // / argument.
100
+ void
101
+ computeOptimizedInterfaceParams (SmallVectorImpl<SILParameterInfo> &Out) const ;
102
+
103
+ // / Add potentially multiple new arguments to NewArgs from the caller's apply
104
+ // / or try_apply inst.
105
+ void addCallerArgs (SILBuilder &Builder, FullApplySite FAS,
106
+ SmallVectorImpl<SILValue> &NewArgs) const ;
107
+
108
+ // / Add potentially multiple new arguments to NewArgs from the thunk's
109
+ // / function arguments.
110
+ void addThunkArgs (SILBuilder &Builder, SILBasicBlock *BB,
111
+ SmallVectorImpl<SILValue> &NewArgs) const ;
112
+
113
+ // / Optimize the argument at ArgOffset and return the index of the next
114
+ // / argument to be optimized.
115
+ // /
116
+ // / The return value makes it easy to SROA arguments since we can return the
117
+ // / amount of SROAed arguments we created.
118
+ unsigned updateOptimizedBBArgs (SILBuilder &Builder, SILBasicBlock *BB,
119
+ unsigned ArgOffset);
120
+
94
121
bool canOptimizeLiveArg () const {
95
122
return Arg->getType ().isObject ();
96
123
}
@@ -123,19 +150,15 @@ struct ResultDescriptor {
123
150
// / @owned or we could not find such a release in the callee, this is null.
124
151
RetainList CalleeRetain;
125
152
126
- // / This is owned to guaranteed.
127
- bool OwnedToGuaranteed;
128
-
129
153
// / Initialize this argument descriptor with all information from A that we
130
154
// / use in our optimization.
131
155
// /
132
156
// / *NOTE* We cache a lot of data from the argument and maintain a reference
133
157
// / to the original argument. The reason why we do this is to make sure we
134
158
// / have access to the original argument's state if we modify the argument
135
159
// / when optimizing.
136
- ResultDescriptor () {}
137
- ResultDescriptor (SILResultInfo RI)
138
- : ResultInfo(RI), CalleeRetain(), OwnedToGuaranteed(false ) {}
160
+ ResultDescriptor () {};
161
+ ResultDescriptor (SILResultInfo RI) : ResultInfo(RI), CalleeRetain() {}
139
162
140
163
ResultDescriptor (const ResultDescriptor &) = delete ;
141
164
ResultDescriptor (ResultDescriptor &&) = default ;
@@ -148,12 +171,100 @@ struct ResultDescriptor {
148
171
}
149
172
};
150
173
151
- // / Returns true if F is a function which the pass know show to specialize
152
- // / function signatures for.
174
+ class FunctionSignatureInfo {
175
+ // / Should this function be optimized.
176
+ bool ShouldOptimize;
177
+
178
+ // / Optimizing this function may lead to good performance potential.
179
+ bool HighlyProfitable;
180
+
181
+ // / Function currently analyzing.
182
+ SILFunction *F;
183
+
184
+ // / The allocator we are using.
185
+ llvm::BumpPtrAllocator &Allocator;
186
+
187
+ // / The alias analysis currently using.
188
+ AliasAnalysis *AA;
189
+
190
+ // / The rc-identity analysis currently using.
191
+ RCIdentityFunctionInfo *RCFI;
192
+
193
+ // / Does any call inside the given function may bind dynamic 'Self' to a
194
+ // / generic argument of the callee.
195
+ bool MayBindDynamicSelf;
196
+
197
+ // / Did we decide to change the self argument? If so we need to
198
+ // / change the calling convention 'method' to 'freestanding'.
199
+ bool ShouldModifySelfArgument = false ;
200
+
201
+ // / A list of structures which present a "view" of precompiled information on
202
+ // / an argument that we will use during our optimization.
203
+ llvm::SmallVector<ArgumentDescriptor, 8 > ArgDescList;
204
+
205
+ // / Keep a "view" of precompiled information on the direct results
206
+ // / which we will use during our optimization.
207
+ llvm::SmallVector<ResultDescriptor, 4 > ResultDescList;
208
+
209
+
210
+ public:
211
+ FunctionSignatureInfo (SILFunction *F, llvm::BumpPtrAllocator &BPA,
212
+ AliasAnalysis *AA, RCIdentityFunctionInfo *RCFI) :
213
+ ShouldOptimize (false ), HighlyProfitable(false ), F(F), Allocator(BPA),
214
+ AA (AA), RCFI(RCFI), MayBindDynamicSelf(computeMayBindDynamicSelf(F)) {
215
+ analyze ();
216
+ }
217
+
218
+ bool shouldOptimize () const { return ShouldOptimize; }
219
+ bool profitableOptimize () const { return HighlyProfitable; }
220
+
221
+ void analyze ();
222
+ bool analyzeParameters ();
223
+ bool analyzeResult ();
224
+
225
+ // / Returns the mangled name of the function that should be generated from
226
+ // / this function analyzer.
227
+ std::string getOptimizedName () const ;
228
+
229
+ bool shouldModifySelfArgument () const { return ShouldModifySelfArgument; }
230
+ ArrayRef<ArgumentDescriptor> getArgDescList () const { return ArgDescList; }
231
+ ArrayRef<ResultDescriptor> getResultDescList () {return ResultDescList;}
232
+ SILFunction *getAnalyzedFunction () const { return F; }
233
+
234
+ private:
235
+ // / Is the given argument required by the ABI?
236
+ // /
237
+ // / Metadata arguments may be required if dynamic Self is bound to any generic
238
+ // / parameters within this function's call sites.
239
+ bool isArgumentABIRequired (SILArgument *Arg) {
240
+ // This implicitly asserts that a function binding dynamic self has a self
241
+ // metadata argument or object from which self metadata can be obtained.
242
+ return MayBindDynamicSelf && (F->getSelfMetadataArgument () == Arg);
243
+ }
244
+ };
245
+
246
+
247
+
153
248
bool canSpecializeFunction (SILFunction *F);
154
249
155
- // / Return true if this argument is used in a non-trivial way.
156
- bool hasNonTrivialNonDebugUse (SILArgument *Arg);
250
+ void
251
+ addReleasesForConvertedOwnedParameter (SILBuilder &Builder,
252
+ SILLocation Loc,
253
+ OperandValueArrayRef Parameters,
254
+ ArrayRef<ArgumentDescriptor> &ArgDescs);
255
+
256
+ void
257
+ addReleasesForConvertedOwnedParameter (SILBuilder &Builder,
258
+ SILLocation Loc,
259
+ ArrayRef<SILArgument*> Parameters,
260
+ ArrayRef<ArgumentDescriptor> &ArgDescs);
261
+ void
262
+ addRetainsForConvertedDirectResults (SILBuilder &Builder,
263
+ SILLocation Loc,
264
+ SILValue ReturnValue,
265
+ SILInstruction *AI,
266
+ ArrayRef<ResultDescriptor> DirectResults);
267
+
157
268
158
269
} // end namespace swift
159
270
0 commit comments