Commit Graph

1032 Commits

Author SHA1 Message Date
swift-ci
1bd8ab63c9 Merge remote-tracking branch 'origin/main' into rebranch 2021-11-30 13:33:50 -08:00
Erik Eckstein
4aae41520a EscapeAnalysis: fix a bug with results in not detecting an escape through an unowned reference.
`ref_to_unowned`  and similar instructions must be checked if the operand/result types are treated as "pointers" in escape analysis.
Fixes a miscompile.

https://bugs.swift.org/browse/SR-15527
rdar://85772200
2021-11-30 14:19:50 +01:00
swift-ci
581a5fe89f Merge remote-tracking branch 'origin/main' into rebranch 2021-11-29 06:33:18 -08:00
Erik Eckstein
2d1045f7bc MemBehavior: handle guaranteed arguments in non-OSSA mode.
In non-OSSA, this is the only case for which we know that if an instruction is within a "borrow-scope".
2021-11-29 09:41:05 +01:00
Ben Barham
30be5117d2 [rebranch][IRGen] Update uses of AttributeList functions
The functions in llvm-project `AttributeList` have been
renamed/refactored to help remove uses of `AttributeList::*Index`.

Update to use these new functions where possible. There's one use of
`AttrIndex` remaining as `replaceAttributeTypeAtIndex` still takes the
index and there is no `param` equivalent. We could add one locally, but
presumably that will be added eventually.
2021-11-13 17:04:29 +10:00
Meghana Gupta
22aa3c5dbe Fix Escape Analysis for OSSA's pattern of array.uninitialized (#39789) 2021-10-18 09:39:19 -07:00
Meghana Gupta
52e88c7a77 Improve OSSA instructions handling in EscapeAnalysis
copy_value/destroy_value/begin_borrow were not handled in EscapeAnalysis::analyzeInstruction.
As a result EscapeState of the values were set to Global leading to very conservative results
for queries like CGNode::escapes.
2021-10-12 17:01:05 -07:00
swift-ci
f0def9afc0 Merge remote-tracking branch 'origin/main' into rebranch 2021-09-22 09:13:41 -07: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
swift-ci
ebad328a4f Merge remote-tracking branch 'origin/main' into rebranch 2021-09-01 09:14:57 -07:00
Min-Yih Hsu
343d842394 [SIL][DebugInfo] PATCH 3/3: Deprecate debug_value_addr SIL instruciton
This patch removes all references to DebugValueAddrInst class and
debug_value_addr instruction in textual SIL files.
2021-08-31 12:01:04 -07:00
Min-Yih Hsu
e1023bc323 [DebugInfo] PATCH 2/3: Duplicate logics regarding debug_value_addr
This patch replace all in-memory objects of DebugValueAddrInst with
DebugValueInst + op_deref, and duplicates logics that handles
DebugValueAddrInst with the latter. All related check in the tests
have been updated as well.

Note that this patch neither remove the DebugValueAddrInst class nor
remove `debug_value_addr` syntax in the test inputs.
2021-08-31 11:57:56 -07:00
swift-ci
a8089662bd Merge remote-tracking branch 'origin/main' into rebranch 2021-08-09 16:13:32 -07:00
Andrew Trick
1f64871b31 MemAccessUtils: unify Box/Class/Tail storage for consistency and usability
It was originally convenient for exclusivity optimization to treat
boxes specially. We wanted to know that the 'Box' kind was always
uniquely identified. But that's not really important. And now that
AccessedStorage is being used more generally, the inconsistency is
problematic.

A consistent model is also must easier to understand and explain.

This also make the implementation of the utility simpler and more powerful.

Functional changes:

isRCIdentical will look through mark_dependence and mark_uninitialized.

