Commit Graph

318 Commits

Author SHA1 Message Date
Meghana Gupta
17285c006f Avoid generating address phis in ArrayPropertyOpt 2022-09-05 23:42:29 -07:00
Meghana Gupta
9007fca45b Get rid of address to pointer conversion in LoopRotate which is present just to avoid the address phi absence assert 2022-09-05 23:42:28 -07:00
Meghana Gupta
2e3be7da07 Avoid generating address phis in LoopRotate 2022-09-05 23:42:20 -07:00
Meghana Gupta
80414ca44b [NFC] Reorganize LoopRotate 2022-09-05 23:41:51 -07:00
Meghana Gupta
b6cf3cd7a1 Fix store_borrow generation and pattern matching in foreach loop unroll optimization 2022-08-16 15:08:22 -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
c4079179ee Trivial fix for an LICM assertion in projectLoadValue
This seems to compile correctly in release builds. But it does go
through an llvm_unreachable path, so really isn't safe to leave unfixed.

When the accessPath has an offset, propagate it through the recursive
calls. This may have happened when the offset was moved outside of the
sequence of path indices. The code rebuilds a path from the indices
without adding back the offset.

LICM asserts during projectLoadValue when it needs to rematerialize a
loaded value within the loop using projections and the loop-invariant
address is an index_addr.

Basically:

  %a = index_addr %4 : $*Wrapper, %1 : $Builtin.Word
  store %_ to %a : $*Wrapper
  br loop:

loop:
  %f = struct_element_addr %a
  %v = load %f : $Value
  %s = struct $Wrapper (%v : $Value)
  store %s to %a : $*Wrapper

Where the store inside the loop is deleted. And where the load is
hoisted out of the loop, but now loads $Wrapper instead of $Value.

Fixes rdar://92191909 (LICM assertion: isSubObjectProjection(), MemAccessUtils.h, line 1069)
2022-04-22 16:07:12 -07:00
Nate Chandler
3e8df52e4c [LoopRotate] Don't phi forwarded guaranteed value.
A guaranteed value produced by a begin_borrow can't be both used as
an operand of an ownership forwarding-instruction and also reborrowed by
being used as a phi argument.

Avoid that by stopping rotation when encountering a header block
containing an ownership-forwarding instruction whose forwarded ownership
kind is guaranteed; such a rotation may result in using both the
original guaranteed value and the resulting guaranteed value as phi
arguments.
2021-12-07 15:54:12 -08:00
Andrew Trick
e85228491d Rename AccessedStorage to AccessStorage
to be consistent with AccessPath and AccessBase.

