Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/HighLevelSILOptimizations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,19 +313,19 @@ Dictionary
~~~~~~~~~~
TBD.

@effects attribute
@_effects attribute
~~~~~~~~~~~~~~~~~~~~~~~~~~~

The @effects attribute describes how a function affects "the state of the world".
The @_effects attribute describes how a function affects "the state of the world".
More practically how the optimizer can modify the program based on information
that is provided by the attribute.

Usage:

@effects(readonly) func foo() { .. }
@_effects(readonly) func foo() { .. }


The @effects attribute supports the following tags:
The @_effects attribute supports the following tags:

readnone

Expand Down Expand Up @@ -363,13 +363,13 @@ releasenone
}
}

@effects(releasenone)
@_effects(releasenone)
func validReleaseNoneFunction(x: Int) -> Int {
global.x = 5
return x + 2
}

@effects(releasenone)
@_effects(releasenone)
func validReleaseNoneFunction(x: Int) -> Int {
var notExternallyVisibleObject = SomeObject()
return x + notExternallyVisibleObject.x
Expand Down
22 changes: 11 additions & 11 deletions docs/proposals/OptimizerEffects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ don't have a more general term for "release", which refers to any
release_value operation.

When referring to unspecified state, I will use the syntax
``@effects(no<effectname>)``. When referring to state reachable via an
``@_effects(no<effectname>)``. When referring to state reachable via an
argument, ``@no<effectname> arg``.

Naturally, we also need a syntax for associating effects with
Expand All @@ -110,7 +110,7 @@ effects at a call site. For now, we assume the predicate only applies
to unspecified state and that the bridged object is always self. That
way we can denote predicated effects as @nonbridged_effects.

In examples, @effects(argonly) means that there are no effects on
In examples, @_effects(argonly) means that there are no effects on
unspecified state.

CoW Optimization Requirements
Expand Down Expand Up @@ -167,7 +167,7 @@ state.

Note: In terms of low-level SIL attributes such a method will be marked:::

@effects(argonly)
@_effects(argonly)
@selfeffects(make_unique)
func makeUnique() {}

Expand Down Expand Up @@ -230,7 +230,7 @@ state.

Note: In terms of low-level SIL attributes such a method will be marked:::

@effects(argonly)
@_effects(argonly)
@selfeffects(preserve_unique, nowrite, nocapture, norelease,
projects_subobject)
func getElement(_ index: Int) -> T {}
Expand Down Expand Up @@ -297,7 +297,7 @@ state.

Note: In terms of low-level SIL attributes such a method will be marked:::

@effects(argonly)
@_effects(argonly)
@selfeffects(preserve_unique, nowrite, nocapture, norelease,
projects_subobject_addr)
func getElementAddr(_ index: Int) -> T {}
Expand All @@ -320,7 +320,7 @@ state.

Note: In terms of low-level SIL attributes such a method will be marked:::

@effects(argonly)
@_effects(argonly)
@selfeffects(preserve_unique, nocapture, norelease)
func appendElementAssumingUnique(@norelease @nowrite elt: T) {}

Expand Down Expand Up @@ -356,7 +356,7 @@ state.

Note: In terms of low-level SIL attributes such a method will be marked:::

@effects(argonly, T.release)
@_effects(argonly, T.release)
@selfeffects(preserve_unique, nocapture)
func setElement(@nowrite e: T, index: Int) {
}
Expand Down Expand Up @@ -536,15 +536,15 @@ Mostly TBD.

The optimizer can only take advantage of user-specified effects before
they have been inlined. Consequently, the optimizer initially preserves
calls to annotated @effects() functions. After optimizing for effects
calls to annotated @_effects() functions. After optimizing for effects
these functions can be inlined, dropping the effects information.

Without special syntax, specifying a pure function would require::

@effects(argonly)
@_effects(argonly)
func foo(@noread @nowrite arg)

A shorthand, such as @effects(none) could easily be
A shorthand, such as @_effects(none) could easily be
introduced. Typically, this shouldn't be needed because the purity of
a function can probably be deduced from its argument types given that
it has no effect on unspecified state. i.e. If the function does not
Expand Down Expand Up @@ -576,7 +576,7 @@ example. But there are two situations to be concerned about:
Solving this requires a system for polymorphic effects. Language
support for polymorphic effects might look something like this::

@effects(T.release)
@_effects(T.release)
func foo<T>(t: T) { ... }

This would mean that foo's unspecified effects are bounded by the
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Attr.def
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ CONTEXTUAL_DECL_ATTR(weak, ReferenceOwnership,
DeclModifier |
NotSerialized, 49)
CONTEXTUAL_DECL_ATTR_ALIAS(unowned, ReferenceOwnership)
DECL_ATTR(effects, Effects,
DECL_ATTR(_effects, Effects,
OnAbstractFunction |
UserInaccessible,
50)
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/AttrKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ enum class InlineKind : uint8_t {
enum : unsigned { NumInlineKindBits =
countBitsUsed(static_cast<unsigned>(InlineKind::Last_InlineKind)) };

/// This enum represents the possible values of the @effects attribute.
/// This enum represents the possible values of the @_effects attribute.
/// These values are ordered from the strongest guarantee to the weakest,
/// so please do not reorder existing values.
enum class EffectsKind : uint8_t {
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ class SILFunction
/// \return the function side effects information.
EffectsKind getEffectsKind() const { return EffectsKindAttr; }

/// \return True if the function is annotated with the @effects attribute.
/// \return True if the function is annotated with the @_effects attribute.
bool hasEffectsKind() const {
return EffectsKindAttr != EffectsKind::Unspecified;
}
Expand Down
4 changes: 2 additions & 2 deletions include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,8 @@ class FunctionSideEffects {
}

protected:
/// Set the side-effects of a function, which has an @effects attribute.
/// Returns true if \a F has an @effects attribute which could be handled.
/// Set the side-effects of a function, which has an @_effects attribute.
/// Returns true if \a F has an @_effects attribute which could be handled.
bool setDefinedEffects(SILFunction *F);

/// Set the side-effects of a semantic call.
Expand Down
6 changes: 3 additions & 3 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2222,7 +2222,7 @@ Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
}

/// Return True if the function \p f is a 'readonly' function. Checking
/// for the SIL @effects(readonly) attribute is not enough because this
/// for the SIL @_effects(readonly) attribute is not enough because this
/// definition does not match the definition of the LLVM readonly function
/// attribute. In this function we do the actual check.
static bool isReadOnlyFunction(SILFunction *f) {
Expand All @@ -2235,11 +2235,11 @@ static bool isReadOnlyFunction(SILFunction *f) {
auto Eff = f->getEffectsKind();

// Swift's readonly does not automatically match LLVM's readonly.
// Swift SIL optimizer relies on @effects(readonly) to remove e.g.
// Swift SIL optimizer relies on @_effects(readonly) to remove e.g.
// dead code remaining from initializers of strings or dictionaries
// of variables that are not used. But those initializers are often
// not really readonly in terms of LLVM IR. For example, the
// Dictionary.init() is marked as @effects(readonly) in Swift, but
// Dictionary.init() is marked as @_effects(readonly) in Swift, but
// it does invoke reference-counting operations.
if (Eff == EffectsKind::ReadOnly || Eff == EffectsKind::ReadNone) {
// TODO: Analyze the body of function f and return true if it is
Expand Down
6 changes: 3 additions & 3 deletions lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ bool FunctionSideEffects::setDefinedEffects(SILFunction *F) {
case EffectsKind::ReadNone:
return true;
case EffectsKind::ReadOnly:
// @effects(readonly) is worthless if we have owned parameters, because
// @_effects(readonly) is worthless if we have owned parameters, because
// the release inside the callee may call a deinit, which itself can do
// anything.
if (!F->hasOwnedParameters()) {
Expand All @@ -356,7 +356,7 @@ bool FunctionSideEffects::summarizeFunction(SILFunction *F) {
if (!F->empty())
ParamEffects.resize(F->getArguments().size());

// Handle @effects attributes
// Handle @_effects attributes
if (setDefinedEffects(F)) {
DEBUG(llvm::dbgs() << " -- has defined effects " << F->getName() << '\n');
return true;
Expand Down Expand Up @@ -463,7 +463,7 @@ bool FunctionSideEffects::summarizeCall(FullApplySite fullApply) {
}

if (SILFunction *SingleCallee = fullApply.getReferencedFunction()) {
// Does the function have any @effects?
// Does the function have any @_effects?
if (setDefinedEffects(SingleCallee))
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/Transforms/PerformanceInliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@ class SILPerformanceInlinerPass : public SILFunctionTransform {
} // end anonymous namespace

/// Create an inliner pass that does not inline functions that are marked with
/// the @_semantics, @effects or global_init attributes.
/// the @_semantics, @_effects or global_init attributes.
SILTransform *swift::createEarlyInliner() {
return new SILPerformanceInlinerPass(
InlineSelection::NoSemanticsAndGlobalInit, "Early");
Expand All @@ -937,7 +937,7 @@ SILTransform *swift::createPerfInliner() {
}

/// Create an inliner pass that inlines all functions that are marked with
/// the @_semantics, @effects or global_init attributes.
/// the @_semantics, @_effects or global_init attributes.
SILTransform *swift::createLateInliner() {
return new SILPerformanceInlinerPass(InlineSelection::Everything, "Late");
}
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ SILFunction *swift::getEligibleFunction(FullApplySite AI,
auto ModuleName = Callee->getModule().getSwiftModule()->getName().str();
bool IsInStdlib = (ModuleName == STDLIB_NAME || ModuleName == SWIFT_ONONE_SUPPORT);

// Don't inline functions that are marked with the @_semantics or @effects
// Don't inline functions that are marked with the @_semantics or @_effects
// attribute if the inliner is asked not to inline them.
if (Callee->hasSemanticsAttrs() || Callee->hasEffectsKind()) {
if (WhatToInline == InlineSelection::NoSemanticsAndGlobalInit) {
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/core/Character.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ extension Character
}

@inlinable // FIXME(sil-serialize-all)
@effects(readonly)
@_effects(readonly)
public init(_builtinUnicodeScalarLiteral value: Builtin.Int32) {
self.init(Unicode.Scalar(_builtinUnicodeScalarLiteral: value))
}
Expand All @@ -139,7 +139,7 @@ extension Character
// integer constant in case of small character literals.
@inlinable // FIXME(sil-serialize-all)
@inline(__always)
@effects(readonly)
@_effects(readonly)
public init(
_builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
utf8CodeUnitCount: Builtin.Word,
Expand Down Expand Up @@ -194,7 +194,7 @@ extension Character
// integer constant in case of small character literals.
@inlinable // FIXME(sil-serialize-all)
@inline(__always)
@effects(readonly)
@_effects(readonly)
public init(
_builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
utf16CodeUnitCount: Builtin.Word
Expand Down Expand Up @@ -483,7 +483,7 @@ extension Character: Hashable {
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
@effects(releasenone)
@_effects(releasenone)
public func hash(into hasher: inout Hasher) {
// FIXME(performance): constructing a temporary string is extremely
// wasteful and inefficient.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Dictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ extension Dictionary: ExpressibleByDictionaryLiteral {
/// - Parameter elements: The key-value pairs that will make up the new
/// dictionary. Each key in `elements` must be unique.
@inlinable // FIXME(sil-serialize-all)
@effects(readonly)
@_effects(readonly)
public init(dictionaryLiteral elements: (Key, Value)...) {
self.init(_nativeBuffer: _NativeDictionaryBuffer.fromArray(elements))
}
Expand Down
Loading