@@ -997,6 +997,35 @@ ReabstractionInfo::createSubstitutedType(SILFunction *OrigF,
997
997
return NewFnTy;
998
998
}
999
999
1000
+ CanSILFunctionType ReabstractionInfo::createThunkType (PartialApplyInst *forPAI) const {
1001
+ if (!hasDroppedMetatypeArgs ())
1002
+ return SubstitutedType;
1003
+
1004
+ llvm::SmallVector<SILParameterInfo, 8 > newParams;
1005
+ auto params = SubstitutedType->getParameters ();
1006
+ unsigned firstAppliedParamIdx = params.size () - forPAI->getArguments ().size ();
1007
+
1008
+ for (unsigned paramIdx = 0 ; paramIdx < params.size (); ++paramIdx) {
1009
+ if (paramIdx >= firstAppliedParamIdx && isDroppedMetatypeArg (param2ArgIndex (paramIdx)))
1010
+ continue ;
1011
+ newParams.push_back (params[paramIdx]);
1012
+ }
1013
+
1014
+ auto newFnTy = SILFunctionType::get (
1015
+ SubstitutedType->getInvocationGenericSignature (),
1016
+ SubstitutedType->getExtInfo (), SubstitutedType->getCoroutineKind (),
1017
+ SubstitutedType->getCalleeConvention (), newParams,
1018
+ SubstitutedType->getYields (), SubstitutedType->getResults (),
1019
+ SubstitutedType->getOptionalErrorResult (),
1020
+ SubstitutedType->getPatternSubstitutions (), SubstitutionMap (),
1021
+ SubstitutedType->getASTContext (),
1022
+ SubstitutedType->getWitnessMethodConformanceOrInvalid ());
1023
+
1024
+ // This is an interface type. It should not have any archetypes.
1025
+ assert (!newFnTy->hasArchetype ());
1026
+ return newFnTy;
1027
+ }
1028
+
1000
1029
// / Convert the substituted function type into a specialized function type based
1001
1030
// / on the ReabstractionInfo.
1002
1031
CanSILFunctionType ReabstractionInfo::
@@ -1067,8 +1096,10 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
1067
1096
: CanGenericSignature ();
1068
1097
1069
1098
SILFunctionType::ExtInfo extInfo = SubstFTy->getExtInfo ();
1099
+ ProtocolConformanceRef conf = SubstFTy->getWitnessMethodConformanceOrInvalid ();
1070
1100
if (extInfo.hasSelfParam () && removedSelfParam) {
1071
1101
extInfo = extInfo.withRepresentation (SILFunctionTypeRepresentation::Thin);
1102
+ conf = ProtocolConformanceRef ();
1072
1103
assert (!extInfo.hasSelfParam ());
1073
1104
}
1074
1105
@@ -1077,7 +1108,7 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
1077
1108
SubstFTy->getCoroutineKind (), SubstFTy->getCalleeConvention (),
1078
1109
SpecializedParams, SpecializedYields, SpecializedResults,
1079
1110
SubstFTy->getOptionalErrorResult (), SubstitutionMap (), SubstitutionMap (),
1080
- M.getASTContext (), SubstFTy-> getWitnessMethodConformanceOrInvalid () );
1111
+ M.getASTContext (), conf );
1081
1112
}
1082
1113
1083
1114
// / Create a new generic signature from an existing one by adding
@@ -2546,14 +2577,16 @@ class ReabstractionThunkGenerator {
2546
2577
protected:
2547
2578
FullApplySite createReabstractionThunkApply (SILBuilder &Builder);
2548
2579
SILArgument *convertReabstractionThunkArguments (
2549
- SILBuilder &Builder, SmallVectorImpl<unsigned > &ArgsNeedingEndBorrows);
2580
+ SILBuilder &Builder, SmallVectorImpl<unsigned > &ArgsNeedingEndBorrows,
2581
+ CanSILFunctionType thunkType);
2550
2582
};
2551
2583
2552
2584
} // anonymous namespace
2553
2585
2554
2586
SILFunction *ReabstractionThunkGenerator::createThunk () {
2587
+ CanSILFunctionType thunkType = ReInfo.createThunkType (OrigPAI);
2555
2588
SILFunction *Thunk = FunctionBuilder.getOrCreateSharedFunction (
2556
- Loc, ThunkName, ReInfo. getSubstitutedType () , IsBare, IsTransparent,
2589
+ Loc, ThunkName, thunkType , IsBare, IsTransparent,
2557
2590
ReInfo.isSerialized (), ProfileCounter (), IsThunk, IsNotDynamic,
2558
2591
IsNotDistributed, IsNotRuntimeAccessible);
2559
2592
// Re-use an existing thunk.
@@ -2594,7 +2627,7 @@ SILFunction *ReabstractionThunkGenerator::createThunk() {
2594
2627
// Handle lowered addresses.
2595
2628
SmallVector<unsigned , 4 > ArgsThatNeedEndBorrow;
2596
2629
SILArgument *ReturnValueAddr =
2597
- convertReabstractionThunkArguments (Builder, ArgsThatNeedEndBorrow);
2630
+ convertReabstractionThunkArguments (Builder, ArgsThatNeedEndBorrow, thunkType );
2598
2631
2599
2632
FullApplySite ApplySite = createReabstractionThunkApply (Builder);
2600
2633
@@ -2650,50 +2683,50 @@ FullApplySite ReabstractionThunkGenerator::createReabstractionThunkApply(
2650
2683
return FullApplySite (TAI);
2651
2684
}
2652
2685
2686
+ static SILFunctionArgument *addFunctionArgument (SILFunction *function,
2687
+ SILType argType,
2688
+ SILArgument *copyAttributesFrom) {
2689
+ SILBasicBlock *entryBB = function->getEntryBlock ();
2690
+ auto *src = cast<SILFunctionArgument>(copyAttributesFrom);
2691
+ auto *arg = entryBB->createFunctionArgument (argType, src->getDecl ());
2692
+ arg->setNoImplicitCopy (src->isNoImplicitCopy ());
2693
+ arg->setLifetimeAnnotation (src->getLifetimeAnnotation ());
2694
+ arg->setClosureCapture (src->isClosureCapture ());
2695
+ return arg;
2696
+ }
2697
+
2653
2698
// / Create SIL arguments for a reabstraction thunk with lowered addresses. This
2654
2699
// / may involve replacing indirect arguments with loads and stores. Return the
2655
2700
// / SILArgument for the address of an indirect result, or nullptr.
2656
2701
// /
2657
2702
// / FIXME: Remove this if we don't need to create reabstraction thunks after
2658
2703
// / address lowering.
2659
2704
SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments (
2660
- SILBuilder &Builder, SmallVectorImpl<unsigned > &ArgsThatNeedEndBorrow) {
2705
+ SILBuilder &Builder, SmallVectorImpl<unsigned > &ArgsThatNeedEndBorrow,
2706
+ CanSILFunctionType thunkType
2707
+ ) {
2661
2708
SILFunction *Thunk = &Builder.getFunction ();
2662
2709
CanSILFunctionType SpecType = SpecializedFunc->getLoweredFunctionType ();
2663
- CanSILFunctionType SubstType = ReInfo.getSubstitutedType ();
2664
2710
auto specConv = SpecializedFunc->getConventions ();
2665
2711
(void )specConv;
2666
- SILFunctionConventions substConv (SubstType , M);
2712
+ SILFunctionConventions substConv (thunkType , M);
2667
2713
2668
2714
assert (specConv.useLoweredAddresses ());
2669
2715
2670
2716
// ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
2671
2717
// results. SpecTy may have fewer formal indirect results.
2672
- assert (SubstType ->getNumIndirectFormalResults ()
2718
+ assert (thunkType ->getNumIndirectFormalResults ()
2673
2719
>= SpecType->getNumIndirectFormalResults ());
2674
2720
2675
- SILBasicBlock *EntryBB = Thunk->getEntryBlock ();
2676
2721
SILArgument *ReturnValueAddr = nullptr ;
2677
2722
auto SpecArgIter = SpecializedFunc->getArguments ().begin ();
2678
- auto cloneSpecializedArgument = [&]() {
2679
- // No change to the argument.
2680
- SILArgument *SpecArg = *SpecArgIter++;
2681
- auto *NewArg =
2682
- EntryBB->createFunctionArgument (SpecArg->getType (), SpecArg->getDecl ());
2683
- NewArg->setNoImplicitCopy (
2684
- cast<SILFunctionArgument>(SpecArg)->isNoImplicitCopy ());
2685
- NewArg->setLifetimeAnnotation (
2686
- cast<SILFunctionArgument>(SpecArg)->getLifetimeAnnotation ());
2687
- NewArg->setClosureCapture (
2688
- cast<SILFunctionArgument>(SpecArg)->isClosureCapture ());
2689
- Arguments.push_back (NewArg);
2690
- };
2723
+
2691
2724
// ReInfo.NumIndirectResults corresponds to SubstTy's formal indirect
2692
2725
// results. SpecTy may have fewer formal indirect results.
2693
- assert (SubstType ->getNumIndirectFormalResults ()
2726
+ assert (thunkType ->getNumIndirectFormalResults ()
2694
2727
>= SpecType->getNumIndirectFormalResults ());
2695
2728
unsigned resultIdx = 0 ;
2696
- for (auto substRI : SubstType ->getIndirectFormalResults ()) {
2729
+ for (auto substRI : thunkType ->getIndirectFormalResults ()) {
2697
2730
if (ReInfo.isFormalResultConverted (resultIdx++)) {
2698
2731
// Convert an originally indirect to direct specialized result.
2699
2732
// Store the result later.
@@ -2703,36 +2736,42 @@ SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
2703
2736
substConv.getSILType (substRI, Builder.getTypeExpansionContext ()));
2704
2737
assert (ResultTy.isAddress ());
2705
2738
assert (!ReturnValueAddr);
2706
- ReturnValueAddr = EntryBB ->createFunctionArgument (ResultTy);
2739
+ ReturnValueAddr = Thunk-> getEntryBlock () ->createFunctionArgument (ResultTy);
2707
2740
continue ;
2708
2741
}
2709
2742
// If the specialized result is already indirect, simply clone the indirect
2710
2743
// result argument.
2711
- assert ((*SpecArgIter)->getType ().isAddress ());
2712
- cloneSpecializedArgument ();
2744
+ SILArgument *specArg = *SpecArgIter++;
2745
+ assert (specArg->getType ().isAddress ());
2746
+ Arguments.push_back (addFunctionArgument (Thunk, specArg->getType (), specArg));
2713
2747
}
2714
2748
assert (SpecArgIter
2715
2749
== SpecializedFunc->getArgumentsWithoutIndirectResults ().begin ());
2716
2750
unsigned numParams = SpecType->getNumParameters ();
2717
- assert (numParams == SubstType ->getNumParameters ());
2751
+ assert (numParams == thunkType ->getNumParameters ());
2718
2752
for (unsigned paramIdx = 0 ; paramIdx < numParams; ++paramIdx) {
2753
+ if (ReInfo.isDroppedMetatypeArg (paramIdx)) {
2754
+ if (paramIdx < ApplySite (OrigPAI).getCalleeArgIndexOfFirstAppliedArg ()) {
2755
+ // Only if the dropped metatype argument is not applied by the `partial_apply`,
2756
+ // we need to add it to the thunk.
2757
+ SILType ParamTy = SpecializedFunc->mapTypeIntoContext (
2758
+ substConv.getSILType (thunkType->getParameters ()[paramIdx],
2759
+ Builder.getTypeExpansionContext ()));
2760
+ SILArgument *origArg = OrigF->getArgumentsWithoutIndirectResults ()[paramIdx];
2761
+ addFunctionArgument (Thunk, ParamTy, origArg);
2762
+ }
2763
+ continue ;
2764
+ }
2765
+ SILArgument *specArg = *SpecArgIter++;
2719
2766
if (ReInfo.isParamConverted (paramIdx)) {
2720
2767
// Convert an originally indirect to direct specialized parameter.
2721
2768
assert (!specConv.isSILIndirect (SpecType->getParameters ()[paramIdx]));
2722
2769
// Instead of passing the address, pass the loaded value.
2723
2770
SILType ParamTy = SpecializedFunc->mapTypeIntoContext (
2724
- substConv.getSILType (SubstType ->getParameters ()[paramIdx],
2771
+ substConv.getSILType (thunkType ->getParameters ()[paramIdx],
2725
2772
Builder.getTypeExpansionContext ()));
2726
2773
assert (ParamTy.isAddress ());
2727
- SILArgument *SpecArg = *SpecArgIter++;
2728
- SILFunctionArgument *NewArg =
2729
- EntryBB->createFunctionArgument (ParamTy, SpecArg->getDecl ());
2730
- NewArg->setNoImplicitCopy (
2731
- cast<SILFunctionArgument>(SpecArg)->isNoImplicitCopy ());
2732
- NewArg->setLifetimeAnnotation (
2733
- cast<SILFunctionArgument>(SpecArg)->getLifetimeAnnotation ());
2734
- NewArg->setClosureCapture (
2735
- cast<SILFunctionArgument>(SpecArg)->isClosureCapture ());
2774
+ SILFunctionArgument *NewArg = addFunctionArgument (Thunk, ParamTy, specArg);
2736
2775
if (!NewArg->getArgumentConvention ().isGuaranteedConvention ()) {
2737
2776
SILValue argVal = Builder.emitLoadValueOperation (
2738
2777
Loc, NewArg, LoadOwnershipQualifier::Take);
@@ -2746,7 +2785,7 @@ SILArgument *ReabstractionThunkGenerator::convertReabstractionThunkArguments(
2746
2785
continue ;
2747
2786
}
2748
2787
// Simply clone unconverted direct or indirect parameters.
2749
- cloneSpecializedArgument ( );
2788
+ Arguments. push_back ( addFunctionArgument (Thunk, specArg-> getType (), specArg) );
2750
2789
}
2751
2790
assert (SpecArgIter == SpecializedFunc->getArguments ().end ());
2752
2791
return ReturnValueAddr;
@@ -2773,7 +2812,7 @@ static bool createPrespecialized(StringRef UnspecializedName,
2773
2812
ReabstractionInfo ReInfo (M.getSwiftModule (), M.isWholeModule (), ApplySite (),
2774
2813
UnspecFunc, Apply.getSubstitutionMap (),
2775
2814
IsNotSerialized,
2776
- /* ConvertIndirectToDirect=*/ true );
2815
+ /* ConvertIndirectToDirect= */ true , /* dropMetatypeArgs= */ false );
2777
2816
2778
2817
if (!ReInfo.canBeSpecialized ())
2779
2818
return false ;
@@ -2945,7 +2984,7 @@ bool usePrespecialized(
2945
2984
funcBuilder.getModule ().getSwiftModule (),
2946
2985
funcBuilder.getModule ().isWholeModule (), apply, refF, newSubstMap,
2947
2986
apply.getFunction ()->isSerialized () ? IsSerialized : IsNotSerialized,
2948
- /* ConvertIndirectToDirect=*/ true , /* dropMetatypeArgs*/ true , nullptr );
2987
+ /* ConvertIndirectToDirect=*/ true , /* dropMetatypeArgs= */ false , nullptr );
2949
2988
2950
2989
if (layoutReInfo.getSpecializedType () == reInfo.getSpecializedType ()) {
2951
2990
layoutMatches.push_back (
@@ -3005,6 +3044,28 @@ bool usePrespecialized(
3005
3044
return false ;
3006
3045
}
3007
3046
3047
+ static bool canDropMetatypeArgs (ApplySite apply, SILFunction *callee) {
3048
+ for (const Operand &argOp : apply.getArgumentOperands ()) {
3049
+ SILValue arg = argOp.get ();
3050
+ if (auto mt = arg->getType ().getAs <MetatypeType>()) {
3051
+ if (mt->hasRepresentation () && mt->getRepresentation () == MetatypeRepresentation::Thin)
3052
+ continue ;
3053
+ // If the passed thick metatype value is not a `metatype` instruction
3054
+ // we don't know the real metatype at runtime. It's not necessarily the
3055
+ // same as the declared metatype. It could e.g. be an upcast of a class
3056
+ // metatype.
3057
+ if (isa<MetatypeInst>(arg))
3058
+ continue ;
3059
+ // But: if the metatype is not used in the callee we don't have to care
3060
+ // what metatype value is passed. We can just remove it.
3061
+ if (callee->isDefinition () && onlyHaveDebugUses (callee->getArgument (apply.getCalleeArgIndex (argOp))))
3062
+ continue ;
3063
+ return false ;
3064
+ }
3065
+ }
3066
+ return true ;
3067
+ }
3068
+
3008
3069
void swift::trySpecializeApplyOfGeneric (
3009
3070
SILOptFunctionBuilder &FuncBuilder,
3010
3071
ApplySite Apply, DeadInstructionSet &DeadApplies,
@@ -3053,7 +3114,7 @@ void swift::trySpecializeApplyOfGeneric(
3053
3114
FuncBuilder.getModule ().isWholeModule (), Apply, RefF,
3054
3115
Apply.getSubstitutionMap (), Serialized,
3055
3116
/* ConvertIndirectToDirect=*/ true ,
3056
- /* dropMetatypeArgs=*/ isMandatory ,
3117
+ /* dropMetatypeArgs=*/ canDropMetatypeArgs (Apply, RefF) ,
3057
3118
&ORE);
3058
3119
if (!ReInfo.canBeSpecialized ())
3059
3120
return ;
@@ -3210,16 +3271,19 @@ void swift::trySpecializeApplyOfGeneric(
3210
3271
auto *FRI = Builder.createFunctionRef (PAI->getLoc (), Thunk);
3211
3272
SmallVector<SILValue, 4 > Arguments;
3212
3273
for (auto &Op : PAI->getArgumentOperands ()) {
3274
+ unsigned calleeArgIdx = ApplySite (PAI).getCalleeArgIndex (Op);
3275
+ if (ReInfo.isDroppedMetatypeArg (calleeArgIdx))
3276
+ continue ;
3213
3277
Arguments.push_back (Op.get ());
3214
3278
}
3215
3279
auto Subs = ReInfo.getCallerParamSubstitutionMap ();
3216
3280
auto FnTy = Thunk->getLoweredFunctionType ();
3217
3281
Subs = SubstitutionMap::get (FnTy->getSubstGenericSignature (), Subs);
3218
- auto *NewPAI = Builder.createPartialApply (
3219
- PAI->getLoc (), FRI, Subs, Arguments,
3220
- PAI->getType ().getAs <SILFunctionType>()->getCalleeConvention (),
3221
- PAI->isOnStack ());
3222
- PAI->replaceAllUsesWith (NewPAI );
3282
+ SingleValueInstruction *newPAI = Builder.createPartialApply (
3283
+ PAI->getLoc (), FRI, Subs, Arguments,
3284
+ PAI->getType ().getAs <SILFunctionType>()->getCalleeConvention (),
3285
+ PAI->isOnStack ());
3286
+ PAI->replaceAllUsesWith (newPAI );
3223
3287
DeadApplies.insert (PAI);
3224
3288
return ;
3225
3289
}
0 commit comments