Commit Graph

200 Commits

Author SHA1 Message Date
Nate Chandler
1c52364d28 [Mem2Reg] Complete single-block trivial enum cases
Add `end_lifetime` for values of non-trivial enum type which aren't
destroyed in non-dead-end blocks.
2025-08-29 15:47:10 -07:00
Nate Chandler
4b3588c9b9 [NFC] Mem2Reg: Delete this dead code.
Since the time that lifetimes in `alloc_stack [lexical]` began to be
represented after promotion by `move_value [lexical]`s, the
`endOwnedLexicalLifetimeBeforeInst` is just an assertion.  In the
future, lifetimes of values never destroyed that leak into dead end
blocks should be completed by OSSACompleteLifetime.  For now, just
delete this code.
2025-08-29 15:45:23 -07:00
Nate Chandler
69abf25f3a [NFC] Mem2Reg: Restructured conditional.
In preparation for adding other cases.  Also improved comments.
2025-08-29 15:45:19 -07:00
Nate Chandler
1f7432dedb [Mem2Reg] Don't skip write-only enum locations.
The lifetimes of the values stored into these locations may need to be
completed: if a trivial case of a non-trivial enum is written to the
location, its lifetime must be completed.

rdar://158139991
2025-08-29 15:45:14 -07:00
Nate Chandler
63a3c65147 [Mem2Reg] Fix isStorageValid.
In a few places, it wasn't getting set to false: `end_borrow`s of
`store_borrow`s and `load [take]`s.
2025-08-29 15:45:12 -07:00
Nate Chandler
09b1c3109d [NFC] Mem2Reg: Remove unused parameter. 2025-08-28 15:32:50 -07:00
Erik Eckstein
bdea6063d7 Mem2Reg: Fix lifetime completion for enum case values.
Enum types may have incomplete lifetimes in address form for trivial case values. When promoted to value form, they will end up with incomplete ossa lifetimes.
Because we know that the incomplete enum values are trivial enum cases we complete their lifetimes with `end_lifetime` instead of `destroy_value`.
This is especially important for Embedded Swift where we are not allowed to insert destroys which were not there before.

Fixes a compiler crash in Embedded Swift caused by de-virtualizing such an inserted destroy and ending up with a non-specialized generic function.

rdar://158807801
2025-08-25 09:35:46 +02:00
Nate Chandler
5da38cb04b [NFC] OSSACanonicalizeGuaranteed: Renamed. 2025-08-18 09:45:27 -07:00
Nate Chandler
8f1d6616af [NFC] OSSACanonicalizeOwned: Renamed. 2025-08-18 09:45:21 -07:00
Nate Chandler
aa85694237 [NFC] OSSACompleteLifetime: Renamed. 2025-08-18 09:45:19 -07:00
Nate Chandler
41877ae7b7 [Mem2Reg] Don't promote proj(unchecked_addr_cast).
In OSSA, the result of an `unchecked_bitwise_cast` must immediately be
copied or `unchecked_bitwise_cast`'d again.  In particular, it is not
permitted to borrow it.  For example, the result can't be borrowed for
the purpose of performinig additional projections (`struct_extract`,
`tuple_extract`) on the borrowed value.  Consequently, we cannot promote
an address if such a promotion would result in such a pattern.  That
means we can't promote an address `%addr` which is used like
`struct_element_addr(unchecked_addr_cast(%addr))` or
`tuple_element_addr(unchecked_addr_cast(%addr))`.  We can still promote
`unchecked_addr_cast(unchecked_addr_cast(%addr))`.

In ownership-lowered SIL, this doesn't apply and we can still promote
address with such projections.

rdar://153693915
2025-07-03 14:52:23 -07:00
Meghana Gupta
4c46faad26 Fix mem2reg for load_borrows with reborrows
StackAllocationPromoter::pruneAllocStackUsage substitutes loads/stores of alloc_stack
with values. For some reason isLoadFromStack was bailing out for load_borrows with
reborrows leaving them to be fixed up by fixBranchesAndUses which uses live in value
from predecessors for substitution which is obviosly incorrect the block containing
the load_borrow has a store before it.