findReferenceRoot is used consistently everywhere increasing analysis precision.
2021-08-09 11:43:40 -07:00
swift-ci
e0e2634b84 Merge remote-tracking branch 'origin/main' into rebranch 2021-07-06 09:35:07 -07:00
Erik Eckstein
7ed04c3ba3 libswift: add CalleeAnalysis
Bridging to BasicCalleeAnalysis
2021-07-01 17:30:56 +02:00
Erik Eckstein
e096b2f14a BasicCalleeAnalysis: make the callee list datastructure more efficient
This avoids copying a SmallVector in case of multiple callees in the list.
Instead, just reference the callee list in the cache.
2021-07-01 17:16:47 +02:00
Erik Eckstein
20c63cc3f5 libswift: add AliasAnalysis 2021-07-01 17:16:47 +02:00
Evan Wilde
8112cda531 Updated F_Text and F_Append
These enum cases were also updated to OF_Text and OF_Append.
2021-06-23 14:29:52 -07:00
Erik Eckstein
4977850092 SIL: remove the notifyDeleteHandlers mechanism
It's not needed anymore with delayed instruction deletion.
It was used for two purposes:
1. For analysis, which cache instructions, to avoid dangling instruction pointers
2. For passes, which maintain worklists of instructions, to remove a deleted instructions from the worklist. This is now done by checking SILInstruction::isDeleted().
2021-05-26 21:57:54 +02: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
3701de4731 AliasAnalysis: check for immutable scopes.
If the "regular" alias analysis thinks that an instruction may write to an address, check if the instruction is in an immutable scope of V.
That means that even if we don't know anything about the instruction (e.g. a call to an unknown function), we can be sure that it cannot write to the address.

An immutable scope is for example a read-only begin_access/end_access scope.
Another example is a borrow scope of an immutable copy-on-write buffer, for example:
   %b = begin_borrow %array_buffer
   %addr = ref_element_addr [immutable] %b : $BufferType, #BufferType.someField
2021-05-18 10:14:44 +02:00
Erik Eckstein
ed7a8026d6 ValueEnumerator: make the index type unsigned instead of size_t
This reduces the size of the index from 8 to 4 bytes, which is important in AliasAnalysis where we use pairs of such indices.
2021-05-18 08:56:22 +02:00
Andrew Trick
b0dc18dd04 Fix an assert in exclusivity diagnostics when inouts escape.
An error found in DiagnoseInvalidEscapingCaptures can indicate invalid
SIL, which will cause DiagnoseStaticExclusivity to assert during SIL
verification. When the source-level closure captures an inout
argument, it appears in SIL to be a non-escaping closure. The SIL
verification then fails because the "nonescaping" closure actually
escapes.

Ensure that capture diagnostics run on closures before exclusivity
enforcement runs on the parent function. Bypass the SIL verification
assert if a diagnostic error was found.