Otherwise, the arbitrary name difference adds constant friction.
2021-09-21 23:18:24 -07:00
Meghana Gupta
64095a6d6b Fix use of MemAcessUtils in LICM (#38784)
AccessPathWithBase::compute can return a valid access path with unidentified base.
In such cases, we cannot LICM stores, because there is no base address to check if it is invariant
2021-08-06 18:34:55 -07:00
Andrew Trick
0f88e0f3cc Rewrite instruction deletion logic in many passes
Fix innumerable latent bugs with iterator invalidation and callback invocation.

Removes dead code earlier and chips away at all the redundant copies the compiler generates.
2021-06-02 07:38:27 -07:00
Erik Eckstein
d2fc6eb3b5 AliasAnalysis: make AliasAnalysis a function analysis and simplify the cache keys
Instead of caching alias results globally for the module, make AliasAnalysis a FunctionAnalysisBase which caches the alias results per function.
Why?
* So far the result caches could only grow. They were reset when they reached a certain size. This was not ideal. Now, they are invalidated whenever the function changes.
* It was not possible to actually invalidate an alias analysis result. This is required, for example in TempRValueOpt and TempLValueOpt (so far it was done manually with invalidateInstruction).
* Type based alias analysis results were also cached for the whole module, while it is actually dependent on the function, because it depends on the function's resilience expansion. This was a potential bug.

I also added a new PassManager API to directly get a function-base analysis:
    getAnalysis(SILFunction *f)

The second change of this commit is the removal of the instruction-index indirection for the cache keys. Now the cache keys directly work on instruction pointers instead of instruction indices. This reduces the number of hash table lookups for a cache lookup from 3 to 1.
This indirection was needed to avoid dangling instruction pointers in the cache keys. But this is not needed anymore, because of the new delayed instruction deletion mechanism.
2021-05-26 21:57:54 +02:00
Erik Eckstein
ef306ca9e0 SILOptimizer: fix some missing header file include directives
NFC
2021-05-26 21:57:54 +02:00
Erik Eckstein
2a17d9a480 ArrayBoundCheckOpts: introduce a limit for the maximum dominator tree recursion depth
This is a quick fix for a stack overflow in case of very large functions.
TODO: Ideally this algorithm would be implemented as an iterative worklist algorithm.

rdar://77563057
2021-05-07 18:13:08 +02:00
Azoy
9ed732f0ab Introduce isDecl and getDeclType
fix enum logic issue

fix tests

guard against null types
2021-04-20 02:22:16 -04:00
Meghana Gupta
1f89d9ff89 Verify critical edges when -sil-verify-all is enabled 2021-03-03 23:45:56 -08:00
Andrew Trick
66752e9724 OSSA: Rewrite address cloning code to fix issues.
Generalize the AccessUseDefChainCloner in MemAccessUtils. It was
always meant to work this way, just needed a client.

Add a new API AccessUseDefChainCloner::canCloneUseDefChain().

Add a bailout for begin_borrow and mark_dependence. Those
projections may appear on an access path, but they can't be
individually cloned without compensating.

Delete InteriorPointerAddressRebaseUseDefChainCloner.

Add a check in OwnershipRAUWHelper for canCloneUseDefChain.

Add test cases for begin_borrow and mark_dependence.
2021-02-24 22:18:21 -08:00
Michael Gottesman
248292b9da [cowarrayopt] Instead of always recomputing the loop we are analyzings exiting blocks when checking for dominance, use a cache.
Saves a bunch of compile time when compiling the stdlib. Specifically, when
compiling the iOS 32 bit stdlib + sil-verify-all, this shaves off ~20% of the
compile time.
2021-02-24 11:13:52 -08:00
Michael Gottesman
f73276259e [loop-rotate] In OSSA, instead of creating address phis, sneak the address through the phi using a RawPointer.
In OSSA, we do not allow for address phis, but in certain cases the logic of
LoopRotate really wants them. To work around this issue, I added some code in
this PR to loop rotate that as a post-pass fixes up any address phis by
inserting address <-> raw pointer adapters and changing the address phi to
instead be of raw pointer type.
2021-02-12 23:20:17 -08:00
Erik Eckstein
fe10f98cf0 SIL: rename the SILBitfield.h header file to BasicBlockBits.h
NFC
2021-02-12 11:15:55 +01:00
Erik Eckstein
f48191966c SILOptimizer: use BasicBlockSet instead of SmallPtrSet in various transformations.
It reduces compile time.
2021-01-27 10:31:17 +01:00
eeckstein
a0884baa3c Merge pull request #35521 from eeckstein/sil-bitfields
SIL: add a utility which can manage per-block bitfields and flags efficiently.
2021-01-22 08:39:13 +01:00
Meghana Gupta
6c32cac98e Enable LoopRotate on OSSA 2021-01-21 16:27:51 -08:00
Meghana Gupta
845e63f901 Support ownershipKind in SILSSAUpdater 2021-01-21 16:27:50 -08:00
Erik Eckstein
3e8612b0d3 SILOptimizer: use the BasicBlockFlag utility in ValueLifetimeAnalysis 2021-01-21 21:31:41 +01:00
swift-ci
13ffb8b181 Merge pull request #35534 from meg-gupta/loopunrolltest 2021-01-21 01:50:33 -08:00
Meghana Gupta
3b60184f53 "[NFC] Add tests for LoopUnroll on OSSA""
Reland #35423
2021-01-20 22:26:18 -08:00
Meghana Gupta
f6f58263b2 Enable ArrayPropertyOpt on OSSA 2021-01-20 13:23:40 -08:00
Meghana Gupta
a7dc4621e4 clang-format some long lines in ArrayPropertyOpt 2021-01-20 13:23:39 -08:00
Meghana Gupta
8d217f362f Merge pull request #35380 from meg-gupta/abcoptsossa
Enable ArrayBoundsCheckElimination on OSSA
2021-01-20 13:21:06 -08:00
Meghana Gupta
00ea81c8df Enable ArrayBoundsCheckElimination on OSSA 2021-01-20 02:13:15 -08:00
Meghana Gupta
a5803f090a Refactor ABCOpts
- Updated free functions as class methods and avoid passing redundant
  args
- Updated ReleaseSafeArrays to be a class member
2021-01-20 01:46:17 -08:00
Ben Barham
16d614412a Revert "[NFC] Add tests for LoopUnroll on OSSA" 2021-01-19 09:00:36 +10:00
Meghana Gupta
246faae927 Merge pull request #35423 from meg-gupta/loopunrollossa
[NFC] Add tests for LoopUnroll on OSSA
2021-01-18 00:03:08 -08:00
Meghana Gupta
e10ffb79b2 Add tests for LoopUnroll on OSSA 2021-01-14 10:31:07 -08:00
Erik Eckstein
b7351780f7 SIL: move all the block-list modifying APIs to SILFunction.
... and remove SILFunction::getBlocks().

It's just a cleanup, NFC.
2021-01-14 17:35:31 +01:00
Meghana Gupta
4f054f17a3 Allow load instructions in ArrayPropertyOpt's checkSafeArrayAddressUses 2021-01-11 16:08:45 -08:00
Meghana Gupta
77a992096d Update a comment about StructAddressUsers 2021-01-11 16:05:35 -08:00
Meghana Gupta
28bf85f22b Merge pull request #35312 from meg-gupta/cowoptossa
Enable COWArrayOpts on OSSA
2021-01-08 16:58:50 -08:00
Meghana Gupta
dae2530799 Enable COWArrayOpts on OSSA
Additional handling of copy_value/destroy_value/load[copy]/
begin_borrow/end_borrow is needed to support OSSA.

TODO: Support handling of 2d array in the pass for OSSA.
Currently hoisting of loads and borrows are not supported in OSSA
2021-01-08 12:03:59 -08:00
Andrew Trick
cec5513373 Fix ForEachLoopUnroll use-after-free miscompile.
This pass generated incorrect borrow scopes:

%stack = alloc_stack
%borrow = begin_borrow %element
store_borrow %borrow to %stack
end_borrow %borrow
try_apply %f(%stack) normal bb1, error bb2
...
destroy_value %element

This was not showing up as a miscompile before because:

- an array holds an extra copy of the unrolled elements, that array is
  now being optimized away completely.

- CopyPropagation now canonicalizes OSSA lifetimes independent of
  unrelated program side effects.

So, since there is no explicit relationship between %borrow and the
OSSA value in %stack, we end up with:

%stack = alloc_stack
%borrow = begin_borrow %element
store_borrow %borrow to %stack
end_borrow %borrow
destroy_value %element
try_apply %f(%stack) normal bb1, error bb2

Fixes rdar://72904101 ([CanonicalOSSA] Fix ForEachLoopUnroll use-after-free miscompile.)
2021-01-07 14:09:54 -08:00
Andrew Trick
437765e7e1 LICM: split loads that are wider than the loop-stored value.
For combined load-store hoisting, split loads that contain the
loop-stored value into a single load from the same address as the
loop-stores, and a set of loads disjoint from the loop-stores. The
single load will be hoisted while sinking the stores to the same
address. The disjoint loads will be hoisted normally in a subsequent
iteration on the same loop.

loop:
  load %outer
  store %inner1
exit:

Will be split into

loop:
  load %inner1
  load %inner2
  store %inner1
exit:

Then, combined load/store hoisting will produce:

  load %inner1
loop:
  load %inner2
exit:
  store %inner1
2020-11-12 13:59:43 -08:00
Andrew Trick
d86099f05f Use AccessPath in LICM.
The LICM algorithm was not robust with respect to address projection
because it identifies a projected address by its SILValue. This should
never be done! Use AccessPath instead.

Fixes regressions caused by rdar://66791257 (Print statement provokes
"Can't unsafeBitCast between types of different sizes" when
optimizations enabled)
2020-11-10 12:19:18 -08:00
Andrew Trick
4106b7698d Fix ArrayPropertyOpt dominator update
Pass the DomTree into SILCloner so that edge splitting
properly creates new domtree nodes.

