Commit Graph

174 Commits

Author SHA1 Message Date
Erik Eckstein
ed8922bc8e PerformanceInliner: always inline synthesized enum comparisons if one of the operands is a constant enum
If there is a "constant" enum argument to a synthesized enum comparison, we can always inline it, because most of it will be constant folded anyway.
This ensures the compiler is not creating terrible code for very simple enum comparisons, like
```
   if someEnum == .someCase {
      ...
   }
```

rdar://85677499
2025-05-27 12:11:03 +02:00
Erik Eckstein
3cbe94d7d1 inliner: tune the heuristic for constructors to be inlined into global initializer functions.
Inlining constructors into global initializers increase the changes that the global can be initialized statically.
2025-05-20 20:46:33 +02:00
Kuba Mracek
9878da9046 [SILOptimizer] Expose SIL inliner heuristics/constants as -Xllvm configurable knobs 2025-04-18 10:03:26 -07:00
Erik Eckstein
6e17385325 add a semantic attribute "optimize.sil.inline.constant.arguments"
This forces inlining the annotated function if its arguments are constant.
2025-04-01 18:12:45 +02:00
Pavel Yaskevich
41c88f864a [SILOptimizer] Turn "is self-recursive" check into analysis
The body of a function has to be re-analyzed for every call
site of the function, which is very expensive and if the
body is not changed would produce the same result.

This takes about ~10% from swift-syntax overall build time
in release configuration.
2025-03-24 00:25:13 -07:00
Meghana Gupta
6908e9b776 Annotate some Span and InlineArray's methods with semantics 2025-02-28 09:52:00 -08:00
Erik Eckstein
6af5876f72 PerformanceInliner: add the @_semantics("optimize.sil.inline.aggressive") attribute to enable inlining into large functions.
This attribute overrides the limit of maximum number of basic blocks in the caller.
2025-02-13 07:40:24 +01:00
Erik Eckstein
3136218a64 PerformanceInliner: allow inlining of small functions even if the caller block limit is exceeded
This can fix performance problems in large functions.

