Commit Graph

162 Commits

Author SHA1 Message Date
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
Nate Chandler
209e3df685 [Mem2Reg] Complete new enum phi lifetimes.
When multi-block `alloc_stack`s of enum type with users are promoted,
lifetimes of stored values are completed to compensate for the legality
of not `destroy_addr`ing the `alloc_stack` in blocks where no
non-trivial value is known to be stored (the none case block of a
`switch_enum` of a load_borrow of the `alloc_stack`, e.g.).

Here, phis created during promotion are lifetime completed as well.
2023-05-15 17:39:54 -07:00
Nate Chandler
f234d8dfbb [Mem2Reg] NFC: Lifted livePhiBlocks into caller.
Previously, the value was computed and destroyed during
`promoteAllocationInBlock`.  Make the value available in
`StackAllocationPromoter`'s top-level routine (`::run`) in preparation
for using it there.
2023-05-15 13:37:06 -07:00
Nate Chandler
62b9323cde [Mem2Reg] NFC: Removed duplicative check.
Because getLexicalValueForStore returns "null" when
lexicalLifetimeEnsured is false, there's no need to check first whether
lexicalLifetimeEnsured is true before calling getLexicalValueForStore
and only taking action if a non-"null" value is returned.
2023-05-15 13:37:06 -07:00
Meghana Gupta
f833bdb090 Enable Mem2Reg of lexical enum values in multiple blocks 2023-04-21 22:55:09 -07:00
Meghana Gupta
0b835f0080 Fix ownership verification error due to multi block mem2reg with store_borrows
@guaranteed stored values will never be added to a phi in mem2reg because
any uses of store borrowed locations have to be accessed via the store borrow return address
and since we ban address phis altogether we will never have input sil which necessitates this.

But, the DJ-edges based algorithm for inserting phi blocks in mem2reg can insert unnecessary phis
which are removed later.

Ensure fixPhiPredBlock handles both owned and guaranteed stored values correctly for this reason.
2023-04-21 12:29:18 -07:00
Meghana Gupta
4496de1dfa Revert "Revert "Enable mem2reg of enum types ""
This reverts commit d6efa98447f7389440ba2c68d6e6f15196fff755.
2023-04-20 13:41:01 -07:00
Saleem Abdulrasool
cec38d780c Revert "Enable mem2reg of enum types " 2023-04-14 07:42:23 -07:00
Meghana Gupta
96a6d44cf9 Enable mem2reg of enum types
Previously it was disabled because we have incomplete address lifetimes for such types,
and transforming to value form in mem2reg would expose verification errors due to incompleteness.

Enable this case here and fixup the lifetimes using the new lifetime completion utility.
2023-04-13 15:51:18 -07:00
Meghana Gupta
5a35479975 Move around utilities, move isWriteAllocation outside the class 2023-04-11 15:40:13 -07:00
Nate Chandler
4198cc0b2a [Mem2Reg] Fix store_borrow user block omission.
Previously, when blocks were added to the worklist, only blocks which
were users of the `alloc_stack` instruction were considered.  For
"guaranteed alloc_stacks" (`store_borrow` locations), that resulted in
not processing blocks which contained uses of the `store_borrow` but not
the `alloc_stack`.  When such a user was an `end_borrow`, the effect was
that no `end_borrow` was created for the newly introduced
`begin_borrow [lexical]`.

Fix this by adding blocks with users of the `store_borrow` to the
worklist.
2023-03-31 18:43:48 -07:00
nate-chandler
1208d32d80 Merge pull request #64356 from nate-chandler/rdar106224845
[Mem2Reg] Instantiate arbitrary empty types.
2023-03-16 10:56:23 -07:00
Nate Chandler
e089e95d09 [Mem2Reg] Instantiate arbitrary empty types.
Currently, memory locations whose type is empty (`SILType::isEmpty`) are
regarded as viable sources for loads.

Previously, though, Mem2Reg only handled loads from empty types formed
only by tupling.  Here, support is added for types formed also by
struct'ing.  As before, this entails recursively instantiating the empty
types until reaching the innermost empty types (which aggregate nothing)
and then aggregating the resulting instances.

