Commit Graph

682 Commits

Author SHA1 Message Date
Michael Gottesman
0d2047a359 [sil-combine] Update RefToRawPointer simplifications for ossa.
These are always safe in OSSA since what we are doing here is hoisting the
ref_to_raw_pointer up the def-use chain without deleting any instructions unless
we know that they do not have any uses (in a strict sense so destroy_value is
considered a use). E.x.:

```
%0 = ...
%1 = unchecked_ref_cast %0
%2 = ref_to_raw_pointer %1
```

->

```
%0 = ...
%1 = unchecked_ref_cast %0
%2 = ref_to_raw_pointer %0
```

Notice, how we are actually not changing %1 at all. Instead we are just moving
an instantaneous use earlier. One thing that is important to realize is that
this /does/ cause us to need to put the ref_to_raw_pointer at the insert
location of %0 since %0's lifetime ends at the unchecked_ref_cast if the value
is owned.

NOTE: I also identified the tests from sil_combine.sil that had to do with these
simplifications and extracted them into sil_combine_casts.sil and did the
ossa/non-ossa tests side by side. I am trying to fix up the SILCombine tests as
I update stuff, so if I find opportunities to move tests into a more descriptive
sub-file, I am going to do so.

As an aside, to make it easier to transition SILCombine away from using a
central builder, I added a withBuilder method that creates a new SILBuilder at a
requested insertPt and uses the same context as the main builder of
SILCombine. It also through the usage of auto makes really concise pieces of
code. Today to do this just using builder, we would do:

```
SILBuilderWithScope builder(insertPt, Builder);
builder.createInst1(insertPt->getLoc(), ...);
builder.createInst2(insertPt->getLoc(), ...);
builder.createInst3(insertPt->getLoc(), ...);
auto *finalValue = builder.createInst4(insertPt->getLoc(), ...);
```

Thats a lot of typing and wastes a really commonly used temp name (builder) in
the local scope! Instead, using this API, one can write:

auto *finalValue = withBuilder(insertPt, [&](auto &b, auto l) {
  b.createInst1(l, ...);
  b.createInst2(l, ...);
  b.createInst3(l, ...);
  return b.createInst4(l, ...);
});

There is significantly less to type and auto handles the types for us. The
withBuilder construct is just syntactic since we always inline it.
2020-12-22 17:25:47 -08:00
Michael Gottesman
6f3e88013e [sil-combine] Update unchecked_ref_cast_addr -> unchecked_ref_cast given loadable types for OSSA.
This involves just performing a load [take] + unchecked_ref_cast + store [init].

The test is ported from sil_combine_cast_foldings.sil
2020-12-22 16:34:43 -08:00
Michael Gottesman
75814e9a7f Merge pull request #35182 from gottesmm/pr-c252916df0109f89d79567d71f8772ba7a2fdb73
[sil-combine] Enable dead alloc_ref elim for ossa.
2020-12-21 15:32:47 -08:00
Michael Gottesman
f4722d20e8 Merge pull request #35181 from gottesmm/pr-6e15491b7d27fb108c6854ea1dfde8a758972512
[sil-combine] Enable convert_escape_to_no_escape -> thin_to_thick_function for ossa.
2020-12-21 15:32:14 -08:00
Michael Gottesman
5720d30c9a [sil-combine] Enable convert_escape_to_no_escape -> thin_to_thick_function for ossa.
Also begin a test file for casts specifically.
2020-12-21 13:10:40 -08:00
Michael Gottesman
04ffcafaa5 [sil-combine] Enable dead alloc_ref elim for ossa.
It was just looking for an alloc_ref that only has dealloc_ref,
set_deallocating, fix_lifetime users.
2020-12-21 13:07:00 -08:00
Michael Gottesman
aa9d68210f [gardening] Fix up some comments to be proper doxygen comments 2020-12-21 11:40:16 -08:00
Michael Gottesman
061632edef [sil-combine] Update fix_lifetime opts for ownership
The one opt we perform here is that we promote fix_lifetime on loadable
alloc_stack addresses to fix_lifetimes on objects by loading the underlying
value and putting the fix lifetime upon it.
2020-12-20 21:22:19 -08:00
Michael Gottesman
d4214b79b1 [sil-combine] Eliminate a dead parameter.
We pass in deadEndBlocks into scCanonicalize's constructor now.
2020-12-20 13:46:46 -08:00
Michael Gottesman
9f6688e185 [sil-combine] Use high level ARC APIs instead of low level ARC APIs in a few cases to make code work in ossa and non-ossa. 2020-12-10 16:50:26 -08:00
Michael Gottesman
259d2bb182 [ownership] Commit a generic replaceAllUsesAndEraseFixingOwnership api and enable SimplifyInstruction on OSSA.
This is a generic API that when ownership is enabled allows one to replace all
uses of a value with a value with a differing ownership by transforming/lifetime
extending as appropriate.

