Commit Graph

2037 Commits

Author SHA1 Message Date
Nate Chandler
1cd2bdfacf [StackNesting] NFC: Allocs are just insts.
Stop requiring that allocation instructions produce single values.
2023-06-05 08:11:28 -07:00
Nate Chandler
389fb97b44 [StackNesting] NFC: Added helper.
Just pull the notion that the alloc corresponds to operand 0 into a
helper method.
2023-06-05 08:11:28 -07:00
Erik Eckstein
a80d0cb8a7 remove now unused utilities
* StaticInitCloner
* some APIs in SILGlobalVariable
2023-05-22 15:34:26 +02:00
Erik Eckstein
4284dc10d0 Optimizer: implement the ObjectOutliner pass in Swift 2023-05-22 15:34:26 +02:00
Erik Eckstein
f3851f7503 Optimizer: implement load simplification in Swift 2023-05-22 15:34:26 +02:00
Erik Eckstein
585395b67c Swift Optimizer: add Context.lookupStdlibFunction 2023-05-22 15:34:26 +02:00
Erik Eckstein
38de5b1ab5 Swift SIL/Optimizer: implement cloning of static init values of globals in Swift
* add the StaticInitCloner utility
* remove bridging of `copyStaticInitializer` and `createStaticInitializer`
* add `Context.mangleOutlinedVariable` and `Context.createGlobalVariable`
2023-05-22 15:34:26 +02:00
Andrew Trick
11053dc4f1 Add salvageLoadDebugInfo to handle LoadInst
Before deleting a load, simply rewrite its debug info to refer to the
loaded address:

%l = load %a
debug_value %l, loc0, scope0, var0

--->

debug_value %a, loc0, scope0, var0, expr op_deref
%l = load %a

Note that alloc_stack addresses do not require the addition of
op_deref because they are already special-cased in IRGen.

This will be called from salvageDebugInfo when it is supported by
optmizations. Until then, it is only called selectively at -Onone.
2023-05-16 09:54:25 -07:00
Andrew Trick
91c4efea95 Move the LoadOperation abstraction to InstructionUtils.h
This is a fundamental abstraction over loads. It was in
OwnershipOptUtils because load_borrow happens to be restricted by
OSSA. Passes should not include OwnershipOptUtils just because they
work with loads.
2023-05-15 15:20:57 -07:00
Michael Gottesman
3ccda34275 Revert "[move-only] Ensure that we treat captured escaping closure arguments as such even if the closure doesn't actually escape"
This reverts commit 224674cad1.

Originally, I made this change since we were going to follow the AST in a strict
way in terms of what closures are considered escaping or not from a diagnostics
perspective. Upon further investigation I found that we actually do something
different for inout escaping semantics and by treating the AST as the one point
of truth, we are being inconsistent with the rest of the compiler. As an
example, the following code is considered by the compiler to not be an invalid
escaping use of an inout implying that we do not consider the closure to be
escaping:

```
func f(_ x: inout Int) {
  let g = {
    _ = x
  }
}
```

in contrast, a var is always considered to be an escape:

```
func f(_ x: inout Int) {
  var g = {
    _ = x
  }
}

test2.swift:3:13: error: escaping closure captures 'inout' parameter 'x'
    var g = {
            ^
test2.swift:2:10: note: parameter 'x' is declared 'inout'
func f(_ x: inout Int) {
         ^
test2.swift:4:11: note: captured here
        _ = x
          ^
```

Of course, if we store the let into memory, we get the error one would expect:

```
var global: () -> () = {}
func f(_ x: inout Int) {
  let g = {
    _ = x
  }
  global = g
}

test2.swift:4:11: error: escaping closure captures 'inout' parameter 'x'
  let g = {
          ^
test2.swift:3:10: note: parameter 'x' is declared 'inout'
func f(_ x: inout Int) {
         ^
test2.swift:5:7: note: captured here
    _ = x
      ^
```