The confusing edge splitting code that was in ArrayPropertyOpt is no
longer needed.

We could cleanup ArrayPropertyOpt even more by moving fixDomTree
into SILCloner. But there's already too much going on in this patch.
2020-11-03 01:40:00 -08:00
Andrew Trick
b06aea022e Layout loop unrolled blocks next to the original loop. 2020-11-03 01:40:00 -08:00
Andrew Trick
834615671e LoopRotate: Avoid introducing new critical edges during rotation. 2020-11-03 01:40:00 -08:00
Andrew Trick
3128eae3f0 Add NestedSemanticFunctionCheck diagnostic
to check for improperly nested '@_semantic' functions.

Add a missing @_semantics("array.init") in ArraySlice found by the
diagnostic.

Distinguish between array.init and array.init.empty.

Categorize the types of semantic functions by how they affect the
inliner and pass pipeline, and centralize this logic in
PerformanceInlinerUtils. The ultimate goal is to prevent inlining of
"Fundamental" @_semantics calls and @_effects calls until the late
pipeline where we can safely discard semantics. However, that requires
significant pipeline changes.

In the meantime, this change prevents the situation from getting worse
and makes the intention clear. However, it has no significant effect
on the pass pipeline and inliner.
2020-10-26 17:02:33 -07:00
Andrew Trick
6f2cda1390 Add AccessUseVisitor and cleanup related APIs.
Add AccesssedStorage::compute and computeInScope to mirror AccessPath.