Fixes rdar://145834542
2025-03-04 10:18:08 -08:00
Anthony Latsis
a84dfc8387 [Gardening] Fix some set but not used variables 2025-01-30 21:34:38 +00:00
Erik Eckstein
51e3e5ed80 Optimizer: rename BorrowArgumentsUpdater -> GuaranteedPhiUpdater
NFC
2024-11-12 09:26:59 +01:00
Erik Eckstein
6b8c6a3c3b SIL: rename updateBorrowedFrom to updateBorrowArguments
NFC
2024-11-12 09:26:58 +01:00
Arnold Schwaighofer
8d8951768c Revert "Merge pull request #76656 from nate-chandler/rdar136388508"
This reverts commit b9228c81d1, reversing
changes made to 6fb2989bcf.

After PR#76686 this bailout should no longer be neccessary.

rdar://136681998
2024-09-26 09:26:21 -07:00
Nate Chandler
c420b0e481 [Mem2Reg] Always bail on dynamic_lifetime.
rdar://136388508
2024-09-23 12:12:11 -07:00
Erik Eckstein
80a0da9615 Optimizer: update borrowed-from instructions in some passes
Fixes verifier crashes (once the borrowed-from verifier is fixed).
2024-08-07 18:02:38 +02:00
Nate Chandler
4a397cc018 [NFC] OwnedLifetimeCan: Take DeadEndBlocksAnalysis
All clients of OwnedLifetimeCanonicalization pass an instance of the
analysis in.  For now, it's unused.
2024-07-22 21:51:28 -07:00
nate-chandler
e9279e2f23 Merge pull request #75292 from nate-chandler/rdar131882748
[Mem2Reg] Bail on address-only types.
2024-07-18 10:52:03 -07:00
Nate Chandler
1b9567b1d3 [Mem2Reg] Bail on address-only types.
It is impossible to have a value of address-only type, so don't try
promoting.

rdar://131882748
2024-07-17 08:11:35 -07:00
Nate Chandler
dd730b849c [LifetimeCompletion] Flag instructions dead_end. 2024-07-03 16:44:35 -07:00
Meghana Gupta
ab3eaf2441 Merge pull request #71881 from meg-gupta/fixmem2reg
Fix mem2reg of lexical enum stack locations
2024-06-30 05:31:24 -07:00
Nate Chandler
7edf36ff6a [Mem2Reg] Cleanup and refactoring. 2024-06-29 14:49:06 -07:00
Meghana Gupta
42c1f9cb33 Fix mem2reg of lexical enum stack locations
When we have a non trivial enum lexical stack location, and we store a
 none value, after mem2reg we can end up with an ownership error
because of the leaking move_value [lexical].

This change avoids creating move_value [lexical] for such stores.

Do the same when we have store_borrow of none values, even though there
is no ownership error in this case, handle it like store for consistency
2024-06-27 17:34:56 -07: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
Nate Chandler
aa3cbe0c67 [NFC] OwnedValueCan: Typed maximizeLifetime. 2024-06-03 15:45:23 -07:00
Nate Chandler
df008924da [NFC] OwnedValueCan: Typed pruneDebugMode. 2024-06-03 15:45:20 -07:00
Nate Chandler
5383df755a [NFC] LifetimeCompletion: Clarify modes.
Completion is done along a boundary, either the availability or the
liveness boundary.  Represent which with a type.  Update docs and names.
2024-05-01 08:57:01 -07:00
Emil Pedersen
523a769e34 [DebugInfo] [Mem2Reg] Move debug info promotion to salvageDebugInfo 2024-04-23 13:12:21 -07:00
Emil Pedersen
e8ce02e0a3 [DebugInfo] Salvage debug info for allocations in SILSROA 2024-04-02 11:34:23 -07:00
Meghana Gupta
50f0fd232c Enable SILCombine of inject_enum_addr for empty types 2024-03-12 13:01:44 -07:00
Nate Chandler
7db84f25b1 [NFC] SIL: Typed move_value's isLexical. 2024-03-08 22:27:52 -08:00
Nate Chandler
9f6c30919b [NFC] SIL: Typed begin_borrow's isLexical. 2024-03-08 22:27:50 -08: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
Nate Chandler
b4e336ebdb [Mem2Reg] Undef types in empty projection sources.
Mem2Reg may materialize the unique instance of empty types when
promoting an address of that empty type.  Previously, it was required
that the top-most type in the aggregate be empty.  This failed to handle
the case where a projection of empty type from a non-empty aggregate was
promoted.

For example:

```
%addr = alloc_stack $((), C)
%empty_addr = tuple_element_addr $addr : $*((), C), 0
%addr = load %empty_addr : $*()
```

where `C` is some non-empty type.

