Commit Graph

94 Commits

Author SHA1 Message Date
Erik Eckstein
bc4310b0eb Optimizer: simplify unchecked_addr_cast for vectors
Reimplement the simplification in swift and add a new transformation:
```
  %1 = unchecked_addr_cast %0 : $*Builtin.FixedArray<N, Element> to $*Element
```
->
```
  %1 = vector_base_addr %0 : $*Builtin.FixedArray<N, Element>
```
2025-05-12 19:25:12 +02:00
Erik Eckstein
dff855034c SILCombine: fix a wrong assert in the SingleBlockOwnedForwardingInstFolder 2025-04-02 17:33:30 +02:00
eeckstein
962be95c75 Merge pull request #79511 from swiftlang/78848-fix
Ensure we're commuting instructions only when internal one has a single use.
2025-03-21 09:16:34 +01:00
Erik Eckstein
35097b5a71 Optimizer: simplify unconditional_checked_cast to existential metatypes.
Replace `unconditional_checked_cast` to an existential metatype with an `init_existential_metatype`, it the source is a conforming type.
Note that init_existential_metatype is better than unconditional_checked_cast because it does not need to do any runtime casting.
2025-03-07 15:59:33 +01:00
Anton Korobeynikov
4310507d35 Ensure we're commuting instructions only when internal one has a single
use. Fix couple of similar single use predicates while there.

Fixes #78848
2025-02-24 13:59:31 -08:00
Erik Eckstein
51628dde12 SILCombine: workaround a problem with differential_function in OSSA
Disable this peephole optimization until the underlying problem is fixed.
https://github.com/swiftlang/swift/issues/78848

Part of rdar://140229560
2025-01-23 16:10:32 +01:00
Erik Eckstein
9aff288be4 Optimizer: re-implement the pointer_to_address SILCombine peephole optimizations in swift
Which consists of
* removing redundant `address_to_pointer`-`pointer_to_address` pairs
* optimize `index_raw_pointer` of a manually computed stride to `index_addr`
* remove or increase the alignment based on a "assumeAlignment" builtin

This is a big code cleanup but also has some functional differences for the `address_to_pointer`-`pointer_to_address` pair removal:

* It's not done if the resulting SIL would result in a (detectable) use-after-dealloc_stack memory lifetime failure.
* It's not done if `copy_value`s must be inserted or borrow-scopes must be extended to comply with ownership rules (this was the task of the OwnershipRAUWHelper).

Inserting copies is bad anyway.
Extending borrow-scopes would only be required if the original lifetime of the pointer extends a borrow scope - which shouldn't happen in save code. Therefore this is a very rare case which is not worth handling.
2024-12-21 08:28:22 +01:00
Tim Kientzle
1d961ba22d Add #include "swift/Basic/Assertions.h" to a lot of source files
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
2024-06-05 19:37:30 -07:00
Michael Gottesman
11f0ff6e32 [sil] Ensure that all SILValues have a parent function by making it so that SILUndef is uniqued at the function instead of module level.
For years, optimizer engineers have been hitting a common bug caused by passes
assuming all SILValues have a parent function only to be surprised by SILUndef.
Generally we see SILUndef not that often so we see this come up later in
testing. This patch eliminates that problem by making SILUndef uniqued at the
function level instead of the module level. This ensures that it makes sense for
SILUndef to have a parent function, eliminating this possibility since we can
define an API to get its parent function.

rdar://123484595
2024-02-27 13:14:47 -08:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
John McCall
d5142668f4 SIL and IRGen support for @isolated(any). SILGen to come. 2024-02-13 03:04:13 -05:00
Meghana Gupta
4c6b5400d3 Disable a silcombine pattern that creates unoptimizable copies
The SILCombine of ref_to_raw_pointer uses ossa rauw which creates a copy.
The copy created cannot be removed because it has an escaping ownership.
Disabling the silcombine for ossa here to avoid generating unoptimizable copies.
2023-12-13 10:42:28 -08:00
Erik Eckstein
c829d5bd77 SimplifyBeginCOWMutation: don't eliminate end_cow_mutation instructions with the [keep_unique] flag
This flag is important for following optimizations. Therefore such `end_cow_mutation` instructions must not be removed.
Also, keep the flag in a SILCombine transformation.

