Commit Graph

1057 Commits

Author SHA1 Message Date
Michael Gottesman
3c411cbc14 [mem-access-utils] Teach memInstMustInitialize that indirect out parameters are initializing.
Just something I noticed while reading the code.
2021-12-03 11:36:08 -08:00
Michael Gottesman
1ea21dbf87 Merge pull request #40287 from gottesmm/pr-8bb19fcfe173f5e7b33ddd95dcbc5566be2262b8
[sil] Ban casting AnyObject with a guaranteed ownership forwarding checked_cast_br and fix up semantic-arc-opts given that.
2021-11-29 21:26:32 -08:00
Michael Gottesman
8e5fb2164a [sil] Ban casting AnyObject with a guaranteed ownership forwarding checked_cast_br and fix up semantic-arc-opts given that.
The reason why I am doing this is that currently checked_cast_br of an AnyObject
may return a different value due to boxing. As an example, this can occur when
performing a checked_cast_br of a __SwiftValue(AnyHashable(Klass())).

To model this in SIL, I added to OwnershipForwardingMixin a bit of information
that states if the instruction directly forwards ownership with a default value
of true. In checked_cast_br's constructor though I specialize this behavior if
the source type is AnyObject and thus mark the checked_cast_br as not directly
forwarding its operand. If an OwnershipForwardingMixin directly forwards
ownership, one can assume that if it forwards ownership, it will always do so in
a way that ensures that each forwarded value is rc-identical to whatever result
it algebraically forwards ownership to. So in the context of checked_cast_br, it
means that the source value is rc-identical to the argument of the success and
default blocks.

I added a verifier check to CheckedCastBr that makes sure that it can never
forward guaranteed ownership and have a source type of AnyObject.

In SemanticARCOpts, I modified the code that builds extended live ranges of
owned values (*) to check if a OwnershipForwardingMixin is directly
forwarding. If it is not directly forwarding, then we treat the use just as an
unknown consuming use. This will then prevent us from converting such an owned
value to guaranteed appropriately in such a case.

I also in SILGen needed to change checked_cast_br emission in SILGenBuilder to
perform an ensurePlusOne on the input operand (converting it to +1 with an
appropriate cleanup) if the source type is an AnyObject. I found this via the
verifier check catching this behavior from SILGen when compiling libswift. This
just shows how important IR verification of invariants can be.

(*) For those unaware, SemanticARCOpts contains a model of an owned value and
all forwarding uses of it called an OwnershipLiveRange.

rdar://85710101
2021-11-29 15:39:00 -08:00
Erik Eckstein
f97876c9e7 RLE: better handling of ref_element/tail_addr [immutable]
Rerun RLE with cutting off the base address of loads at `ref_element/tail_addr [immutable]`. This increases the chance of catching loads of immutable COW class properties or elements.
2021-11-29 09:41:05 +01:00
Erik Eckstein
27dc5afb10 libswift: add a few utilities
* add the IntegerLiteralInst + the Builder function to create it
* add Value.nonDebugUses
* add a general utility Sequence.isEmpty
* add PassContext.replaceAllUses
* add a function to erase all `debug_value` uses in PassContext.erase
2021-11-29 09:41:05 +01:00
Meghana Gupta
39f74bb980 Merge pull request #40002 from meg-gupta/newfixoutliner
Fix OSSA Outliner for scoped guaranteed values
2021-11-17 15:39:36 -08:00
Andrew Trick
76b30e30f5 SILVerifier - allow rebind_memory token to cross functions
Remove a completely unnecessary assertion to handle reasonable use
cases.
2021-11-15 19:10:40 -08:00
Andrew Trick
90c0c8b60f Add rebind_memory SIL instruction.
Required for UnsafeRawPointer.withMemoryReboud(to:).

%out_token = rebind_memory %0 : $Builtin.RawPointer to %in_token

%0 must be of $Builtin.RawPointer type

%in_token represents a cached set of bound types from a prior memory state.

%out_token is an opaque $Builtin.Word representing the previously bound
types for this memory region.

