Commit Graph

173 Commits

Author SHA1 Message Date
Michael Gottesman
fced2398c5 [semantic-arc] Change LiveRange to work with Operand instead of Operand->getUser().
This is just better information to have since one wants to not only know the
instruction, but also the specific value used on the instruction since behavior
can vary depending upon that. The operand is what ties the two together so it is
a natural fit.

Now that this is done, I am going to work on refactoring out converting a
LiveRange from @owned -> @guaranteed. It will be a consuming operation using a
move operator since once the transformation has completed, the LiveRange no
longer exists.

I need this refactored functionality since I am going to need it when
eliminating phi-webs.
2020-03-04 17:07:48 -08:00
Michael Gottesman
bdf6143df5 [ownership] Add simple support for concatenating together simple live ranges that do not need LiveRange analysis.
Specifically, this PR adds support for optimizing simple cases where we do not
need to compute LiveRanges with the idea of first doing simple transforms that
involve small numbers of instructions first. With that in mind, we only optimize
cases where our copy_value has a single consuming user and our owned value has a
single destroy_value. To understand the transform here, consider the following
SIL:

```
  %0 = ...
  %1 = copy_value %0                 (1)
  apply %guaranteedUser(%0)          (2)
  destroy_value %0                   (3)
  apply %cviConsumer(%1)             (4)
```

We want to eliminate (2) and (3), effectively joining the lifetimes of %0 and
%1, transforming the code to:

```
  %0 = ...
  apply %guaranteedUser(%0)          (2)
  apply %cviConsumer(%0)             (4)
```

Easily, we can always do this transform in this case since we know that %0's
lifetime ends strictly before the end of %1's due to (3) being before (4). This
means that any uses that require liveness of %0 must be before (4) and thus no
use-after-frees can result from removing (3) since we are not shrinking the
underlying object's lifetime. Lets consider a different case where (3) and (4)
are swapped.

```
  %0 = ...
  %1 = copy_value %0                 (1)
  apply %guaranteedUser(%0)          (2)
  apply %cviConsumer(%1)             (4)
  destroy_value %0                   (3)
```

In this case, since there aren't any liveness requiring uses of %0 in between
(4) and (3), we can still perform our transform. But what if there was a
liveness requiring user in between (4) and (3). To analyze this, lets swap (2)
and (4), yielding:

```
  %0 = ...
  %1 = copy_value %0                 (1)
  apply %cviConsumer(%1)             (4)
  apply %guaranteedUser(%0)          (2)
  destroy_value %0                   (3)
```

In this case, if we were to perform our transform, we would get a use-after-free
due do the transform shrinking the lifetime of the underlying object here from
ending at (3) to ending at (4):

```
  %0 = ...
  apply %cviConsumer(%1)             (4)
  apply %guaranteedUser(%0)          (2) // *kaboom*
```

So clearly, if (3) is after (4), clearly, we need to know that there aren't any
liveness requiring uses in between them to be able to perform this
optimization. But is this enough? Turns out no. There are two further issues
that we must consider:

1. If (4) is forwards owned ownership, it is not truly "consuming" the
underlying value in the sense of actually destroying the underlying value. This
can be worked with by using the LiveRange abstraction. That being said, this PR
is meant to contain simple transforms that do not need to use LiveRange. So, we
bail if we see a forwarding instruction.

2. At the current time, we may not be able to find all normal uses since all of
the instructions that are interior pointer constructs (e.x.: project_box) have
not been required yet to always be guarded by borrows (the eventual end
state). Thus we can not shrink lifetimes in general safely until that piece of
work is done.

Given all of those constraints, we only handle cases here where (3) is strictly
before (4) so we know 100% we are not shrinking any lifetimes. This effectively
is causing our correctness to rely on SILGen properly scoping lifetimes. Once
all interior pointers are properly guarded, we will be able to be more
aggressive here.

With that in mind, we perform this transform given the following conditions
noting that this pattern often times comes up around return values:

1. If the consuming user is a return inst. In such a case, we know that the
   destroy_value must be before the actual return inst.

2. If the consuming user is in the exit block and the destroy_value is not.

3. If the consuming user and destroy_value are in the same block and the
   consuming user is strictly later in that block than the destroy_value.

In all of these cases, we are able to optimize without the need for LiveRanges.
I am going to add support for this in a subsequent commit.
2020-03-01 19:59:54 -08:00
Michael Gottesman
ae6cd35751 [ownership] Add helper method Operand::isConsumingUse() const.
This just provides a higher level of abstraction around determining if an
operand consumes its associated value needing to touch the ownership kind
map/etc.