This API supports all pairings of ownership /except/ replacing a value with
OwnershipKind::None with a value without OwnershipKind::None. This is a more
complex optimization that we do not support today. As a result, we include on
our state struct a helper routine that callers can use to know if the two values
that they want to process can be handled by the algorithm.

My moticiation is to use this to to update InstSimplify and SILCombiner in a
less bug prone way rather than just turn stuff off.

Noting that this transformation inserts ownership instructions, I have made sure
to test this API in two ways:

1. With Mandatory Combiner alone (to make sure it works period).

2. With Mandatory Combiner + Semantic ARC Opts to make sure that we can
   eliminate the extra ownership instructions it inserts.

As one can see from the tests, the optimizer today is able to handle all of
these transforms except one conditional case where I need to eliminate a dead
phi arg. I have a separate branch that hits that today but I have exposed unsafe
behavior in ClosureLifetimeFixup that I need to fix first before I can land
that. I don't want that to stop this PR since I think the current low level ARC
optimizer may be able to help me here since this is a simple transform it does
all of the time.
2020-12-09 11:53:56 -08:00
Arnold Schwaighofer
5d28fbdd18 SILCombiner: Use a substitution list with concrete type if we can cast the apply operand
This works around an issue where using an apply with an unsubstituted
substitution map causes issues in downstream optimizations.

```
  %9 = alloc_stack $@opened("60E354F4-17B9-11EB-9427-ACDE48001122") NonClassProto
  copy_addr %8 to [initialization] %9 : $*@opened("60E354F4-17B9-11EB-9427-ACDE48001122") NonClassProto
  %11 = witness_method $ConformerClass, #NonClassProto.myVariable!getter : <Self where Self : NonClassProto> (Self) -> () -> SomeValue :
           $@convention(witness_method: NonClassProto) <τ_0_0 where τ_0_0 : NonClassProto> (@in_guaranteed τ_0_0) -> SomeValue
  apply %11<@opened("60E354F4-17B9-11EB-9427-ACDE48001122") NonClassProto>(%9) : $@convention(witness_method: NonClassProto) <τ_0_0 where τ_0_0 : NonClassProto> (@in_guaranteed τ_0_0) -> SomeValue
```

The problem arise when the devirtualizer replace
`witness_method $ConformerClass, #NonClassProto.myVariable!getter` with the
underlying implementation. That implementation for better or worse is further
constrained to `Self : ConformerClass` and applying an opened existential
which is not class constraint is a recipe for disaster. The proper
solution would probably be for the devirtualizer to insert the cast if necessary
and update the substitution list.
That fix will be left for another day though.

rdar://70582785
2020-10-26 14:06:42 -07:00
Meghana Gupta
06eaf6bba4 Disable SILCombine of unchecked_bitwise_cast to unchecked_ref_cast in OSSA
unchecked_ref_cast is a forwarding cast while unchecked_bitwise_cast is
not. We cannot just convert one to other in OSSA. Disable it now.
2020-10-20 20:44:59 -07:00
Erik Eckstein
28220ff259 SILCombine: make the alloc_stack-enum optimization a bit more tolerant.
When eliminating an enum from an alloc_stack, accept "dead" inject_enum_addr instructions, which inject different enum cases.
2020-09-30 16:44:58 +02:00
Andrew Trick
5ae231eaab Rename getFieldNo() to getFieldIndex().
Do I really need to justify this?
2020-09-24 22:44:13 -07:00
Erik Eckstein
b9612b2edb SILCombine: fix an assertion crash in SILCombine when casting AnyClass to Any
This caused a problem when propagating the concrete type of an existential: if the concrete type is itself an opened existential, it was not added to the OpenedArchetypeTracker.

https://bugs.swift.org/browse/SR-13444
rdar://problem/68077098
2020-09-01 14:53:48 +02:00
Erik Eckstein
63c275c45f SILOptimizer: move String concatination optimization from SILCombine/ConstantFolding to StringOptimization.
This simplifies some code and it's not required to try this optimization on every run of SILCombine and ConstantPropagation.
2020-08-04 16:16:11 +02:00
Erik Eckstein
662f03ec4c SILCombine: optimize casts of existential boxes.
Optimize the unconditional_checked_cast_addr in this pattern:

   %box = alloc_existential_box $Error, $ConcreteError
   %a = project_existential_box $ConcreteError in %b : $Error
   store %value to %a : $*ConcreteError
   %err = alloc_stack $Error
   store %box to %err : $*Error
   %dest = alloc_stack $ConcreteError
   unconditional_checked_cast_addr Error in %err : $*Error to ConcreteError in %dest : $*ConcreteError