By reverting to the old behavior where allocbox to stack ran early, noncopyable
types now have the same sort of semantics: let closures that capture a
noncopyable type that do not on the face of it escape are considered
non-escaping, while if the closure is ever stored into memory (e.x.: store into
a global, into a local var) or escapes, we get the appropriate escaping
diagnostics. E.x.:

```
public struct E : ~Copyable {}
public func borrowVal(_ e: borrowing E) {}
public func consumeVal(_ e: consuming E) {}

func f1() {
  var e = E()

  // Mutable borrowing use of e. We can consume e as long as we reinit at end
  // of function. We don't here, so we get an error.
  let c1: () -> () = {
    borrowVal(e)
    consumeVal(e)
  }

  // Mutable borrowing use of e. We can consume e as long as we reinit at end
  // of function. We do do that here, so no error.
  let c2: () -> () = {
    borrowVal(e)
    consumeVal(e)
    e = E()
  }
}

```
2023-05-14 13:34:36 -07:00
Erik Eckstein
6d13bf188f SIL Optimizer: handle dead-end infinite loops in StackNesting
Fixes a verifier crash caused by a not properly nested alloc-dealloc pair

rdar://109204178
2023-05-11 16:16:13 +02:00
nate-chandler
3d146b8230 Merge pull request #65686 from nate-chandler/canonicalize-guaranteed-value/dont-hoist-forwards
[CanonicalizeGuaranteedValue] Rewrite forwards in place.
2023-05-11 07:01:12 -07:00
Erik Eckstein
13108d69f6 SILOptimizer: remove the obsolete MandatoryGenericSpecializer pass 2023-05-11 08:11:44 +02:00
Erik Eckstein
dc3cb18029 Swift Optimizer: add the MandatoryPerformanceOptimizations pass
As a replacement for the old MandatoryGenericSpecializer

The pass it not enabled yet in the pass pipeline
2023-05-11 08:11:44 +02:00
Erik Eckstein
b9169064c6 Swift SIL: add some APIs
* `Options.assertConfiguration`
* `Argument.isIndirectResult`
* in `Function`: `selfArgument`, `isTransparent`, `performanceConstraints` and `inlineStrategy`
* `BuiltinInst.substitutionMap`
* `SubstitutionMap.replacementTypes`
* `Type.canBeClass`
2023-05-11 08:11:44 +02:00
Erik Eckstein
82734b6ac2 Swift Optimizer: simplification for apply, try_apply, begin_apply and partial_apply
* move the apply of partial_apply transformation from simplify-apply to simplify-partial_apply
* delete dead partial_apply instructions
* devirtualize apply, try_apply and begin_apply
2023-05-11 08:11:44 +02:00
Erik Eckstein
92a17f8a01 Optimizer: extract the NamedReturnValueOptimization from CopyForwarding to a separate function pass
This allows to run the NamedReturnValueOptimization only late in the pipeline.
The optimization shouldn't be done before serialization, because it might prevent predictable memory optimizations in the caller after inlining.
2023-05-11 08:11:44 +02:00
Erik Eckstein
fa1ecff143 Swift Optimizer: rewrite the MemBehaviorDumper test pass in swift. 2023-05-09 08:25:09 +02:00
Erik Eckstein
df7c71badb Optimizer: remove the now obsolete GlobalOpt pass 2023-05-08 21:23:36 +02:00
Erik Eckstein
960ca70def Swift Optimizer: add the module pass ReadOnlyGlobalVariables
It marks global `var` variables as `let` if they are never written.
2023-05-08 21:23:36 +02:00
Erik Eckstein
6d6b94e430 Swift Optimizer: add the InitializeStaticGlobals function pass
It converts a lazily initialized global to a statically initialized global variable.

When this pass runs on a global initializer `[global_init_once_fn]` it tries to create a static initializer for the initialized global.
```
  sil [global_init_once_fn] @globalinit {
    alloc_global @the_global
    %a = global_addr @the_global
    %i = some_const_initializer_insts
    store %i to %a
  }
```

