@@ -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
}
@@ -3211,57 +3281,6 @@ static bool usePrespecialized(
3211
3281
return false ;
3212
3282
}
3213
3283
3214
- static bool isUsedAsDynamicSelf (SILArgument *arg) {
3215
- for (Operand *use : arg->getUses ()) {
3216
- if (use->isTypeDependent ())
3217
- return true ;
3218
- }
3219
- return false ;
3220
- }
3221
-
3222
- static bool canDropMetatypeArgs (ApplySite apply, SILFunction *callee) {
3223
- if (!callee->isDefinition ())
3224
- return false ;
3225
-
3226
- auto calleeArgs = callee->getArguments ();
3227
- unsigned firstAppliedArgIdx = apply.getCalleeArgIndexOfFirstAppliedArg ();
3228
- for (unsigned calleeArgIdx = 0 ; calleeArgIdx < calleeArgs.size (); ++calleeArgIdx) {
3229
- SILArgument *calleeArg = calleeArgs[calleeArgIdx];
3230
- auto mt = calleeArg->getType ().getAs <MetatypeType>();
3231
- if (!mt)
3232
- continue ;
3233
-
3234
- if (isUsedAsDynamicSelf (calleeArg))
3235
- return false ;
3236
-
3237
- if (calleeArg->getType ().getASTType ()->hasDynamicSelfType ())
3238
- return false ;
3239
-
3240
- // We don't drop metatype arguments of not applied arguments (in case of `partial_apply`).
3241
- if (firstAppliedArgIdx > calleeArgIdx)
3242
- return false ;
3243
-
3244
- if (mt->hasRepresentation () && mt->getRepresentation () == MetatypeRepresentation::Thin)
3245
- continue ;
3246
-
3247
- // If the passed thick metatype value is not a `metatype` instruction
3248
- // we don't know the real metatype at runtime. It's not necessarily the
3249
- // same as the declared metatype. It could e.g. be an upcast of a class
3250
- // metatype.
3251
- SILValue callerArg = apply.getArguments ()[calleeArgIdx - firstAppliedArgIdx];
3252
- if (isa<MetatypeInst>(callerArg))
3253
- continue ;
3254
-
3255
- // But: if the metatype is not used in the callee we don't have to care
3256
- // what metatype value is passed. We can just remove it.
3257
- if (callee->isDefinition () && onlyHaveDebugUses (calleeArg))
3258
- continue ;
3259
-
3260
- return false ;
3261
- }
3262
- return true ;
3263
- }
3264
-
3265
3284
void swift::trySpecializeApplyOfGeneric (
3266
3285
SILOptFunctionBuilder &FuncBuilder,
3267
3286
ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -3314,8 +3333,7 @@ void swift::trySpecializeApplyOfGeneric(
3314
3333
FuncBuilder.getModule ().isWholeModule (), Apply, RefF,
3315
3334
Apply.getSubstitutionMap (), serializedKind,
3316
3335
/* ConvertIndirectToDirect=*/ true ,
3317
- /* dropUnusedArguments=*/
3318
- canDropMetatypeArgs (Apply, RefF),
3336
+ /* dropUnusedArguments=*/ true ,
3319
3337
&ORE);
3320
3338
if (!ReInfo.canBeSpecialized ())
3321
3339
return ;
0 commit comments