This instruction's semantics are identical to ``bind_memory``, except
that the types to which memory will be bound, and the extent of the
memory region is unknown at compile time. Instead, the bound-types are
represented by a token that was produced by a prior memory binding
operation. ``%in_token`` must be the result of bind_memory or
2021-11-14 22:44:46 -08:00
Michael Gottesman
4aa4ac3027 [moveOnly] Add checker that validates that if a let/param copyable value has _move applied to it, the let doesn't have any later uses.
This is just an initial prototype for people to play with. It is as always
behind the -enable-experimental-move-only flag.

NOTE: In this PR I implemented this only for 'local let' like things (local
lets/params). I did not implement in this PR support for local var and haven't
done anything with class ivars or globals.

rdar://83957028
2021-11-04 17:13:29 -07:00
Meghana Gupta
59cb243385 Add a new utility to mark a new block as reachable in DeadEndBlocks 2021-11-01 14:03:22 -07:00
Michael Gottesman
f9122a79b7 [moveOnly] Implement a new _copy function that performs an explicit copy value.
The key thing is that the move checker will not consider the explicit copy value
to be a copy_value that can be rewritten, ensuring that any uses of the result
of the explicit copy_value (consuming or other wise) are not checked.

Similar to the _move operator I recently introduced, this is a transparent
function so we can perform one level of specialization and thus at least be
generic over all concrete types.
2021-10-29 15:37:46 -07:00
eeckstein
d5ae51130d Merge pull request #39902 from eeckstein/performance-annotations
First prototype of Performance Annotations
2021-10-29 07:39:41 +02:00
nate-chandler
03361671be Merge pull request #39939 from nate-chandler/dce/keep-outer-borrow-scope-alive-when-reborrowing
[DCE] Keep outer borrows alive when reborrowing.
2021-10-28 15:31:29 -07:00
Erik Eckstein
ff2db93922 SIL/IRGen: analysis of runtime effects for an instruction
Define the possible runtime effects of an instruction in an enum `RuntimeEffect`.
Add a new utility `swift:getRuntimeEffect` to estimate the runtime effects of an instruction.

Also, add a mechanism to validate the correctness of the analysis in IRGen: annotate all runtime functions in RuntimeFunctions.def with the actual effect what the runtime function has or can have. Then check if the effects of emitted runtime functions for an instruction match what `getRuntimeEffect` predicts.
This check is only enabled on demand by defining the CHECK_RUNTIME_EFFECT_ANALYSIS macro in RuntimeEffect.h
2021-10-28 18:43:14 +02:00
Michael Gottesman
114789707c [moveOnly] Implement a semi-generic _move function that can be used on non-generic, non-existential values.
This patch introduces a new stdlib function called _move:

```Swift
  @_alwaysEmitIntoClient
  @_transparent
  @_semantics("lifetimemanagement.move")
  public func _move<T>(_ value: __owned T) -> T {
  #if $ExperimentalMoveOnly
    Builtin.move(value)
  #else
    value
  #endif
  }
```

It is a first attempt at creating a "move" function for Swift, albeit a skleton
one since we do not yet perform the "no use after move" analysis. But this at
leasts gets the skeleton into place so we can built the analysis on top of it
and churn tree in a manageable way. Thus in its current incarnation, all it does
is take in an __owned +1 parameter and returns it after moving it through
Builtin.move.

Given that we want to use an OSSA based analysis for our "no use after move"
analysis and we do not have opaque values yet, we can not supporting moving
generic values since they are address only. This has stymied us in the past from
creating this function. With the implementation in this PR via a bit of
cleverness, we are now able to support this as a generic function over all
concrete types by being a little clever.

The trick is that when we transparent inline _move (to get the builtin), we
perform one level of specialization causing the inlined Builtin.move to be of a
loadable type. If after transparent inlining, we inline builtin "move" into a
context where it is still address only, we emit a diagnostic telling the user
that they applied move to a generic or existential and that this is not yet
supported.

The reason why we are taking this approach is that we wish to use this to
implement a new (as yet unwritten) diagnostic pass that verifies that _move
(even for non-trivial copyable values) ends the lifetime of the value. This will
ensure that one can write the following code to reliably end the lifetime of a
let binding in Swift:

```Swift
  let x = Klass()
  let _ = _move(x)
  // hypotheticalUse(x)
```

