Skip to content

Commit c3de7c1

Browse files
committed
MandatoryGenericSpecializer: drop metatype arguments in specialized functions
And replace them with explicit `metatype` instruction in the entry block. This allows such metatype instructions to be deleted if they are dead. rdar://94388453
1 parent 30cd386 commit c3de7c1

File tree

4 files changed

+61
-8
lines changed

4 files changed

+61
-8
lines changed

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ class ReabstractionInfo {
6262
/// argument has a trivial type.
6363
SmallBitVector TrivialArgs;
6464

65+
/// A 1-bit means that the argument is a metatype argument. The argument is
66+
/// dropped and replaced by a `metatype` instruction in the entry block.
67+
/// Only used if `dropMetatypeArgs` is true.
68+
SmallBitVector droppedMetatypeArgs;
69+
6570
/// Set to true if the function has a re-abstracted (= converted from
6671
/// indirect to direct) resilient argument or return type. This can happen if
6772
/// the function is compiled within the type's resilience domain, i.e. in
@@ -79,6 +84,10 @@ class ReabstractionInfo {
7984
/// specializer.
8085
bool ConvertIndirectToDirect;
8186

87+
/// If true, drop metatype arguments.
88+
/// See `droppedMetatypeArgs`.
89+
bool dropMetatypeArgs = false;
90+
8291
/// The first NumResults bits in Conversions refer to formal indirect
8392
/// out-parameters.
8493
unsigned NumFormalIndirectResults;
@@ -191,6 +200,7 @@ class ReabstractionInfo {
191200
SubstitutionMap ParamSubs,
192201
IsSerialized_t Serialized,
193202
bool ConvertIndirectToDirect = true,
203+
bool dropMetatypeArgs = false,
194204
OptRemark::Emitter *ORE = nullptr);
195205

196206
/// Constructs the ReabstractionInfo for generic function \p Callee with
@@ -243,6 +253,16 @@ class ReabstractionInfo {
243253
/// Returns true if there are any conversions from indirect to direct values.
244254
bool hasConversions() const { return Conversions.any(); }
245255

256+
/// Returns true if the argument at `ArgIdx` is a dropped metatype argument.
257+
/// See `droppedMetatypeArgs`.
258+
bool isDroppedMetatypeArg(unsigned ArgIdx) const {
259+
return droppedMetatypeArgs.test(ArgIdx);
260+
}
261+
262+
/// Returns true if there are any dropped metatype arguments.
263+
/// See `droppedMetatypeArgs`.
264+
bool hasDroppedMetatypeArgs() const { return droppedMetatypeArgs.any(); }
265+
246266
/// Remove the arguments of a partial apply, leaving the arguments for the
247267
/// partial apply result function.
248268
void prunePartialApplyArgs(unsigned numPartialApplyArgs) {

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ void GenericCloner::populateCloned() {
105105
entryArgs.push_back(ASI);
106106
return true;
107107
}
108+
} else if (ReInfo.isDroppedMetatypeArg(ArgIdx)) {
109+
// Replace the metatype argument with an `metatype` instruction in the
110+
// entry block.
111+
auto *mtInst = getBuilder().createMetatype(Loc, mappedType);
112+
entryArgs.push_back(mtInst);
113+
return true;
108114
} else {
109115
// Handle arguments for formal parameters.
110116
unsigned paramIdx = ArgIdx - origConv.getSILArgIndexOfFirstParam();

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,9 @@ bool ReabstractionInfo::canBeSpecialized(ApplySite Apply, SILFunction *Callee,
550550
ReabstractionInfo::ReabstractionInfo(
551551
ModuleDecl *targetModule, bool isWholeModule, ApplySite Apply,
552552
SILFunction *Callee, SubstitutionMap ParamSubs, IsSerialized_t Serialized,
553-
bool ConvertIndirectToDirect, OptRemark::Emitter *ORE)
553+
bool ConvertIndirectToDirect, bool dropMetatypeArgs, OptRemark::Emitter *ORE)
554554
: ConvertIndirectToDirect(ConvertIndirectToDirect),
555+
dropMetatypeArgs(dropMetatypeArgs),
555556
TargetModule(targetModule), isWholeModule(isWholeModule),
556557
Serialized(Serialized) {
557558
if (!prepareAndCheck(Apply, Callee, ParamSubs, ORE))
@@ -683,6 +684,7 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
683684
SubstitutedType->getParameters().size();
684685
Conversions.resize(NumArgs);
685686
TrivialArgs.resize(NumArgs);
687+
droppedMetatypeArgs.resize(NumArgs);
686688

687689
SILFunctionConventions substConv(SubstitutedType, M);
688690
TypeExpansionContext resilienceExp = getResilienceExpansion();
@@ -737,11 +739,17 @@ void ReabstractionInfo::createSubstitutedAndSpecializedTypes() {
737739
case ParameterConvention::Indirect_In_Constant:
738740
case ParameterConvention::Indirect_Inout:
739741
case ParameterConvention::Indirect_InoutAliasable:
742+
break;
743+
740744
case ParameterConvention::Direct_Owned:
741745
case ParameterConvention::Direct_Unowned:
742-
case ParameterConvention::Direct_Guaranteed:
746+
case ParameterConvention::Direct_Guaranteed: {
747+
CanType ty = PI.getInterfaceType();
748+
if (dropMetatypeArgs && isa<MetatypeType>(ty) && !ty->hasArchetype())
749+
droppedMetatypeArgs.set(IdxToInsert);
743750
break;
744751
}
752+
}
745753
}
746754

747755
// Produce a specialized type, which is the substituted type with
@@ -852,11 +860,16 @@ createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
852860
// No conversion: re-use the original, substituted result info.
853861
SpecializedResults.push_back(RI);
854862
}
855-
unsigned ParamIdx = 0;
863+
unsigned idx = 0;
856864
for (SILParameterInfo PI : SubstFTy->getParameters()) {
865+
unsigned paramIdx = idx++;
857866
PI = PI.getUnsubstituted(M, SubstFTy, context);
858-
bool isTrivial = TrivialArgs.test(param2ArgIndex(ParamIdx));
859-
if (!isParamConverted(ParamIdx++)) {
867+
868+
if (isDroppedMetatypeArg(param2ArgIndex(paramIdx)))
869+
continue;
870+
871+
bool isTrivial = TrivialArgs.test(param2ArgIndex(paramIdx));
872+
if (!isParamConverted(paramIdx)) {
860873
// No conversion: re-use the original, substituted parameter info.
861874
SpecializedParams.push_back(PI);
862875
continue;
@@ -1854,7 +1867,8 @@ GenericFuncSpecializer::GenericFuncSpecializer(
18541867
ClonedName = Mangler.manglePrespecialized(ParamSubs);
18551868
} else {
18561869
ClonedName = Mangler.mangleReabstracted(ParamSubs,
1857-
ReInfo.needAlternativeMangling());
1870+
ReInfo.needAlternativeMangling(),
1871+
ReInfo.hasDroppedMetatypeArgs());
18581872
}
18591873
}
18601874
LLVM_DEBUG(llvm::dbgs() << " Specialized function " << ClonedName << '\n');
@@ -1995,6 +2009,9 @@ prepareCallArguments(ApplySite AI, SILBuilder &Builder,
19952009
return true;
19962010
}
19972011

2012+
if (ReInfo.isDroppedMetatypeArg(ArgIdx))
2013+
return true;
2014+
19982015
// Handle arguments for formal parameters.
19992016
unsigned paramIdx = ArgIdx - substConv.getSILArgIndexOfFirstParam();
20002017
if (!ReInfo.isParamConverted(paramIdx)) {
@@ -2418,7 +2435,7 @@ static bool createPrespecialized(StringRef UnspecializedName,
24182435
ReabstractionInfo ReInfo(M.getSwiftModule(), M.isWholeModule(), ApplySite(),
24192436
UnspecFunc, Apply.getSubstitutionMap(),
24202437
IsNotSerialized,
2421-
/*ConvertIndirectToDirect=*/true, nullptr);
2438+
/*ConvertIndirectToDirect=*/true);
24222439

24232440
if (!ReInfo.canBeSpecialized())
24242441
return false;
@@ -2599,7 +2616,9 @@ void swift::trySpecializeApplyOfGeneric(
25992616
ReabstractionInfo ReInfo(FuncBuilder.getModule().getSwiftModule(),
26002617
FuncBuilder.getModule().isWholeModule(), Apply, RefF,
26012618
Apply.getSubstitutionMap(), Serialized,
2602-
/*ConvertIndirectToDirect=*/true, &ORE);
2619+
/*ConvertIndirectToDirect=*/ true,
2620+
/*dropMetatypeArgs=*/ isMandatory,
2621+
&ORE);
26032622
if (!ReInfo.canBeSpecialized())
26042623
return;
26052624

test/SILOptimizer/performance-annotations.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,11 @@ func testGlobalWithComplexInit() -> Int {
131131
return Str.s3 // expected-note {{called from here}}
132132
}
133133

134+
func metatypeArg<T>(_ t: T.Type, _ b: Bool) { // expected-error {{Using type 'Int' can cause metadata allocation or locks}}
135+
}
136+
137+
@_noAllocation
138+
func callFuncWithMetatypeArg() {
139+
metatypeArg(Int.self, false) // expected-note {{called from here}}
140+
}
141+

0 commit comments

Comments
 (0)