Skip to content

Commit 26c963f

Browse files
committed
Generic specializer API changes to prepare for the new @_specialize attribute and partial specializations.
1 parent f7253bf commit 26c963f

File tree

4 files changed

+245
-22
lines changed

4 files changed

+245
-22
lines changed

include/swift/SILOptimizer/Utils/Generics.h

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,69 @@ class ReabstractionInfo {
5353
/// out-parameters.
5454
unsigned NumFormalIndirectResults;
5555

56-
/// The function type after applying the substitutions of the original
57-
/// apply site.
56+
/// The function type after applying the substitutions used to call the
57+
/// specialized function.
5858
CanSILFunctionType SubstitutedType;
5959

6060
/// The function type after applying the re-abstractions on the
6161
/// SubstitutedType.
6262
CanSILFunctionType SpecializedType;
6363

64+
/// The generic environment to be used by the specialization.
65+
GenericEnvironment *SpecializedGenericEnv;
66+
67+
/// The generic signature of the specialization.
68+
/// It is nullptr if the specialization is not polymorphic.
69+
GenericSignature *SpecializedGenericSig;
70+
71+
// Set of the substitutions used by the caller's apply instruction before
72+
// any transformations performed by the generic specializer.
73+
// It uses archetypes.
74+
SubstitutionList OriginalParamSubs;
75+
76+
// Set of substitutions to be used by the caller's apply when it calls a
77+
// specialized function.
78+
// It uses archetypes.
79+
SubstitutionList CallerParamSubs;
80+
81+
// Set of substitutions to be used by the cloner during cloning.
82+
// It maps to concrete types for any types which were replaced by
83+
// concrete types in the caller's apply substitution list. All other
84+
// types are replaced by their respective archetypes.
85+
SubstitutionList ClonerParamSubs;
86+
87+
// Reference to the original generic non-specialized function.
88+
SILFunction *OriginalF;
89+
90+
// The apply site which invokes the generic function.
91+
ApplySite Apply;
92+
93+
// Set if a specialized function has unbound generic parameters.
94+
bool HasUnboundGenericParams;
95+
96+
// Substitutions to be used for creating a new function type
97+
// for the specialized function.
98+
// It uses interface types.
99+
SubstitutionMap CallerInterfaceSubs;
100+
101+
// Create a new substituted type with the updated signature.
102+
CanSILFunctionType createSubstitutedType(SILFunction *OrigF,
103+
const SubstitutionMap &SubstMap,
104+
bool HasUnboundGenericParams);
105+
106+
void createSubstitutedAndSpecializedTypes();
64107
public:
65108
/// Constructs the ReabstractionInfo for generic function \p Orig with
66109
/// substitutions \p ParamSubs.
67110
/// If specialization is not possible getSpecializedType() will return an
68111
/// invalid type.
69-
ReabstractionInfo(SILFunction *Orig, SubstitutionList ParamSubs);
112+
ReabstractionInfo(ApplySite Apply, SILFunction *Callee,
113+
SubstitutionList ParamSubs);
114+
115+
/// Constructs the ReabstractionInfo for generic function \p Orig with
116+
/// additional requirements. Requirements may contain new layout,
117+
/// conformances or same concrete type requirements.
118+
ReabstractionInfo(SILFunction *Orig, ArrayRef<Requirement> Requirements);
70119

71120
/// Returns true if the \p ParamIdx'th (non-result) formal parameter is
72121
/// converted from indirect to direct.
@@ -81,6 +130,16 @@ class ReabstractionInfo {
81130
return Conversions.test(ResultIdx);
82131
}
83132

133+
/// Gets the total number of original function arguments.
134+
unsigned getNumArguments() const { return Conversions.size(); }
135+
136+
/// Returns true if the \p ArgIdx'th argument is converted from an
137+
/// indirect
138+
/// result or parameter to a direct result or parameter.
139+
bool isArgConverted(unsigned ArgIdx) const {
140+
return Conversions.test(ArgIdx);
141+
}
142+
84143
/// Returns true if there are any conversions from indirect to direct values.
85144
bool hasConversions() const { return Conversions.any(); }
86145

@@ -92,6 +151,15 @@ class ReabstractionInfo {
92151
Conversions.resize(Conversions.size() - numPartialApplyArgs);
93152
}
94153

154+
/// Returns the index of the first argument of an apply site, which may be
155+
/// > 0 in case of a partial_apply.
156+
unsigned getIndexOfFirstArg(ApplySite Apply) const {
157+
unsigned numArgs = Apply.getNumArguments();
158+
assert(numArgs == Conversions.size() ||
159+
(numArgs < Conversions.size() && isa<PartialApplyInst>(Apply)));
160+
return Conversions.size() - numArgs;
161+
}
162+
95163
/// Get the function type after applying the substitutions to the original
96164
/// generic function.
97165
CanSILFunctionType getSubstitutedType() const { return SubstitutedType; }
@@ -101,10 +169,45 @@ class ReabstractionInfo {
101169
/// possible.
102170
CanSILFunctionType getSpecializedType() const { return SpecializedType; }
103171

172+
GenericEnvironment *getSpecializedGenericEnvironment() const {
173+
return SpecializedGenericEnv;
174+
}
175+
176+
SubstitutionList getCallerParamSubstitutions() const {
177+
return CallerParamSubs;
178+
}
179+
180+
SubstitutionList getClonerParamSubstitutions() const {
181+
return ClonerParamSubs;
182+
}
183+
184+
SubstitutionList getOriginalParamSubstitutions() const {
185+
return OriginalParamSubs;
186+
}
187+
104188
/// Create a specialized function type for a specific substituted type \p
105189
/// SubstFTy by applying the re-abstractions.
106190
CanSILFunctionType createSpecializedType(CanSILFunctionType SubstFTy,
107191
SILModule &M) const;
192+
193+
SILFunction *getNonSpecializedFunction() const { return OriginalF; }
194+
195+
/// Map type into a context of the specialized function.
196+
Type mapTypeIntoContext(Type type) const;
197+
198+
/// Map SIL type into a context of the specialized function.
199+
SILType mapTypeIntoContext(SILType type) const;
200+
201+
SILModule &getModule() const { return OriginalF->getModule(); }
202+
203+
/// Returns true if generic specialization is possible.
204+
bool canBeSpecialized() const;
205+
206+
/// Returns true if it is a full generic specialization.
207+
bool isFullSpecialization() const;
208+
209+
/// Returns true if it is a partial generic specialization.
210+
bool isPartialSpecialization() const;
108211
};
109212

110213
/// Helper class for specializing a generic function given a list of
@@ -118,6 +221,7 @@ class GenericFuncSpecializer {
118221

119222
SubstitutionMap ContextSubs;
120223
std::string ClonedName;
224+
121225
public:
122226
GenericFuncSpecializer(SILFunction *GenericFunc,
123227
SubstitutionList ParamSubs,
@@ -129,7 +233,7 @@ class GenericFuncSpecializer {
129233

130234
/// Return a newly created specialized function.
131235
SILFunction *tryCreateSpecialization();
132-
236+
133237
/// Try to specialize GenericFunc given a list of ParamSubs.
134238
/// Returns either a new or existing specialized function, or nullptr.
135239
SILFunction *trySpecialization() {
@@ -142,6 +246,10 @@ class GenericFuncSpecializer {
142246

143247
return SpecializedF;
144248
}
249+
250+
StringRef getClonedName() {
251+
return ClonedName;
252+
}
145253
};
146254

147255
// =============================================================================

lib/SILOptimizer/IPO/UsePrespecialized.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,21 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
8888
if (Subs.empty())
8989
continue;
9090

91-
ReabstractionInfo ReInfo(ReferencedF, Subs);
91+
// Bail if any generic type parameters are unbound.
92+
// TODO: Remove this limitation once public partial specializations
93+
// are supported and can be provided by other modules.
94+
if (hasArchetypes(Subs))
95+
continue;
9296

93-
auto SpecType = ReInfo.getSpecializedType();
94-
if (!SpecType)
97+
ReabstractionInfo ReInfo(AI, ReferencedF, Subs);
98+
99+
if (!ReInfo.canBeSpecialized())
95100
continue;
96101

97-
// Bail any callee generic type parameters are dependent on the generic
98-
// parameters of the caller.
99-
if (SpecType->hasArchetype() || hasArchetypes(Subs))
102+
auto SpecType = ReInfo.getSpecializedType();
103+
// Bail if any generic types parameters of the concrete type
104+
// are unbound.
105+
if (SpecType->hasArchetype())
100106
continue;
101107

102108
// Create a name of the specialization.

lib/SILOptimizer/Utils/GenericCloner.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ SILFunction *GenericCloner::initCloned(SILFunction *Orig,
4040
// Create a new empty function.
4141
SILFunction *NewF = Orig->getModule().createFunction(
4242
getSpecializedLinkage(Orig, Orig->getLinkage()), NewName,
43-
ReInfo.getSpecializedType(), nullptr, Orig->getLocation(), Orig->isBare(),
44-
Orig->isTransparent(), Fragile, Orig->isThunk(),
45-
Orig->getClassVisibility(), Orig->getInlineStrategy(),
46-
Orig->getEffectsKind(), Orig, Orig->getDebugScope());
43+
ReInfo.getSpecializedType(), ReInfo.getSpecializedGenericEnvironment(),
44+
Orig->getLocation(), Orig->isBare(), Orig->isTransparent(),
45+
Fragile, Orig->isThunk(), Orig->getClassVisibility(),
46+
Orig->getInlineStrategy(), Orig->getEffectsKind(), Orig,
47+
Orig->getDebugScope());
4748
for (auto &Attr : Orig->getSemanticsAttrs()) {
4849
NewF->addSemanticsAttr(Attr);
4950
}

0 commit comments

Comments
 (0)