Commit Graph

2592 Commits

Author SHA1 Message Date
Robert Widmann
37e82a6133 [NFC] getWitnessMethodConformanceOrNone -> getWitnessMethodConformanceOrInvalid 2019-10-29 16:56:20 -07:00
Robert Widmann
3e1a61f425 [NFC] Fold The Tri-State In Optional<ProtocolConformanceRef>
ProtocolConformanceRef already has an invalid state.  Drop all of the
uses of Optional<ProtocolConformanceRef> and just use
ProtocolConformanceRef::forInvalid() to represent it.  Mechanically
translate all of the callers and callsites to use this new
representation.
2019-10-29 16:55:56 -07:00
Erik Eckstein
fbd41f7f66 DestroyHoisting: support of begin_apply and end_apply instructions
This enables destroy hoisting when accessor co-routines are not yet inlined.

https://bugs.swift.org/browse/SR-11675
rdar://problem/56704059
2019-10-29 15:43:48 +01:00
Michael Gottesman
386568c7e9 [gardening] Move ome from Transform -> Mandatory as per @atrick's request. 2019-10-28 16:26:13 -07:00
Andrew Trick
9dc59d2967 Fix TempRValue: Add checkTempObjectDestroy bail out logic.
This avoids use-after-free bugs that can be introduced by removing a
copy without replacing all corresponding destroys.

Add more descriptive comments since multiple bugs have been introduced
in this pass.

None of this will be relevant once the pass is converted to OSSA.
2019-10-27 21:42:44 -07:00
Michael Gottesman
7ee5ad7318 [sil] Rename {,Strong}Copy{Unowned,Unmanaged}. 2019-10-26 17:03:47 -07:00
Joe Groff
1a1d9e63f7 Merge pull request #27887 from jckarter/subst-sil-function-type-interface
SIL: Add fields to SILFunctionType for substituted function types.
2019-10-26 10:44:48 -07:00
Joe Groff
03c7919b4a SIL: Add fields to SILFunctionType for substituted function types.
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711

This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:

- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
  of the function to its concrete implementation. This will allow, for instance, a protocol
  witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
  type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
  to the protocol interface without relying on the pile of hacks that is the `witness_method`
  protocol.

