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;

lib/Demangling/OldRemangler.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,6 +2549,24 @@ ManglingError Remangler::mangleOutlinedDestroy(Node *node, unsigned depth) {
25492549
Buffer << "Wh";
25502550
return mangleSingleChildNode(node, depth + 1);
25512551
}
2552+
ManglingError Remangler::mangleOutlinedInitializeWithCopyNoValueWitness(Node *node,
2553+
unsigned depth) {
2554+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2555+
}
2556+
2557+
ManglingError Remangler::mangleOutlinedAssignWithTakeNoValueWitness(Node *node,
2558+
unsigned depth) {
2559+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2560+
}
2561+
2562+
ManglingError Remangler::mangleOutlinedAssignWithCopyNoValueWitness(Node *node,
2563+
unsigned depth) {
2564+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2565+
}
2566+
2567+
ManglingError Remangler::mangleOutlinedDestroyNoValueWitness(Node *node, unsigned depth) {
2568+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2569+
}
25522570
ManglingError Remangler::mangleOutlinedEnumTagStore(Node *node, unsigned depth) {
25532571
Buffer << "Wi";
25542572
return mangleSingleChildNode(node, depth + 1);

lib/Demangling/Remangler.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,6 +3315,34 @@ ManglingError Remangler::mangleOutlinedDestroy(Node *node, unsigned depth) {
33153315
Buffer << "WOh";
33163316
return ManglingError::Success;
33173317
}
3318+
3319+
ManglingError Remangler::mangleOutlinedInitializeWithCopyNoValueWitness(Node *node,
3320+
unsigned depth) {
3321+
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
3322+
Buffer << "WOC";
3323+
return ManglingError::Success;
3324+
}
3325+
3326+
ManglingError Remangler::mangleOutlinedAssignWithTakeNoValueWitness(Node *node,
3327+
unsigned depth) {
3328+
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
3329+
Buffer << "WOD";
3330+
return ManglingError::Success;
3331+
}
3332+
3333+
ManglingError Remangler::mangleOutlinedAssignWithCopyNoValueWitness(Node *node,
3334+
unsigned depth) {
3335+
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
3336+
Buffer << "WOF";
3337+
return ManglingError::Success;
3338+
}
3339+
3340+
ManglingError Remangler::mangleOutlinedDestroyNoValueWitness(Node *node, unsigned depth) {
3341+
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
3342+
Buffer << "WOH";
3343+
return ManglingError::Success;
3344+
}
3345+
33183346
ManglingError Remangler::mangleOutlinedEnumGetTag(Node *node, unsigned depth) {
33193347
RETURN_IF_ERROR(mangleChildNodes(node, depth + 1));
33203348
Buffer << "WOg";

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6216,7 +6216,8 @@ IRGenModule::getOrCreateHelperFunction(StringRef fnName, llvm::Type *resultTy,
62166216
ArrayRef<llvm::Type*> paramTys,
62176217
llvm::function_ref<void(IRGenFunction &IGF)> generate,
62186218
bool setIsNoInline,
6219-
bool forPrologue) {
6219+
bool forPrologue,
6220+
bool isPerformanceConstraint) {
62206221
llvm::FunctionType *fnTy =
62216222
llvm::FunctionType::get(resultTy, paramTys, false);
62226223

@@ -6225,7 +6226,7 @@ IRGenModule::getOrCreateHelperFunction(StringRef fnName, llvm::Type *resultTy,
62256226
Module.getOrInsertFunction(fnName, fnTy).getCallee());
62266227

62276228
if (llvm::Function *def = shouldDefineHelper(*this, fn, setIsNoInline)) {
6228-
IRGenFunction IGF(*this, def);
6229+
IRGenFunction IGF(*this, def, isPerformanceConstraint);
62296230
if (DebugInfo && !forPrologue)
62306231
DebugInfo->emitArtificialFunction(IGF, def);
62316232
generate(IGF);

lib/IRGen/IRGenFunction.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,14 @@ static llvm::cl::opt<bool> EnableTrapDebugInfo(
4040
llvm::cl::desc("Generate failure-message functions in the debug info"));
4141

4242
IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn,
43+
bool isPerformanceConstraint,
4344
OptimizationMode OptMode,
4445
const SILDebugScope *DbgScope,
4546
llvm::Optional<SILLocation> DbgLoc)
4647
: IGM(IGM), Builder(IGM.getLLVMContext(),
4748
IGM.DebugInfo && !IGM.Context.LangOpts.DebuggerSupport),
48-
OptMode(OptMode), CurFn(Fn), DbgScope(DbgScope) {
49+
OptMode(OptMode), isPerformanceConstraint(isPerformanceConstraint),
50+
CurFn(Fn), DbgScope(DbgScope) {
4951

5052
// Make sure the instructions in this function are attached its debug scope.
5153
if (IGM.DebugInfo) {
@@ -83,6 +85,12 @@ bool IRGenFunction::canStackPromotePackMetadata() const {
8385
!packMetadataStackPromotionDisabled;
8486
}
8587

88+
bool IRGenFunction::outliningCanCallValueWitnesses() const {
89+
if (!IGM.getOptions().UseTypeLayoutValueHandling)
90+
return false;
91+
return !isPerformanceConstraint && !IGM.Context.LangOpts.hasFeature(Feature::Embedded);
92+
}
93+
8694
ModuleDecl *IRGenFunction::getSwiftModule() const {
8795
return IGM.getSwiftModule();
8896
}

lib/IRGen/IRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class IRGenFunction {
7474
/// If != OptimizationMode::NotSet, the optimization mode specified with an
7575
/// function attribute.
7676
OptimizationMode OptMode;
77+
bool isPerformanceConstraint;
7778

7879
llvm::Function *CurFn;
7980
ModuleDecl *getSwiftModule() const;
@@ -82,6 +83,7 @@ class IRGenFunction {
8283
const IRGenOptions &getOptions() const;
8384

8485
IRGenFunction(IRGenModule &IGM, llvm::Function *fn,
86+
bool isPerformanceConstraint = false,
8587
OptimizationMode Mode = OptimizationMode::NotSet,
8688
const SILDebugScope *DbgScope = nullptr,
8789
llvm::Optional<SILLocation> DbgLoc = llvm::None);
@@ -252,6 +254,8 @@ class IRGenFunction {
252254
/// heapified.
253255
bool canStackPromotePackMetadata() const;
254256

257+
bool outliningCanCallValueWitnesses() const;
258+
255259
void setupAsync(unsigned asyncContextIndex);
256260
bool isAsync() const { return asyncContextLocation.isValid(); }
257261

lib/IRGen/IRGenMangler.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -552,48 +552,53 @@ class IRGenMangler : public Mangle::ASTMangler {
552552
}
553553

554554
std::string mangleOutlinedInitializeWithTakeFunction(CanType t,
555-
CanGenericSignature sig) {
555+
CanGenericSignature sig,
556+
bool noValueWitness) {
556557
beginMangling();
557558
appendType(t, sig);
558559
if (sig)
559560
appendGenericSignature(sig);
560-
appendOperator("WOb");
561+
appendOperator(noValueWitness ? "WOB" : "WOb");
561562
return finalize();
562563
}
563564
std::string mangleOutlinedInitializeWithCopyFunction(CanType t,
564-
CanGenericSignature sig) {
565+
CanGenericSignature sig,
566+
bool noValueWitness) {
565567
beginMangling();
566568
appendType(t, sig);
567569
if (sig)
568570
appendGenericSignature(sig);
569-
appendOperator("WOc");
571+
appendOperator(noValueWitness ? "WOC" : "WOc");
570572
return finalize();
571573
}
572574
std::string mangleOutlinedAssignWithTakeFunction(CanType t,
573-
CanGenericSignature sig) {
575+
CanGenericSignature sig,
576+
bool noValueWitness) {
574577
beginMangling();
575578
appendType(t, sig);
576579
if (sig)
577580
appendGenericSignature(sig);
578-
appendOperator("WOd");
581+
appendOperator(noValueWitness ? "WOD" : "WOd");
579582
return finalize();
580583
}
581584
std::string mangleOutlinedAssignWithCopyFunction(CanType t,
582-
CanGenericSignature sig) {
585+
CanGenericSignature sig,
586+
bool noValueWitness) {
583587
beginMangling();
584588
appendType(t, sig);
585589
if (sig)
586590
appendGenericSignature(sig);
587-
appendOperator("WOf");
591+
appendOperator(noValueWitness ? "WOF" : "WOf");
588592
return finalize();
589593
}
590594
std::string mangleOutlinedDestroyFunction(CanType t,
591-
CanGenericSignature sig) {
595+
CanGenericSignature sig,
596+
bool noValueWitness) {
592597
beginMangling();
593598
appendType(t, sig);
594599
if (sig)
595600
appendGenericSignature(sig);
596-
appendOperator("WOh");
601+
appendOperator(noValueWitness ? "WOH" : "WOh");
597602
return finalize();
598603
}
599604

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,8 @@ class IRGenModule {
11751175
ArrayRef<llvm::Type*> paramTypes,
11761176
llvm::function_ref<void(IRGenFunction &IGF)> generate,
11771177
bool setIsNoInline = false,
1178-
bool forPrologue = false);
1178+
bool forPrologue = false,
1179+
bool isPerformanceConstraint = false);
11791180

11801181
llvm::Constant *getOrCreateRetainFunction(const TypeInfo &objectTI, SILType t,
11811182
llvm::Type *llvmType, Atomicity atomicity);

lib/IRGen/IRGenSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,7 @@ IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM, SILFunction *f)
18201820
: IRGenFunction(IGM,
18211821
IGM.getAddrOfSILFunction(f, ForDefinition,
18221822
f->isDynamicallyReplaceable()),
1823+
f->isPerformanceConstraint(),
18231824
f->getOptimizationMode(), f->getDebugScope(),
18241825
f->getLocation()),
18251826
CurSILFn(f) {

0 commit comments

Comments
 (0)