I also refactored parts of the code base where it made sense to use this instead
of messing with the ownership kind map itself.
2020-02-13 17:58:03 -08:00
Saleem Abdulrasool
075a93a475 SIL: add an explicit move assignment operation instantiation 2020-01-01 13:16:45 -08:00
Saleem Abdulrasool
86ca0a1747 SIL: explicitly instantiate the Operand move ctor
GCC 7 does not like the missing move constructor and does not implicitly
synthesize one.  Explicitly indicate that this should be synthesized.
2020-01-01 13:15:55 -08:00
Brent Royal-Gordon
99faa033fc [NFC] Standardize dump() methods in frontend
By convention, most structs and classes in the Swift compiler include a `dump()` method which prints debugging information. This method is meant to be called only from the debugger, but this means they’re often unused and may be eliminated from optimized binaries. On the other hand, some parts of the compiler call `dump()` methods directly despite them being intended as a pure debugging aid. clang supports attributes which can be used to avoid these problems, but they’re used very inconsistently across the compiler.

This commit adds `SWIFT_DEBUG_DUMP` and `SWIFT_DEBUG_DUMPER(<name>(<params>))` macros to declare `dump()` methods with the appropriate set of attributes and adopts this macro throughout the frontend. It does not pervasively adopt this macro in SILGen, SILOptimizer, or IRGen; these components use `dump()` methods in a different way where they’re frequently called from debugging code. Nor does it adopt it in runtime components like swiftRuntime and swiftReflection, because I’m a bit worried about size.