Allow recovering the begin_access for Nested storage.

Adds AccessedStorage.visitRoots().
2020-10-16 15:00:10 -07:00
Andrew Trick
cc0aa2f8b8 Add an AccessPath abstraction and formalize memory access
Things that have come up recently but are somewhat blocked on this:

- Moving AccessMarkerElimination down in the pipeline
- SemanticARCOpts correctness and improvements
- AliasAnalysis improvements
- LICM performance regressions
- RLE/DSE improvements

Begin to formalize the model for valid memory access in SIL. Ignoring
ownership, every access is a def-use chain in three parts:

object root -> formal access base -> memory operation address

AccessPath abstracts over this path and standardizes the identity of a
memory access throughout the optimizer. This abstraction is the basis
for a new AccessPathVerification.

With that verification, we now have all the properties we need for the
type of analysis requires for exclusivity enforcement, but now
generalized for any memory analysis. This is suitable for an extremely
lightweight analysis with no side data structures. We currently have a
massive amount of ad-hoc memory analysis throughout SIL, which is
incredibly unmaintainable, bug-prone, and not performance-robust. We
can begin taking advantage of this verifably complete model to solve
that problem.

The properties this gives us are:

Access analysis must be complete over memory operations: every memory
operation needs a recognizable valid access. An access can be
unidentified only to the extent that it is rooted in some non-address
type and we can prove that it is at least *not* part of an access to a
nominal class or global property. Pointer provenance is also required
for future IRGen-level bitfield optimizations.

Access analysis must be complete over address users: for an identified
object root all memory accesses including subobjects must be
discoverable.

Access analysis must be symmetric: use-def and def-use analysis must
be consistent.

AccessPath is merely a wrapper around the existing accessed-storage
utilities and IndexTrieNode. Existing passes already very succesfully
use this approach, but in an ad-hoc way. With a general utility we
can:

- update passes to use this approach to identify memory access,
  reducing the space and time complexity of those algorithms.

- implement an inexpensive on-the-fly, debug mode address lifetime analysis

- implement a lightweight debug mode alias analysis

- ultimately improve the power, efficiency, and maintainability of
  full alias analysis

- make our type-based alias analysis sensistive to the access path
2020-10-16 15:00:10 -07:00
Andrew Trick
2767b51d61 Change Projection to support signed indices.
Change ProjectionIndex for ref_tail_addr to std::numeric_limits<int>::max();
This is necessary to disambiguate the tail elements from
ref_element_addr field zero.
2020-10-16 15:00:09 -07:00