Commit Graph

200 Commits

Author SHA1 Message Date
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
Meghana Gupta
a0a0ebb558 Enable Mem2Reg for allocs with load_borrow (#59350) 2022-06-15 14:37:10 -07:00
Anton Korobeynikov
df6e2ebbd5 [NFC] Fix use-after-free issues in debug printing inside SIL Mem2Reg (#42183)
Turned printing of addresses of instructions into instructions while there.
2022-05-02 11:35:09 -07:00
nate-chandler
4343d940ba Merge pull request #41751 from nate-chandler/mem2reg/bail-on-load-take-complex-projections
[Mem2Reg] Skip load [take] of cast projections.
2022-03-09 17:14:34 -08:00
Nate Chandler
3508d41459 [Mem2Reg] Skip load [take] of cast projections.
Already, load [take]s of struct_element_addr|tuple_element_addr
projections resulted in Mem2Reg bailing.  Expand that to include load
[take]s involving unchecked_addr_cast.

To handle load [take]s of (struct|tuple)_element_addr projections, it
would be necessary to replace the running value with a value obtained
from the original product by recursive destructuring, replacing the
value at the load [take]n address with undef, and then restructuring.

To handle load [take]s of cast projections, it would be necessary to use
unchecked_value_cast instead of unchecked_bitwise_cast.  But we would
need to still use unchecked_bitwise_cast in the case of load [copy]
because otherwise we would lose the original value--unchecked_value_cast
forwards ownership, and not all casts can be reversed (because they may
narrow).

For now, just bail out in the face of these complex load [take]s.
2022-03-09 08:39:33 -08:00
Erik Eckstein
a62a5caaf4 SILMem2Reg: fix a problem with leaking enum values
When optimizing an enum `store` to an `alloc_stack`, require that all uses are in the same block.
Otherwise it could be a `switch_enum` of an optional where the none-case does not have a destroy of the enum value.
After transforming such an `alloc_stack`, the value would leak in the none-case block.

It fixes the same OSSA verification error as done for TempRValueOpt in a previous commit.
2022-03-09 09:47:48 +01:00
Michael Gottesman
0e3bca99f5 [debug-var] When comparing address debug_value against value debug_value remove the diexpr from the address SILDebugVariable.
Otherwise they will never compare the same. Also restore the test that was
updated for the previous commit to its old state. I did this to ensure that each
commit would compile successfully and so that I could show the test associated
with this commit.
2022-02-09 14:06:23 -08:00
Nate Chandler
1464c1b1ff [NFC] Renamed LexicalLifetimesOption cases.
The cases' new names more accurately reflect what behavior occurs when
SILOptions::LexicalLifetimes is assigned that case.
2021-12-10 18:36:28 -08:00
Michael Gottesman
72eb5e2eec [move-operator] Specify if LexicalLifetimes is enabled using an enum instead of a bool.
The reason why I am doing this is that we are going to be enabling lexical
lifetimes early in the pipeline so that I can use it for the move operator's
diagnostics.

To make it easy for passes to know whether or not they should support lexical
lifetimes, I included a query on SILOptions called
supportsLexicalLifetimes. This will return true if the pass (given the passed in
option) should insert the lexical lifetime flag. This ensures that passes that
run in both pipelines (e.x.: AllocBoxToStack) know whether or not to set the
lexical lifetime flag without having to locally reason about it.

This is just chopping off layers of a larger patch I am upstreaming.

NOTE: This is technically NFC since it leaves the default alone of not inserting
lexical lifetimes at all.
2021-11-15 13:47:22 -08:00
Nate Chandler
ee9d309116 [NFC] Added TODO about phi pruning of lifetimes. 2021-11-02 11:51:04 -07:00
Nate Chandler
09dde09a8d [Mem2Reg] Replaced loop with getSingleSuccessor.
Thanks to the lack of critical edges in SIL, if a block B dominated by P
has a successor S which is not dominated by P, then B must have only a
single successor.  Used this fact to replace a loop over successors to a
call to getSinglePredecessor.

Also added an assertion that, in the notation above, B is dominated by
P.
2021-11-02 11:50:28 -07:00
Nate Chandler
797eab10c6 [Mem2Reg] Handled unreachables for single-block allocations.
Previously, it was asserted that any single-block allocation which had
valid memory after all instructions in the block were visited terminated
in unreachable.  That assertion was false--while all paths through that
block must end in unreachable, the block itself need not be terminated
with an unreachable inst.  Here, that is corrected by walking forward
from the block until blocks terminated by unreachables or blocks not
dominated by the block containing the alloc_stack are reached.  In the
first case, the lifetime is ended just before the unreachable inst.  In
the second, the lifetime is ended just before the branch to such a
successor block (i.e. just before the branch to a block which is not
dominated by the block containing the alloc_stack).
2021-10-27 13:42:51 -07:00
Nate Chandler
0fc25cc7f2 [Mem2Reg] Skipped unreachable blocks.
Uses of an alloc_stack instruction in an unreachable block must also be
unreachable.  Don't waste time optimizing unreachable code.
2021-10-27 13:38:57 -07:00