The pass creates a static initializer for the global:
```
  sil_global @the_global = {
    %initval = some_const_initializer_insts
  }
```

and removes the allocation and store instructions from the initializer function:
```
  sil [global_init_once_fn] @globalinit {
    %a = global_addr @the_global
    %i = some_const_initializer_insts
  }
```

The initializer then becomes a side-effect free function which let's the builtin-simplification remove the `builtin "once"` which calls the initializer.
2023-05-08 21:23:36 +02:00
Erik Eckstein
2b117fd3ee Swift Optimizer: add APIs to copy from or to a global static initializer
* `Context.copyStaticInitializer(fromInitValue:, to:)`
* `FunctionPassContext.createStaticInitializer(for:,initValue:)`
2023-05-08 21:23:36 +02: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
3e04b8681c make ModulePassContext conform to CustomStringConvertible
and let its description return a dump of the whole module.
This is useful for debugging
2023-05-08 21:23:36 +02:00
Erik Eckstein
e95c6425f2 Swift SIL: add some APIs for global variables 2023-05-08 21:23:36 +02:00
Erik Eckstein
9b51e69dac Swift Optimizer: constant fold builtins in the simplification passes 2023-05-08 21:23:36 +02:00
Nate Chandler
5ab9a00e31 [CanonicalizeGuaranteedValue] Cleared everything. 2023-05-04 20:12:16 -07:00
Nate Chandler
88103a7287 [InstructionDeleter] Add fixLifetime argument.
Clients may not want the lifetime to be fixed up.
2023-05-04 20:12:16 -07:00
Michael Gottesman
224674cad1 [move-only] Ensure that we treat captured escaping closure arguments as such even if the closure doesn't actually escape
Specifically, we already have the appropriate semantics for arguments captured
by escaping closures but in certain cases allocbox to stack is able to prove
that the closure doesn’t actually escape. This results in the capture being
converted into a non-escaping SIL form. This then causes the move checker to
emit the wrong kind of error.

The solution is to create an early allocbox to stack that doesn’t promote move
only types in boxes from heap -> stack if it is captured by an escaping closure
but does everything else normally. Then once the move checking is completed, we
run alloc box to stack an additional time to ensure that we keep the guarantee
that heap -> stack is performed in those cases.

rdar://108905586
2023-05-04 12:25:19 -07:00
eeckstein
ddc0219928 Merge pull request #65592 from eeckstein/fix-sil-verifier
MemoryLifetimeVerifier: be more precise with indirect function arguments.
2023-05-04 07:52:34 +02:00
Erik Eckstein
4b33b99ee2 MemoryLifetimeVerifier: be more precise with indirect function arguments.
Optimizations can rely on alias analysis to know that an in-argument (or parts of it) is not actually read.
We have to do the same in the verifier: if alias analysis says that an in-argument is not read, there is no need that the memory location is initialized.

Fixes a false verifier error.
rdar://106806899
2023-05-03 14:33:45 +02:00
Erik Eckstein
da3f126322 CalleeAnalysis: no need to provide the PassManager to the getMemBehaviorFn
A NFC simplification
2023-05-03 14:33:45 +02:00
Nate Chandler
f952b0cc7e [PrunedLiveness] Removed invalidate.
The method doesn't do what clients expect.
2023-05-02 11:51:53 -07:00
Nate Chandler
3e08f5141b [CanonicalizeBorrowScope] Adopted BitfieldRef. 2023-05-02 11:51:53 -07:00
Nate Chandler
3c4275a422 [CanonicalizeOSSALifetime] Renamed member.
The member just clears the values.  After it adopted BitfieldRef, the
call to invalidate on the liveness instance was already superfluous.
2023-05-02 11:51:52 -07:00
Michael Gottesman
7e992cef6c [move-only] When emitting exclusivity diagnostics for move only types, do not suggest to the user to make a local copy.
It doesn't make sense to give this note since one can't make a copy of a
noncopyable type.