to:
   ...
   retain_value %value : $ConcreteError
   destroy_addr %err : $*Error
   store %value to %dest $*ConcreteError

This lets the alloc_existential_box become dead and it can be removed in following optimizations.
The same optimization is also done for conditional_checked_cast_addr.

There is also an implication for debugging:
Each "throw" in the code calls the runtime function swift_willThrow. The function is used by the debugger to set a breakpoint and also add hooks.
This optimization can completely eliminate a "throw", including the runtime call.
So, with optimized code, the user might not see the program to break at a throw, whereas in the source code it is actually throwing.
On the other hand, eliminating the existential box is a significant performance win and we don't guarantee any debugging behavior for optimized code anyway. So I think this is a reasonable trade-off.
I added an option "-Xllvm -keep-will-throw-call" to keep the runtime call which can be used if someone want's to reliably break on "throw" in optimized builds.

rdar://problem/66055678
2020-07-29 21:57:51 +02:00
Michael Gottesman
ac3109a21d [eager-specializer] Fix for ownership and add a bunch of missing code coverage for ossa.
Specifically, we were missing a bunch of coverage around specializing guaranteed
parameters and non-trivial values in general.
2020-07-09 21:46:19 -07:00
Erik Eckstein
1a0c4d07a6 Reinstate "SILCombine: Constant-fold MemoryLayout<T>.offset(of: \.literalKeyPath)"
This reinstates commit d7d829c059 with a fix for C tail-allocated arrays.

Replace a call of the getter of AnyKeyPath._storedInlineOffset with a "constant" offset, in case of a keypath literal.
"Constant" offset means a series of struct_element_addr and tuple_element_addr instructions with a 0-pointer as base address.
These instructions can then be lowered to "real" constants in IRGen for concrete types, or to metatype offset lookups for generic or resilient types.

Replace:
  %kp = keypath ...
  %offset = apply %_storedInlineOffset_method(%kp)
with:
  %zero = integer_literal $Builtin.Word, 0
  %null_ptr = unchecked_trivial_bit_cast %zero to $Builtin.RawPointer
  %null_addr = pointer_to_address %null_ptr
  %projected_addr = struct_element_addr %null_addr
   ... // other address projections
  %offset_ptr = address_to_pointer %projected_addr
  %offset_builtin_int = unchecked_trivial_bit_cast %offset_ptr
  %offset_int = struct $Int (%offset_builtin_int)
  %offset = enum $Optional<Int>, #Optional.some!enumelt, %offset_int

rdar://problem/53309403
2020-07-03 18:40:47 +02:00
Erik Eckstein
723a205f0b Revert "SILCombine: Constant-fold MemoryLayout<T>.offset(of: \.literalKeyPath)"
This reverts commit d7d829c059.

The test stdlib/KeyPath.swift is failing on linux.

rdar://problem/64997950
2020-07-01 21:49:52 +02:00
Erik Eckstein
d7d829c059 SILCombine: Constant-fold MemoryLayout<T>.offset(of: \.literalKeyPath)
Replace a call of the getter of AnyKeyPath._storedInlineOffset with a "constant" offset, in case of a keypath literal.
"Constant" offset means a series of struct_element_addr and tuple_element_addr instructions with a 0-pointer as base address.
These instructions can then be lowered to "real" constants in IRGen for concrete types, or to metatype offset lookups for generic or resilient types.

Replace:
  %kp = keypath ...
  %offset = apply %_storedInlineOffset_method(%kp)
with:
  %zero = integer_literal $Builtin.Word, 0
  %null_ptr = unchecked_trivial_bit_cast %zero to $Builtin.RawPointer
  %null_addr = pointer_to_address %null_ptr
  %projected_addr = struct_element_addr %null_addr
   ... // other address projections
  %offset_ptr = address_to_pointer %projected_addr
  %offset_builtin_int = unchecked_trivial_bit_cast %offset_ptr
  %offset_int = struct $Int (%offset_builtin_int)
  %offset = enum $Optional<Int>, #Optional.some!enumelt, %offset_int

