Commit Graph

411 Commits

Author SHA1 Message Date
Andrew Trick
4ce6fcf18f Fix SIL function side effects to handle unapplied escaping
Fixes rdar://113339972 DeadStoreElimination causes uninitialized closure context

Before this fix, the recently enabled function side effect implementation
would return no side effects for a partial apply that is not applied
in the same function. This resulted in DeadStoreElimination
incorrectly eliminating the initialization of the closure context.

The fix is to model the effects of capturing the arguments for the
closure context. The effects of running the closure body will be
considered later, at the point that the closure is
applied. Running the closure does, however, depend on the captured
values to be valid. If the value being captured is addressible,
then we need to model the effect of reading from that memory. In
this case, the capture reads from a local stack slot:

    %stack = alloc_stack $Klass
    store %ref to %stack : $*Klass
    %closure = partial_apply [callee_guaranteed] %f(%stack)
      : $@convention(thin) (@in_guaranteed Klass) -> ()

Later, when the closure is applied, we won't have any reference back
to the original stack slot. The application may not even happen in a caller.

Note that, even if the closure will be applied in the current
function, the side effects of the application are insufficient to
cover the side effects of the capture. For example, the closure
body itself may not read from an argument, but the context must
still be valid in case it is copied or if the capture itself was
not a bitwise-move.

As an optimization, we ignore the effect of captures for on-stack
partial applies. Such captures are always either a bitwise-move
or, more commonly, capture the source value by address. In these
cases, the side effects of applying the closure are sufficient to
cover the effects of the captures. And, if an on-stack closure is
not invoked in the current function (or passed to a callee) then
it will never be invoked, so the captures never have effects.
2023-08-16 11:58:11 -07:00
Erik Eckstein
afc0f617e0 Optimizer: support statically initialized globals which contain pointers to other globals
For example:
```
  var p = Point(x: 10, y: 20)
  let o = UnsafePointer(&p)
```

Also support outlined arrays with pointers to other globals. For example:
```
var g1 = 1
var g2 = 2

func f() -> [UnsafePointer<Int>] {
  return [UnsafePointer(&g1), UnsafePointer(&g2)]
}
```
2023-08-10 20:50:36 +02:00
Erik Eckstein
538d7306bd MandatoryPerformanceOptimizations: better handling of statically initialized globals which contain a pointer to another global
E.g.
```
  var p = Point(x: 10, y: 20)
  let o = UnsafePointer(&p)
```

MandatoryPerformanceOptimization must inline the accessor to the referenced global.
2023-08-10 20:49:20 +02:00
Erik Eckstein
7e33e554ef SIL: a few changes regarding access to a GlobalVariable's static initializer instructions
* add `GlobalVariable.staticInitializerInstructions` to access all initializer instructions of a global
* implement `GlobalVariable.staticInitValue` with `GlobalVariable.staticInitializerInstructions`
* this requires that `InstructionList.reversed()` works without accessing the parent block of the iterator instruction
* allow `Context.erase(instruction:)` to delete instructions from a global's initializer list, which means to handle the case where a deleted instruction has no parent function.
2023-08-10 20:49:20 +02:00
Erik Eckstein
89d3326ff4 Swift Optimizer: add a simplification for pointer_to_address
For a redundant pair of pointer-address conversions, e.g.

   %2 = address_to_pointer %1
   %3 = pointer_to_address %2 [strict]

replace all uses of %3 with %1.
2023-08-10 20:49:20 +02:00
Erik Eckstein
e45b82f4db AccessUtils: add AccessBase.hasLocalOwnershipLifetime 2023-08-10 20:49:20 +02:00
Erik Eckstein
8223b3e210 MandatoryPerformanceOptimizations: fix some problems with inilning
* don't inline functions if it's not possible - by checking `SILInliner::canInlineApplySite`
* fix stack nesting after inlining a `begin_apply`
2023-08-10 15:01:47 +02:00
Erik Eckstein
799bd0a5f5 Swift Optimizer: some reformatting in the optimization passes
Use tail closures for all optimization passes.
NFC.
2023-08-04 10:33:52 +02:00
Kuba (Brecka) Mracek
8510bdd7f0 Merge pull request #67587 from kubamracek/move-target-const-folding-to-swift-simplification
Move target const folding to swift simplification
2023-08-01 15:19:26 -07:00
Kuba Mracek
5dac59ce71 Move TargetConstantFolding pass to the simplification passes in Swift, enable using MemoryLayout's .size, .stride, .alignment fields in forced-const global initializers 2023-07-31 10:54:07 -07:00
Nate Chandler
e5d87f75a8 [SIL] Add source formal type to checked_cast_br.
It is necessary for opaque values where for casts that will newly start
out as checked_cast_brs and be lowered to checked_cast_addr_brs, since
the latter has the source formal type, IRGen relies on being able to
access it, and there's no way in general to obtain the source formal
type from the source lowered type.
2023-07-27 15:04:15 -07:00
Erik Eckstein
64255651f5 MandatoryPerformanceOptimizations: refine the inlining decisions in global initializers
We inline a function (e.g. a struct initializer) into a global init function if the result is part of the initialized global.
Now, also handle functions with indirect return values. Such function can result from not-reabstracted generic specializations.
Handle cases where the result is stored into a temporary alloc_stack or directly stored to (a part) of the global variable.
2023-07-26 11:06:50 +02:00
Erik Eckstein
393711d5f4 SimplifyBuiltin: ignore debug_step and debug_value when checking for side-effects in the callee of a builtin.once 2023-07-26 11:06:50 +02:00
Erik Eckstein
c567167b66 InitializeStaticGlobals: add a peephole to merge element stores to a single store.
Sometimes structs are not stored in one piece, but as individual elements. Merge such individual stores to a single store of the whole struct.
This enables generating a statically initialized global.
2023-07-26 11:06:50 +02:00
Erik Eckstein
29246fd80b AliasAnalysis: add complexity budget for the getMemEffectsFunction 2023-07-21 07:19:56 +02:00
Erik Eckstein
4d20423e00 Optimizer: re-implement the RedundantLoadElimination pass in Swift
The new implementation has several benefits compared to the old C++ implementation:

* It is significantly simpler. It optimizes each load separately instead of all at once with bit-field based dataflow.
* It's using alias analysis more accurately which enables more loads to be optimized
* It avoids inserting additional copies in OSSA

The algorithm is a data flow analysis which starts at the original load and searches for preceding stores or loads by following the control flow in backward direction.
The preceding stores and loads provide the "available values" with which the original load can be replaced.
2023-07-21 07:19:56 +02:00
Erik Eckstein
86771468fc Swift Optimizer: move StoreInst.split into OpUtils.swift
To make it available in other optimizations as well.
Also, a few problems:
* Use destructre instructions when in OSSA
* Don't split the store if it's nominal type has unreferenceable stoarge
* rename it to `trySplit` because it's not guaranteed to work

Also, add the counterpart for load instructions: `LoadInst.trySplit()`
2023-07-21 07:19:56 +02:00
Erik Eckstein
8739befa92 AccessUtils: let two tail-access bases with the same reference root be equivalent
This is possible now because projection path now models index-addressing correctly.
2023-07-21 07:19:56 +02:00
Erik Eckstein
80778dedd6 AccessUtils: use the begin_apply result instead of the begin_apply instruction for a yield access base
A begin_apply can yield multiple addresses. We need to store the result of the apply in order to distinguish between two AccessBases with different results from the same begin_apply.
2023-07-21 07:19:55 +02:00
Erik Eckstein
f623a879ce Swift Optimizer: add LoadInst.set(ownership:) 2023-07-21 07:19:12 +02:00
Erik Eckstein
ff913d2fa6 Swift Optimizer: add the FunctionPassContext.swiftArrayDecl API 2023-07-21 07:19:12 +02:00
Erik Eckstein
ee3d702019 Swift SIL: add NominalTypeDecl.isStructWithUnreferenceableStorage 2023-07-21 07:19:12 +02:00
Erik Eckstein
2baaf4890e Swift SIL: add a few new create functions in Builder 2023-07-21 07:19:12 +02:00
Erik Eckstein
2e9de24e2a Swift Optimizer: add the SSAUpdater utility 2023-07-21 07:19:12 +02:00
Erik Eckstein
45963939dd SwiftCompilerSources: fix a compiler error when building with hosttools
Fixes a simple copy-paste error, introduced in https://github.com/apple/swift/pull/67296
2023-07-20 16:50:26 +02:00
zoecarver
782641af68 [cxx-interop] ExpirementalFeature -> LanguageFeature. 2023-07-18 17:42:35 -07:00
zoecarver
2115f7aaf8 [cxx-interop] Add NewCxxMethodSafetyHeuristics feature and guard swift compiler sources changes on it. 2023-07-18 17:42:34 -07:00
Erik Eckstein
89b0de3563 StackPromotion: fix a crash due to a problem in liferange evaluation
The analysis to check if an alloc_ref outlives it's "inner" liferange had a bug which resulted in a crash in the StackPromotion pass