rdar://108511627
2023-04-25 10:51:04 -07:00
Ravi Kandhadai
e02d27c7d2 [Constant Evaluator] Enable SILConstants::setIndexedElement function
to work with aggregates containing unknown values. Such aggregates
can be generated when an instruction is skipped during constant
evaluation and its results are used to create a struct.
2023-04-06 21:41:39 -07:00
Anton Korobeynikov
8990a12bee Fix use after free when pullback is used multiple times. (#64647)
Linear maps are captured in vjp routine via callee-guaranteed partial apply and are passed as @owned references to the enclosing pullback that finally consumes them. Necessary retains are inserted by a partial apply forwarder.

However, this is not the case when the function being differentiated contains loops as heap-allocated context is used and bare pointer is captured by the pullback partial apply. As a result, partial apply forwarder does not retain the linear maps that are owned by a heap-allocated context, however, they are still treated as @owned references and therefore are released in the pullback after the first call. As a result, subsequent pullback calls release linear maps and we'd end with possible use-after-free.

Ensure we retain values when we load values from the context.

Reproducible only when:

 * Loops (so, heap-allocated context)
 * Pullbacks of thick functions (so context is non-zero)
 * Multiple pullback calls
 * Some cleanup while there

Fixes #64257
2023-03-28 01:36:38 -07:00
Nate Chandler
1a7c4a4d12 [NFC] Renamed DestroyAddrHoisting.
It was previously named SSADestroyHoisting which is rather misleading
considering that it deals with addresses and hoists destroy_addrs.
2023-03-27 14:15:03 -07:00
Nate Chandler
ec3f005f31 [CanonOSSALifetime] Run on lexical lifetimes.
Previously, the utility bailed out on lexical lifetimes because it
didn't respect deinit barriers.  Here, deinit barriers are found and
added to liveness if the value is lexical.  This enables copies to be
propagated without hoisting destroys over deinit barriers.

rdar://104630103
2023-03-25 21:17:26 -07:00
Nate Chandler
5614b63481 [Reachability] Added findBarriersBackward. 2023-03-25 12:27:57 -07:00
Nate Chandler
4d4042931b [Reachability] NFC: Allow more initial blocks.
Allow clients to specify any number (an array) of blocks beyond which
dataflow won't propagate rather than 1 or 0 (a pointer).
2023-03-25 12:27:57 -07:00
Nate Chandler
3e9f112be2 [Reachability] Removed restrictive assert. 2023-03-25 12:27:57 -07:00
Andrew Trick
747d8a35fd [NFC] ParseTestSpecification rename a variable
Because it doesn't really hold a "string".
2023-03-23 01:56:19 -07:00
Andrew Trick
119e712c32 Merge pull request #64534 from atrick/liveblocks-bitfield
Cleanup PrunedLiveBlocks
2023-03-22 16:33:08 -07:00
Andrew Trick
cbe856e53a Cleanup PrunedLiveBlocks
Use BasicBlockBitfield to record per-block liveness state. This has
been the intention since BasicBlockBitfield was first introduced.

Remove the per-field bitfield from PrunedLiveBlocks. This
(re)specializes the data structure for scalar liveness and drastically
simplifies the implementation.

This utility is fundamental to all ownership utilities. It will be on
the critical path in many areas of the compiler, including at
-Onone. It needs to be minimal and as easy as possible for compiler
engineers to understand, investigate, and debug.

This is in preparation for fixing bugs related to multi-def liveness
as used by the move checker.
2023-03-22 02:36:57 -07:00
Andrew Trick
ae64ff5cb0 Rename PrunedLiveness.clear() to invalidate()
Because SILBitfield cannot be cleared.
2023-03-22 01:36:48 -07:00
Andrew Trick
15796e3ff9 PrunedLiveness: add a SILFunction argument
So that liveness can migrate to using a SILBitfield.
2023-03-22 01:36:48 -07:00
Erik Eckstein
67299b4471 SIL bridging: work around an unresolved symbol linker error
Works around  problem https://github.com/apple/swift/issues/64502
2023-03-21 15:33:09 +01:00