Without the diagnostic pass, if one were to write another hypothetical use of x
after the _move, the compiler would copy x to at least hypotheticalUse(x)
meaning the lifetime of x would not end at the _move, =><=.

So to implement this diagnostic pass, we want to use the OSSA infrastructure and
that only works on objects! So how do we square this circle: by taking advantage
of the mandatory SIL optimzier pipeline! Specifically we take advantage of the
following:

1. Mandatory Inlining and Predictable Dead Allocation Elimination run before any
   of the move only diagnostic passes that we run.

2. Mandatory Inlining is able to specialize a callee a single level when it
   inlines code. One can take advantage of this to even at -Onone to
   monomorphosize code.

and then note that _move is such a simple function that predictable dead
allocation elimination is able to without issue eliminate the extra alloc_stack
that appear in the caller after inlining without issue. So we (as the tests
show) get SIL that for concrete types looks exactly like we just had run a
move_value for that specific type as an object since we promote away the
stores/loads in favor of object operations when we eliminate the allocation.

In order to prevent any issue with this being used in a context where multiple
specializations may occur, I made the inliner emit a diagnostic if it inlines
_move into a function that applies it to an address only value. The diagnostic
is emitted at the source location where the function call occurs so it is easy
to find, e.x.:

```
func addressOnlyMove<T>(t: T) -> T {
    _move(t) // expected-error {{move() used on a generic or existential value}}
}

moveonly_builtin_generic_failure.swift:12:5: error: move() used on a generic or existential value
    _move(t)
    ^
```

To eliminate any potential ABI impact, if someone calls _move in a way that
causes it to be used in a context where the transparent inliner will not inline
it, I taught IRGen that Builtin.move is equivalent to a take from src -> dst and
marked _move as always emit into client (AEIC). I also took advantage of the
feature flag I added in the previous commit in order to prevent any cond_fails
from exposing Builtin.move in the stdlib. If one does not pass in the flag
-enable-experimental-move-only then the function just returns the value without
calling Builtin.move, so we are safe.

rdar://83957028
2021-10-27 19:36:49 -07:00
Nate Chandler
5d85ad393c [SILOpt] Add utility to find guaranteed roots.
The new utility looks through ownership forwarding instructions to find
the original values with guaranteed ownership.
2021-10-27 10:44:18 -07:00
Jonathan Grynspan
f1bf7badba [SE-0322] Temporary uninitialized buffers
Adds two new IRGen-level builtins (one for allocating, the other for deallocating), a stdlib shim function for enhanced stack-promotion heuristics, and the proposed public stdlib functions.
2021-10-25 11:20:10 -04:00
Nate Chandler
42f318d9ef [Basic] Renamed GraphNodeWorklist.
Addressed the TODO saying that DAGNodeWorklist should be renamed
GraphNodeWorklist.
2021-10-18 08:55:13 -07:00
Nate Chandler
51fd5f4156 Used DAGNodeWorklist in visitTransitiveEndBorrows.
Replaced a SmallSetVector worklist with a GraphNodeWorklist to avoid
infinitely pushing and popping the same value the same value into and
out from the worklist.
2021-10-15 13:35:22 -07:00
Andrew Trick
4183abc822 Fix an obvious bug in findLastUserInBlock.
This crept in the last commit because of rebasing but was never used.
2021-10-14 16:51:53 -07:00
Andrew Trick
b4a47b6463 Fix findInnerTransitiveUsesForAddress; add AddressUseKind
findInnerTransitiveUsesForAddress was incorrectly returning true for
pointer escapes.

Introduce enum AddressUseKind { NonEscaping, PointerEscape, Unknown };