- A bool for whether the generic signature of the function is "implied" by the substitutions.
  If true, the generic signature isn't really part of the calling convention of the function.
  This will allow closure types to distinguish a closure being passed to a generic function, like
  `<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
  which will make it easier for us to differentiate the representation of those as types, for
  instance by giving them different pointer authentication discriminators to harden arm64e
  code.

This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.

This does bifurcate some existing APIs:

- SILFunctionType now has two accessors to get its generic signature.
  `getSubstGenericSignature` gets the generic signature that is used to apply its
  substitution map, if any. `getInvocationGenericSignature` gets the generic signature
  used to invoke the function at apply sites. These differ if the generic signature is
  implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
  and results of the function. They now have two APIs to get that type. `getInterfaceType`
  returns the unsubstituted type of the generic interface, and
  `getArgumentType`/`getReturnValueType` produce the substituted type that is used at
  apply sites.
2019-10-25 13:38:51 -07:00
Michael Gottesman
26a734e58e [sil] Rename ValueOwnershipKind::{Any,None} 2019-10-25 10:28:25 -07:00
Jordan Rose
6c1afdcd10 Constify ReplaceOpaqueTypesWithUnderlyingTypes's DeclContext
No functionality change.
2019-10-23 17:34:42 -07:00
Jordan Rose
a7f6e3da9d OpaqueArchetypeSpecializer: inlinable functions are now in this module
...not the one they came from. This is important when specializing an
inlinable function that takes an opaque type as a generic argument:
that opaque type should still be considered opaque even if it came
from the same module as the inlinable function.

rdar://problem/56410009
2019-10-23 17:34:42 -07:00
Jordan Rose
b08014aacd Make OpaqueSubstitutionKind an enum class. No functionality change.
Also fix a comment typo while I'm here.
2019-10-23 17:34:42 -07:00
swift-ci
d74b512e22 Merge pull request #27771 from gottesmm/pr-d94d2ddde5fb71505e74c2de5d0e951939faed35 2019-10-18 00:08:58 -07:00
Michael Gottesman
3e79381aea [gardening] Eliminate unneeded llvm:: namespace from containers in allocbox to stack.
The specific types are:

* SmallVector{,Impl}
* SmallPtrSet{,Impl}
* StringRef

At the time AllocBoxToStack was not written, these containers had not been
injected into the swift namespace. They are now, so this commit just eliminates
the unnecessary llvm:: namespace in favor of referring to these containers
without qualification.

I also changed a SmallSet to be a SmallPtrSet. SmallSet's implementation just
delegates to SmallPtrSet anyways, so this just eliminates an anti-pattern.
2019-10-17 22:41:26 -07:00
Arnold Schwaighofer
da0099e83f Merge pull request #27666 from aschwaighofer/fix_replace_opaque_types_with_underlying
ReplaceOpaqueTypesWithUnderlyingTypes: We can't look through opaque archetypes if the underlying type contains a type not accessible from the current context
2019-10-17 12:40:06 -07:00
Erik Eckstein
e7ddae6852 TempRValueOptPass: accept try_apply as user of the temporary object
So far we only handled apply, but not try_apply.
2019-10-16 13:11:02 +02:00
Erik Eckstein
aa0d60a95f TempRValueOptPass: some small cosmetic changes
1. WitnessMethodInst doesn't need to be handled as use because it's operand is a typedependent operand, which we exclude anyway when looking at the uses.
2. Replace a list of handled instructions with a default value in the switch. It's easy to forget to add an instruction here. So it's safer to have a default behavior.
2019-10-16 13:11:01 +02:00
Erik Eckstein
fb76ce299c TempRValueOptPass: fix a miscompile with open_existential_addr
The uses of open_existential_addr were not handled correctly.

rdar://problem/56130674
2019-10-15 21:20:33 +02:00
eeckstein
8fc1501081 Revert "EscapeAnalysis: make the use-point analysis more precise" 2019-10-15 19:21:26 +02:00
Erik Eckstein
d1072621ba EscapeAnalysis: make the use-point analysis more precise
In canEscapeToUsePoint only check the content node if it's a reference (see comment why this is needed).
For all other node types, especially addresses, handle defer edges by propagating use-point infomation backward in the graph.
This makes escape analysis more precise with address types, e.g. don't consider an inout address to escape to an apply if just the loaded value is passed to an apply argument.
2019-10-14 20:43:46 +02:00
Arnold Schwaighofer
b75691cdde ReplaceOpaqueTypesWithUnderlyingTypes: We can't look through opaque archetypes if the underlying type contains a type not accessible from the current context
We can't access types in the same module if they are private: they could
be in a different TU.
We can't access types from different modules if they are private or
internal.

Some more information can be gleaned from the resilience expansion: A
minimally resilient function can't reference private or internal types.

rdar://56093964
2019-10-14 10:54:21 -07:00
Erik Eckstein
f372d70c48 DeadStoreElimination: don't require values stored back to memory if the control flow ends in an unreachable
This makes dead store elimination less conservative, e.g. if error checks are in the control flow.
2019-10-14 13:07:22 +02:00
Erik Eckstein
1c0dcc16e5 DeadStoreElimination: add debug dump functions
NFC
2019-10-14 13:07:22 +02:00
Jordan Rose
171ff440fc Remove swift::reversed in favor of llvm::reverse (#27610)
The former predates the latter, but we don't need it anymore! The
latter has more features anyway.

No functionality change.
2019-10-10 17:16:09 -07:00
Michael Gottesman
19b55ed280 Merge pull request #27599 from gottesmm/pr-b367ebec31812f3fe81f71280f06107d97e18318
[ome] Just erase the destructure rather than trying to get rid of dea…
2019-10-10 10:24:44 -07:00
Michael Gottesman
1b29d860b8 [ome] Just erase the destructure rather than trying to get rid of dead instructions due to simplifyInstruction.
This ensures that we do not run into any iterator invalidation issues. It does
worsen the passes output slightly, but avoiding the complexity is worth it and
other later passes will clean up the dead code.

rdar://55811732
2019-10-10 09:07:29 -07:00
Jordan Rose
a1ea211f22 Add llvm::iterator_range to LLVM.h
If we're going to get rid of swift::IteratorRange, let's make
llvm::iterator_range easy to use.

No functionality change.
2019-10-08 15:24:06 -07:00
Andrew Trick
bddc69c8a6 Organize SILOptimizer/Utils headers. Remove Local.h.
The XXOptUtils.h convention is already established and parallels
the SIL/XXUtils convention.

New:
- InstOptUtils.h
- CFGOptUtils.h
- BasicBlockOptUtils.h
- ValueLifetime.h

Removed:
- Local.h
- Two conflicting CFG.h files

This reorganization is helpful before I introduce more
utilities for block cloning similar to SinkAddressProjections.

Move the control flow utilies out of Local.h, which was an
unreadable, unprincipled mess. Rename it to InstOptUtils.h, and
confine it to small APIs for working with individual instructions.
These are the optimizer's additions to /SIL/InstUtils.h.

Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now
there is only SIL/CFG.h, resolving the naming conflict within the
swift project (this has always been a problem for source tools). Limit
this header to low-level APIs for working with branches and CFG edges.

Add BasicBlockOptUtils.h for block level transforms (it makes me sad
that I can't use BBOptUtils.h, but SIL already has
BasicBlockUtils.h). These are larger APIs for cloning or removing
whole blocks.
2019-10-02 11:34:54 -07:00
Michael Gottesman
e2e114f11b Merge pull request #27463 from gottesmm/pr-cab8832ce5d2768bd6581460dc3f4403be592012
[ownership] Emit a PrettyStackTrace msg telling to re-run with -sil-v…
2019-10-02 11:22:22 -07:00
Michael Gottesman
b0e947b0b3 [ownership] Emit a PrettyStackTrace msg telling to re-run with -sil-verify-all if we hit a verifier error before ownership lowering.
We have been getting a bunch of different bugs reported that were initially
identified as being caused by the ownership model eliminator (due to this
verification failure), but that turned out in reality to be a different failure.

To ease triaging, this commit puts in a pretty stack trace msg that tells the
person doing the triaging to re-run with -sil-verify-all enabled to track down
the actual pass that introduces the verification failure.
2019-10-01 11:34:00 -07:00
Michael Gottesman
aa00865715 [simplify-cfg] Add a visitedBlocks set to hasSameUltimateSuccessor to prevent infinite loops.
Previously, we were not handling properly blocks that we could visit multiple
times. In this commit, I added a SmallPtrSet to ensure that we handle all of the
same cases that we handled previously.

The key reason that we want to follow this approach rather than something else
is that the previous algorithm on purpose allowed for side-entrances from other
checks since often times when we have multiple checks, all of the .none branches
funnel together into a single ultimate block.

This can be seen by the need of this code to support the test two_chained_calls
in simplify_switch_enum_objc.sil.

rdar://55861081
2019-09-30 17:03:06 -07:00
Michael Gottesman
fab7752983 [simplify-cfg] Add option sil-simplify-cfg-simplify-unconditional-branches for testing purposes
I am going to use this in a subsequent commit to make sure we do not infinite
loop upon a test case.

rdar://55861081
2019-09-30 17:03:06 -07:00
Adrian Prantl
5b92814a0e Debug Info: Add missing debug info propagation to SILCloner.
While tightening the requirements of the debug info generator in
IRGenSIL I noticed that SILCloner didn't correctly transfer variable
debug info on alloc_box and alloc_stack instructions. In order to make
these mistakes easier to find I added an assertion to SILBuilder and
fixed all issues uncovered by that assertion, too.

The result is a moderate increase in debug info coverage in optimized code.

On stdlib/public/core/OSX/x86_64/Swift.o "variables with location"
increases from 60134 to 60299.
2019-09-24 14:10:25 -07:00
Michael Gottesman
20c5dff4b5 [builtin] Implement polymorphic builtins for all BUILTIN_BINARY_OPERATIONs.
TLDR: This patch introduces a new kind of builtin, "a polymorphic builtin". One
calls it like any other builtin, e.x.:

```
Builtin.generic_add(x, y)
```

but it has a contract: it must be specialized to a concrete builtin by the time
we hit Lowered SIL. In this commit, I add support for the following generic
operations:

Type           | Op
------------------------
FloatOrVector  |FAdd
FloatOrVector  |FDiv
FloatOrVector  |FMul
FloatOrVector  |FRem
FloatOrVector  |FSub
IntegerOrVector|AShr
IntegerOrVector|Add
IntegerOrVector|And
IntegerOrVector|ExactSDiv
IntegerOrVector|ExactUDiv
IntegerOrVector|LShr
IntegerOrVector|Mul
IntegerOrVector|Or
IntegerOrVector|SDiv
IntegerOrVector|SRem
IntegerOrVector|Shl
IntegerOrVector|Sub
IntegerOrVector|UDiv
IntegerOrVector|Xor
Integer        |URem

NOTE: I only implemented support for the builtins in SIL and in SILGen. I am
going to implement the optimizer parts of this in a separate series of commits.

DISCUSSION
----------

Today there are polymorphic like instructions in LLVM-IR. Yet, at the
swift and SIL level we represent these operations instead as Builtins whose
names are resolved by splatting the builtin into the name. For example, adding
two things in LLVM:

```
  %2 = add i64 %0, %1
  %2 = add <2 x i64> %0, %1
  %2 = add <4 x i64> %0, %1
  %2 = add <8 x i64> %0, %1
