@@ -455,6 +455,82 @@ static bool shouldNotSpecialize(SILFunction *Callee, SILFunction *Caller,
455
455
return false ;
456
456
}
457
457
458
+ // Addressable parameters cannot be dropped because the address may
459
+ // escape. They also can't be promoted to direct convention, so there
460
+ // is no danger in preserving them.
461
+ static bool canConvertArg (CanSILFunctionType substType, unsigned paramIdx,
462
+ SILFunction *caller) {
463
+ return !substType->isAddressable (paramIdx, caller);
464
+ }
465
+
466
+ // If there is no read from an indirect argument, this argument has to be
467
+ // dropped. At the call site the store to the argument's memory location could
468
+ // have been removed (based on the callee's memory effects). Therefore,
469
+ // converting such an unused indirect argument to a direct argument, would load
470
+ // an uninitialized value at the call site. This would lead to verifier errors
471
+ // and in worst case to a miscompile because IRGen can implicitly use dead
472
+ // arguments, e.g. for getting the type of a class reference.
473
+ static bool canDropUnusedArg (ApplySite apply, SILFunction *callee,
474
+ CanSILFunctionType substType,
475
+ unsigned paramIdx) {
476
+ FullApplySite fas = apply.asFullApplySite ();
477
+ if (!fas) {
478
+ return false ;
479
+ }
480
+ Operand &op = fas.getOperandsWithoutIndirectResults ()[paramIdx];
481
+ return !callee->argumentMayRead (&op, op.get ());
482
+ }
483
+
484
+ static bool isUsedAsDynamicSelf (SILArgument *arg) {
485
+ for (Operand *use : arg->getUses ()) {
486
+ if (use->isTypeDependent ())
487
+ return true ;
488
+ }
489
+ return false ;
490
+ }
491
+
492
+ static bool canDropMetatypeArg (ApplySite apply, SILFunction *callee,
493
+ unsigned paramIdx) {
494
+ if (!callee->isDefinition ())
495
+ return false ;
496
+
497
+ unsigned calleeArgIdx =
498
+ apply.getSubstCalleeConv ().getSILArgIndexOfFirstParam () + paramIdx;
499
+ SILArgument *calleeArg = callee->getArguments ()[calleeArgIdx];
500
+
501
+ if (isUsedAsDynamicSelf (calleeArg))
502
+ return false ;
503
+
504
+ if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
505
+ return false ;
506
+
507
+ // We don't drop metatype arguments of not applied arguments (in case of
508
+ // `partial_apply`).
509
+ unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
510
+ if (firstAppliedArgIdx > calleeArgIdx)
511
+ return false ;
512
+
513
+ auto mt = calleeArg->getType ().castTo <MetatypeType>();
514
+ if (mt->hasRepresentation ()
515
+ && mt->getRepresentation () == MetatypeRepresentation::Thin) {
516
+ return true ;
517
+ }
518
+ // If the passed thick metatype value is not a `metatype` instruction
519
+ // we don't know the real metatype at runtime. It's not necessarily the
520
+ // same as the declared metatype. It could e.g. be an upcast of a class
521
+ // metatype.
522
+ SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
523
+ if (isa<MetatypeInst>(callerArg))
524
+ return true ;
525
+
526
+ // But: if the metatype is not used in the callee we don't have to care
527
+ // what metatype value is passed. We can just remove it.
528
+ if (onlyHaveDebugUses (calleeArg))
529
+ return true ;
530
+
531
+ return false ;
532
+ }
533
+
458
534
// / Prepares the ReabstractionInfo object for further processing and checks
459
535
// / if the current function can be specialized at all.
460
536
// / Returns false, if the current function cannot be specialized.
@@ -771,7 +847,7 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
771
847
for (SILParameterInfo PI : SubstitutedType->getParameters ()) {
772
848
auto IdxToInsert = IdxForParam;
773
849
++IdxForParam;
774
- unsigned argIdx = i++;
850
+ unsigned paramIdx = i++;
775
851
776
852
SILFunctionConventions substConv (SubstitutedType, getModule ());
777
853
TypeCategory tc = getParamTypeCategory (PI, substConv, getResilienceExpansion ());
@@ -782,22 +858,14 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
782
858
case ParameterConvention::Indirect_In_CXX:
783
859
case ParameterConvention::Indirect_In:
784
860
case ParameterConvention::Indirect_In_Guaranteed: {
785
- if (Callee && Apply && dropUnusedArguments) {
786
- // If there is no read from an indirect argument, this argument has to
787
- // be dropped. At the call site the store to the argument's memory location
788
- // could have been removed (based on the callee's memory effects).
789
- // Therefore, converting such an unused indirect argument to a direct
790
- // argument, would load an uninitialized value at the call site.
791
- // This would lead to verifier errors and in worst case to a miscompile
792
- // because IRGen can implicitly use dead arguments, e.g. for getting the
793
- // type of a class reference.
794
- if (FullApplySite fas = Apply.asFullApplySite ()) {
795
- Operand &op = fas.getOperandsWithoutIndirectResults ()[argIdx];
796
- if (!Callee->argumentMayRead (&op, op.get ())) {
797
- droppedArguments.set (IdxToInsert);
798
- break ;
799
- }
800
- }
861
+ if (Apply && !canConvertArg (SubstitutedType, paramIdx,
862
+ Apply.getFunction ())) {
863
+ continue ;
864
+ }
865
+ if (Callee && Apply && dropUnusedArguments
866
+ && canDropUnusedArg (Apply, Callee, SubstitutedType, paramIdx)) {
867
+ droppedArguments.set (IdxToInsert);
868
+ break ;
801
869
}
802
870
Conversions.set (IdxToInsert);
803
871
if (tc == LoadableAndTrivial)
@@ -822,8 +890,10 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
822
890
case ParameterConvention::Direct_Unowned:
823
891
case ParameterConvention::Direct_Guaranteed: {
824
892
CanType ty = PI.getInterfaceType ();
825
- if (dropUnusedArguments && isa<MetatypeType>(ty) && !ty->hasArchetype ())
893
+ if (dropUnusedArguments && isa<MetatypeType>(ty) && !ty->hasArchetype ()
894
+ && Apply && Callee && canDropMetatypeArg (Apply, Callee, paramIdx)) {
826
895
droppedArguments.set (IdxToInsert);
896
+ }
827
897
break ;
828
898
}
829
899
}
@@ -2916,7 +2986,8 @@ static bool createPrespecialized(StringRef UnspecializedName,
2916
2986
ReabstractionInfo ReInfo (M.getSwiftModule (), M.isWholeModule (), ApplySite (),
2917
2987
UnspecFunc, Apply.getSubstitutionMap (),
2918
2988
IsNotSerialized,
2919
- /* ConvertIndirectToDirect= */ true , /* dropMetatypeArgs=*/ false );
2989
+ /* ConvertIndirectToDirect= */ true ,
2990
+ /* dropUnusedArguments=*/ false );
2920
2991
2921
2992
if (!ReInfo.canBeSpecialized ())
2922
2993
return false ;
@@ -3005,7 +3076,7 @@ static bool usePrespecialized(
3005
3076
funcBuilder.getModule ().isWholeModule (), apply, refF,
3006
3077
apply.getSubstitutionMap (), IsNotSerialized,
3007
3078
/* ConvertIndirectToDirect=*/ true ,
3008
- /* dropMetatypeArgs =*/ false );
3079
+ /* dropUnusedArguments =*/ false );
3009
3080
3010
3081
for (auto *SA : refF->getSpecializeAttrs ()) {
3011
3082
if (!SA->isExported ())
@@ -3149,7 +3220,8 @@ static bool usePrespecialized(
3149
3220
funcBuilder.getModule ().getSwiftModule (),
3150
3221
funcBuilder.getModule ().isWholeModule (), apply, refF, newSubstMap,
3151
3222
apply.getFunction ()->getSerializedKind (),
3152
- /* ConvertIndirectToDirect=*/ true , /* dropMetatypeArgs=*/ false , nullptr );
3223
+ /* ConvertIndirectToDirect=*/ true ,
3224
+ /* dropUnusedArguments=*/ false , nullptr );
3153
3225
3154
3226
if (layoutReInfo.getSpecializedType () == reInfo.getSpecializedType ()) {
3155
3227
layoutMatches.push_back (
@@ -3209,57 +3281,6 @@ static bool usePrespecialized(
3209
3281
return false ;
3210
3282
}
3211
3283
3212
- static bool isUsedAsDynamicSelf (SILArgument *arg) {
3213
- for (Operand *use : arg->getUses ()) {
3214
- if (use->isTypeDependent ())
3215
- return true ;
3216
- }
3217
- return false ;
3218
- }
3219
-
3220
- static bool canDropMetatypeArgs (ApplySite apply, SILFunction *callee) {
3221
- if (!callee->isDefinition ())
3222
- return false ;
3223
-
3224
- auto calleeArgs = callee->getArguments ();
3225
- unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
3226
- for (unsigned calleeArgIdx = 0 ; calleeArgIdx < calleeArgs.size (); ++calleeArgIdx) {
3227
- SILArgument *calleeArg = calleeArgs[calleeArgIdx];
3228
- auto mt = calleeArg->getType ().getAs <MetatypeType>();
3229
- if (!mt)
3230
- continue ;
3231
-
3232
- if (isUsedAsDynamicSelf (calleeArg))
3233
- return false ;
3234
-
3235
- if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
3236
- return false ;
3237
-
3238
- // We don't drop metatype arguments of not applied arguments (in case of `partial_apply`).
3239
- if (firstAppliedArgIdx > calleeArgIdx)
3240
- return false ;
3241
-
3242
- if (mt->hasRepresentation () && mt->getRepresentation () == MetatypeRepresentation::Thin)
3243
- continue ;
3244
-
3245
- // If the passed thick metatype value is not a `metatype` instruction
3246
- // we don't know the real metatype at runtime. It's not necessarily the
3247
- // same as the declared metatype. It could e.g. be an upcast of a class
3248
- // metatype.
3249
- SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
3250
- if (isa<MetatypeInst>(callerArg))
3251
- continue ;
3252
-
3253
- // But: if the metatype is not used in the callee we don't have to care
3254
- // what metatype value is passed. We can just remove it.
3255
- if (callee->isDefinition () && onlyHaveDebugUses (calleeArg))
3256
- continue ;
3257
-
3258
- return false ;
3259
- }
3260
- return true ;
3261
- }
3262
-
3263
3284
void swift::trySpecializeApplyOfGeneric (
3264
3285
SILOptFunctionBuilder &FuncBuilder,
3265
3286
ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -3312,7 +3333,7 @@ void swift::trySpecializeApplyOfGeneric(
3312
3333
FuncBuilder.getModule ().isWholeModule (), Apply, RefF,
3313
3334
Apply.getSubstitutionMap (), serializedKind,
3314
3335
/* ConvertIndirectToDirect=*/ true ,
3315
- /* dropMetatypeArgs =*/ canDropMetatypeArgs (Apply, RefF) ,
3336
+ /* dropUnusedArguments =*/ true ,
3316
3337
&ORE);
3317
3338
if (!ReInfo.canBeSpecialized ())
3318
3339
return ;
0 commit comments