Clients need to handle each of these cases differently.
2021-10-12 19:58:11 -07:00
Andrew Trick
014b155b14 Temporarily disable addresseses in findInnerGuaranteedUses
Because not all OSSA utility fixes have been committed yet.
2021-10-12 19:58:11 -07:00
Andrew Trick
52e1fc2418 Fix findTransitiveGuaranteedUses to only record leaf uses.
Recording uses is now optional. This utility is also used simply to
check for PointerEscape. When uses are recorded, they are used to
extend a live range. There could be a large number of transitive uses
that we don't want to pass back to the caller.
2021-10-12 19:58:11 -07:00
Andrew Trick
a336bcdea9 Fix findTransitiveUses to only record leaf uses.
Recording uses is now optional. This utility is also used simply to
check for PointerEscape. When uses are recorded, they are used to
extend a live range. There could be a large number of transitive uses
that we don't want to pass back to the caller.
2021-10-12 19:58:10 -07:00
Andrew Trick
1678354332 Fix an obvious bug in InteriorPointerOperand::findTransitiveUses().
The return value was inverted, meaning the OSSA utilities simply
bailed out in most cases.

Fixing this means potentially exposing other OSSA bugs.
2021-10-12 19:58:10 -07:00
Mishal Shah
c2fd49cebb Merge pull request #39473 from apple/rebranch
Update swift:main to support llvm-project:stable/20210726 changes (Rebranch merge)
2021-10-11 09:00:51 -07:00
Andrew Trick
5830ceaca9 Merge pull request #39638 from atrick/cleanup-addressownership
Add AddressOwnership utility and cleanup OSSA rauw
2021-10-08 14:45:00 -07:00
Andrew Trick
767e094cfe Add AddressOwnership OSSA utility
This replaces the recent BorrowedAddress utility (the address may not
be borrowed!)

APIs:

AddressOwnership::hasLocalOwnershipLifetime() - convenience on top of
AccessBase::hasLocalOwnershipLifetime().

AddressOwnership::getOwnershipReferenceRoot() - convenience on top of
AccessBase::getOwnershipReferenceRoot().

AddressOwnership::findTransitiveUses() - wrapper API over the internal
helper findTransitiveUsesForAddress()

AddressOwnership::areUsesWithinLifetime() - wrapper adds a quick check
on top of BorrowedValue::areUsesWithinLifetime()
2021-10-07 15:34:09 -07:00
Andrew Trick
b1352b490b Rename visitExtendedLocalScopeEndingUses
To visitExtendedScopeEndingUses.

We need to talk about the "local" scope, which does not cross
reborrows, in contrast to the extended scope. So the name was a
contradiction that could cause confusion elsewhere.
2021-10-07 14:32:40 -07:00
Andrew Trick
ac2f7b75ec Add BorrowingOperand::hasEmptyRequiredEndingUses()
Temporary check for malformed borrow scopes. Def-use traversals expect
at least one scope-ending use. Otherwise we can end up missing the
borrow entirely and miscompiling. SIL should guarantee scope-ending
uses on all paths, but that isn't fully enforced yet.
2021-10-07 14:32:32 -07:00
Erik Eckstein
7849f09e52 SIL: remove the unused alloc_value_buffer, project_value_buffer and dealloc_value_buffer instructions.
Those instructions were use for the materializeForSet implementation, which was replaced by modify-coroutines.
2021-10-07 07:41:54 +02:00
Andrew Trick
8996fb8af2 Add functionality to the OSSA BorrowedValue utility.
This abstraction is heavily used to ask about the current borrow scope
enclosing some uses. Give it the functionality it needs.

Add BorrowedValue::computeLiveness(PrunedLiveness). Get the borrow
scope's live range. A trivial 4-line implementation.

Cleanup BorrowedValue::areUsesWithinScope(). Quick check to see if a set
of uses known to be dominated by the borrow are within the borrow scope.

Add BorrowedValue::hasReborrow(). Is this local borrow scope
reborrowed? If not, then it's local scope-ending operations are the
end of its required lifetime.

Simplify BorrowedValue::gatherReborrows() to use OperandOwnership::Reborrow.
2021-10-06 15:48:08 -07:00
Andrew Trick
70a14ff61b Rename ForwardingOperand.getOwnershipKind()
to getForwardingOwnershipKind() just to distinguish it from
SILValue.getOwnershipKind() and be able to grep for them each.
2021-10-06 15:48:08 -07:00
swift-ci
60dc24b9f5 Merge pull request #39577 from atrick/liveness-boundary 2021-10-06 13:02:21 -07:00
swift-ci
3f8fea8508 Merge remote-tracking branch 'origin/main' into rebranch 2021-10-06 10:17:29 -07:00
Andrew Trick
ab0601d97a Add PrunedLiveness::computeSSALiveness
Straighforward API to build pruned liveness from a single SSA value.