Fixes rdar://75364904 (Crash with assertion `noescape partial_apply
has unexpected use`)
2021-05-05 17:06:30 -07:00
Michael Gottesman
c834520b88 [simplify-instruction] When eliminating extracts from an aggregate we just constructed, look through ownership insts.
Just an oversight. When used with -enable-ossa-modules, this eliminates the
reported ARC traffic issue in:

SR-12377
rdar://60832825
2021-03-31 18:30:03 -07:00
Erik Eckstein
479517f71d AccessSummaryAnalysis: relax the verification of expected no-escape partial_apply uses
* add is_escaping_closure as allowed instruction
* don't restrict the uses of copy_value to be a store

Fixes a verification crash (only in assert builds).

https://bugs.swift.org/browse/SR-14394
rdar://75740622
2021-03-29 13:21:43 +02:00
Erik Eckstein
67ce72cebb MemBehavior: fix minor bugs for `begin_access and end_access`.
* ``begin_access [modify]`` returned MayWrite, but "modify" means, it can be a read as well.
Instead, return MayReadWrite. Only for ``begin_access [init]`` return MayWrite.
This is more or less cosmetic - probably this bug had no real impact on any optimization.

* ``begin_access [deinit]`` needs to return MayReadWrite for the same reason ``destroy_addr`` returns MayReadWrite (see SILInstruction::MemoryBehavior).
2021-03-24 12:16:07 +01:00
Erik Eckstein
74fe92ffdb SILCombine: remove dead unconditional_checked_cast
rdar://72200045
2021-03-09 19:38:35 +01:00
Andrew Trick
f6624e355a Add EscapeAnalysis::findObjectKind to mitigate deinit side effects
Deinitializer side effects severely handicap the connection-graph
based EscapeAnalysis. Because it's not flow-sensitive, this approach
falls apart whenever an object is released in the current function,
which makes it seem to have escaped everywhere (it generally doesn't
matter if it doesn't escape until the release point, but the analysis
can't discern that).

This can be slightly mitigated by realizing that releasing an object
can only cause things it points to to escape if the object itself has
references or pointers.

Fix: Don't create a escaping content node when releasing an object
that can't contain any references or pointers.  The previous commit,
"Fix EscapeAnalysis::mayReleaseContent" would defeat release-hoisting
in important cases without doing anything else. Adding this extra
precision to the connection graph avoids some regressions.
2021-02-19 12:35:11 -08:00
Andrew Trick
23696e4dff Fix EscapeAnalysis::mayReleaseContent
The previous implementation made extremely subtle and specific
assumptions about how the API is used which doesn't apply
everywhere. It was trying very hard to avoid regressing performance
relative to an even older implementation that didn't even try to consider deinitializer side effects.

The aggressive logic was based on the idea that a release must have a
corresponding retain somewhere in the same function and we don't care
if the last release happens early if there are no more aliasing
uses. All the unit tests I wrote previously were based on release
hoisting, which happens to work given the way the API is used.

But this logic is incorrect for retain sinking. In that case sinking
past an "unrelated" release could cause the object to be freed
early. See test/SILOptimizer/arc_crash.swift.

With SemanticARC and other SIL improvements being made, I'm afraid
bugs like this will begin to surface.

To fix it, just remove the subtle logic to leave behind a simple and
sound EscapeAnalysis API. To do better, we will need to rewrite the
AliasAnalysis logic for release side effects, which is currently
a tangled web. In the meantime, SemanticARC can handle many cases without EscapeAnalysis.

Fixes rdar://74469299 (ARC miscompile:
EscapeAnalysis::mayReleaseContent; potential use-after-free)

While fixing this, add support for address-type queries too:

Fixes rdar://74360041 (Assertion failed:
(!releasedReference->getType().isAddress() && "an address is never a
reference"), function mayReleaseContent
2021-02-18 19:00:22 -08:00
Erik Eckstein
db29d77918 SILCombine: don't create a strong_retain/strong_release with an Optional<reference> as an operand
strong_retain/strong_release with an optional reference as operand are rejected by the verifier and are not supported by IRGen.
SILCombine created such retains/releases when optimizing ref_cast instructions.

This fixes a compiler crash.
rdar://74146617
2021-02-12 10:03:22 +01:00
Erik Eckstein
542a378436 SIL: add FunctionRefInst::getReferencedFunction()
If we know that we have a FunctionRefInst (and not another variant of FunctionRefBaseInst), we know that getting the referenced function will not be null (in contrast to FunctionRefBaseInst::getReferencedFunctionOrNull).

NFC
2021-02-09 19:56:43 +01:00
Varun Gandhi
caf1a55eea Merge pull request #35229 from mininny/switch-find-to-contains
[NFC] Replace uses of find(x) != end() idiom with contains(x) for StringRef and Set-like types
2021-02-08 13:57:43 -08:00
Minhyuk Kim
53d1fc481e Replace usages of .find(Key) != .end() to .contains(Key) in llvm sets 2021-02-06 18:24:20 +09:00
Erik Eckstein
1c6bcd2344 FunctionSignatureOptimization: prevent owned->guaranteed specialization in case of a dealloc_partial_ref
If an argument is deallocated in the function, it cannot be converted to a guaranteed argument.
We already handled the dealloc_ref instruction, but were missing the dealloc_partial_ref instruction.

It fixes a miscompile.
rdar://73871606
2021-02-05 20:49:55 +01: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
Erik Eckstein
011358edd6 SIL: let SingleValueInstruction only inherit from a single SILNode.
This removes the ambiguity when casting from a SingleValueInstruction to SILNode, which makes the code simpler. E.g. the "isRepresentativeSILNode" logic is not needed anymore.
Also, it reduces the size of the most used instruction class - SingleValueInstruction - by one pointer.

Conceptually, SILInstruction is still a SILNode. But implementation-wise SILNode is not a base class of SILInstruction anymore.
Only the two sub-classes of SILInstruction - SingleValueInstruction and NonSingleValueInstruction - inherit from SILNode. SingleValueInstruction's SILNode is embedded into a ValueBase and its relative offset in the class is the same as in NonSingleValueInstruction (see SILNodeOffsetChecker).
This makes it possible to cast from a SILInstruction to a SILNode without knowing which SILInstruction sub-class it is.
Casting to SILNode cannot be done implicitly, but only with an LLVM `cast` or with SILInstruction::asSILNode(). But this is a rare case anyway.
2021-01-27 16:40:15 +01:00
Erik Eckstein
cff273597a EscapeAnalysis: change the parameter of isNonWritableMemoryAddress from SILNode* to SILValue
A small cleanup, NFC.
2021-01-27 16:40:14 +01:00
Eric Miotto
8e7f9c9cbd Revert "SIL: let SingleValueInstruction only inherit from a single SILNode." 2021-01-26 10:02:24 -08:00
Erik Eckstein
ff1991740a SIL: let SingleValueInstruction only inherit from a single SILNode.
This removes the ambiguity when casting from a SingleValueInstruction to SILNode, which makes the code simpler. E.g. the "isRepresentativeSILNode" logic is not needed anymore.
Also, it reduces the size of the most used instruction class - SingleValueInstruction - by one pointer.

Conceptually, SILInstruction is still a SILNode. But implementation-wise SILNode is not a base class of SILInstruction anymore.
Only the two sub-classes of SILInstruction - SingleValueInstruction and NonSingleValueInstruction - inherit from SILNode. SingleValueInstruction's SILNode is embedded into a ValueBase and its relative offset in the class is the same as in NonSingleValueInstruction (see SILNodeOffsetChecker).
This makes it possible to cast from a SILInstruction to a SILNode without knowing which SILInstruction sub-class it is.
Casting to SILNode cannot be done implicitly, but only with an LLVM `cast` or with SILInstruction::asSILNode(). But this is a rare case anyway.
2021-01-25 09:30:04 +01:00
Erik Eckstein
ea72895024 EscapeAnalysis: change the parameter of isNonWritableMemoryAddress from SILNode* to SILValue
A small cleanup, NFC.
2021-01-25 09:30:04 +01:00
Erik Eckstein
763bfed6a4 SILOptimizer: use the BasicBlockFlag utility in ReachableBlocks 2021-01-21 21:31:41 +01:00
Meghana Gupta
8d217f362f Merge pull request #35380 from meg-gupta/abcoptsossa
Enable ArrayBoundsCheckElimination on OSSA
2021-01-20 13:21:06 -08:00
Michael Gottesman
2243ffefa4 Merge pull request #35461 from gottesmm/ossa-interior-ptr-fixup
[ownership] Implement Interior Pointer handling API for RAUWing addresses
2021-01-20 09:53:48 -08:00
Meghana Gupta
00ea81c8df Enable ArrayBoundsCheckElimination on OSSA 2021-01-20 02:13:15 -08:00
Nate Chandler
d2e5fa7f42 Tweaked comment.
Matched the comment on the definition of NonLocalAccessBlocks::compute()
to that on the declaration.
2021-01-19 09:34:15 -08:00
Michael Gottesman
4a71042d31 [ownership] Add a DeadEndBlocksAnalysis that vends/saves DeadEndBlocks in between passes.
Importantly this also lets us use the analysis framework to validate that we do
properly invalidate DeadEndBlocks, preventing bugs.

I did not thread this all over the compiler. Instead I just used it for now in
SemanticARCOpts just to add some coverage without threading it into too many
places.
2021-01-18 15:23:14 -08:00
Michael Gottesman
5136581648 [inst-simplify] Fail simplification if we have ownership and are not passed a non-null deadEndBlocks.
I am trying to be more careful about this rather than letting someone make this
mistake in the future. I also added some comments and a DeadEndBlocks instance
to TempRValueElimination so that it gets full simplifications in OSSA.
2021-01-17 20:08:24 -08:00
Michael Gottesman
38e2a3bfcf [inst-simplify] Eliminate address_to_pointer/pointer_to_address identity transforms using new interior pointer handling utility.
Btw for those curious, the reason why this optimization is important is that the
stdlib often times performs reinterpret casts using address to pointer, pointer
to address to perform the case. So we need to be able to reliably eliminate
these. Since the underlying base object's liveness is already what provides the
liveness to the underlying address, our approach of treating this as a lifetime
extension requiring pattern makes sense since we are adding information into the
IR by canonicalizing these escapes to be normal address operations.

NOTE: In this commit, we only handle the identity transform. In a subsequent
commit, I am going to hit the non-identity transform that is handled by
SILCombine.

Also, I added some specific more general OSSA RAUW tests for this case to
ossa_rauw_tests using this functionality in a more exhaustive way that would be
in appropriate in sil_combine_ossa.sil (since I am stress testing this specific
piece of code).
2021-01-17 20:08:24 -08:00