rdar://119178823
2023-12-06 08:59:58 +01:00
Anton Korobeynikov
118fd86012 Ensure we can fold apply of a differentiable_function_inst. Also fixes one small potential issue while there. (#65605)
Fixes #65489 #67992
2023-09-05 15:22:02 -07:00
Evan Wilde
f3ff561c6f [NFC] add llvm namespace to Optional and None
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
                     bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".

I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
2023-06-27 09:03:52 -07:00
Meghana Gupta
16c300c2af Remove OwnershipForwardingConversionInst, ConversionInst.
Add new ConversionOperation abstraction, use this in place of ConversionInst
2023-06-15 10:53:28 -07:00
Erik Eckstein
54aacf64e1 SIL: don't allow upcast to be done on address types
It's not needed and just complicates the SIL
2023-05-22 15:34:26 +02:00
Meghana Gupta
e5e61036e3 Update SILCombine now that OSSA RAUW always inserts borrow before the value to be replaced 2023-03-23 11:45:55 -07:00
Meghana Gupta
3812dad9b9 Fix SILCombine of pointer_to_address instruction
This change ensures the insertion point of the unchecked_addr_cast is after
any copies/borrows that OSSA rauw may create.

Before this fix we could end up creating invalid SIL where operands do not
dominate its instruction.
2023-03-22 12:42:09 -07:00
Anton Korobeynikov
a5e83817b2 Reapply "Implement several peephole optimizations to unblock further optimizations of autodiff code" with correctness fix (#62012)
* Implement several peephole optimizations to unblock further optimizations of autodiff code

1. Simplify differentiable_function_extract of differentiable_function.
Before:
%x = differentiable_function(%orig, %jvp, %vjp)
%y = differentiable_function_extract [original] %x
After:
%y = %orig

2. Push conversion instructions inside of differentiable_function.
This unblocks inlining and specialization.
Before:
%x = differentiable_function(%orig, %jvp, %vjp)
%y = convert_escape_to_noescape %x
After:
%orig' = convert_escape_to_noescape %orig
%jvp' = convert_escape_to_noescape %jvp
%vjp' = convert_escape_to_noescape %vjp
%y = differentiable_function(%orig', %jvp', %vjp')

3. Another peephole is needed for reordering function conversion instructions to enable full inlining:
(convert_escape_to_noescape (convert_function (thin_to_thick_function x)))
=>
(convert_escape_to_noescape (thin_to_thick_function (convert_function x)))

Co-authored-by: Dan Zheng <danielzheng@google.com>
2022-11-16 23:21:27 -08:00
Meghana Gupta
5e20112e0c Revert "Implement several peephole optimizations to unblock further optimizations of autodiff code (#60520)"
This reverts commit 2f5492f572.
2022-10-25 13:35:14 -07:00
Anton Korobeynikov
2f5492f572 Implement several peephole optimizations to unblock further optimizations of autodiff code (#60520)
* Implement several peephole optimizations to unblock further optimizations of autodiff code

1. Simplify differentiable_function_extract of differentiable_function.
Before:
%x = differentiable_function(%orig, %jvp, %vjp)
%y = differentiable_function_extract [original] %x
After:
%y = %orig

2. Push conversion instructions inside of differentiable_function.
This unblocks inlining and specialization.
Before:
%x = differentiable_function(%orig, %jvp, %vjp)
%y = convert_escape_to_noescape %x
After:
%orig' = convert_escape_to_noescape %orig
%jvp' = convert_escape_to_noescape %jvp
%vjp' = convert_escape_to_noescape %vjp
%y = differentiable_function(%orig', %jvp', %vjp')

3. Another peephole is needed for reordering function conversion instructions to enable full inlining:
(convert_escape_to_noescape (convert_function (thin_to_thick_function x)))
=>
(convert_escape_to_noescape (thin_to_thick_function (convert_function x)))

* Remove broken disabled folding transform:
  - It is disabled
  - It is broken
  - It is certainly not something mandatory

Co-authored-by: Dan Zheng <danielzheng@google.com>
2022-09-26 09:44:04 -07:00
Erik Eckstein
97b2354be6 SIL: add needsStackProtection flags for address_to_pointer and index_addr instructions.
Also add new "unprotected" variants of the `addressof` builtins:
* `Builtin.unprotectedAddressOf`
* `Builtin.unprotectedAddressOfBorrow`
2022-09-08 08:42:22 +02:00
Slava Pestov
9d96ed940f AST: Rename 'canonical wrt. generic signature' to 'reduced'
We had two notions of canonical types, one is the structural property
where it doesn't contain sugared types, the other one where it does
not contain reducible type parameters with respect to a generic
signature.

Rename the second one to a 'reduced type'.
2022-08-09 12:46:31 -04:00
Erik Eckstein
e8e61a9565 SIL: create cond_fail 1 instead of builtin "int_trap" for unconditional failures
`int_trap` doesn't provide a failure message, which makes crash reports hard to understand.
This is mostly the case for optimized casts which fail.

rdar://97681511
2022-07-28 16:05:07 +02:00
Joe Groff
1aa0fb8126 Merge pull request #60252 from jckarter/silgen-no-sizeof-value-argument
SILGen: Drop value argument when lowering Builtin.sizeof/alignof/strideof
2022-07-27 13:27:46 -07:00
Joe Groff
24158b2aab SILGen: Drop value argument when lowering Builtin.sizeof/alignof/strideof.
The metatype value isn't needed to do the memory layout computation, and
IRGen only looks at the substitutions passed to the generic signature, so
we can reduce SIL code size, and avoid leaving behind useless metadata
accesses, if we don't emit it.
2022-07-27 09:03:23 -07:00
Michael Gottesman
1e6187c4f4 [sil] Update all usages of old API SILValue::getOwnershipKind() in favor of new ValueBase::getOwnershipKind().
Andy some time ago already created the new API but didn't go through and update
the old occurences. I did that in this PR and then deprecated the old API. The
tree is clean, so I could just remove it, but I decided to be nicer to
downstream people by deprecating it first.
2022-07-26 11:46:23 -07:00
Andrew Trick
4180acf1a6 Add dynamic alignment optimization for 32-bit SIL. 2021-12-01 11:42:32 -08:00
Andrew Trick
c47fe03241 Optimize Builtin.assumeAlignment -> pointer_to_address
Case #1. Literal zero = natural alignment
   %1 = integer_literal $Builtin.Int64, 0
   %2 = builtin "uncheckedAssertAlignment"
	(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
   %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int

   Erases the `pointer_to_address` `[align=]` attribute:

Case #2. Literal nonzero = forced alignment.

   %1 = integer_literal $Builtin.Int64, 16
   %2 = builtin "uncheckedAssertAlignment"
	(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
   %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*Int

   Promotes the `pointer_to_address` `[align=]` attribute to a higher value.

Case #3. Folded dynamic alignment

   %1 = builtin "alignof"<T>(%0 : $@thin T.Type) : $Builtin.Word
   %2 = builtin "uncheckedAssertAlignment"
	(%0 : $Builtin.RawPointer, %1 : $Builtin.Int64) : $Builtin.RawPointer
   %3 = pointer_to_address %2 : $Builtin.RawPointer to [align=1] $*T

   Erases the `pointer_to_address` `[align=]` attribute.
2021-11-30 12:23:46 -08:00
Andrew Trick
8db4bb523d Fix SILCombine to use OSSA RAUW prepareReplacement
These SILCombine patterns produce new instructions that use the the
original value after it is updated for OSSA. The RAUW utility needs to
copy/borrow the original value before SILCombine can generate the new
replacement. Then SILCombine can pass that replacement back to RAUW to
perform the final replaceAllUsesWith.

1. PointerToAddress and RawPointerToRef

Fixes bugs where RAUW inserts borrows in the wrong place.

2. UncheckedBitwiseCast

The OSSA RAUW helper is incorrect here for producing a new
UncheckedRefCast. Simply don't use it. Since a bitwise cast is an
"Unowned" pointer escape, simply convert the unchecked_bitwise_cast
opcode to unchecked_ref_cast with Unowned forwarding ownership.

3. ConvertFunction

Make sure RAUW is never called with a replacement value that has
different ownership than the original.
2021-10-18 09:01:15 -07:00
Andrew Trick
0407a4e34a Add UpdatingInstructionIterator.
Track in-use iterators and update them both when instructions are
deleted and when they are added.

Safe iteration in the presence of arbitrary changes now looks like
this:

    for (SILInstruction *inst : deleter.updatingRange(&bb)) {
      modify(inst);
    }
2021-06-02 07:38:27 -07:00
Michael Gottesman
729c089244 Merge pull request #35769 from gottesmm/pr-24641c31dd4cd867a16902b73ef96df6882ffd1c
[sil-combine] When folding (unchecked_trivial_bit_cast (unchecked_ref_cast)), make sure to move the unchecked_trivial_bit_cast to before the unchecked_ref_cast.
2021-02-05 08:06:11 -08:00
Michael Gottesman
73745163cb [sil-combine] When folding (unchecked_trivial_bit_cast (unchecked_ref_cast)), make sure to move the unchecked_trivial_bit_cast to before the unchecked_ref_cast.
The reason that this needs to be done is that if the unchecked_ref_cast is an
owned value, it will end the lifetime of its operand meaning that we can't just
use it for a later unchecked_trivial_bit_cast.
2021-02-04 20:36:22 -08:00
Michael Gottesman
62d554669c [ownership] Rename OwnershipForwardingMixin::{get,set}OwnershipKind() -> {get,set}ForwardingOwnershipKind().
TLDR: This is just an NFC rename in preparation for changing
SILValue::getOwnershipKind() of any forwarding instructions to return
OwnershipKind::None if they have a trivial result despite forwarding ownership
that isn't OwnershipKind::None (consider an unchecked_enum_data of a trivial
payload from a non-trivial enum).

This ensures that one does not by mistake use this routine instead of
SILValue::getOwnershipKind(). The reason why these two things must be
distinguished is that the forwarding ownership kind of an instruction that
inherits from OwnershipForwardingMixin is explicitly not the ValueOwnershipKind
of the result of the instruction. Instead it is a separate piece of state that:

1. For certain forwarding instructions, defines the OwnershipConstraint of the
forwarding instruction.

2. Defines the ownership kind of the result of the value. If the result of the
value is non-trivial then it is exactly the set ownership kind. If the result is
trivial, we use OwnershipKind::None instead. As an example of this, consider an
unchecked_enum_data that extracts from a non-trivial enum a trivial payload:

```
enum Either {
case int(Int)
case obj(Klass)
}

%1 = load_borrow %0 : $*Either
%2 = unchecked_enum_data %1 : $Either, #Either.int!enumelt.1 // Int type
end_borrow %1 : $Either
```

If we were to identify the forwarding ownership kind (guaranteed) of
unchecked_enum_data with the value ownership kind of its result, we would
violate ownership since we would be passing a guaranteed value to the operand of
the unchecked_enum_data that will only accept values with
OwnershipKind::None. =><=.
2021-02-04 16:53:50 -08:00
Erik Eckstein
d33ea9f350 SIL: remove the JointPostDominanceSetComputer helper struct.
Instead make `findJointPostDominatingSet` a stand-alone function.
There is no need to keep the temporary SmallVector alive across multiple calls of findJointPostDominatingSet for the purpose of re-using malloc'ed memory. The worklist usually contains way less elements than its small size.
2021-02-02 10:20:35 +01:00
Michael Gottesman
2fad943df0 [sil-combine] Update convert_function canonicalization for ownership.
Some notes:

1. I moved the identity round-trip case to InstSimplify since that is where
   optimizations like that are.

2. I did not update in this commit the code that eliminates convert_function
   when it is only destroyed. In a subsequent commit I am going to implement
   that in a general way and apply it to all forwarding instructions.

3. I implemented eliminating convert_function with ownership only uses in a
   utility so that I can reuse it for other similar optimizations in SILCombine.
2021-01-28 12:10:16 -08:00
Michael Gottesman
6c960af9fa [sil-combine] Enable unchecked_ref_cast formation from rawpointer_to_ref round trips when compiling with ownership. 2021-01-28 12:10:15 -08:00
Michael Gottesman
29d2458876 [sil-combine] Enable unchecked_addr_cast formation in ownership mode. 2021-01-28 12:10:15 -08:00
Meghana Gupta
514cd9cfc3 Handle empty case in SILCombine's
SingleBlockOwnedForwardingInstFolder::add function's  assert
2021-01-26 19:56:32 -08:00
Michael Gottesman
68b4671a78 [sil-combine] Enable sil-combine simplifications for {thick_to_objc,objc_to_thick}_metatype.
Metatype always have none ownership, so we can just perform this.

I also removed a test (peephole_thick_to_objc_metatype.sil) that I had in a
previous commit renamed to sil_combine_peephole_thick_to_objc_metatype.sil. This
was os that this matched the rest of the sil_combine tests that have the
'sil_combine_*' prefix.
2021-01-25 20:20:14 -08:00
Michael Gottesman
2abd7e8604 [sil-combine] Update unchecked_bitwise_cast canonicalizations for ownership.
The only interesting thing that I did in this commit is I added a parameter to
OwnershipRAUWHelper::perform that lets one pass in a transformed version of
newValue. The assumption is that the transformation if it is done is done at the
location of oldValue.
2021-01-25 18:05:26 -08:00
Michael Gottesman
f39df1d73b [sil-combine] Address comments from post-commit review of cd7c9e97e4. 2021-01-22 14:26:59 -08:00
Michael Gottesman
cd7c9e97e4 [sil-combine] Fix cast optimizer based optimizations for ownership. 2021-01-20 13:19:02 -08:00
Michael Gottesman
3acb7df298 [ownership] Some more comment post-commit fixes for ffa55937c4. 2021-01-14 13:30:47 -08:00
Michael Gottesman
f92b75cafa [sil-combine] Enable unchecked_trivial_bitcast for ownership.
Instruction just deals with trivial values.
2021-01-13 10:43:41 -08:00
Michael Gottesman
2ff6fdfd0a [sil-combine] Update ownership for bridge_object_to_ref.
This just uses the infrastructure in place from fixing
upcast/unchecked_ref_cast.
2021-01-13 10:43:41 -08:00
Michael Gottesman
7ecee99097 [sil-combine] Implement a new class SingleBlockOwnedForwardingInstFolder to help eliminate chains of owned forwarding insts and use it to update upcast and unchecked_ref_cast for ownership.
b644c80f90fb7099ec956bb44065b50e432c5146 caused all owned forwarding
instructions to be sunk to their uses in the exact cases where we could
eliminate the parent forwarding inst (namely that the value we want to fold has
no non-debug, non-consuming users). So I was able to implement this just by
implementing a single basic block algorithm that works via a planner struct
using said canonicalization. One initializes the planner struct with the
instruction that is going to either be eliminated or have its forwarding operand
set. Then one adds each of the individual chains that lead to the use that we
wish to fold, each time checking that we can eliminate the instruction.

Once the user has added all of the intermediate forwarding instructions, by
construction (see paragraph above), we know we can optimize. So we eliminate all
intermediate values and then depending on whether the user called the set value
or replace value method we either set front's operand to be the passed in value
or we RAUW/erase front with that value. It is important to note that before we
do one of those two operations, front's operand is undef, so we need to perform
one of these two operations.
2021-01-13 10:43:41 -08:00
Michael Gottesman
56e9ca4543 [sil-combine] Update unchecked_addr_cast simplifications for ownership. 2021-01-13 10:43:41 -08:00
Michael Gottesman
cff4e504cd [sil-combine] Update pointer_to_address canonicalizations for OSSA.
For now I am not performing the [strict] elimination until I bring up the
interior pointer OSSA utilities. I want to make further progress before I loop
back around to that.
2021-01-13 10:43:41 -08:00