This 3-line function allows PrunedLiveness to be used anywhere
ValueLifetimeAnalysis was used in OSSA form. Aside from simplicity and
efficiency, the difference is that this composes with other utilities
that only care about PrunedLiveBlocks, PrunedLiveness, or
PrunesLivenessBounary independent of how those data structures were generated.
2021-10-06 09:23:17 -07:00
Andrew Trick
c056ca6f7a Add PrunedLivenessBoundary mini-abstraction
Simple wrapper to compute the boundary of PrunedLiveness.

Pervasively useful utility for working with OSSA reference lifetimes
and borrow scopes.

This can also replace the implementation in
CanonicalOSSALifetime. This will greatly simplify that utility's
logic, preparing it to handle diagnostics (like move-only SILValue
checking) and other features.
2021-10-06 09:23:17 -07:00
Andrew Trick
ec64297893 Add PrunedLiveness::isWithinBoundary API
A perfectly straightforward liveness check. Used by OSSA utilities to
check that an instruction is within a lifetime or scope.
2021-10-06 09:23:02 -07:00
Andrew Trick
add3406cfe Move PrunedLiveness so it can be used as a lightweight OSSA helper.
For use in OwnershipUtils.
2021-10-06 09:23:02 -07:00
Andrew Trick
47791631c0 Change findOwnershipReferenceRoot to stop at phis.
This API should not handle is phis because the phi argument's ownedhip
is independent from the phi itself. The client assumes that the
returned root is in the same lifetime/scope of the access.
2021-10-06 09:18:14 -07:00
Andrew Trick
e9e3ce7ea5 Add findOwnershipReferenceAggregate().
Simple convenience on top of findOwnershipReferenceRoot to handle
guaranteed values forwarded through struct/tuple extract.

Note: eventually this should be handled by a ReferenceRoot abstraction
that stores the component path.
2021-10-06 09:18:14 -07:00
Andrew Trick
20ee76e07a Add AccessBase::hasLocalOwnershipLifetime()
Replaces AccessStorage::isGuaranteedForFunction().

OSSA utilities need to determine whether two addresses with the same
AccessStorage are directly substitutable without "fixing-up" the OSSA
lifetime. Checking whether the access base is within a local borrow
scope is the first step.
2021-10-06 09:18:14 -07:00
Andrew Trick
150208395e Implement AccessBase::compute(SILValue sourceAddress)
Missing implementation from the previous commit that introduced
AccessBase. Now we can directly ask for an AccessBase value.
2021-10-06 09:18:14 -07:00
Andrew Trick
0435fef009 Add checkReachingBlockDominates utility.
This is a tiny routine that is useful for writing assertions to be
used for quick sanity checks without computing Dominance.

It doesn't always make sense to require a pass to maintain and pass
around Dominance just for an assert.
2021-10-04 12:58:10 -07:00
swift-ci
899723065c Merge remote-tracking branch 'origin/main' into rebranch 2021-09-27 09:13:14 -07:00
Alastair Houghton
8be084f30a Merge pull request #39187 from al45tair/problem/79725187
[Demangler] Improve remangler error handling
2021-09-27 17:03:49 +01:00
swift-ci
591233f5b8 Merge remote-tracking branch 'origin/main' into rebranch 2021-09-24 05:33:19 -07:00
Erik Eckstein
fc772fff50 libswift: add more instructions and other small utilities
* ApplySite.arguments
* BasicBlock != operator
* some Function argument related properties
* Operand.isTypeDependent
* Type.isTrivial
* bridging of raw_ostream::write
2021-09-24 11:36:41 +02:00
swift-ci
2fce52d379 Merge remote-tracking branch 'origin/main' into rebranch 2021-09-23 12:14:03 -07:00
Zoe Carver
6300b8b4f8 Merge pull request #39356 from zoecarver/cxx-interop-lib-swift
[cxx-interop][libswift] Use `std::string` instead of `BridgedStringRef` 🚀
2021-09-23 15:06:19 -04:00