Skip to content

Commit 8033476

Browse files
committed
Function-level optimization attributes.
For now these are underscored attributes, i.e. compiler internal attributes: @_optimize(speed) @_optimize(size) @_optimize(none) Those attributes override the command-line specified optimization mode for a specific function. The @_optimize(none) attribute is equivalent to the already existing @_semantics("optimize.sil.never") attribute
1 parent 8f9361a commit 8033476

28 files changed

+322
-32
lines changed

include/swift/AST/Attr.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ SIMPLE_DECL_ATTR(_implicitly_unwrapped_optional,
299299
ImplicitlyUnwrappedOptional,
300300
OnFunc | OnVar | OnSubscript | OnConstructor | RejectByParser, 72)
301301

302+
DECL_ATTR(_optimize, Optimize,
303+
OnFunc | OnConstructor | OnDestructor | OnSubscript | OnVar |
304+
UserInaccessible, 73)
305+
302306
#undef TYPE_ATTR
303307
#undef DECL_ATTR_ALIAS
304308
#undef SIMPLE_DECL_ATTR

include/swift/AST/Attr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/Basic/UUID.h"
2222
#include "swift/Basic/STLExtras.h"
2323
#include "swift/Basic/Range.h"
24+
#include "swift/Basic/OptimizationMode.h"
2425
#include "swift/Basic/Version.h"
2526
#include "swift/AST/Identifier.h"
2627
#include "swift/AST/AttrKind.h"
@@ -925,6 +926,23 @@ class InlineAttr : public DeclAttribute {
925926
}
926927
};
927928