rdar://problem/53309403
2020-07-01 15:10:22 +02:00
Erik Eckstein
fc3e68a9d5 SILCombine: optimize a load from global static let
Propagate a value from a static "let" global variable.
This optimization is also done by GlobalOpt, but not with de-serialized globals, which can occur with cross-module optimization.
2020-06-22 16:49:26 +02:00
Erik Eckstein
6a9d08793a SILCombine: a peephole optimization to optimize alloc_stack of enums.
Replaces an alloc_stack of an enum by an alloc_stack of the payload if only one enum case (with payload) is stored to that location.

For example:

  %loc = alloc_stack $Optional<T>
  %payload = init_enum_data_addr %loc
  store %value to %payload
  ...
  %take_addr = unchecked_take_enum_data_addr %loc
  %l = load %take_addr

is transformed to

  %loc = alloc_stack $T
  store %value to %loc
  ...
  %l = load %loc

https://bugs.swift.org/browse/SR-12710
2020-06-10 09:23:37 +02:00
Anthony Latsis
9fd1aa5d59 [NFC] Pre- increment and decrement where possible 2020-06-01 15:39:29 +03:00
Erik Eckstein
33c8e16ce0 SIL optimizer: Support begin_cow_mutation and end_cow_mutation in some optimizations.
Mostly this is about "looking through" a begin_cow_mutation or end_cow_mutation.
2020-05-26 18:01:17 +02:00
Erik Eckstein
01465d9ba4 SILCombine: Remove a cast if it's only used by an end_cow_mutation.
(end_cow_mutation (upcast X)) -> (end_cow_mutation X)
(end_cow_mutation (unchecked_ref_cast X)) -> (end_cow_mutation X)
2020-05-26 18:01:17 +02:00
Saleem Abdulrasool
cebe79d482 SIL: use object libraries instead of globbing
This simplifies the handling of the subdirectories in the SIL and
SILOptimizer paths.  Create individual libraries as object libraries
which allows the analysis of the source changes to be limited in scope.
Because these are object libraries, this has 0 overhead compared to the
previous implementation.  However, string operations over the filenames
are avoided.  The cost for this is that any new sub-library needs to be
added into the list rather than added with the special local function.
2020-05-18 18:56:34 +00:00
Michael Gottesman
82728d3e53 Merge pull request #31808 from gottesmm/pr-b5aedd90dfc12a3be8e463e234898c646c5e654a
[gardening] Propagate type info to silence static analyzer nullptr error.
2020-05-15 12:00:00 -07:00
Michael Gottesman
d60d6dde22 [gardening] Propagate type info to silence static analyzer nullptr error.
The static analyzer flags this as a nullptr dereference since FullApplySite::isa
can fail if given a non-ApplySite. Of course though, the SILInstruction is an
apply! We just created it! This commit helps the static analyzer by propagating
this type information by not downcasting our ApplyInst to SILInstruction and
then just use FullApplySite's ApplyInst constructor instead.
2020-05-15 00:59:08 -07:00
Erik Eckstein
8f2632939a Builtins to support copy-on-write SIL instructions
* Builtin.COWBufferForReading -> ref_element_addr [immutable] / ref_tail_addr [immutable]
* Builtin.beginCOWmutation -> begin_cow_mutation
* Builtin.endCOWmutation -> end_cow_mutation
2020-05-14 08:39:54 +02:00
Arnold Schwaighofer
5c4bbf3de9 Merge pull request #31736 from aschwaighofer/fix_protocol_conformance_subst
Existentials don't always conform to a protocol via an abstract confo…
2020-05-13 11:27:25 -07:00
Meghana Gupta
96b774f2e5 Recommit #31595 with fixes (#31732)
Add new pattern in SILCombine to optimize redundant thick to objc metatype conversions

Add pattern to catch the following redundant conversion:

%tmp1 = thick_to_objc_metatype %x
%tmp2 = objc_to_thick_metatype %tmp1
...
%tmp3 = <sil operation> %tmp2

to:

%tmp3 = <sil operation> %x

Similarly add pattern for redundant conversion of objc_to_thick_metatype
followed by thick_to_objc_metatype.

Fixes rdar://62932799
2020-05-12 16:26:30 -07:00
Arnold Schwaighofer
b40b1be41d Existentials don't always conform to a protocol via an abstract conformance
So it is not always correct to use the current conformance when substituting.

rdar://62894495
2020-05-12 12:20:01 -07:00
Arnold Schwaighofer
7ce30d7fd0 Revert "Add new pattern in SILCombine to optimize redundant thick to objc metatype conversions (#31595)"
This reverts commit 488333c4a2.

It looks like this might have caused a heap-use-after free on an asan
bot.

