Skip to content

Commit 86f23b0

Browse files
committed
SIL: add the [perf_constraint] flag in SILFunction
Specifies that the optimizer and IRGen must not add runtime calls which are not in the function originally. This attribute is set for functions with performance constraints or functions which are called from functions with performance.
1 parent 0bdc011 commit 86f23b0

File tree

8 files changed

+49
-5
lines changed

8 files changed

+49
-5
lines changed

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/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/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/SIL/IR/SILFunction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ void SILFunction::init(
210210
this->UseStackForPackMetadata = DoUseStackForPackMetadata;
211211
this->HasUnsafeNonEscapableResult = false;
212212
this->HasResultDependsOnSelf = false;
213+
this->IsPerformanceConstraint = false;
213214
this->stackProtection = false;
214215
this->Inlined = false;
215216
this->Zombie = false;

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,6 +3367,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
33673367
case PerformanceConstraints::NoObjCBridging: OS << "[no_objc_bridging] "; break;
33683368
}
33693369

3370+
if (isPerformanceConstraint())
3371+
OS << "[perf_constraint] ";
3372+
33703373
if (getEffectsKind() == EffectsKind::ReadOnly)
33713374
OS << "[readonly] ";
33723375
else if (getEffectsKind() == EffectsKind::ReadNone)

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ static bool parseDeclSILOptional(
675675
SILFunction **usedAdHocRequirementWitness, Identifier *objCReplacementFor,
676676
SILFunction::Purpose *specialPurpose, Inline_t *inlineStrategy,
677677
OptimizationMode *optimizationMode, PerformanceConstraints *perfConstraints,
678+
bool *isPerformanceConstraint,
678679
bool *markedAsUsed, StringRef *section, bool *isLet, bool *isWeakImported,
679680
bool *needStackProtection, AvailabilityContext *availability,
680681
bool *isWithoutActuallyEscapingThunk,
@@ -774,6 +775,8 @@ static bool parseDeclSILOptional(
774775
*perfConstraints = PerformanceConstraints::NoExistentials;
775776
else if (perfConstraints && SP.P.Tok.getText() == "no_objc_bridging")
776777
*perfConstraints = PerformanceConstraints::NoObjCBridging;
778+
else if (isPerformanceConstraint && SP.P.Tok.getText() == "perf_constraint")
779+
*isPerformanceConstraint = true;
777780
else if (markedAsUsed && SP.P.Tok.getText() == "used")
778781
*markedAsUsed = true;
779782
else if (section && SP.P.Tok.getText() == "section") {
@@ -7033,6 +7036,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
70337036
Inline_t inlineStrategy = InlineDefault;
70347037
OptimizationMode optimizationMode = OptimizationMode::NotSet;
70357038
PerformanceConstraints perfConstr = PerformanceConstraints::None;
7039+
bool isPerformanceConstraint = false;
70367040
bool markedAsUsed = false;
70377041
StringRef section;
70387042
SmallVector<std::string, 1> Semantics;
@@ -7050,7 +7054,8 @@ bool SILParserState::parseDeclSIL(Parser &P) {
70507054
&useStackForPackMetadata, &hasUnsafeNonEscapableResult,
70517055
&isExactSelfClass, &DynamicallyReplacedFunction,
70527056
&AdHocWitnessFunction, &objCReplacementFor, &specialPurpose,
7053-
&inlineStrategy, &optimizationMode, &perfConstr, &markedAsUsed,
7057+
&inlineStrategy, &optimizationMode, &perfConstr,
7058+
&isPerformanceConstraint, &markedAsUsed,
70547059
&section, nullptr, &isWeakImported, &needStackProtection,
70557060
&availability, &isWithoutActuallyEscapingThunk, &Semantics,
70567061
&SpecAttrs, &ClangDecl, &MRK, FunctionState, M) ||
@@ -7106,6 +7111,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
71067111
FunctionState.F->setInlineStrategy(inlineStrategy);
71077112
FunctionState.F->setOptimizationMode(optimizationMode);
71087113
FunctionState.F->setPerfConstraints(perfConstr);
7114+
FunctionState.F->setIsPerformanceConstraint(isPerformanceConstraint);
71097115
FunctionState.F->setEffectsKind(MRK);
71107116

71117117
if (ClangDecl)
@@ -7302,6 +7308,7 @@ bool SILParserState::parseSILGlobal(Parser &P) {
73027308
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
73037309
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
73047310
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7311+
nullptr,
73057312
nullptr, nullptr, nullptr, nullptr, nullptr, &isLet,
73067313
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
73077314
nullptr, nullptr, State, M) ||
@@ -7356,7 +7363,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
73567363
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
73577364
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
73587365
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7359-
nullptr, nullptr, SP, M))
7366+
nullptr, nullptr, nullptr, SP, M))
73607367
return true;
73617368

73627369
ValueDecl *VD;
@@ -7426,7 +7433,7 @@ bool SILParserState::parseSILVTable(Parser &P) {
74267433
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
74277434
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
74287435
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7429-
nullptr, nullptr, VTableState, M))
7436+
nullptr, nullptr, nullptr, VTableState, M))
74307437
return true;
74317438

74327439
// Parse the class name.
@@ -7537,7 +7544,7 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) {
75377544
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75387545
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75397546
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7540-
nullptr, nullptr, moveOnlyDeinitTableState, M))
7547+
nullptr, nullptr, nullptr, moveOnlyDeinitTableState, M))
75417548
return true;
75427549

75437550
// Parse the class name.
@@ -8024,7 +8031,7 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
80248031
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
80258032
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
80268033
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8027-
nullptr, nullptr, WitnessState, M))
8034+
nullptr, nullptr, nullptr, WitnessState, M))
80288035
return true;
80298036

80308037
// Parse the protocol conformance.

0 commit comments

Comments
 (0)