Skip to content

Commit 0943504

Browse files
authored
Merge pull request #71385 from eeckstein/perf-constraint-flag
IRGen: don't use value witness functions in outlined value operations for functions with performance constraints
2 parents e738b8a + 38bfc03 commit 0943504

29 files changed

+267
-61
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ private func optimizeFunctionsTopDown(using worklist: inout FunctionWorklist,
5050
return
5151
}
5252

53+
// It's not required to set the perf_constraint flag on all functions in embedded mode.
54+
// Embedded mode already implies that flag.
55+
if !moduleContext.options.enableEmbeddedSwift {
56+
f.set(isPerformanceConstraint: true, context)
57+
}
58+
5359
optimize(function: f, context, &worklist)
5460
}
5561

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,12 @@ extension Function {
620620
}
621621
}
622622

623+
func set(isPerformanceConstraint: Bool, _ context: FunctionPassContext) {
624+
context.notifyEffectsChanged()
625+
bridged.setIsPerformanceConstraint(isPerformanceConstraint)
626+
}
627+
628+
623629
func fixStackNesting(_ context: FunctionPassContext) {
624630
context._bridged.fixStackNesting(bridged)
625631
}

docs/ABI/Mangling.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,9 +328,13 @@ with a differentiable function used for differentiable programming.
328328
global ::= generic-signature? type 'WOs' // Outlined release
329329
global ::= generic-signature? type 'WOb' // Outlined initializeWithTake
330330
global ::= generic-signature? type 'WOc' // Outlined initializeWithCopy
331+
global ::= generic-signature? type 'WOC' // Outlined initializeWithCopy, not using value witness
331332
global ::= generic-signature? type 'WOd' // Outlined assignWithTake
333+
global ::= generic-signature? type 'WOD' // Outlined assignWithTake, not using value witness
332334
global ::= generic-signature? type 'WOf' // Outlined assignWithCopy
335+
global ::= generic-signature? type 'WOF' // Outlined assignWithCopy, not using value witness
333336
global ::= generic-signature? type 'WOh' // Outlined destroy
337+
global ::= generic-signature? type 'WOH' // Outlined destroy, not using value witness
334338
global ::= generic-signature? type 'WOi` // Outlined store enum tag
335339
global ::= generic-signature? type 'WOj` // Outlined enum destructive project
336340
global ::= generic-signature? type 'WOg` // Outlined enum get tag

docs/SIL.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,14 @@ The clang node owner.
12801280

12811281
Specifies the performance constraints for the function, which defines which type
12821282
of runtime functions are allowed to be called from the function.
1283+
::
1284+
1285+
sil-function-attribute ::= '[perf_constraint]'
12831286

1287+
Specifies that the optimizer and IRGen must not add runtime calls which are not
1288+
in the function originally. This attribute is set for functions with performance
1289+
constraints or functions which are called from functions with performance
1290+
constraints.
12841291

12851292
Argument Effects
12861293
````````````````

include/swift/Demangling/DemangleNodes.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,5 +381,10 @@ NODE(AsyncRemoved)
381381
// Added in Swift 5.TBD
382382
NODE(ObjectiveCProtocolSymbolicReference)
383383

