Skip to content

Commit 89bba66

Browse files
committed
Mangling: add a closure specialization mangling for arguments which specialize for the same closure as a previous argument
For example: ``` %1 = partial_apply %closure apply %f(%1, %1) // first argument: `.closure(%1)` // second argument: `.previousArgumentIndex(0)` ```
1 parent ea6e3c9 commit 89bba66

File tree

12 files changed

+138
-79
lines changed

12 files changed

+138
-79
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,8 @@ private struct PullbackClosureInfo {
14271427

14281428
func specializedCalleeName(_ context: FunctionPassContext) -> String {
14291429
let closureArgs = Array(self.closureArgDescriptors.map {
1430-
(argumentIndex: $0.closureArgIndex, argumentValue: $0.closure)
1430+
(argumentIndex: $0.closureArgIndex,
1431+
argumentValue: FunctionPassContext.ClosureArgumentMangling.closure($0.closure))
14311432
})
14321433
return context.mangle(withClosureArguments: closureArgs, from: pullbackFn)
14331434
}

SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,34 @@ struct FunctionPassContext : MutatingContext {
111111
return String(taking: bridgedPassContext.mangleOutlinedVariable(function.bridged))
112112
}
113113

114-
func mangle(withClosureArguments closureArgs: [(argumentIndex: Int, argumentValue: Value)],
114+
enum ClosureArgumentMangling {
115+
case closure(SingleValueInstruction)
116+
117+
/// The argument specializes for the same closure as a previous argument, e.g.
118+
/// ```
119+
/// %1 = partial_apply %closure
120+
/// apply %f(%1, %1) // first argument: `.closure(%1)`
121+
/// // second argument: `.previousArgumentIndex(0)`
122+
case previousArgumentIndex(Int)
123+
}
124+
125+
func mangle(withClosureArguments closureArgs: [(argumentIndex: Int, argumentValue: ClosureArgumentMangling)],
115126
from applySiteCallee: Function
116127
) -> String {
117-
closureArgs.withBridgedArrayRef{ bridgedClosureArgs in
128+
let bridgedArgManglings = closureArgs.map {
129+
switch $0.argumentValue {
130+
case .closure(let closure):
131+
return BridgedPassContext.ClosureArgMangling(argIdx: $0.argumentIndex,
132+
inst: Optional<Instruction>(closure).bridged,
133+
otherArgIdx: -1)
134+
case .previousArgumentIndex(let idx):
135+
return BridgedPassContext.ClosureArgMangling(argIdx: $0.argumentIndex,
136+
inst: OptionalBridgedInstruction(),
137+
otherArgIdx: idx)
138+
}
139+
}
140+
141+
return bridgedArgManglings.withBridgedArrayRef{ bridgedClosureArgs in
118142
String(taking: bridgedPassContext.mangleWithClosureArgs(bridgedClosureArgs, applySiteCallee.bridged))
119143
}
120144
}

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ Some kinds need arguments, which precede ``Tf``.
13621362
ARG-SPEC-KIND ::= 'n' // Unmodified argument
13631363
ARG-SPEC-KIND ::= 'c' // Consumes n 'type' arguments which are closed over types in argument order
13641364
// and one 'identifier' argument which is the closure symbol name
1365+
ARG-SPEC-KIND ::= 'C' NATURAL-ZERO // the same closure as a previous argument <n>
13651366
ARG-SPEC-KIND ::= 'p' CONST-PROP // Constant propagated argument
13661367
ARG-SPEC-KIND ::= 'e' 'D'? 'G'? 'X'? // Generic argument, with optional dead, owned=>guaranteed or exploded-specifier
13671368
ARG-SPEC-KIND ::= 'd' 'G'? 'X'? // Dead argument, with optional owned=>guaranteed or exploded-specifier

include/swift/Demangling/Demangle.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ enum class FunctionSigSpecializationParamKind : unsigned {
117117
InOutToOut = 8,
118118
ConstantPropKeyPath = 9,
119119
ConstantPropStruct = 10,
120+
ClosurePropPreviousArg = 11,
120121

121122
// Option Set Flags use bits 6-31. This gives us 26 bits to use for option
122123
// flags.

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,15 @@ struct BridgedPassContext {
187187
bool specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const;
188188
BridgedOwnedString mangleOutlinedVariable(BridgedFunction function) const;
189189
BridgedOwnedString mangleAsyncRemoved(BridgedFunction function) const;
190+
191+
struct ClosureArgMangling {
192+
SwiftInt argIdx;
193+
OptionalBridgedInstruction inst;
194+
SwiftInt otherArgIdx;
195+
};
196+
190197
BridgedOwnedString mangleWithDeadArgs(BridgedArrayRef bridgedDeadArgIndices, BridgedFunction function) const;
191-
BridgedOwnedString mangleWithClosureArgs(BridgedArrayRef closureArgIndices,
192-
BridgedFunction applySiteCallee) const;
198+
BridgedOwnedString mangleWithClosureArgs(BridgedArrayRef closureArgManglings, BridgedFunction applySiteCallee) const;
193199
BridgedOwnedString mangleWithConstCaptureArgs(BridgedArrayRef bridgedConstArgs,
194200
BridgedFunction applySiteCallee) const;
195201
BridgedOwnedString mangleWithBoxToStackPromotedArgs(BridgedArrayRef bridgedPromotedArgIndices,

include/swift/SILOptimizer/Utils/SpecializationMangler.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class FunctionSignatureSpecializationMangler : public SpecializationMangler {
6868
BoxToValue = 3,
6969
BoxToStack = 4,
7070
InOutToOut = 5,
71+
ClosurePropPreviousArg = 6, // the same closure as a previous `ClosureProp` argument
7172

7273
First_Option = 0,
7374
Last_Option = 31,
@@ -82,8 +83,20 @@ class FunctionSignatureSpecializationMangler : public SpecializationMangler {
8283
LastOptionSetEntry = 32768,
8384
};
8485

85-
using ArgInfo = std::pair<ArgumentModifierIntBase,
86-
NullablePtr<SILInstruction>>;
86+
struct ArgInfo {
87+
ArgumentModifier kind;
88+
union {
89+
SILInstruction *inst;
90+
unsigned otherArgIdx; // only for `ClosurePropPreviousArg`
91+
};
92+
93+
ArgInfo(ArgumentModifier kind) : kind(kind), inst(nullptr) {}
94+
95+
void append(ArgumentModifier modifier) {
96+
kind = ArgumentModifier(ArgumentModifierIntBase(kind) | ArgumentModifierIntBase(modifier));
97+
}
98+
};
99+
87100
// Information for each SIL argument in the original function before
88101
// specialization. This includes SIL indirect result argument required for
89102
// the original function type at the current stage of compilation.
@@ -99,9 +112,8 @@ class FunctionSignatureSpecializationMangler : public SpecializationMangler {
99112
void setArgumentConstantProp(unsigned OrigArgIdx, SILInstruction *constInst);
100113
void appendStringAsIdentifier(StringRef str);
101114

102-
void setArgumentClosureProp(unsigned OrigArgIdx, PartialApplyInst *PAI);
103-
void setArgumentClosureProp(unsigned OrigArgIdx,
104-
ThinToThickFunctionInst *TTTFI);
115+
void setArgumentClosureProp(unsigned OrigArgIdx, SILInstruction *closure);
116+
void setArgumentClosurePropPreviousArg(unsigned OrigArgIdx, unsigned otherArgIdx);
105117
void setArgumentDead(unsigned OrigArgIdx);
106118
void setArgumentOwnedToGuaranteed(unsigned OrigArgIdx);
107119
void setArgumentGuaranteedToOwned(unsigned OrigArgIdx);
@@ -120,8 +132,7 @@ class FunctionSignatureSpecializationMangler : public SpecializationMangler {
120132
private:
121133
void mangleConstantProp(SILInstruction *constInst);
122134
void mangleClosureProp(SILInstruction *Inst);
123-
void mangleArgument(ArgumentModifierIntBase ArgMod,
124-
NullablePtr<SILInstruction> Inst);
135+
void mangleArgument(ArgInfo argInfo);
125136
void mangleReturnValue(ReturnValueModifierIntBase RetMod);
126137
};
127138

lib/Demangling/Demangler.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3430,6 +3430,18 @@ NodePointer Demangler::demangleFuncSpecParam(Node::Kind Kind) {
34303430
return addChild(Param, createNode(
34313431
Node::Kind::FunctionSignatureSpecializationParamKind,
34323432
uint64_t(FunctionSigSpecializationParamKind::ClosureProp)));
3433+
case 'C': {
3434+
// Consumes an identifier and multiple type parameters.
3435+
// The parameters will be added later.
3436+
addChild(Param, createNode(
3437+
Node::Kind::FunctionSignatureSpecializationParamKind,
3438+
uint64_t(FunctionSigSpecializationParamKind::ClosurePropPreviousArg)));
3439+
int prevArgIdx = demangleNatural();
3440+
if (prevArgIdx < 0)
3441+
return nullptr;
3442+
return addChild(Param, createNode(
3443+
Node::Kind::FunctionSignatureSpecializationParamPayload, (Node::IndexType)prevArgIdx));
3444+
}
34333445
case 'p': {
34343446
for (;;) {
34353447
switch (nextChar()) {

lib/Demangling/NodePrinter.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,15 @@ void NodePrinter::printFunctionSigSpecializationParams(NodePointer Node,
12471247
}
12481248
Printer << "]";
12491249
break;
1250+
case FunctionSigSpecializationParamKind::ClosurePropPreviousArg:
1251+
if (Idx + 2 > End)
1252+
return;
1253+
Printer << "[";
1254+
print(Node->getChild(Idx++), depth + 1);
1255+
Printer << " ";
1256+
print(Node->getChild(Idx++), depth + 1);
1257+
Printer << "]";
1258+
break;
12501259
default:
12511260
assert(
12521261
((V & unsigned(FunctionSigSpecializationParamKind::OwnedToGuaranteed)) ||
@@ -1889,11 +1898,15 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
18891898
case Node::Kind::FunctionSignatureSpecializationParam:
18901899
printer_unreachable("should be handled in printSpecializationPrefix");
18911900
case Node::Kind::FunctionSignatureSpecializationParamPayload: {
1892-
std::string demangledName = demangleSymbolAsString(Node->getText());
1893-
if (demangledName.empty()) {
1894-
Printer << Node->getText();
1895-
} else {
1896-
Printer << demangledName;
1901+
if (Node->hasText()) {
1902+
std::string demangledName = demangleSymbolAsString(Node->getText());
1903+
if (demangledName.empty()) {
1904+
Printer << Node->getText();
1905+
} else {
1906+
Printer << demangledName;
1907+
}
1908+
} else if (Node->hasIndex()) {
1909+
Printer << Node->getIndex();
18971910
}
18981911
return nullptr;
18991912
}
@@ -1971,6 +1984,9 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
19711984
case FunctionSigSpecializationParamKind::ClosureProp:
19721985
Printer << "Closure Propagated";
19731986
return nullptr;
1987+
case FunctionSigSpecializationParamKind::ClosurePropPreviousArg:
1988+
Printer << "Same As Argument";
1989+
return nullptr;
19741990
case FunctionSigSpecializationParamKind::ExistentialToGeneric:
19751991
case FunctionSigSpecializationParamKind::Dead:
19761992
case FunctionSigSpecializationParamKind::OwnedToGuaranteed:

lib/Demangling/Remangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,9 @@ Remangler::mangleFunctionSignatureSpecializationParam(Node *node,
16021602
case FunctionSigSpecializationParamKind::ClosureProp:
16031603
Buffer << 'c';
16041604
break;
1605+
case FunctionSigSpecializationParamKind::ClosurePropPreviousArg:
1606+
Buffer << 'C' << node->getChild(idx++)->getIndex();
1607+
break;
16051608
case FunctionSigSpecializationParamKind::BoxToValue:
16061609
Buffer << 'i';
16071610
break;

lib/SILOptimizer/Utils/OptimizerBridging.cpp

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -274,32 +274,21 @@ BridgedOwnedString BridgedPassContext::mangleWithDeadArgs(BridgedArrayRef bridge
274274
}
275275

276276
BridgedOwnedString BridgedPassContext::mangleWithClosureArgs(
277-
BridgedArrayRef bridgedClosureArgs, BridgedFunction applySiteCallee
277+
BridgedArrayRef closureArgManglings, BridgedFunction applySiteCallee
278278
) const {
279-
280-
struct ClosureArgElement {
281-
SwiftInt argIdx;
282-
BridgeValueExistential argValue;
283-
};
284-
285279
auto pass = Demangle::SpecializationPass::ClosureSpecializer;
286280
auto serializedKind = applySiteCallee.getFunction()->getSerializedKind();
287281
Mangle::FunctionSignatureSpecializationMangler mangler(applySiteCallee.getFunction()->getASTContext(),
288282
pass, serializedKind, applySiteCallee.getFunction());
289283

290-
auto closureArgs = bridgedClosureArgs.unbridged<ClosureArgElement>();
291-
292-
for (ClosureArgElement argElmt : closureArgs) {
293-
auto closureArg = argElmt.argValue.value.getSILValue();
294-
auto closureArgIndex = argElmt.argIdx;
284+
auto closureArgs = closureArgManglings.unbridged<ClosureArgMangling>();
295285

296-
if (auto *PAI = dyn_cast<PartialApplyInst>(closureArg)) {
297-
mangler.setArgumentClosureProp(closureArgIndex,
298-
const_cast<PartialApplyInst *>(PAI));
286+
for (ClosureArgMangling argElmt : closureArgs) {
287+
auto closureArgIndex = (unsigned)argElmt.argIdx;
288+
if (SILInstruction *inst = argElmt.inst.unbridged()) {
289+
mangler.setArgumentClosureProp(closureArgIndex, inst);
299290
} else {
300-
auto *TTTFI = cast<ThinToThickFunctionInst>(closureArg);
301-
mangler.setArgumentClosureProp(closureArgIndex,
302-
const_cast<ThinToThickFunctionInst *>(TTTFI));
291+
mangler.setArgumentClosurePropPreviousArg(closureArgIndex, argElmt.otherArgIdx);
303292
}
304293
}
305294

0 commit comments

Comments
 (0)