Despite the large number of files and lines affected, this change is NFC.
2019-10-31 18:37:42 -07:00
Varun Gandhi
033be473a8 [NFC] Change ValueOwnershipKind::Any to ValueOwnershipKind::None in comments. (#27925)
Follow-up to PR #27879.
2019-10-29 16:50:45 -07:00
Michael Gottesman
26a734e58e [sil] Rename ValueOwnershipKind::{Any,None} 2019-10-25 10:28:25 -07:00
Jordan Rose
a1ea211f22 Add llvm::iterator_range to LLVM.h
If we're going to get rid of swift::IteratorRange, let's make
llvm::iterator_range easy to use.

No functionality change.
2019-10-08 15:24:06 -07:00
Michael Gottesman
d535e3e6cf [ownership] Allow for the ownership verifier to be run in non-asserts builds if -sil-verify-all is set.
This is matching the behavior of the rest of the verifier. NOTE: Both early exit
if said flag is not set, so this should not hit compile time in any way unless
the flag is set (in which case someone is asking for more verification...).

While I was here, I also noticed an ancillary bug where we were not checking if
a value was from in a block that was in a SILGlobalVariable or a SILFunction. We
already had a check that stopped this early when validating ownership of
SILInstructions. I guess we have never had a situation where the verifier was
given values to run on SILGlobalVariable blocks.
2019-10-02 12:36:17 -07:00
Michael Gottesman
7b2fc076f7 [sil] Add new API ValueBase:getUsersOfType<T>().
For some time now we have had the API ValueBase::getSingleUserOfType<T>() but we
never implemented getUsersOfType<T>() using transform/filter iterators.

Since there wasn't a specific API, several incarnations of this API have been
created for BeginBorrow, LoadBorrow, BeginAccess.

In this commit, I introduce the API and use it to excise the redundant code in
those above mentioned 3 instructions.
2019-09-06 16:40:51 -07:00
Michael Gottesman
af565e7cc0 [sil-parser] Fix harmless bug when parsing ossa.
Specifically, we were preferring the always correct ownership kind specified by
the FunctionType and ignoring what we parsed from the argument. This PR changes
ossa to give a nice error when this is detected and fixes the places where this
tests were written incorrectly.
2019-08-27 10:18:49 -07:00
Saleem Abdulrasool
731c31f9a5 MSVC: litter the code with llvm_unreachable (NFC)
Add `llvm_unreachable` to mark covered switches which MSVC does not
analyze correctly and believes that there exists a path through the
function without a return value.
2019-06-01 19:02:46 -07:00
Michael Gottesman
72a093da52 [semantic-arc-opts] Teach the guaranteed copy_value peephole how to handle instructions that can forward either owned or guaranteed ownership.
This fixes issues exposed by my turning off the Nominal Type RValue peephole. It
should give us some nice ARC wins as well potentially.
2019-03-21 13:50:41 -07:00
Slava Pestov
8915f96e3e SIL: Replace SILType::isTrivial(SILModule) with isTrivial(SILFunction) 2019-03-12 01:16:04 -04:00
Michael Gottesman
33e5aba554 Merge pull request #20855 from gottesmm/pr-94ee6e6c6e2d268f47f17dead77e4feb169c24e6
[ownership] Replace ValueOwnershipKind::Trivial with ValueOwnershipKi…
2018-12-05 14:47:04 -08:00
Michael Gottesman
0af0d5fddc [ownership] Replace ValueOwnershipKind::Trivial with ValueOwnershipKind::Any.
In a previous commit, I banned in the verifier any SILValue from producing
ValueOwnershipKind::Any in preparation for this.

This change arises out of discussions in between John, Andy, and I around
ValueOwnershipKind::Trivial. The specific realization was that this ownership
kind was an unnecessary conflation of the a type system idea (triviality) with
an ownership idea (@any, an ownership kind that is compatible with any other
ownership kind at value merge points and can only create). This caused the
ownership model to have to contort to handle the non-payloaded or trivial cases
of non-trivial enums. This is unnecessary if we just eliminate the any case and
in the verifier separately verify that trivial => @any (notice that we do not
verify that @any => trivial).

NOTE: This is technically an NFC intended change since I am just replacing
Trivial with Any. That is why if you look at the tests you will see that I
actually did not need to update anything except removing some @trivial ownership
since @any ownership is represented without writing @any in the parsed sil.

rdar://46294760
2018-12-04 23:01:43 -08:00
Adrian Prantl
ff63eaea6f Remove \brief commands from doxygen comments.
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.

Patch produced by

      for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
2018-12-04 15:45:04 -08:00
Michael Gottesman
71c13b7594 [sil] Rename ValueOwnershipKindClassifier.cpp -> ValueOwnership.cpp and remove ValueOwnershipKindClassifier.h
This matches the name of OperandOwnership.cpp which performs an anologous
function. I also was able to eliminate an unneeded header.  The key thing here
is that the only reason that we had ValueOwnershipKindClassifier.h was because
we needed some defs from it in SILValue.cpp for SILValue::getOwnershipKind()
... which is great except for the fact that ValueOwnershipKindClassifier is
basically the implementation of SILValue::getOwnershipKind().

So what this patch does is moves the implementation of
SILValue::getOwnershipKind() from SILValue.cpp -> ValueOwnership.cpp and then
puts the visitor into an anonymous namespace in that file.

I also added a little comment in SILValue.h that says that
SILValue::getOwnershipKind() is implemented in ValueOwnership.cpp, not
SILValue.cpp.
2018-10-29 23:50:54 -07:00
Erik Eckstein
ac2b5720b0 SILOptimizer: support static large string literal generation for the new UTF8 String implementation
In the new string implementation there is a subtract of a (small) constant from the literal pointer. We convert

((ptr - offset) | bits

to

(ptr + (bits - offset))

which can still be represented as a relocation.
2018-10-25 10:18:23 -07:00
Michael Gottesman
157091d5c6 [ownership] Extract out from SILOwnershipVerifier the OperandOwnershipKindMapClassifier
NOTE: This is not the final form of how operand ownership restraints will be
represented. This patch is instead an incremental change that extracts out this
functionality from the ownership verifier as a pure refactor.

rdar://44667493
2018-10-01 22:14:41 -07:00
Jason Mittertreiner
8ac9a657a8 Fix 'operator ==' is ambiguous with MSVC (#19501)
When compiling with MSVC on Windows, this error among other similar
conflicts with AnyValue occur:

Defined the overloads so it selects the correct one.
2018-09-24 12:39:44 -07:00
Michael Gottesman
af7d301512 [sil] Make ValueOwnershipKind(unsigned) explicit to prevent implicit casts from ints/bools to ValueOwnershipKind.
I hit this problem while splitting classifying operand ownership from the
ownership verifier itself. There is no reason to allow for this implicit
conversion. Just makes updating code more error prone.

rdar://44667493
2018-09-21 09:58:02 -07:00
Sho Ikeda
03fbd4a6de [gardening][SIL] Replace typedef with using 2018-04-05 13:53:20 +09:00
swift-ci
d830b970db Merge remote-tracking branch 'origin/master' into master-llvm-swift5-transition 2018-02-19 10:50:38 -08:00
Michael Gottesman
71b508e402 Refactor compatibleOwnershipKind, trivialOrCompatibleOwnershipKinds onto ValueOwnershipKind instead of being free functions.
I have a bunch of work that I have done on a side branch some time ago to split
determining what value ownership kinds are able to be associated with a specific
operand.

This PR just upstreams a small part of the larger change.
2018-02-19 07:01:44 -08:00
swift-ci
00cf2a4070 Merge remote-tracking branch 'origin/master' into master-next 2017-12-28 08:49:22 -08:00
David Zarzycki
68c696dbc1 [SIL] NFC: Replace boilerplate projection with swift::ArrayRefView 2017-12-28 09:51:29 -05:00
swift-ci
f8dde3619a Merge remote-tracking branch 'origin/master' into master-next 2017-12-27 10:49:23 -08:00
David Zarzycki
3910c0d211 [SIL] NFC: Remove TailAllocatedOperandList template
Please use InstructionBaseWithTrailingOperands template now. It is more type safe and more space efficient.
2017-12-27 11:18:54 -05:00
swift-ci
0302515cf0 Merge remote-tracking branch 'origin/master' into master-next 2017-12-18 12:48:55 -08:00
David Zarzycki
7368cc9a8b [SIL] NFC: Convert SILNode to new inline bitfield macros 2017-12-16 09:31:21 -05:00
swift-ci
7ad712de8e Merge remote-tracking branch 'origin/master' into master-next 2017-10-24 18:49:07 -07:00
Michael Gottesman
36a8d0d5c0 [sil] Add support for the destructure_{struct,tuple} instructions.
rdar://31521023
2017-10-24 18:36:37 -07:00
Michael Gottesman
6df5462ee2 [sil] Add support for multiple value instructions by adding MultipleValueInstruction{,Result}.
rdar://31521023
2017-10-24 18:36:37 -07:00
swift-ci
34c8e98893 Merge remote-tracking branch 'origin/master' into master-next 2017-10-15 16:29:23 -07:00
Chris Lattner
cd99f859e3 NFC code cleanup changes:
- Hoist a duplicated static function with a fixme out to SILValue::getLoc()
 - Fix a whitespace issue.
2017-10-15 15:31:41 -07:00
swift-ci
135a4286b5 Merge remote-tracking branch 'origin/master' into master-next 2017-09-25 10:29:30 -07:00
John McCall
ab3f77baf2 Make SILInstruction no longer a subclass of ValueBase and
introduce a common superclass, SILNode.

This is in preparation for allowing instructions to have multiple
results.  It is also a somewhat more elegant representation for
instructions that have zero results.  Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction.  Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.

A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.

Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
2017-09-25 02:06:26 -04:00
swift-ci
b51e2e6837 Merge remote-tracking branch 'origin/master' into master-next 2017-09-15 13:29:49 -07:00
Joe Groff
78d75428d6 SILGen: Lower key path subscript indexes.
And fill out SIL support for parsing, printing, and serializing key path
patterns with captured indexes.
2017-09-15 10:00:32 -07:00
swift-ci
546836ceff Merge remote-tracking branch 'origin/master' into master-next 2017-09-11 15:08:53 -07:00
Roman Levenstein
74908ce818 Create utility functions for mapping between the numeric opcode of a SILValue/SILInstruction and its mnemonic name
Use it for the stats collection, but also for SIL printing.
2017-09-10 21:47:55 -07:00
Davide Italiano
d98a15875d [SILValue] Prefer const_cast<> to C-style cast.
Prevents a quite spammy warning with new versions of clang
(in the particular case, trunk as per today).
2017-09-09 16:59:16 -07:00
John McCall
a5d328690d PointerLikeTypeTraits is now a struct, not a class.
We compile with a pedantic warning that complains about these things,
and the massive flood of warnings is actually causing problems for the
build infrastructure.
2017-08-17 17:01:17 -04:00
Erik Eckstein
6377cc095a SIL: Replace TransitivelyUnreachableBlocks with DeadEndBlocks
We had both utilities doing the same thing.
NFC
2017-07-24 09:50:42 -07:00
Michael Gottesman
38cd78024b Add template <T> ValueBase::getSingleUserOfType.
Looping over all users and returning the only user of a specific type is a
common pattern in the compiler. This method just allows for the loop to be
eliminated.
2017-07-13 14:22:42 -07:00
Michael Gottesman
c3a5c51586 [gardening] Move SILInstruction::replaceAllUsesWithUndef onto ValueBase.
This allows this method to also be used on SILArguments.
2017-06-05 17:01:02 -07:00
Michael Gottesman
c28a62d97c [ome] Make sure to rewire all project_box we insert through the mark_uninitialized project_box to preserve DI behavior.
Once I update DI in a bit, this will no longer be necessary.

rdar://29870610
2017-04-03 12:17:44 -07:00
Michael Gottesman
00bcd15765 [sil] Add a new API ValueBase::getSingleUser()
This API returns nullptr if the ValueBase has more than one user and an
Operand * otherwise.
2017-04-02 10:51:08 -07:00