rdar://141320229
2025-02-13 07:30:44 +01:00
Meghana Gupta
984f9f6cd2 Remove unreachable blocks after inlining 2024-12-10 17:01:11 -08:00
Anton Korobeynikov
55d51b782d Closure specialization might create functions with lots of arguments. (#77629)
Increase inlining benefits for functions with more than 5 arguments and / or results.
We assume that each argument beyond these 5 would be passed on stack and therefore would incur a pair of load and store.
2024-11-20 16:31:47 -08:00
Erik Eckstein
51e3e5ed80 Optimizer: rename BorrowArgumentsUpdater -> GuaranteedPhiUpdater
NFC
2024-11-12 09:26:59 +01:00
Erik Eckstein
6b8c6a3c3b SIL: rename updateBorrowedFrom to updateBorrowArguments
NFC
2024-11-12 09:26:58 +01:00
Kavon Farvardin
ba0aac3f39 Merge pull request #76093 from kavon/coldsplit-2
ColdBlockInfo: overhaul analysis pass
2024-09-12 16:06:07 -07:00
Kavon Farvardin
7203a4fa73 ColdBlockInfo: overhaul analysis pass
The old analysis pass doesn't take into account profile data, nor does
it consider post-dominance. It primarily dealt with _fastPath/_slowPath.

A block that is dominated by a cold block is itself cold. That's true
whether it's forwards or backwards dominance.

We can also consider a call to any `Never` returning function as a
cold-exit, though the block(s) leading up to that call may be executed
frequently because of concurrency. For now, I'm ignoring the concurrency
case and assuming it's cold. To make use of this "no return" prediction,
use the `-enable-noreturn-prediction` flag, which is currently off by
default.
2024-09-03 15:41:10 -07:00
Slava Pestov
ae77d6f0c1 AST: Replace one-off predicates with SubstitutionMap::getRecursiveProperties() 2024-08-21 13:19:10 -04:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Kshitij
12faf79911 [Autodiff] Adds logic to rewrite call-sites using functions specialized by the closure-spec optimization 2024-05-21 12:02:28 -07:00
Erik Eckstein
e14c1d1f62 SIL, Optimizer: update and handle borrowed-from instructions
Compute, update and handle borrowed-from instruction in various utilities and passes.
Also, used borrowed-from to simplify `gatherBorrowIntroducers` and `gatherEnclosingValues`.
Replace those utilities by `Value.getBorrowIntroducers` and `Value.getEnclosingValues`, which return a lazily computed Sequence of borrowed/enclosing values.
2024-04-10 13:38:10 +02:00
Ben Barham
9779c18da3 Rename startswith to starts_with
LLVM is presumably moving towards `std::string_view` -
`StringRef::startswith` is deprecated on tip. `SmallString::startswith`
was just renamed there (maybe with some small deprecation inbetween, but
if so, we've missed it).

The `SmallString::startswith` references were moved to
`.str().starts_with()`, rather than adding the `starts_with` on
`stable/20230725` as we only had a few of them. Open to switching that
over if anyone feels strongly though.
2024-03-13 22:25:47 -07:00
Erik Eckstein
71fcae7fe8 SwiftCompilerSources: add the ability to implement SIL verification in swift 2024-02-22 07:12:10 +01:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Meghana Gupta
8cb2086c62 [NFC] Add debug msgs to inliner 2023-12-13 10:38:12 -08:00
Kshitij
12e3a6ecfb [AutoDiff] Modify inlining logic to award inlining benefits to VJPs
Similar to #69029 but for VJPs.
2023-10-27 06:43:59 -10:00
Erik Eckstein
5b7cd4ef71 PerformanceInliner: favor inlining of co-routines
Not inlined co-routines are so expensive that they should be inlined, unless they are really large.
So far co-routines didn't get any special treatment in the inliner, except generic co-routines.
With this change, even non-generic co-routines are treated as high-priority to inline.

rdar://117201823
2023-10-24 10:36:19 +02:00
Kshitij
f973aa1423 [Autodiff] Modify inliner logic to award inlining benefits to linear maps w/ control-flow
For linear maps containing control-flow, closures (representing the pullbacks
of intermediate values) may be passed as arguments, however, they may be
hidden behind a branch-tracing enum (tracing execution flow of the original
function).

Such linear maps did not use to get inlining benefits as the compiler
could not see that the intermediate pullback closures were actually part
of the input.

This change modifies the inliner logic to correctly award inlining
benefits to linear maps containing control-flow, by checking if a
"callee" in the linear map actually traces back to an input closure that
was received as part of a branch-tracing enum input argument.

Fixes #68945
2023-10-08 14:37:13 -07:00
Erik Eckstein
480d3f490e SIL Optimizer: handle begin_dealloc_ref and end_init_let_ref in various optimizations 2023-09-19 15:10:30 +02:00
Evan Wilde
250082df25 [NFC] Reformat all the LLVMs
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
2023-06-27 09:03:52 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
Erik Eckstein
ee2924fd27 Inliner: don't distinguish between the "mid-level" and "late" inliner
Now that we handle inlined global initializers in LICM, CSE and the StringOptimization, we don't need to have a separate mid-level inliner pass, which treats global accessors specially.
2023-05-08 21:23:36 +02:00
Erik Eckstein
260e68b102 Passmanager: fix a problem with skipping the inliner pass
A pass is skipped if no other pass changed the function since the previous run of the same pass.
Don't do this is if a pass depends on the function bodies of called functions, e.g. the inliner.
Other passes might change the callees, e.g. function signature opts, which makes it worth to run the inliner
again, even if the function itself didn't change.
2023-05-08 21:23:36 +02:00
Erik Eckstein
0a4b0a8da7 PerformanceInliner: protect against misuse of @inline(__always)
Inline-always should only be used on relatively small functions. It must not be used on recursive functions.
Add a check that prevents that inlining of large @inline(__always) functions.

https://github.com/apple/swift/issues/64319
rdar://106655649
2023-03-27 17:29:37 +02:00
Nate Chandler
a8c5d4e4ce [PerformanceInliner] Stack nest at OSSA lowering.
Now that in OSSA `partial_apply [on_stack]`s are represented as owned
values rather than stack locations, it is possible for their destroys to
violate stack discipline.  A direct lowering of the instructions to
non-OSSA would violate stack nesting.

Previously, when inlining, it was assumed that non-coroutine callees
maintained stack discipline.  And, when inlining an OSSA function into a
non-OSSA function, OSSA instructions were lowered directly.  The result
was that stack discipline could be violated.

Here, when inlining a function in OSSA form into a function lowered out
of OSSA form, stack nesting is fixed up.
2023-02-28 15:40:46 -08:00
Nate Chandler
32685ce68e [Inliner] Add per-inlining verification.
Previously, there was an -Xllvm option to verify after all inlining to a
particlar caller.  That makes it a chore to track down which apply's
inlining resulted in invalid code.  Here, a new option is added that
verifies after each run of the inliner.
2023-02-28 15:40:46 -08:00
swift-ci
ec2d7fc847 Merge pull request #62198 from nate-chandler/opaque-values/3/20221118
[AddressLowering] Don't end_borrow trivial args.
2022-11-29 17:07:24 -08:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01:00
Nate Chandler
42aa21cc81 [NFC] Moved inlining printing to PassManager. 2022-11-18 16:29:51 -08:00
Erik Eckstein
0403a21d34 use the new side effects in the performance inliner 2022-11-09 08:06:19 +01:00
Erik Eckstein
13dad3ad47 PerformanceInliner: tweak the inlining heuristic for callees which return an allocated object
There are examples of such functions, which were previously captured by `isPureCall` in the inliner. But the implementation of `isPureCall` was wrong.
With the new (and correct) side effect analysis we need to correctly handle such functions in the inlining heuristic.
2022-11-09 08:06:19 +01:00
Josh Soref
730b16c569 Spelling siloptimizer
* access
* accessed
* accesses
* accessor
* acquiring
* across
* activated
* additive
* address
* addresses'
* aggregated
* analysis
* and
* appropriately
* archetype
* argument
* associated
* availability
* barriers
* because
* been
* beginning
* belongs
* beneficial
* blocks
* borrow
* builtin
* cannot
* canonical
* canonicalize
* clazz
* cleanup
* coalesceable
* coalesced
* comparisons
* completely
* component
* computed
* concrete
* conjunction
* conservatively
* constituent
* construct
* consuming
* containing
* covered
* creates
* critical
* dataflow
* declaration
* defined
* defining
* definition
* deinitialization
* deliberately
* dependencies
* dependent
* deserialized
* destroy
* deterministic
* deterministically
* devirtualizes
* diagnostic
* diagnostics
* differentiation
* disable
* discipline
* dominate
* dominates
* don't
* element
* eliminate
* eliminating
* elimination
* embedded
* encounter
* epilogue
* epsilon
* escape
* escaping
* essential
* evaluating
* evaluation
* evaluator
* executing
* existential
* existentials
* explicit
* expression
* extended
* extension
* extract
* for
* from
* function
* generic
* guarantee
* guaranteed
* happened
* heuristic
* however
* identifiable
* immediately
* implementation
* improper
* include
* infinite
* initialize
* initialized
* initializer
* inside
* instruction
* interference
* interferes
* interleaved
* internal
* intersection
* intractable
* intrinsic
* invalidates
* irreducible
* irrelevant
* language
* lifetime
* literal
* looks
* materialize
* meaning
* mergeable
* might
* mimics
* modification
* modifies
* multiple
* mutating
* necessarily
* necessary
* needsmultiplecopies
* nonetheless
* nothing
* occurred
* occurs
* optimization
* optimizing
* original
* outside
* overflow
* overlapping
* overridden
* owned
* ownership
* parallel
* parameter
* paths
* patterns
* pipeline
* plottable
* possible
* potentially
* practically
* preamble
* precede
* preceding
* predecessor
* preferable
* preparation
* probably
* projection
* properties
* property
* protocol
* reabstraction
* reachable
* recognized
* recursive
* recursively
* redundant
* reentrancy
* referenced
* registry
* reinitialization
* reload
* represent
* requires
* response
* responsible
* retrieving
* returned
* returning
* returns
* rewriting
* rewritten
* sample
* scenarios
* scope
* should
* sideeffects
* similar
* simplify
* simplifycfg
* somewhat
* spaghetti
* specialization
* specializations
* specialized
* specially
* statistically
* substitute
* substitution
* succeeds
* successful
* successfully
* successor
* superfluous
* surprisingly
* suspension
* swift
* targeted
* that
* that our
* the
* therefore
* this
* those
* threshold
* through
* transform
* transformation
* truncated
* ultimate
* unchecked
* uninitialized
* unlikely
* unmanaged
* unoptimized key
* updataflow
* usefulness
* utilities
* villain
* whenever
* writes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-10-03 18:31:33 -04:00
Nate Chandler
5b5ed561c5 Added printing during inlining.
Enable caller and callee to be printed as inlining runs.  The printing
is filtered based on -sil-print-function/-sil-print-functions and
includes finer-grained info than those do already.  The caller before
and after each callee is inlined can be printed as well as the callee
on its own as it exists when inlining occurs.
2022-03-15 13:11:47 -07:00
Erik Eckstein
7c28d7a625 migrate SILInliner to use InstructionDeleter 2021-10-28 18:43:14 +02:00
Andrew Trick
e85228491d Rename AccessedStorage to AccessStorage
to be consistent with AccessPath and AccessBase.

Otherwise, the arbitrary name difference adds constant friction.
2021-09-21 23:18:24 -07:00
Erik Eckstein
cf17fd4df4 SILOptimizer: Use BasicBlockData in the StackNesting utility 2021-01-20 16:09:01 +01:00
Erik Eckstein
b7351780f7 SIL: move all the block-list modifying APIs to SILFunction.
... and remove SILFunction::getBlocks().

It's just a cleanup, NFC.
2021-01-14 17:35:31 +01:00
Andrew Trick
6f2cda1390 Add AccessUseVisitor and cleanup related APIs.
Add AccesssedStorage::compute and computeInScope to mirror AccessPath.

Allow recovering the begin_access for Nested storage.

Adds AccessedStorage.visitRoots().
2020-10-16 15:00:10 -07:00
Arnold Schwaighofer
b994bf3191 Add support for _specialize(exported: true, ...)
This attribute allows to define a pre-specialized entry point of a
generic function in a library.

The following definition provides a pre-specialized entry point for
`genericFunc(_:)` for the parameter type `Int` that clients of the
library can call.

```
@_specialize(exported: true, where T == Int)
public func genericFunc<T>(_ t: T) { ... }
```

Pre-specializations of internal `@inlinable` functions are allowed.

```
@usableFromInline
internal struct GenericThing<T> {
  @_specialize(exported: true, where T == Int)
  @inlinable
  internal func genericMethod(_ t: T) {
  }
}
```

There is syntax to pre-specialize a method from a different module.

```
import ModuleDefiningGenericFunc

@_specialize(exported: true, target: genericFunc(_:), where T == Double)
func prespecialize_genericFunc(_ t: T) { fatalError("dont call") }

```

Specially marked extensions allow for pre-specialization of internal
methods accross module boundries (respecting `@inlinable` and
`@usableFromInline`).

```
import ModuleDefiningGenericThing
public struct Something {}

@_specializeExtension
extension GenericThing {
  @_specialize(exported: true, target: genericMethod(_:), where T == Something)
  func prespecialize_genericMethod(_ t: T) { fatalError("dont call") }
}
```

rdar://64993425
2020-10-12 09:19:29 -07:00
Kuba (Brecka) Mracek
5bf15f81b1 Add a -ignore-always-inline frontend flag which ignores @inline(__always) attributes. (#33466) 2020-09-01 20:20:09 -07:00
Michael Gottesman
96097b0879 [opt-remark] Add @_semantics("optremark{.$SIL_PASS_NAME}") that force opt remarks on functions.
More specifically, if one wants to force emit /all/ opt-remarks on a function, mark it with:

```
@_semantics("optremark")
```

If one wants to emit opt-remarks only for a specific SIL pass (like lets say
sil-opt-remark-gen), one can write:

```
@_semantics("optremark.sil-opt-remark-gen")
```

I made the pattern matching strict so if you just put in a '.' or add additional
suffixes, it will not pattern match. I think that this is sufficient for a
prototyping tool.

This is useful if one wants to play around with opt-remarks when optimizing code
in Xcode or any IDE that can use serialized diagnostics.
2020-07-26 14:55:02 -07:00
Michael Gottesman
750c8d32ac [opt-remark] Have OptEmitter store a SILFunction instead of a SILModule.
In all of these cases, we already had a SILFunction and were just grabbing its
SILModule instead of passing it in. So this is just an NFC change.

The reason why I am doing this is so that I can force emit opt-remarks on
functions with the semantics attribute "optremark", so I need to be able to
access the SILFunction in the optimization remark infrastructure.
2020-07-24 17:11:47 -07:00
Andrew Trick
5826e75b00 Generalize the MemAccessUtils API.
For use outside access enforcement passes.

Add isUniquelyIdentifiedAfterEnforcement.

Rename functions for clarity and generality.

Rename isUniquelyIdentifiedOrClass to isFormalAccessBase.

Rename findAccessedStorage to identifyFormalAccess.

Rename findAccessedStorageNonNested to findAccessedStorage.

Part of generalizing the utility for use outside the access
enforcement passes.
2020-07-17 10:13:20 -07:00