929+
/// Represents the optimize attribute.
930+
class OptimizeAttr : public DeclAttribute {
931+
OptimizationMode Mode;
932+
public:
933+
OptimizeAttr(SourceLoc atLoc, SourceRange range, OptimizationMode mode)
934+
: DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false),
935+
Mode(mode) {}
936+
937+
OptimizeAttr(OptimizationMode mode)
938+
: OptimizeAttr(SourceLoc(), SourceRange(), mode) {}
939+
940+
OptimizationMode getMode() const { return Mode; }
941+
static bool classof(const DeclAttribute *DA) {
942+
return DA->getKind() == DAK_Optimize;
943+
}
944+
};
945+
928946
/// Represents the side effects attribute.
929947
class EffectsAttr : public DeclAttribute {
930948
EffectsKind Kind;

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,10 +1365,10 @@ ERROR(opened_attribute_id_value,none,
13651365
ERROR(opened_attribute_expected_rparen,none,
13661366
"expected ')' after id value for 'opened' attribute", ())
13671367

1368-
// inline
1369-
ERROR(inline_attribute_expect_option,none,
1370-
"expected '%0' option such as 'never'", (StringRef))
1371-
ERROR(inline_attribute_unknown_option,none,
1368+
// inline, optimize
1369+
ERROR(optimization_attribute_expect_option,none,
1370+
"expected '%0' option such as '%1'", (StringRef, StringRef))
1371+
ERROR(optimization_attribute_unknown_option,none,
13721372
"unknown option '%0' for attribute '%1'", (StringRef, StringRef))
13731373

13741374
// effects

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,8 +1024,6 @@ ERROR(functions_mutating_and_not,none,
10241024
ERROR(static_functions_not_mutating,none,
10251025
"static functions must not be declared mutating", ())
10261026

1027-
ERROR(transparent_stored_property,none,
1028-
"@_transparent cannot be applied to stored properties", ())
10291027
ERROR(transparent_in_protocols_not_supported,none,
10301028
"@_transparent is not supported on declarations within protocols", ())
10311029
ERROR(transparent_in_classes_not_supported,none,
@@ -3705,8 +3703,8 @@ ERROR(class_designated_init_inlineable_resilient,none,
37053703
"'%select{@_transparent|@inline(__always)|@_inlineable|%error}1' and must "
37063704
"delegate to another initializer", (Type, unsigned))
37073705

3708-
ERROR(inlineable_stored_property,
3709-
none, "'@_inlineable' attribute cannot be applied to stored properties", ())
3706+
ERROR(attribute_invalid_on_stored_property,
3707+
none, "@%0 cannot be applied to stored properties", (StringRef))
37103708

37113709
ERROR(inlineable_dynamic_not_supported,
37123710
none, "'@_inlineable' attribute cannot be applied to 'dynamic' declarations", ())

include/swift/AST/PrintOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ struct PrintOptions {
386386
result.PrintImplicitAttrs = false;
387387
result.ExcludeAttrList.push_back(DAK_Exported);
388388
result.ExcludeAttrList.push_back(DAK_Inline);
389+
result.ExcludeAttrList.push_back(DAK_Optimize);
389390
result.ExcludeAttrList.push_back(DAK_Rethrows);
390391
result.PrintOverrideKeyword = false;
391392
result.AccessFilter = AccessLevel::Public;

include/swift/Serialization/ModuleFormat.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 384; // Last change: begin_apply
57+
const uint16_t VERSION_MINOR = 385; // Last change: Optimization attribute
5858

5959
using DeclIDField = BCFixed<31>;
6060

@@ -1401,6 +1401,11 @@ namespace decls_block {
14011401
BCFixed<2> // inline value
14021402
>;
14031403

1404+
using OptimizeDeclAttrLayout = BCRecordLayout<
1405+
Optimize_DECL_ATTR,
1406+
BCFixed<2> // optimize value
1407+
>;
1408+
14041409
// Encodes a VersionTuple:
14051410
//
14061411
// Major

lib/AST/Attr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
340340
case DAK_AccessControl:
341341
case DAK_Ownership:
342342
case DAK_Effects:
343+
case DAK_Optimize:
343344
if (DeclAttribute::isDeclModifier(getKind())) {
344345
Printer.printKeyword(getAttrName());
345346
} else {
@@ -577,6 +578,18 @@ StringRef DeclAttribute::getAttrName() const {
577578
}
578579
llvm_unreachable("Invalid inline kind");
579580
}
581+
case DAK_Optimize: {
582+
switch (cast<OptimizeAttr>(this)->getMode()) {
583+
case OptimizationMode::NoOptimization:
584+
return "_optimize(none)";
585+
case OptimizationMode::ForSpeed:
586+
return "_optimize(speed)";
587+
case OptimizationMode::ForSize:
588+
return "_optimize(size)";
589+
default:
590+
llvm_unreachable("Invalid optimization kind");
591+
}
592+
}
580593
case DAK_Effects:
581594
switch (cast<EffectsAttr>(this)->getKind()) {
582595
case EffectsKind::ReadNone:

lib/Parse/ParseDecl.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,8 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
613613
}
614614

615615
if (Tok.isNot(tok::identifier)) {
616-
diagnose(Loc, diag::inline_attribute_expect_option, AttrName);
616+
diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
617+
"none");
617618
return false;
618619
}
619620

@@ -623,7 +624,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
623624
else if (Tok.getText() == "__always")
624625
kind = InlineKind::Always;
625626
else {
626-
diagnose(Loc, diag::inline_attribute_unknown_option,
627+
diagnose(Loc, diag::optimization_attribute_unknown_option,
627628
Tok.getText(), AttrName);
628629
return false;
629630
}
@@ -642,6 +643,46 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
642643
break;
643644
}
644645

646+
case DAK_Optimize: {
647+
if (!consumeIf(tok::l_paren)) {
648+
diagnose(Loc, diag::attr_expected_lparen, AttrName,
649+
DeclAttribute::isDeclModifier(DK));
650+
return false;
651+
}
652+
653+
if (Tok.isNot(tok::identifier)) {
654+
diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
655+
"speed");
656+
return false;
657+
}
658+
659+
OptimizationMode optMode = OptimizationMode::NotSet;
660+
if (Tok.getText() == "none")
661+
optMode = OptimizationMode::NoOptimization;
662+
else if (Tok.getText() == "speed")
663+
optMode = OptimizationMode::ForSpeed;
664+
else if (Tok.getText() == "size")
665+
optMode = OptimizationMode::ForSize;
666+
else {
667+
diagnose(Loc, diag::optimization_attribute_unknown_option,
668+
Tok.getText(), AttrName);
669+
return false;
670+
}
671+
consumeToken(tok::identifier);
672+
AttrRange = SourceRange(Loc, Tok.getRange().getStart());
673+
674+
if (!consumeIf(tok::r_paren)) {
675+
diagnose(Loc, diag::attr_expected_rparen, AttrName,
676+
DeclAttribute::isDeclModifier(DK));
677+
return false;
678+
}
679+
680+
if (!DiscardAttribute)
681+
Attributes.add(new (Context) OptimizeAttr(AtLoc, AttrRange, optMode));
682+
683+
break;
684+
}
685+
645686
case DAK_Ownership: {
646687
// Handle weak/unowned/unowned(unsafe).
647688
Ownership Kind = AttrName == "weak" ? Ownership::Weak : Ownership::Unowned;

lib/ParseSIL/ParseSIL.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,9 @@ void SILParser::convertRequirements(SILFunction *F,
878878
static bool parseDeclSILOptional(bool *isTransparent,
879879
IsSerialized_t *isSerialized,
880880
IsThunk_t *isThunk, bool *isGlobalInit,
881-
Inline_t *inlineStrategy, bool *isLet,
881+
Inline_t *inlineStrategy,
882+
OptimizationMode *optimizationMode,
883+
bool *isLet,
882884
SmallVectorImpl<std::string> *Semantics,
883885
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
884886
ValueDecl **ClangDecl,
@@ -907,6 +909,12 @@ static bool parseDeclSILOptional(bool *isTransparent,
907909
*isGlobalInit = true;
908910
else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
909911
*inlineStrategy = NoInline;
912+
else if (optimizationMode && SP.P.Tok.getText() == "Onone")
913+
*optimizationMode = OptimizationMode::NoOptimization;
914+
else if (optimizationMode && SP.P.Tok.getText() == "Ospeed")
915+
*optimizationMode = OptimizationMode::ForSpeed;
916+
else if (optimizationMode && SP.P.Tok.getText() == "Osize")
917+
*optimizationMode = OptimizationMode::ForSize;
910918
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
911919
*inlineStrategy = AlwaysInline;
912920
else if (MRK && SP.P.Tok.getText() == "readnone")
@@ -5012,13 +5020,15 @@ bool SILParserTUState::parseDeclSIL(Parser &P) {
50125020
IsThunk_t isThunk = IsNotThunk;
50135021
bool isGlobalInit = false;
50145022
Inline_t inlineStrategy = InlineDefault;
5023+
OptimizationMode optimizationMode = OptimizationMode::NotSet;
50155024
SmallVector<std::string, 1> Semantics;
50165025
SmallVector<ParsedSpecAttr, 4> SpecAttrs;
50175026
ValueDecl *ClangDecl = nullptr;
50185027
EffectsKind MRK = EffectsKind::Unspecified;
50195028
if (parseSILLinkage(FnLinkage, P) ||
50205029
parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
5021-
&inlineStrategy, nullptr, &Semantics, &SpecAttrs,
5030+
&inlineStrategy, &optimizationMode, nullptr,
5031+
&Semantics, &SpecAttrs,
50225032
&ClangDecl, &MRK, FunctionState) ||
50235033
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
50245034
P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -5045,6 +5055,7 @@ bool SILParserTUState::parseDeclSIL(Parser &P) {
50455055
FunctionState.F->setThunk(IsThunk_t(isThunk));
50465056
FunctionState.F->setGlobalInit(isGlobalInit);
50475057
FunctionState.F->setInlineStrategy(inlineStrategy);
5058+
FunctionState.F->setOptimizationMode(optimizationMode);
50485059
FunctionState.F->setEffectsKind(MRK);
50495060
if (ClangDecl)
50505061
FunctionState.F->setClangNodeOwner(ClangDecl);
@@ -5173,7 +5184,7 @@ bool SILParserTUState::parseSILGlobal(Parser &P) {
51735184
SILParser State(P);
51745185
if (parseSILLinkage(GlobalLinkage, P) ||
51755186
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
5176-
nullptr, &isLet, nullptr, nullptr, nullptr,
5187+
nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
51775188
nullptr, State) ||
51785189
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
51795190
P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
@@ -5216,7 +5227,7 @@ bool SILParserTUState::parseSILVTable(Parser &P) {
52165227

52175228
IsSerialized_t Serialized = IsNotSerialized;
52185229
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
5219-
nullptr, nullptr, nullptr, nullptr, nullptr,
5230+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
52205231
nullptr, VTableState))
52215232
return true;
52225233

@@ -5565,7 +5576,7 @@ bool SILParserTUState::parseSILWitnessTable(Parser &P) {
55655576

55665577
IsSerialized_t isSerialized = IsNotSerialized;
55675578
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
5568-
nullptr, nullptr, nullptr, nullptr, nullptr,
5579+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
55695580
nullptr, WitnessState))
55705581
return true;
55715582

lib/SIL/SILModule.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
354354
*this, SA->getRequirements(), SA->isExported(), kind));
355355
}
356356

357+
if (auto *OA = Attrs.getAttribute<OptimizeAttr>()) {
358+
F->setOptimizationMode(OA->getMode());
359+
}
360+
357361
// @_silgen_name and @_cdecl functions may be called from C code somewhere.
358362
if (Attrs.hasAttribute<SILGenNameAttr>() ||
359363
Attrs.hasAttribute<CDeclAttr>())

0 commit comments

Comments
 (0)