Commit Graph

3719 Commits

Author SHA1 Message Date
Erik Eckstein
1de19a1b32 SimplifyCFG: fix a compile time problem with block merging
When merging many blocks to a single block (in the wrong order), instructions are getting moved over and over again.
This is quadratic and can result in very long compile times for large functions.
To fix this, always move the instruction to smaller block to the larger block.

rdar://problem/56268570
2020-04-10 20:10:24 +02:00
Erik Eckstein
d73686a5b5 SILCombine: limit the worklist size for instruction canonicalization
To be precise: don't add instruction uses to the worklist if it already has more than 10000 elements.
This avoids quadratic behavior for very large functions.

rdar://problem/56268570
2020-04-10 20:10:24 +02:00
Andrew Trick
8636c39259 Fix assert in MemAccessUtils isLetAccess
Assertion failed:
(accessedAddress == getAccessedAddress(accessedAddress) &&
"caller must find the address root"), function isLetAddress,
file /Users/rjmccall/dev/swift/swift/lib/SIL/Utils/MemAccessUtils.cpp,
line 63.

Teach the getAccessedAddress utility to iterate through nested access
markers with projections interposed.

Fixes <rdar://problem/61464370>
Crash in SILOptimizer/access_marker_verify.swift
2020-04-08 22:04:16 -07:00
Erik Eckstein
fdb52061cc SIL: fix the hash function for Projection
The hash function didn't take the "index" of an projection into account. This lead to quadratic behavior in redundant load elimination and dead store elimination when compiling very large functions with many loads and stores.

rdar://problem/56268570
2020-04-07 15:00:48 +02:00
Dan Zheng
1775e8ae16 [AutoDiff upstream] Add VJPEmitter.
`VJPEmitter` is a cloner that emits VJP functions. It implements reverse-mode
automatic differentiation, along with `PullbackEmitter`.