384+
NODE(OutlinedInitializeWithCopyNoValueWitness)
385+
NODE(OutlinedAssignWithTakeNoValueWitness)
386+
NODE(OutlinedAssignWithCopyNoValueWitness)
387+
NODE(OutlinedDestroyNoValueWitness)
388+
384389
#undef CONTEXT_NODE
385390
#undef NODE

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ struct BridgedFunction {
542542
BRIDGED_INLINE void setThunk(ThunkKind) const;
543543
BRIDGED_INLINE bool needsStackProtection() const;
544544
BRIDGED_INLINE void setNeedStackProtection(bool needSP) const;
545+
BRIDGED_INLINE void setIsPerformanceConstraint(bool isPerfConstraint) const;
545546
BRIDGED_INLINE bool isResilientNominalDecl(BridgedNominalTypeDecl decl) const;
546547
BRIDGED_INLINE BridgedType getLoweredType(BridgedASTType type) const;
547548

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,10 @@ void BridgedFunction::setNeedStackProtection(bool needSP) const {
672672
getFunction()->setNeedStackProtection(needSP);
673673
}
674674

675+
void BridgedFunction::setIsPerformanceConstraint(bool isPerfConstraint) const {
676+
getFunction()->setIsPerformanceConstraint(isPerfConstraint);
677+
}
678+
675679
bool BridgedFunction::isResilientNominalDecl(BridgedNominalTypeDecl decl) const {
676680
return decl.unbridged()->isResilient(getFunction()->getModule().getSwiftModule(),
677681
getFunction()->getResilienceExpansion());

include/swift/SIL/SILFunction.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,14 @@ class SILFunction
445445

446446
unsigned HasResultDependsOnSelf : 1;
447447

448+
/// True, if this function or a caller (transitively) has a performance
449+
/// constraint.
450+
/// If true, optimizations must not introduce new runtime calls or metadata
451+
/// creation, which are not there after SILGen.
452+
/// Note that this flag is not serialized, because it's computed locally
453+
/// within a module by the MandatoryOptimizations pass.
454+
unsigned IsPerformanceConstraint : 1;
455+
448456
static void
449457
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
450458
const GenericSpecializationInformation *genericInfo) {
@@ -1031,6 +1039,13 @@ class SILFunction
10311039
perfConstraints = perfConstr;
10321040
}
10331041

1042+
// see `IsPerformanceConstraint`
1043+
bool isPerformanceConstraint() const { return IsPerformanceConstraint; }
1044+
1045+
void setIsPerformanceConstraint(bool flag = true) {
1046+
IsPerformanceConstraint = flag;
1047+
}
1048+
10341049
/// \returns True if the function is optimizable (i.e. not marked as no-opt),
10351050
/// or is raw SIL (so that the mandatory passes still run).
10361051
bool shouldOptimize() const;

lib/Demangling/Demangler.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3427,6 +3427,34 @@ NodePointer Demangler::demangleWitness() {
34273427
}
34283428
case 'O': {
34293429
switch (nextChar()) {
3430+
case 'C': {
3431+
if (auto sig = popNode(Node::Kind::DependentGenericSignature))
3432+
return createWithChildren(Node::Kind::OutlinedInitializeWithCopyNoValueWitness,
3433+
popNode(Node::Kind::Type), sig);
3434+
return createWithChild(Node::Kind::OutlinedInitializeWithCopyNoValueWitness,
3435+
popNode(Node::Kind::Type));
3436+
}
3437+
case 'D': {
3438+
if (auto sig = popNode(Node::Kind::DependentGenericSignature))
3439+
return createWithChildren(Node::Kind::OutlinedAssignWithTakeNoValueWitness,
3440+
popNode(Node::Kind::Type), sig);
3441+
return createWithChild(Node::Kind::OutlinedAssignWithTakeNoValueWitness,
3442+
popNode(Node::Kind::Type));
3443+
}
3444+
case 'F': {
3445+
if (auto sig = popNode(Node::Kind::DependentGenericSignature))
3446+
return createWithChildren(Node::Kind::OutlinedAssignWithCopyNoValueWitness,
3447+
popNode(Node::Kind::Type), sig);
3448+
return createWithChild(Node::Kind::OutlinedAssignWithCopyNoValueWitness,
3449+
popNode(Node::Kind::Type));
3450+
}
3451+
case 'H': {
3452+
if (auto sig = popNode(Node::Kind::DependentGenericSignature))
3453+
return createWithChildren(Node::Kind::OutlinedDestroyNoValueWitness,
3454+
popNode(Node::Kind::Type), sig);
3455+
return createWithChild(Node::Kind::OutlinedDestroyNoValueWitness,
3456+
popNode(Node::Kind::Type));
3457+
}
34303458
case 'y': {
34313459
if (auto sig = popNode(Node::Kind::DependentGenericSignature))
34323460
return createWithChildren(Node::Kind::OutlinedCopy,

lib/Demangling/NodePrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,10 @@ class NodePrinter {
573573
case Node::Kind::OutlinedAssignWithTake:
574574
case Node::Kind::OutlinedAssignWithCopy:
575575
case Node::Kind::OutlinedDestroy:
576+
case Node::Kind::OutlinedInitializeWithCopyNoValueWitness:
577+
case Node::Kind::OutlinedAssignWithTakeNoValueWitness:
578+
case Node::Kind::OutlinedAssignWithCopyNoValueWitness:
579+
case Node::Kind::OutlinedDestroyNoValueWitness:
576580
case Node::Kind::OutlinedEnumTagStore:
577581
case Node::Kind::OutlinedEnumGetTag:
578582
case Node::Kind::OutlinedEnumProjectDataForLoad:
@@ -1381,18 +1385,22 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
13811385
print(Node->getChild(0), depth + 1);
13821386
return nullptr;
13831387
case Node::Kind::OutlinedInitializeWithCopy:
1388+
case Node::Kind::OutlinedInitializeWithCopyNoValueWitness:
13841389
Printer << "outlined init with copy of ";
13851390
print(Node->getChild(0), depth + 1);
13861391
return nullptr;
13871392
case Node::Kind::OutlinedAssignWithTake:
1393+
case Node::Kind::OutlinedAssignWithTakeNoValueWitness:
13881394
Printer << "outlined assign with take of ";
13891395
print(Node->getChild(0), depth + 1);
13901396
return nullptr;
13911397
case Node::Kind::OutlinedAssignWithCopy:
1398+
case Node::Kind::OutlinedAssignWithCopyNoValueWitness:
13921399
Printer << "outlined assign with copy of ";
13931400
print(Node->getChild(0), depth + 1);
13941401
return nullptr;
13951402
case Node::Kind::OutlinedDestroy:
1403+
case Node::Kind::OutlinedDestroyNoValueWitness:
13961404
Printer << "outlined destroy of ";
13971405
print(Node->getChild(0), depth + 1);
13981406
return nullptr;

0 commit comments

Comments
 (0)