@@ -165,17 +165,10 @@ class FunctionSignatureTransform {
165
165
void OwnedToGuaranteedTransformFunctionParameters ();
166
166
167
167
// / Find any owned to guaranteed opportunities.
168
- bool OwnedToGuaranteedAnalyze () {
169
- bool Result = OwnedToGuaranteedAnalyzeResults ();
170
- bool Params = OwnedToGuaranteedAnalyzeParameters ();
171
- return Params || Result;
172
- }
168
+ bool OwnedToGuaranteedAnalyze ();
173
169
174
170
// / Do the actual owned to guaranteed transformations.
175
- void OwnedToGuaranteedTransform () {
176
- OwnedToGuaranteedTransformFunctionResults ();
177
- OwnedToGuaranteedTransformFunctionParameters ();
178
- }
171
+ void OwnedToGuaranteedTransform ();
179
172
180
173
// / Set up epilogue work for the thunk result based in the given argument.
181
174
void OwnedToGuaranteedAddResultRelease (ResultDescriptor &RD,
@@ -203,25 +196,8 @@ class FunctionSignatureTransform {
203
196
// / Every transformation must defines this interface. Default implementation
204
197
// / simply passes it through.
205
198
void addThunkArgument (ArgumentDescriptor &AD, SILBuilder &Builder,
206
- SILBasicBlock *BB,
207
- llvm::SmallVectorImpl<SILValue> &NewArgs) {
208
- // Dead argument.
209
- if (AD.IsEntirelyDead ) {
210
- return ;
211
- }
212
-
213
- // Explode the argument.
214
- if (AD.Explode ) {
215
- llvm::SmallVector<SILValue, 4 > LeafValues;
216
- AD.ProjTree .createTreeFromValue (Builder, BB->getParent ()->getLocation (),
217
- BB->getArgument (AD.Index ), LeafValues);
218
- NewArgs.append (LeafValues.begin (), LeafValues.end ());
219
- return ;
220
- }
221
-
222
- // All other arguments get pushed as what they are.
223
- NewArgs.push_back (BB->getArgument (AD.Index ));
224
- }
199
+ SILBasicBlock *BB,
200
+ llvm::SmallVectorImpl<SILValue> &NewArgs);
225
201
226
202
// / Take ArgumentDescList and ResultDescList and create an optimized function
227
203
// / based on the current function we are analyzing. This also has the side effect
@@ -247,105 +223,35 @@ class FunctionSignatureTransform {
247
223
}
248
224
249
225
// / Run the optimization.
250
- bool run (bool hasCaller) {
251
- bool Changed = false ;
252
- SILFunction *F = TransformDescriptor.OriginalFunction ;
253
-
254
- if (!hasCaller && canBeCalledIndirectly (F->getRepresentation ())) {
255
- DEBUG (llvm::dbgs () << " function has no caller -> abort\n " );
256
- return false ;
257
- }
258
-
259
- // Run OwnedToGuaranteed optimization.
260
- if (OwnedToGuaranteedAnalyze ()) {
261
- Changed = true ;
262
- DEBUG (llvm::dbgs () << " transform owned-to-guaranteed\n " );
263
- OwnedToGuaranteedTransform ();
264
- }
265
-
266
- // Run DeadArgument elimination transformation. We only specialize
267
- // if this function has a caller inside the current module or we have
268
- // already created a thunk.
269
- if ((hasCaller || Changed) && DeadArgumentAnalyzeParameters ()) {
270
- Changed = true ;
271
- DEBUG (llvm::dbgs () << " remove dead arguments\n " );
272
- DeadArgumentTransformFunction ();
273
- }
274
-
275
- // Run ArgumentExplosion transformation. We only specialize
276
- // if this function has a caller inside the current module or we have
277
- // already created a thunk.
278
- //
279
- // NOTE: we run argument explosion last because we've already initialized
280
- // the ArgumentDescList to have unexploded number of arguments. Exploding
281
- // it without changing the argument count is not going to help with
282
- // owned-to-guaranteed transformation.
283
- //
284
- // In order to not miss any opportunity, we send the optimized function
285
- // to the passmanager to optimize any opportunities exposed by argument
286
- // explosion.
287
- if ((hasCaller || Changed) && ArgumentExplosionAnalyzeParameters ()) {
288
- Changed = true ;
289
- }
290
-
291
- // Check if generic signature of the function could be changed by
292
- // removed some unused generic arguments.
293
- if (F->getLoweredFunctionType ()->isPolymorphic () &&
294
- createOptimizedSILFunctionType () != F->getLoweredFunctionType ()) {
295
- Changed = true ;
296
- }
297
-
298
- // Create the specialized function and invalidate the old function.
299
- if (Changed) {
300
- createFunctionSignatureOptimizedFunction ();
301
- }
302
- return Changed;
303
- }
226
+ bool run (bool hasCaller);
304
227
305
228
// / Run dead argument elimination of partially applied functions.
229
+ // /
306
230
// / After this optimization CapturePropagation can replace the partial_apply
307
231
// / by a direct reference to the specialized function.
308
- bool removeDeadArgs (int minPartialAppliedArgs) {
309
- if (minPartialAppliedArgs < 1 )
310
- return false ;
311
-
312
- if (!DeadArgumentAnalyzeParameters ())
313
- return false ;
314
-
315
- SILFunction *F = TransformDescriptor.OriginalFunction ;
316
- auto ArgumentDescList = TransformDescriptor.ArgumentDescList ;
317
-
318
- // Check if at least the minimum number of partially applied arguments
319
- // are dead. Otherwise no partial_apply can be removed anyway.
320
- unsigned Size = ArgumentDescList.size ();
321
- for (unsigned Idx : range (Size)) {
322
- if (Idx < Size - minPartialAppliedArgs) {
323
- // Don't remove arguments other than the partial applied ones, even if
324
- // they are dead.
325
- ArgumentDescList[Idx].IsEntirelyDead = false ;
326
- continue ;
327
- }
328
-
329
- // Is the partially applied argument dead?
330
- if (!ArgumentDescList[Idx].IsEntirelyDead )
331
- return false ;
232
+ bool removeDeadArgs (int minPartialAppliedArgs);
233
+ };
332
234
333
- // Currently we require that all dead parameters have trivial types. The
334
- // reason is that it's very hard to find places where we can release those
335
- // parameters (as a replacement for the removed partial_apply).
336
- //
337
- // TODO: Maybe we can skip this restriction when we have semantic ARC.
338
- if (ArgumentDescList[Idx].Arg ->getType ().isTrivial (F->getModule ()))
339
- continue ;
340
- return false ;
341
- }
235
+ void FunctionSignatureTransform::addThunkArgument (
236
+ ArgumentDescriptor &AD, SILBuilder &Builder, SILBasicBlock *BB,
237
+ llvm::SmallVectorImpl<SILValue> &NewArgs) {
238
+ // Dead argument.
239
+ if (AD.IsEntirelyDead ) {
240
+ return ;
241
+ }
342
242
343
- DEBUG (llvm::dbgs () << " remove dead arguments for partial_apply\n " );
344
- DeadArgumentTransformFunction ();
345
- createFunctionSignatureOptimizedFunction ();
346
- return true ;
243
+ // Explode the argument.
244
+ if (AD.Explode ) {
245
+ llvm::SmallVector<SILValue, 4 > LeafValues;
246
+ AD.ProjTree .createTreeFromValue (Builder, BB->getParent ()->getLocation (),
247
+ BB->getArgument (AD.Index ), LeafValues);
248
+ NewArgs.append (LeafValues.begin (), LeafValues.end ());
249
+ return ;
347
250
}
348
- };
251
+
252
+ // All other arguments get pushed as what they are.
253
+ NewArgs.push_back (BB->getArgument (AD.Index ));
254
+ }
349
255
350
256
} // end anonymous namespace
351
257
@@ -798,6 +704,107 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
798
704
assert (F->getDebugScope ()->Parent != NewF->getDebugScope ()->Parent );
799
705
}
800
706
707
+ // Run the optimization.
708
+ bool FunctionSignatureTransform::run (bool hasCaller) {
709
+ bool Changed = false ;
710
+ SILFunction *F = TransformDescriptor.OriginalFunction ;
711
+
712
+ if (!hasCaller && canBeCalledIndirectly (F->getRepresentation ())) {
713
+ DEBUG (llvm::dbgs () << " function has no caller -> abort\n " );
714
+ return false ;
715
+ }
716
+
717
+ // Run OwnedToGuaranteed optimization.
718
+ if (OwnedToGuaranteedAnalyze ()) {
719
+ Changed = true ;
720
+ DEBUG (llvm::dbgs () << " transform owned-to-guaranteed\n " );
721
+ OwnedToGuaranteedTransform ();
722
+ }
723
+
724
+ // Run DeadArgument elimination transformation. We only specialize
725
+ // if this function has a caller inside the current module or we have
726
+ // already created a thunk.
727
+ if ((hasCaller || Changed) && DeadArgumentAnalyzeParameters ()) {
728
+ Changed = true ;
729
+ DEBUG (llvm::dbgs () << " remove dead arguments\n " );
730
+ DeadArgumentTransformFunction ();
731
+ }
732
+
733
+ // Run ArgumentExplosion transformation. We only specialize
734
+ // if this function has a caller inside the current module or we have
735
+ // already created a thunk.
736
+ //
737
+ // NOTE: we run argument explosion last because we've already initialized
738
+ // the ArgumentDescList to have unexploded number of arguments. Exploding
739
+ // it without changing the argument count is not going to help with
740
+ // owned-to-guaranteed transformation.
741
+ //
742
+ // In order to not miss any opportunity, we send the optimized function
743
+ // to the passmanager to optimize any opportunities exposed by argument
744
+ // explosion.
745
+ if ((hasCaller || Changed) && ArgumentExplosionAnalyzeParameters ()) {
746
+ Changed = true ;
747
+ }
748
+
749
+ // Check if generic signature of the function could be changed by
750
+ // removed some unused generic arguments.
751
+ if (F->getLoweredFunctionType ()->isPolymorphic () &&
752
+ createOptimizedSILFunctionType () != F->getLoweredFunctionType ()) {
753
+ Changed = true ;
754
+ }
755
+
756
+ // Create the specialized function and invalidate the old function.
757
+ if (Changed) {
758
+ createFunctionSignatureOptimizedFunction ();
759
+ }
760
+ return Changed;
761
+ }
762
+
763
+ // Run dead argument elimination of partially applied functions.
764
+ //
765
+ // After this optimization CapturePropagation can replace the partial_apply by a
766
+ // direct reference to the specialized function.
767
+ bool FunctionSignatureTransform::removeDeadArgs (int minPartialAppliedArgs) {
768
+ if (minPartialAppliedArgs < 1 )
769
+ return false ;
770
+
771
+ if (!DeadArgumentAnalyzeParameters ())
772
+ return false ;
773
+
774
+ SILFunction *F = TransformDescriptor.OriginalFunction ;
775
+ auto ArgumentDescList = TransformDescriptor.ArgumentDescList ;
776
+
777
+ // Check if at least the minimum number of partially applied arguments
778
+ // are dead. Otherwise no partial_apply can be removed anyway.
779
+ unsigned Size = ArgumentDescList.size ();
780
+ for (unsigned Idx : range (Size)) {
781
+ if (Idx < Size - minPartialAppliedArgs) {
782
+ // Don't remove arguments other than the partial applied ones, even if
783
+ // they are dead.
784
+ ArgumentDescList[Idx].IsEntirelyDead = false ;
785
+ continue ;
786
+ }
787
+
788
+ // Is the partially applied argument dead?
789
+ if (!ArgumentDescList[Idx].IsEntirelyDead )
790
+ return false ;
791
+
792
+ // Currently we require that all dead parameters have trivial types. The
793
+ // reason is that it's very hard to find places where we can release those
794
+ // parameters (as a replacement for the removed partial_apply).
795
+ //
796
+ // TODO: Maybe we can skip this restriction when we have semantic ARC.
797
+ if (ArgumentDescList[Idx].Arg ->getType ().isTrivial (F->getModule ()))
798
+ continue ;
799
+ return false ;
800
+ }
801
+
802
+ DEBUG (llvm::dbgs () << " remove dead arguments for partial_apply\n " );
803
+ DeadArgumentTransformFunction ();
804
+ createFunctionSignatureOptimizedFunction ();
805
+ return true ;
806
+ }
807
+
801
808
// ===----------------------------------------------------------------------===//
802
809
// Dead Argument Elimination
803
810
// ===----------------------------------------------------------------------===//
@@ -1084,6 +1091,17 @@ OwnedToGuaranteedAddResultRelease(ResultDescriptor &RD, SILBuilder &Builder,
1084
1091
}
1085
1092
}
1086
1093
1094
+ bool FunctionSignatureTransform::OwnedToGuaranteedAnalyze () {
1095
+ bool Result = OwnedToGuaranteedAnalyzeResults ();
1096
+ bool Params = OwnedToGuaranteedAnalyzeParameters ();
1097
+ return Params || Result;
1098
+ }
1099
+
1100
+ void FunctionSignatureTransform::OwnedToGuaranteedTransform () {
1101
+ OwnedToGuaranteedTransformFunctionResults ();
1102
+ OwnedToGuaranteedTransformFunctionParameters ();
1103
+ }
1104
+
1087
1105
// ===----------------------------------------------------------------------===//
1088
1106
// Argument Explosion Transformation
1089
1107
// ===----------------------------------------------------------------------===//
0 commit comments