Here, that case is handled by using `undef` for each non-empty field in
the projected-from aggregate.

In the example,

```
%empty = tuple ()
%tuple = tuple (%empty : $(), undef : $C)
%empty_again = tuple_extract %tuple : $((), C), 0
```

rdar://122417297
2024-02-09 13:54:14 -08:00
Meghana Gupta
c89dcd8019 Fix handling of none value stores to non-trivial enums in Mem2Reg
We allow none values to be stored to a non-trivial enum.
For such store_borrow, `LiveValues::forValues` used
an Owned storage type, but endLexicalLifetime expected Guaranteed
storage type, leading to a compiler crash.

For store_borrow, use the LiveValues::forGuaranteed and for store
use LiveValues::forOwned to avoid this.

Fixes rdar://114390472
2023-09-04 23:31:29 -07:00
Nate Chandler
0403ab102d [Mem2Reg] Don't canonicalize erased vals.
To eliminate copies which become newly spurious, Mem2Reg canonicalizes
the lifetimes of values that are stored and of newly introduced phis
after rewriting.

It's possible, however, for the values that are stored to be deleted
during canonicalization if a value and its copy are both stored to the
address.  Such values must not be canonicalized.  So check whether
values have been erased before canonicalizing them.

rdar://113762355
2023-08-14 15:08:57 -07:00
Nate Chandler
4f16bb1a74 [Mem2Reg] Don't canonicalize undef.
They aren't the kind of values whose lifetimes are eligible for
canonicalization.

rdar://113121424
2023-07-31 16:20:37 -07:00
Nate Chandler
f276ebf37e [Mem2Reg] Only lifetime canonicalize in OSSA.
Bail both on collecting stores and canonicalizing values if the function
being optimized doesn't have ownership.
2023-07-31 16:16:28 -07:00
Nate Chandler
b563c4ea3d [Mem2Reg] Canonicalize new phis.
Mem2Reg introduces new OSSA values in the form of phis.  Take
responsibility for canonicalizing their lifetimes.
2023-07-28 13:21:13 -07:00
Nate Chandler
52ce100ef4 [Mem2Reg] Canonicalize stored values.
Stored values may now be canonicalizable, now that they have one less
consuming use.
2023-07-28 13:19:52 -07:00
Nate Chandler
7fb9bcade8 [Mem2Reg] NFC: Lifted livePhiBlocks higher.
Move it all the way up into MemoryToRegisters::run in preparation for
using it to canonicalize new phis.
2023-07-26 21:27:35 -07:00
Nate Chandler
c9e0bb5a67 [Mem2Reg] NFC: Removed spurious typealias.
`BlockSetVector` is not much shorter than `BasicBlockSetVector`, and there's
no reason to tie the type to `StackAllocationPromoter`.
2023-07-26 21:27:35 -07:00
Nate Chandler
496761407c [Mem2Reg] NFC: Fixed comments.
Corrected the comments describing what the
`promoteSingleBlockAllocation` and `promoteMultiBlockAllocation`
functions do since they were no longer accurate.
2023-07-26 21:27:35 -07:00
Nate Chandler
e321fc4dc8 [Mem2Reg] NFC: Improved function name.
Previously there were the functions `promoteSingleAllocation` and
`removeSingleBlockAllocation`.  The distinction between these based on
the name alone is a bit subtle.  Shortened the name of
`promoteSingleAllocation` to `promoteAllocation`.
2023-07-26 21:27:35 -07:00
Evan Wilde
250082df25 [NFC] Reformat all the LLVMs
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
2023-06-27 09:03:52 -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
Nate Chandler
d928def87f [Mem2Reg] Recognize store_borrows for debug_value.
When `debug_value`s are visited, if their operand is the stack address,
they are rewritten as `debug_value`s of the stored value, provided it is
known.

Previously, the check for whether the operand is the stack address,
however, just compared the `debug_value`'s operand with the
`alloc_stack`.  For owned `alloc_stack`s (i.e. those that are not
"store_borrow locations"), that was correct.  For guaranteed
`alloc_stack`s (i.e. those that are "store_borrow locations"), however,
this failed to recognize the the values produced by the `store_borrow`
instructions (which amount to aliases for the `alloc_stack`) as the
stack address.

Here, this is fixed by checking whether the `debug_value`'s operand is
either (1) the `alloc_stack` itself or (2) some `store_borrow` whose
destination is the `alloc_stack`.

rdar://109894792
2023-06-02 12:23:21 -07:00