rdar://106224845
2023-03-14 10:54:22 -07:00
Nate Chandler
3019be9090 [Mem2Reg] Owned lexical lifetimes get moves. 2023-02-16 16:39:54 -08:00
Nate Chandler
66b8b2f827 [Mem2Reg] NFC: Split up lexical lifetime starts.
Split the beginning of lexical lifetimes up according to whether the
lifetimes (and alloc_stacks) are owned or guaranteed.
2023-02-16 16:39:54 -08:00
Nate Chandler
05642793ff [Mem2Reg] NFC: Entype'd LiveValues ownership.
Previously, LiveValues consisted always of three values: the value which
was stored, the borrow, and the copy.  For store_borrows, there never
was a copy.  Treating the two different scenarios as if they were the
same was confusing already.  It was only get when we switch to
representing owned lexical lifetimes with move_values.
2023-02-16 16:39:54 -08:00
Nate Chandler
a70aa13a43 [Gardening] Tweaked comment.
Fixed reference to renamed function argument.
2023-02-15 18:16:33 -08:00
Nate Chandler
1fada55c73 [Gardening] Described states variable could be in. 2023-02-15 18:16:33 -08:00
Nate Chandler
253888fbf8 [NFC] Eliminated spurious variable state.
The type Optional<Ty *> implied that there was a meaningful distinction
between None and Some(nullptr) but that was not the case here.  Replaced
it with a bare Ty *.
2023-02-15 18:16:33 -08:00
Nate Chandler
220597e68e [NFC] Removed unneeded variable.
No need to bind to the StoreBorrowInst to get the source because it's
already bound to the local variable `stored`.  And no need to bind to a
more specific type to find the next instruction.
2023-02-15 18:16:33 -08:00
Nate Chandler
a805179188 [Mem2Reg] Never borrow lifetimed stored_borrows.
Extend the definition of isGuaranteedLexicalValue--by means of which
Mem2Reg determines whether to borrow introducing a begin_borrow
[lexical] of a value which is store_borrow'd to an alloc_stack
[lexical]--to include every guaranteed lexical value.
2023-02-15 18:16:33 -08:00
Nate Chandler
b8c2269ff5 [NFC] Changed function name.
Because lexical borrows are already avoided for store_borrows of lexical
values, the function is already misnamed: it's not that Mem2Reg should
necessarily _add_ a lexical lifetime, but rather that it should ensure
that there is one.  Considering that we should do the same for owned
lexical values, the renaming will remain appropriate later.  Finally,
name it so that it can switch from being a boolean to returning a
tristate (none, guaranteed, owned) when that becomes necessary (as it
will when we need to distinguish among the states to determine what phis
look like).
2023-02-15 18:16:33 -08:00
Nate Chandler
06ed5d7801 [NFC] Removed spurious templating.
Now that StackAllocationPromoter::initializationPoints maps to either a
StoreInst or a StoreBorrowInst, there is no longer a subtype of
SILInstruction * at which the BlockToInstMap could be specialized, so
just eliminate the template argument and erase some angle brackets.
2023-02-15 18:16:33 -08:00
Erik Eckstein
c180d1363e SIL: simplify deleting instruction while iterating over instructions.
Add `deletableInstructions()` and `reverseDeletableInstructions()` in SILBasicBlock.
It allows deleting instructions while iterating over all instructions of the block.
This is a replacement for `InstructionDeleter::updatingRange()`.
It's a simpler implementation than the existing `UpdatingListIterator` and `UpdatingInstructionIteratorRegistry`, because it just needs to keep the prev/next pointers for "deleted" instructions instead of the iterator-registration machinery.
It's also safer, because it doesn't require to delete instructions via a specific instance of an InstructionDeleter (which can be missed easily).
2022-12-12 19:08:54 +01:00
Erik Eckstein
ab1b343dad use new llvm::Optional API
`getValue` -> `value`
`getValueOr` -> `value_or`
`hasValue` -> `has_value`
`map` -> `transform`

The old API will be deprecated in the rebranch.
To avoid merge conflicts, use the new API already in the main branch.