rdar://63135437
2020-05-12 07:07:53 -07:00
Meghana Gupta
488333c4a2 Add new pattern in SILCombine to optimize redundant thick to objc metatype conversions (#31595)
Add pattern to catch the following redundant conversion:

%tmp1 = thick_to_objc_metatype %x
%tmp2 = objc_to_thick_metatype %tmp1
...
%tmp3 = <sil operation> %tmp2

to:

%tmp3 = <sil operation> %x

Similarly add pattern for redundant conversion of objc_to_thick_metatype
followed by thick_to_objc_metatype.

Fixes rdar://62932799
2020-05-12 01:08:19 -07:00
Joe Groff
c5863ac0f3 SILOptimizer: Constant fold the _kvcKeyPathString of literal key paths.
Eliminate the intermediate key path object when a literal key path is passed to a function that
just wants its KVC string to pass down to an ObjC API.
2020-05-07 13:33:01 -07:00
Arnold Schwaighofer
147144baa6 SIL: Thread type expansion context through to function convention apis
This became necessary after recent function type changes that keep
substituted generic function types abstract even after substitution to
correctly handle automatic opaque result type substitution.

Instead of performing the opaque result type substitution as part of
substituting the generic args the underlying type will now be reified as
part of looking at the parameter/return types which happens as part of
the function convention apis.

rdar://62560867
2020-05-04 13:53:30 -07:00
Arnold Schwaighofer
b5f5495e98 SILCombine: Fix update of substitution map when substituting opened opaque archetypes
When performing the substitution of the 'concrete' type that happens to
be an opened archetype we need to force the substitution to actually
call the conformance remapping function.

rdar://62202282
SR-12571
2020-04-27 14:52:39 -07:00
Saleem Abdulrasool
618ced846b Merge pull request #31310 from compnerd/unreachable
sprinkle some `llvm_unreachable` for MSVC (NFC)
2020-04-25 09:44:39 -07:00
Saleem Abdulrasool
fa46f7131c sprinkle some llvm_unreachable for MSVC (NFC)
MSVC does not realize that the switch is exhaustive and requires that
the path is explicitly marked as unreachable.  This silences the C4715
warning ("not all control paths return a value").
2020-04-24 18:59:07 -07:00
Michael Gottesman
c3fb485c7d [sil-combine] Refactor rewriteApplyCallee -> cloneFullApplySiteReplacingCallee and move into InstOptUtils.h.
I am going to use this in mandatory combine, and it seems like a generally
useful transformation.

I also updated the routine to construct its own SILBuilder that injects a user
passed in SILBuilderContext eliminating the bad pattern of passing in
SILBuilders.

This should be an NFC change.
2020-04-23 20:33:14 -07:00
David Zarzycki
e2c4aa13ed [SILOptimizer] Do not hardcode unowned for loadable ref storage types 2020-04-17 10:40:59 -04: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
d951279e53 Merge pull request #30892 from atrick/silcombine-builtin-same-metatype
Add Builtin.is_same_metatype to SILCombine.
2020-04-08 14:48:13 -07:00
Andrew Trick
ba75b3b3fb Add Builtin.is_same_metatype to SILCombine.
To optimize String decoding.
2020-04-08 11:34:22 -07:00
Dan Zheng
606c070e11 [SILOptimizer] Disable SILCombiner::visitPartialApplyInst for method callees.
Disable `SILCombiner::visitPartialApplyInst` from rewriting `partial_apply` with
with `@convention(method)` callee to `thin_to_thick_function`.

This fixes SIL verification errors: `thin_to_thick_function` only supports
`@convention(thin)` operands.

Resolves SR-12548.
2020-04-08 12:40:44 +00:00
Mishal Shah
cf474db442 Revert "SILOptimizer: Peephole to eliminate closures which just apply a witness_method" 2020-03-31 12:12:40 -07:00
Slava Pestov
dcd6c6d9fa SILOptimizer: Peephole to eliminate closures which just apply a witness_method
A partial_apply of a function_ref whose body consists of just an
apply of a witness_method can be simplified down to a simple
partial_apply of the witness_method:

sil @foo:
  %fn = witness_method ...
  %result = apply %fn(...)
  return %result

sil @bar:
  %fn = function_ref @foo
  %closure = partial_apply %fn(...)

  ===>

sil @bar:
  %fn = witness_method ...
  %closure = partial_apply %fn(...)
2020-03-31 00:47:17 -04:00
swift-ci
22d7267899 Merge pull request #30625 from zoecarver/fix/sil-combine-empty-visitors 2020-03-25 00:04:09 -07:00