```

Each of the add operations are done by the same polymorphic instruction. In
constrast, we splat out these Builtins in swift today, i.e.:

```
let x, y: Builtin.Int32
Builtin.add_Int32(x, y)
let x, y: Builtin.Vec4xInt32
Builtin.add_Vec4xInt32(x, y)
...
```

In SIL, we translate these verbatim and then IRGen just lowers them to the
appropriate polymorphic instruction. Beyond being verbose, these prevent these
Builtins (which need static types) from being used in polymorphic contexts where
we can guarantee that eventually a static type will be provided.

In contrast, the polymorphic builtins introduced in this commit can be passed
any type, with the proviso that the expert user using this feature can guarantee
that before we reach Lowered SIL, the generic_add has been eliminated. This is
enforced by IRGen asserting if passed such a builtin and by the SILVerifier
checking that the underlying builtin is never called once the module is in
Lowered SIL.

In forthcoming commits, I am going to add two optimizations that give the stdlib
tool writer the tools needed to use this builtin:

1. I am going to add an optimization to constant propagation that changes a
"generic_*" op to the type of its argument if the argument is a type that is
valid for the builtin (i.e. integer or vector).

2. I am going to teach the SILCloner how to specialize these as it inlines. This
ensures that when we transparent inline, we specialize the builtin automatically
and can then form SSA at -Onone using predictable memory access operations.

The main implication around these polymorphic builtins are that if an author is
not able to specialize the builtin, they need to ensure that after constant
propagation, the generic builtin has been DCEed. The general rules are that the
-Onone optimizer will constant fold branches with constant integer operands. So
if one can use a bool of some sort to trigger the operation, one can be
guaranteed that the code will not codegen. I am considering putting in some sort
of diagnostic to ensure that the stdlib writer has a good experience (e.x. get
an error instead of crashing the compiler).
2019-09-19 11:42:10 -07:00
Andrew Trick
f22371bf0b Add SIL SinkAddressProjections utility to avoid address phis.
Enable this utility during jump-threading in SimplifyCFG.

Ultimately, the SIL verifier should prevent all address-phis and we'll
need to use this utility in a few more places.

Fixes <rdar://problem/55320867> SIL verification failed: Unknown
formal access pattern: storage
2019-09-18 18:02:59 -07:00
Erik Eckstein
d07593b352 PerformanceInliner: enable generic inlining of co-routines
Co-routines are so expensive (e.g. Array.subscript.read) that it makes sense to enable generic inlining of co-routines.
This will speed up array iteration (e.g. for elem in array { }) in a generic context significantly.
Another example is ManagedBuffer.header.read, which gets much faster.
In both cases, the speedup is mainly because there is no malloc happening anymore.

https://bugs.swift.org/browse/SR-11231
rdar://problem/53777612
2019-09-09 19:18:31 +02:00
Slava Pestov
d434188157 SIL: Refactor TypeConverter to not require a SILModule
This mostly requires changing various entry points to pass around a
TypeConverter instead of a SILModule. I've left behind entry points
that take a SILModule for a few methods like SILType::subst() to
avoid creating even more churn.
2019-09-06 21:50:15 -04:00
Slava Pestov
22cb6f1176 AST: Introduce ProtocolDecl::get{AssociatedType,ProtocolRequirement}() 2019-09-03 22:39:35 -04:00
Arnold Schwaighofer
6842134152 Outliner fix: Make sure the enum actually has an operand before we access it
rdar://54837190
2019-08-29 09:29:09 -07:00
swift-ci
b8f42d6165 Merge pull request #26466 from nvzqz/is_concrete_builtin 2019-08-28 19:10:37 -07:00
Erik Eckstein
0e08976600 SILOptimizer: a new optimization to hoist destroys of memory locations
DestroyHoisting moves destroys of memory locations up the control flow as far as possible.
Beside destroy_addr, also "store [assign]" is considered a destroy, because is is equivalent to an destroy_addr + a "store [init]".
The main purpose of this optimization is to minimize copy-on-write operations for arrays, etc. Especially if such COW containers  are used as enum payloads and modified in-place. E.g.

switch e {
  case .A(var arr):
    arr.append(x)
    self = .A(arr)
...

In such a case DestroyHoisting can move the destroy of the self-assignment up before the switch and thus let the array buffer only be single-referenced at the time of the append.

When we have ownership SIL throughout the pass pipeline this optimization will replace the current destroy hoisting optimization in CopyForwarding.
For now, this optimization only runs in the mandatory pipeline (but not for -Onone) where we already have ownership SIL.

SR-10605
rdar://problem/50463362
2019-08-28 15:40:05 +02:00
Erik Eckstein
8b11e7ce23 SILOptimizer: handle copy_addr [take] in TempRValueOpt 2019-08-28 12:14:38 +02:00
Nikolai Vazquez
ba0612f2e9 Add Builtin.isConcrete<T>(T.Type) -> Int1
Returns `true` if `T.Type` is known to refer to a concrete type. The
implementation allows for the optimizer to specialize this at -O and
eliminate conditional code.

Includes `Swift._isConcrete<T>(T.Type) -> Bool` wrapper function.
2019-08-27 16:51:09 -07:00
Michael Gottesman
5fc1d1d349 [ownership] Define a new instruction copy_unmanaged_value.
This provides a singular instruction for convert an unmanaged value to a ref,
then strong_retain it. I expanded the definition of UNCHECKED_REF_STORAGE to
include these copy like instructions. This instruction is valid in all SIL.

The reason why I am adding this instruction is that currently when we emit an
access to an unowned (unsafe) ivar, we use an unmanaged_to_ref and a strong
retain. This can look to the optimizer like a strong retain that can potentially
be optimized. By combining the two together into a new instruction, we can avoid
this potential problem since the pattern matching will break.
2019-08-25 21:26:40 -07:00
Arnold Schwaighofer
02683f8254 Merge pull request #26717 from aschwaighofer/fix_specialization_of_thin_to_thick
SpecializeOpaqueArchetypes: Fix specialization of thin_to_thick_function
2019-08-20 07:28:15 -07:00
Erik Eckstein
496ca10302 SimplifyCFG: fix a bug in switch_enum -> select_enum conversion
This bug is > 3 years old. Looks like we didn't hit this SIL code pattern so far.

https://bugs.swift.org/browse/SR-11263
rdar://problem/54312894
2019-08-19 20:32:21 +02:00
Arnold Schwaighofer
058c43e38f SpecializeOpaqueArchetypes: Fix specialization of thin_to_thick_function 2019-08-19 10:07:16 -07:00
swift-ci
bcad9406b7 Merge pull request #26660 from gottesmm/pr-48ba69f9596b774f285285b8aa2f740cb7308563 2019-08-16 12:57:35 -07:00
Michael Gottesman
378c6adbd6 [simplify-cfg] When determining/searching for the end of a switch_enums diamond using single successors, make sure we do not have single block self-loop.
Otherwise, we infinite loop.

rdar://52131975
2019-08-16 11:54:29 -07:00
Erik Eckstein
32c0feb577 SIL: add a [dynamic_lifetime] flag to alloc_stack and alloc_box
This flag is set by DefinitInitialization if the lifetime of the stored value is controlled dynamically.
If the flag is set, it's not (easily) possibly to statically calculate the lifetime of the stored value.
2019-08-13 09:29:05 +02:00