rdar://102362022
2022-11-21 19:44:24 +01:00
Josh Soref
730b16c569 Spelling siloptimizer
* access
* accessed
* accesses
* accessor
* acquiring
* across
* activated
* additive
* address
* addresses'
* aggregated
* analysis
* and
* appropriately
* archetype
* argument
* associated
* availability
* barriers
* because
* been
* beginning
* belongs
* beneficial
* blocks
* borrow
* builtin
* cannot
* canonical
* canonicalize
* clazz
* cleanup
* coalesceable
* coalesced
* comparisons
* completely
* component
* computed
* concrete
* conjunction
* conservatively
* constituent
* construct
* consuming
* containing
* covered
* creates
* critical
* dataflow
* declaration
* defined
* defining
* definition
* deinitialization
* deliberately
* dependencies
* dependent
* deserialized
* destroy
* deterministic
* deterministically
* devirtualizes
* diagnostic
* diagnostics
* differentiation
* disable
* discipline
* dominate
* dominates
* don't
* element
* eliminate
* eliminating
* elimination
* embedded
* encounter
* epilogue
* epsilon
* escape
* escaping
* essential
* evaluating
* evaluation
* evaluator
* executing
* existential
* existentials
* explicit
* expression
* extended
* extension
* extract
* for
* from
* function
* generic
* guarantee
* guaranteed
* happened
* heuristic
* however
* identifiable
* immediately
* implementation
* improper
* include
* infinite
* initialize
* initialized
* initializer
* inside
* instruction
* interference
* interferes
* interleaved
* internal
* intersection
* intractable
* intrinsic
* invalidates
* irreducible
* irrelevant
* language
* lifetime
* literal
* looks
* materialize
* meaning
* mergeable
* might
* mimics
* modification
* modifies
* multiple
* mutating
* necessarily
* necessary
* needsmultiplecopies
* nonetheless
* nothing
* occurred
* occurs
* optimization
* optimizing
* original
* outside
* overflow
* overlapping
* overridden
* owned
* ownership
* parallel
* parameter
* paths
* patterns
* pipeline
* plottable
* possible
* potentially
* practically
* preamble
* precede
* preceding
* predecessor
* preferable
* preparation
* probably
* projection
* properties
* property
* protocol
* reabstraction
* reachable
* recognized
* recursive
* recursively
* redundant
* reentrancy
* referenced
* registry
* reinitialization
* reload
* represent
* requires
* response
* responsible
* retrieving
* returned
* returning
* returns
* rewriting
* rewritten
* sample
* scenarios
* scope
* should
* sideeffects
* similar
* simplify
* simplifycfg
* somewhat
* spaghetti
* specialization
* specializations
* specialized
* specially
* statistically
* substitute
* substitution
* succeeds
* successful
* successfully
* successor
* superfluous
* surprisingly
* suspension
* swift
* targeted
* that
* that our
* the
* therefore
* this
* those
* threshold
* through
* transform
* transformation
* truncated
* ultimate
* unchecked
* uninitialized
* unlikely
* unmanaged
* unoptimized key
* updataflow
* usefulness
* utilities
* villain
* whenever
* writes

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
2022-10-03 18:31:33 -04:00
Meghana Gupta
b47230135a Fix Mem2Reg check on end_borrows of store_borrow
Instead of checking if the end_borrow is ending the lifetime of the store_borrow of the asi under consideration,
this code was checking if the store_borrow source is the runningValue which is incorrect in cases where a store_borrow
src to another destination gets replaced during mem2reg. This PR fixes the issue.
2022-09-08 12:00:02 -07:00
Meghana Gupta
17664c0c60 Fix store_borrow multi block handling in mem2reg 2022-08-30 12:48:37 -07:00
Meghana Gupta
e0f8711b23 Fix SILMem2Reg while marking end_borrow of store_borrow as deinit point
Fixes rdar://99229461
2022-08-27 21:01:16 -07:00
Meghana Gupta
ed7788fff1 Get rid of isStorageValid flag on lastStoreInst 2022-08-25 13:50:08 -07:00
Meghana Gupta
8e9117dda3 Handle store_borrow in SILMem2Reg 2022-08-25 13:25:15 -07:00
Meghana Gupta
13223f6edf Remove fake use of lexical copy 2022-08-22 15:27:52 -07:00
Meghana Gupta
0c2fd6b419 Remove unnecessary edge case 2022-08-22 15:27:52 -07:00
Meghana Gupta
7f6fd0bcf8 Reorganize if to reduce indentation 2022-08-22 15:27:47 -07:00
Meghana Gupta
8769cbec07 Simplify SILMem2Reg by using computeDominatedBoundaryBlocks api instead of computing in-place 2022-08-19 09:46:53 -07:00
Ben Barham
6de34f37e5 [NFC] Revert SmallVector<T> -> SmallVector<T, N> fixes
With the change to include `SmallVector.h` directly in `LLVM.h` rather
than forward declaring in the only case it matters (ie. Clang <= 5),
these fixes are no longer needed. Since defaulted version is preferred
when there's no better choice (which is presumably the case if that's
how they were originally added), use it instead. Some uses were instead
changed to add `llvm::` so remove that too.
2022-08-05 21:25:55 -07:00
Meghana Gupta
cf6c177117 Fix mem2reg assert to allow phi arguments (#59796)
rdar://96171577
2022-06-30 19:11:44 -07:00
Meghana Gupta
f99eb1df26 Fix possible iterator invalidation in SILMem2Reg 2022-06-21 14:22:26 -07:00
Meghana Gupta
344ef14796 Fix load_borrow replacement in SILMem2Reg 2022-06-21 14:22:20 -07:00