rdar://112275272
2023-07-17 14:55:55 +02:00
Kuba (Brecka) Mracek
e34c20fdf5 Merge pull request #67243 from kubamracek/section-ump
Allow forced constant-folding of global initializers to work on UnsafeMutablePointer types
2023-07-13 20:07:05 -07:00
Kuba Mracek
c09710bc9a Enhance enum simplifications in SILOptimizer to allow forced constant-folding of global initializers to work on UnsafeMutablePointer types 2023-07-13 08:31:53 -07:00
Kuba Mracek
d4d5228534 Allow constant folding IntToPtr builtin (make it isValidInStaticInitializerOfGlobal) 2023-07-12 20:51:40 -07:00
Erik Eckstein
9cb83c33eb DeadStoreElimination: some refactoring and improvements
Addresses review feedback of https://github.com/apple/swift/pull/67122
2023-07-11 22:33:03 +02:00
Erik Eckstein
efcd90af7d Swift SIL: rename ownership enums and properties in LoadInst and StoreInst
`ownership` is a bad name in `LoadInst`, because it hides `Value.ownership`.
Therefore rename it to `loadOwnership`.
Do the same for ownership in StoreInst to be consistent.
2023-07-11 22:33:02 +02:00
Kuba (Brecka) Mracek
2961cafb05 Merge pull request #66844 from kubamracek/static-init-structs
Allow using structs with trivial initializers in globals that require static initialization (e.g. @_section attribute)
2023-07-10 15:11:55 -07:00
Kuba Mracek
2bf728d6cb MandatoryPerformanceOptimizations: Use Set<PathFunctionTuple> to track inlined functions 2023-07-10 08:58:13 -07:00
Kuba Mracek
145f12f6a3 Allow using structs with trivial initializers in globals that require static initialization (e.g. @_section attribute)
Before this change, if a global variable is required to be statically initialized (e.g. due to @_section attribute), we don't allow its type to be a struct, only a scalar type works. This change improves on that by teaching MandatoryPerformanceOptimizations pass to inline struct initializer calls into initializer of globals, as long as they are simple enough so that we can be sure that we don't trigger recursive/infinite inlining.
2023-07-08 19:26:59 -07:00
Erik Eckstein
baaf5565b0 Optimizer: reimplement DeadStoreElimination in swift
The old C++ pass didn't catch a few cases.
Also:
* The new pass is significantly simpler: it doesn't perform dataflow for _all_ memory locations at once using bitfields, but handles each store separately. (In both implementations there is a complexity limit in place to avoid quadratic complexity)
* The new pass works with OSSA
2023-07-05 21:33:25 +02:00
Erik Eckstein
f96c13e925 MemBehavior: correctly handle debug_value
debug_value just "reads" the operand if it is an address.
2023-07-05 21:33:25 +02:00
Erik Eckstein
0494795ab4 Swift SIL: make BasicBlock Equatable 2023-07-05 21:33:25 +02:00
Erik Eckstein
ab915c308d Swift SIL: add the Deallocation.allocatedValue instruction API 2023-07-05 21:33:25 +02:00
Erik Eckstein
ff88efc1f6 - walk utils 2023-07-05 21:33:25 +02:00
Erik Eckstein
d635c89eb4 AccessUtils: add AccessBase.isEqual and AccessPath.isEqualOrOverlaps
Also add `Value.referenceRoot`
2023-07-05 21:33:25 +02:00
Erik Eckstein
205c841ed8 Swift SIL: add some Builder APIs
* `createStructExtract`
* `createStructElementAddr`
* `createTupleExtract`
* `createTupleElementAddr`
2023-07-05 21:33:24 +02:00
Erik Eckstein
8bb3e45b41 WalkUtils: more precise handling of existential projections and index_addr 2023-07-05 21:33:24 +02:00
Erik Eckstein
0d3fe6382e SmallProjectionPath: model existential projections and indexed elements
add field types:
  `x`:    existential address projection, like `open_existential_addr`
  `i<n>`: indexed element with constant index, like `index_addr` with an integer literal as index
  `i*`:   indexed element with an unknown index
2023-07-05 21:33:24 +02:00
Erik Eckstein
b03ef3cc80 AliasAnalysis: rename the main API functions
Instead of
  aliasAnalysis.mayRead(inst: i, fromAddress: a)
it's more natural to write
  i.mayRead(fromAddress: a, aliasAnalysis)
2023-07-05 21:33:24 +02:00
Erik Eckstein
36c8229562 StackPromotion: fix a problem with promoted allocations in dead-end regions
Allocations in dead-end regions cannot be promoted unconditionally, because such an object could escape to another thread.

rdar://111570874
2023-07-02 18:58:02 +02:00
John McCall
65e2e8c2fe Fix some SILArgument infrastructure for pack results.
Getting this right convinces the memory verifier to not complain
about untouched empty pack result arguments, which should be
innocuous.
2023-06-30 02:08:57 -04:00
Erik Eckstein
e77e2bcff7 IRGen: don't initialize the object headers of bare objects
For `alloc_ref [bare] [stack]` and `global_value [bare]` omit the object header initialization.
The `bare` flag means that the object header is not used.

This was already done with a peephole optimization inside IRGen for `global_value`. But now rely on the SIL `bare` flag.
2023-06-29 06:57:05 +02:00
Erik Eckstein
55c8c433c0 SILOptimizer: add the StripObjectHeader optimization pass
It sets the `[bare]` attribute for `alloc_ref` and `global_value` instructions if their header (reference count and metatype) is not used throughout the lifetime of the object.
2023-06-29 06:57:05 +02:00