`VJPEmitter` clones an original function, replacing function applications with
VJP function applications. In VJP functions, each basic block takes a pullback
struct (containing callee pullbacks) and produces a predecessor enum: these data
structures are consumed by pullback functions.
2020-04-05 20:35:35 -07:00
Dan Zheng
8081482b57 [AutoDiff upstream] Add common SIL differentiation utilities. 2020-04-05 20:35:35 -07:00
Dan Zheng
146c11ec80 [AutoDiff upstream] Add differentiable_function canonicalization. (#30818)
Canonicalizes `differentiable_function` instructions by filling in missing
derivative function operands.

Derivative function emission rules, based on the original function value:

- `function_ref`: look up differentiability witness with the exact or a minimal
  superset derivative configuration. Emit a `differentiability_witness_function`
  for the derivative function.
- `witness_method`: emit a `witness_method` with the minimal superset derivative
  configuration for the derivative function.
- `class_method`: emit a `class_method` with the minimal superset derivative
  configuration for the derivative function.

If an *actual* emitted derivative function has a superset derivative
configuration versus the *desired* derivative configuration, create a "subset
parameters thunk" to thunk the actual derivative to the desired type.

For `differentiable_function` instructions formed from curry thunk applications:
clone the curry thunk (with type `(Self) -> (T, ...) -> U`) and create a new
version with type `(Self) -> @differentiable (T, ...) -> U`.

Progress towards TF-1211.
2020-04-05 20:19:10 -07:00
marcrasi
15f512b81b [AutoDiff] fix SR-12493 (#30817)
We simply needed to upstream `TypeSubstCloner::visitDifferentiableFunctionExtractInst`.
The code has a detailed comment explaining what it does.
2020-04-05 19:36:10 -07:00
Andrew Trick
64348904e9 Merge pull request #30786 from atrick/fix-access-api
Fix the getAddressAccess API.
2020-04-02 21:21:51 -07:00
Andrew Trick
ec1545fac2 Fix the getAddressAccess API.
The API was accidentally undefined, presumably because I checked in
the wrong code or there was a bad merge. The API will be used by
upcoming commits.

Meanwhile, getAccessedAddress was not stripping access markers, which
means some analysis may have been too conservative.

This fix could expose issues by making existing analyses more effective.
2020-04-02 18:49:46 -07:00
Dan Zheng
aa66cce808 [AutoDiff upstream] Add differentiation transform.
The differentiation transform does the following:
- Canonicalizes differentiability witnesses by filling in missing derivative
  function entries.
- Canonicalizes `differentiable_function` instructions by filling in missing
  derivative function operands.
- If necessary, performs automatic differentiation: generating derivative
  functions for original functions.
  - When encountering non-differentiability code, produces a diagnostic and
    errors out.

Partially resolves TF-1211: add the main canonicalization loop.

To incrementally stage changes, derivative functions are currently created
with empty bodies that fatal error with a nice message.

Derivative emitters will be upstreamed separately.
2020-04-02 15:43:57 -07:00
marcrasi
495b571278 [AutoDiff upstream] Add @differentiable function reabstraction. (#30692)
Add SILGen logic for reabstracting `@differentiable` functions.

Resolves TF-1223.

Co-authored-by: Dan Zheng <danielzheng@google.com>
2020-03-28 12:27:14 -07:00
marcrasi
f6562d3a67 [AutoDiff upstream] differentiable function conversion pipeline (#30660)
Add the `@differentiable` function conversion pipeline:

- New expressions that convert between `@differentiable`,
  `@differentiable(linear)`, and non-`@differentiable` functions:
  - `DifferentiableFunction`
  - `LinearFunction`
  - `DifferentiableFunctionExtractOriginal`
  - `LinearFunctionExtractOriginal`
  - `LinearToDifferentiableFunction`
- All the AST handling (e.g. printing) necessary for those expressions.
- SILGen for those expressions.
- CSApply code that inserts these expressions to implicitly convert between
  the various function types.
- Sema tests for the implicit conversions.
- SILGen tests for the SILGen of these expressions.

Resolves TF-833.
2020-03-27 01:27:39 -07:00
ematejska
75691d641e [AutoDiff upstream] Add linear function SIL instructions (#30638)
Add `linear_function` and `linear_function_extract` instructions.

`linear_function` creates a `@differentiable(linear)` function-typed value from
an original function operand and a transpose function operand (optional).

`linear_function_extract` extracts either the original or transpose function
value from a `@differentiable(linear)` function.

Resolves TF-1142 and TF-1143.
2020-03-26 09:41:14 -07:00
Michael Gottesman
78c3be9052 [ownership] Change LLChecker APIs that use an out array to return leaked blocks to caller to instead use a callback.
NFC.
2020-03-24 21:47:40 -07:00
Michael Gottesman
63deebc83a Merge pull request #30602 from gottesmm/pr-ddf5c7c0e3c6e9ace5c3b695b19e43d13bb6ec3b
[ownership] Replace all uses outside of the SILOwnershipVerifier of LinearLifetimeChecker::checkValue() and make it a private implementation detail.
2020-03-24 12:20:00 -07:00
Michael Gottesman
84232cf177 [ownership] Replace all uses outside of the SILOwnershipVerifier of LinearLifetimeChecker::checkValue() and make it a private implementation detail.
HOW THIS WAS DONE: I did this by refactoring the last usages of checkValue into
a higher level API that uses checkValue as an implementation detail:
completeConsumingUseSet(...). All of these places in
MandatoryInlining/PredictableMemOpts all wanted behavior where we complete a set
of consuming uses for a value, detecting if the consuming use is in a different
loop nest from the value.

WHY DO THIS: The reason why I wanted to do this is that checkValue is a lower
level API that drives the actual low level computation. We shouldn't expose its
interface to the LinearLifetimeChecker's users since it is our own private
implementation detail that also has some sharp edges.

AN ADDITIONAL BENEFIT: Additionally by hiding the declaration of checkValue, the
last public use of LinearLifetimeError and ErrorBehaviorKind was not
private. This allowed me to then move the declarations of those two to a private
header (./lib/SIL/LinearLifetimeCheckerPrivate.h) and make their declarations
private to LinearLifetimeChecker as well. As such, I renamed them to
LinearLifetimeChecker::Error and LinearLifetimeChecker::ErrorBehaviorKind.
2020-03-23 20:42:53 -07:00
Dan Zheng
cc7e9fc39e [AutoDiff upstream] [SIL] Add differentiable function instructions.
Add `differentiable_function` and `differentiable_function_extract`
instructions.

`differentiable_function` creates a `@differentiable` function-typed
value from an original function operand and derivative function operands
(optional).

`differentiable_function_extract` extracts either the original or
derivative function value from a `@differentiable` function.

The differentiation transform canonicalizes `differentiable_function`
instructions, filling in derivative function operands if missing.

Resolves TF-1139 and TF-1140.
2020-03-22 23:53:43 -07:00
Dan Zheng
11551e13d0 [AutoDiff] NFC: formatting. (#30573)
Run `clang-format` on changes in https://github.com/apple/swift/pull/30564.
2020-03-22 21:30:33 -07:00
Dan Zheng
723b2d2cbe [AutoDiff upstream] Add derivative function witness/vtable entry SILGen. (#30569)
`@differentiable` attribute on protocol requirements and non-final class
members now produces derivative function entries in witness tables and vtables.

This enables `witness_method` and `class_method` differentiation.

Existing type-checking rules:

- Witness declarations of `@differentiable` protocol requirements must have a
  `@differentiable` attribute with the same configuration (or a configuration
  with superset parameter indices).
  - Witness table derivative function entries are SILGen'd for `@differentiable`
    witness declarations.

- Class vtable derivative function entries are SILGen'd for non-final
  `@differentiable` class members.
  - These derivative entries can be overridden or inherited, just like other
    vtable entries.

Resolves TF-1212.
2020-03-22 16:59:01 -07:00
Michael Gottesman
e9a3c7f26b Merge pull request #30497 from gottesmm/pr-71c57ac72c9ecc07f75dd86474bf57988d7aa006
[ownership] Convert a few small visitor methods to be const.
2020-03-22 16:18:50 -07:00
Dan Zheng
aab622e913 [AutoDiff upstream] Add derivative function SILDeclRefs. (#30564)
`@differentiable` attribute on protocol requirements and non-final class members
will produce derivative function entries in witness tables and vtables.

This patch adds an optional derivative function configuration
(`AutoDiffDerivativeFunctionIdentifier`) to `SILDeclRef` to represent these
derivative function entries.

Derivative function configurations consist of:
- A derivative function kind (JVP or VJP).
- Differentiability parameter indices.

Resolves TF-1209.
Enables TF-1212: upstream derivative function entries in witness tables/vtables.
2020-03-22 11:50:29 -07:00
Andrew Trick
ed55ef264e Merge pull request #30490 from atrick/add-apply-pointer-traits
Add PointerLikeTypeTraits to ApplySite and FullApplySite.
2020-03-20 15:20:57 -07:00
Slava Pestov
fcf3118417 Merge pull request #30499 from slavapestov/remove-curried-declrefs
SIL: Remove curried SILDeclRefs
2020-03-19 14:59:47 -04:00
Slava Pestov
9ec80df97e SIL: Remove curried SILDeclRefs 2020-03-19 02:20:21 -04:00
Michael Gottesman
8682002244 [ownership] Rename BorrowScopeOperandKind -> BorrowingOperandKind.
I missed this when I was doing the original refactoring. This was again done
using Xcode's refactoring functionality!
2020-03-18 23:05:40 -07:00
Michael Gottesman
e320ee1cd8 [ownership] Convert a few small visitor methods to be const. 2020-03-18 22:59:00 -07:00
Michael Gottesman
47e74473f1 [ownership] Rename BorrowScopeIntroducingValue -> BorrowedValue and BorrowScopeOperand -> BorrowingOperand.
Andy and I for some time have been discussing the right name for these two
"ownership concepts". What we realized is that the "ing" on
BorrowScopeIntroducingValue is very unfortunate since this value is the result
of a new borrow scope being introduced. So the name should be really:
BorrowScopeIntroducedValue. Given that is sort of unsatisfying, we settled on
the name BorrowedValue.

Once we found the name BorrowedValue, we naturally realized that
BorrowScopeOperand -> BorrowingOperand followed. This is because the operand is
the operand of the instruction that is creating the new borrow scope. So in a
sense the Operand is the "Use" that causes the original value to become
borrowed. So a BorrowingOperand is where the action is and is "active".
2020-03-18 19:43:30 -07:00
Andrew Trick
ff5ce958ad Add PointerLikeTypeTraits to ApplySite and FullApplySite.
So they can be used in ADTs like SmallPtrSet.
2020-03-18 18:12:07 -07:00
Dmitri Gribenko
841eeb05b0 Merge pull request #30403 from MForster/forster/string-fixes
Cherry-pick StringRef->std::string conversion fixes into `master`
2020-03-17 12:09:36 +01:00
Michael Gottesman
7ac7620c78 Merge pull request #30425 from gottesmm/pr-a62f3926b9e0b421c35408e66cf592f84295cd24
[ownership] Treat open_existential_box as an interior pointer producting instruction.
2020-03-16 14:06:15 -07:00
eeckstein
b5c0b6de9d Merge pull request #30381 from eeckstein/lazy_properties
Improve optimization of lazy properties.
2020-03-16 08:32:19 +01:00
Michael Gottesman
f3df836652 [ownership] Treat open_existential_box as an interior pointer producting instruction.
This means that it can only have a guaranteed object as an operandand that we
validate that all uses of the result address of open_existential_box occur only
within the lifetime of said object's borrow scope.
2020-03-15 23:21:45 -07:00
Meghana Gupta
8e800e49bf Recommit #29812 with fixes (#30342) 2020-03-13 19:34:16 -07:00
Fred Riss
259d78a350 Adapt to llvm.org StringRef API change 2020-03-13 19:08:22 +01:00
Erik Eckstein
ae93e60072 SIL: add a lazy_property_getter flag to SILFunction
It is set on getter-functions for lazy properties.
2020-03-13 09:49:55 +01:00
Ravi Kandhadai
e3a8a96469 [OSLogOptimization] Fix the symbolic closure folding code to only create
new closures when all captures of the symbolic closure, including address-typed
captures, are symbolic constants. For other closures, they must have been
autoclosures passed to the log call and therefore they need not be duplicated
but reused as such.

This eliminates the need to copy_value the non-constant captured values of
closures. Instead the closure itself is copied as a whole.

Fixes <rdar://problem/60344043>
2020-03-12 12:42:43 -07:00
John McCall
4ee87d4f6d Use the right generic signature when producing a substituted function type from an interface type.
Doing this requires us to re-introduce the concept of the contextual generic signature to SIL type lowering, but hopefully just in a few places.

As the FIXME notes, I found a problem here for substituted function types, but I need to land this first to fix ProcedureKit in the source-compatibility test suite.
2020-03-11 15:25:43 -04:00
Michael Gottesman
1c1fae381d Merge pull request #30341 from gottesmm/pr-91997a0048cde708ab0a33c5e524a8c8f9422956
Recommit #30289 with ASAN fix.
2020-03-11 00:43:38 -07:00
Michael Gottesman
6b88599412 Revert "Merge pull request #30327 from rintaro/revert-30289"
This reverts commit 0a6ccd802f, reversing
changes made to 7c5d74e86b.
2020-03-10 16:52:58 -07:00
Rintaro Ishizaki
ccbc26d947 Revert "Use in_guaranteed for let captures (#29812)"
This reverts commit 13b9915c6f.
2020-03-10 16:08:08 -07:00
Meghana Gupta
13b9915c6f Use in_guaranteed for let captures (#29812)
* Use in_guaranteed for let captures

With this all let values will be captured with in_guaranteed convention
by the closure. Following are the main changes :

SILGen changes:
- A new CaptureKind::Immutable is introduced, to capture let values as in_guaranteed.
- SILGen of in_guaranteed capture had to be fixed.
  in_guaranteed captures as per convention are consumed by the closure. And so SILGen should not generate a destroy_addr for an in_guaranteed capture.
  But LetValueInitialization can push Dealloc and Release states of the captured arg in the Cleanup stack, and there is no way to access the CleanupHandle and disable the emission of destroy_addr while emitting the captures in SILGenFunction::emitCaptures.
  So we now create, temporary allocation of the in_guaranteed capture iduring SILGenFunction::emitCaptures without emitting destroy_addr for it.

SILOptimizer changes:
- Handle in_guaranteed in CopyForwarding.
- Adjust dealloc_stack of in_guaranteed capture to occur after destroy_addr for on_stack closures in ClosureLifetimeFixup.

IRGen changes :
  - Since HeapLayout can be non-fixed now, make sure emitSize is used conditionally
  - Don't consider ClassPointerSource kind parameter type for fulfillments while generating code for partial apply forwarder.
    The TypeMetadata of ClassPointSource kind sources are not populated in HeapLayout's NecessaryBindings. If we have a generic parameter on the HeapLayout which can be fulfilled by a ClassPointerSource, its TypeMetaData will not be found while constructing the dtor function of the HeapLayout.
    So it is important to skip considering sources of ClassPointerSource kind, so that TypeMetadata of a dependent generic parameters gets populated in HeapLayout's NecessaryBindings.
2020-03-10 12:23:02 -07:00
John McCall
07f03bd287 Use pattern substitutions to consistently abstract yields.
The design implemented in this patch is that we lower the types of accessors with pattern substitutions when lowering them against a different accessor, which happens with class overrides and protocol witnesses, and that we introduce pattern substitutions when substituting into a non-patterned coroutine type.  This seems to achieve consistent abstraction without introduce a ton of new complexity.

An earlier version of this patch tried to define witness thunks (conservatively, just for accessors) by simply applying the requirement substitutions directly to the requirement.  Conceptually that should work, but I ran into a lot of trouble with things that assumed that pattern substitutions didn't conceal significant substitution work.  for example, resolving a dependent member in a component type could find a new use of an opaque archetype when the code assumed that such types had already been substituted away.  So while I think that is definiteely a promising direction, I had to back that out in order to make the number of changes manageable for a single PR.

As part of this, I had to fix a number of little bugs here and there, some of which I just introduced.  One of these bugfixes is a place where the substitution code was trying to improperly abstract function types when substituting them in for a type parameter, and it's been in the code for a really long time, and I'm really not sure how it's never blown up before.

I'm increasingly of the opinion that invocation substitutions are not actually necessary, but that --- after we've solved the substitution issues above --- we may want the ability to build multiple levels of pattern substitution so that we can guarantee that e.g. witness thunks always have the exact component structure of the requirement before a certain level of substitution, thus allowing the witness substitutions to be easily extracted.
2020-03-10 01:26:31 -04:00
Michael Gottesman
e9896fb3da [ownership] Change init_existential_ref to be forwarding for both guaranteed and owned.
Otherwise in call frames like the one in the test in this commit get unneeded
ARC traffic. We should never pessimize read only code that doesnt need
side-effects with side-effects if we can avoid it.

I am seeing this a bunch when I look at SIL from projects that use a lot of
protocols. Specifically, one has a sort of trampoline code that wraps a ref
counted object in an existential ref container (which from an ARC perspective
doesn't imply ownership) and then calls a method on it or passes it off to some
other code.

Because of this requirement, there is a copy/destroy that can not be eliminated
unless we can devirt/inline/eliminate the init_existential_ref box, inline
enough that the low level ARC optimizer can hit it. We shouldn't rely on such
properties if we do not need to.
2020-03-08 23:21:57 -07:00
John McCall
be576c6246 Require types to be contextually canonical in AbstractionPatterns.
Because violations of this might have made an AbstractionPattern incorrectly show up as abstract, it's possible that this will cause an ABI change.  However, I haven't been able to find any examples where it does, and certainly there's no way we can promise to maintain the old behavior, especially since it's not done consistently.
2020-03-08 01:37:49 -05:00
John McCall
ceff414820 Distinguish invocation and pattern substitutions on SILFunctionType.
In order to allow this, I've had to rework the syntax of substituted function types; what was previously spelled `<T> in () -> T for <X>` is now spelled `@substituted <T> () -> T for <X>`.  I think this is a nice improvement for readability, but it did require me to churn a lot of test cases.

Distinguishing the substitutions has two chief advantages over the existing representation.  First, the semantics seem quite a bit clearer at use points; the `implicit` bit was very subtle and not always obvious how to use.  More importantly, it allows the expression of generic function types that must satisfy a particular generic abstraction pattern, which was otherwise impossible to express.

As an example of the latter, consider the following protocol conformance:

```
protocol P { func foo() }
struct A<T> : P { func foo() {} }
```

The lowered signature of `P.foo` is `<Self: P> (@in_guaranteed Self) -> ()`.  Without this change, the lowered signature of `A.foo`'s witness would be `<T> (@in_guaranteed A<T>) -> ()`, which does not preserve information about the conformance substitution in any useful way.  With this change, the lowered signature of this witness could be `<T> @substituted <Self: P> (@in_guaranteed Self) -> () for <A<T>>`, which nicely preserves the exact substitutions which relate the witness to the requirement.

When we adopt this, it will both obviate the need for the special witness-table conformance field in SILFunctionType and make it far simpler for the SILOptimizer to devirtualize witness methods.  This patch does not actually take that step, however; it merely makes it possible to do so.

As another piece of unfinished business, while `SILFunctionType::substGenericArgs()` conceptually ought to simply set the given substitutions as the invocation substitutions, that would disturb a number of places that expect that method to produce an unsubstituted type.  This patch only set invocation arguments when the generic type is a substituted type, which we currently never produce in type-lowering.

My plan is to start by producing substituted function types for accessors.  Accessors are an important case because the coroutine continuation function is essentially an implicit component of the function type which the current substitution rules simply erase the intended abstraction of.  They're also used in narrower ways that should exercise less of the optimizer.
2020-03-07 16:25:59 -05:00
Michael Gottesman
491f826263 [ownership] Implement getSingleOwnedValueIntroducer and getAllOwnedValueIntroducers().
These enable robust walking up the def-use ossa graph to find the value that
introduces an independent underlying owned value, looking through forwarding
insts.
2020-03-06 12:01:13 -08:00
Michael Gottesman
9ab0427528 [ownership] Add a new construct: OwnedValueIntroducer for dealing with non-forwarding owned values at a higher level.
This is a similar concept to "rc-identity" that we talk about in the low level
ARC optimizer. The main idea is that all owned values in a program can be
partitioned into two different kinds of values:

1. Introducer values that exist independently of any other local values in the
function. It is a point of truth from which the owned objects lifetime extends
from and is in a certain sense an initialization (in a category theoretic sense)
in the lifetime of the underlying object that we are manipulating.

2. Forwarding values do not represent an object lifetime that is "truly"
independent of any other value locally: its liveness comes from passing on
liveness from some introducer or some other forwarding value.

The reason why I am adding this new construct is that I am beginning to
implement a new form of ARC optimization that enables us to convert @owned SIL
phi arguments to @guaranteed phi arguments. As part of that, I need to have a
way to in a systematic way finding the underlying incoming values (using the
logic used to determine forwarding in the ownership verifier).

This is the first part of that effort, defining the ontology we are going to
work with. Keep in mind this is just a seed ontology, if I missed any "owned
introducers" (I am sure I did), feel free to add them.
2020-03-06 12:01:13 -08:00
Michael Gottesman
c4ed7bd0be Merge pull request #30249 from gottesmm/pr-1c59567660f53bc35248d864c54d25e2760a74d0
[ownership] Implement InteriorPointer abstraction/validate current recognized ones addresses are not used outside of parent object's borrowed lifetime.
2020-03-06 02:54:29 -08:00
Michael Gottesman
0aec5a7f43 [ownership] Implement InteriorPointer abstraction/validate current recognized ones addresses are not used outside of parent object's borrowed lifetime.
Currently, we only classify ref_element_addr and ref_tail_addr. But we should
expand this to project_box, project_existential_box and open_existential_box as
well.
2020-03-05 20:28:59 -08:00