Commit Graph

137 Commits

Author SHA1 Message Date
Andrew Trick
d82e0ff781 SILInliner: Critical edges have no code size impact.
I think unconditional branches should be free, period. They will
mostly be removed during LLVM code gen. However, fixing this requires
signficant adjustments to inlining heuristics to avoid microbenchmark
regressions at -Osize. So, instead I am just making this less
sensitive to critical edges for the sake of pipeline stability.
2020-10-26 10:49:18 -07:00
Andrew Trick
7f09bbf80c Merge pull request #33698 from atrick/fix-smallstring
Fix undefined behavior in SmallString.withUTF8
2020-10-26 08:24:35 -07:00
Joe Groff
a664a33b52 SIL: Add instructions to represent async suspend points.
`get_async_continuation[_addr]` begins a suspend operation by accessing the continuation value that can resume
the task, which can then be used in a callback or event handler before executing `await_async_continuation` to
suspend the task.
2020-10-01 14:21:52 -07:00
Andrew Trick
42bf92a216 Make bind_memory free to inline.
bind_memory has no actual code size cost, and this is the only way to
allow rebinding memory within critical standard library
code like SmallString without regressing performance.
2020-09-24 18:36:42 -07:00
Michael Gottesman
5e36ae1c7c [sil] Add a forwarding cast called unchecked_value_cast.
Today unchecked_bitwise_cast returns a value with ObjCUnowned ownership. This is
important to do since the instruction can truncate memory meaning we want to
treat it as a new object that must be copied before use.

This means that in OSSA we do not have a purely ossa forwarding unchecked
layout-compatible assuming cast. This role is filled by unchecked_value_cast.
2020-07-09 21:14:32 -07:00
Erik Eckstein
67605553df SIL: a new instruction 'base_addr_for_offset' for field offset calculations.
The ``base_addr_for_offset`` instruction creates a base address for offset calculations.
The result can be used by address projections, like ``struct_element_addr``, which themselves return the offset of the projected fields.
IR generation simply creates a null pointer for ``base_addr_for_offset``.
2020-07-01 15:10:08 +02:00
Erik Eckstein
f5a8f600ea SIL: new instructions for copy-on-write support
* a new [immutable] attribute on ref_element_addr and ref_tail_addr
* new instructions: begin_cow_mutation and end_cow_mutation

These new instructions are intended to be used for the stdlib's COW containers, e.g. Array.
They allow more aggressive optimizations, especially for Array.
2020-05-14 08:39:54 +02:00
ematejska
75691d641e [AutoDiff upstream] Add linear function SIL instructions (#30638)
Add `linear_function` and `linear_function_extract` instructions.

`linear_function` creates a `@differentiable(linear)` function-typed value from
an original function operand and a transpose function operand (optional).

`linear_function_extract` extracts either the original or transpose function
value from a `@differentiable(linear)` function.

Resolves TF-1142 and TF-1143.
2020-03-26 09:41:14 -07:00
Dan Zheng
cc7e9fc39e [AutoDiff upstream] [SIL] Add differentiable function instructions.
Add `differentiable_function` and `differentiable_function_extract`
instructions.

`differentiable_function` creates a `@differentiable` function-typed
value from an original function operand and derivative function operands
(optional).

`differentiable_function_extract` extracts either the original or
derivative function value from a `@differentiable` function.

The differentiation transform canonicalizes `differentiable_function`
instructions, filling in derivative function operands if missing.

Resolves TF-1139 and TF-1140.
2020-03-22 23:53:43 -07:00
Dan Zheng
a49428ca7c [AutoDiff upstream] Add differentiability_witness_function instruction. (#29765)
The `differentiability_witness_function` instruction looks up a
differentiability witness function (JVP, VJP, or transpose) for a referenced
function via SIL differentiability witnesses.

Add round-trip parsing/serialization and IRGen tests.

Notes:
- Differentiability witnesses for linear functions require more support.
  `differentiability_witness_function [transpose]` instructions do not yet
  have IRGen.
- Nothing currently generates `differentiability_witness_function` instructions.
  The differentiation transform does, but it hasn't been upstreamed yet.

Resolves TF-1141.
2020-02-13 16:55:46 -08:00
David Zarzycki
f185dd66f1 [QoI] Fix -Wrange-loop-analysis warnings 2020-01-19 13:29:23 -05:00
Michael Gottesman
8264009e83 [inlining] Fix inlining of coroutines to properly handle owned values passed as guaranteed args.
Previously, we were inserting the end_borrow after the call site, rather than
after the end_apply, abort_apply.
2019-10-29 09:25:46 -07:00
Michael Gottesman
750c4cc487 [sil] Refactor out BeginApplyInst::getCoroutineEndPoints() impl from Inliner into method on the class itself.
I found this to be really useful outside of the inliner since this is exactly
what I needed to ensure that borrowed values used by a begin_apply, have the
end_apply/abort_apply as uses. I am adding that in a forthcoming commit.

NFC.
2019-10-27 18:38:58 -07:00
Michael Gottesman
7ee5ad7318 [sil] Rename {,Strong}Copy{Unowned,Unmanaged}. 2019-10-26 17:03:47 -07:00
Joe Groff
03c7919b4a SIL: Add fields to SILFunctionType for substituted function types.
https://forums.swift.org/t/improving-the-representation-of-polymorphic-interfaces-in-sil-with-substituted-function-types/29711

This prepares SIL to be able to more accurately preserve the calling convention of
polymorphic generic interfaces by letting the type system represent "substituted function types".
We add a couple of fields to SILFunctionType to support this:

- A substitution map, accessed by `getSubstitutions()`, which maps the generic signature
  of the function to its concrete implementation. This will allow, for instance, a protocol
  witness for a requirement of type `<Self: P> (Self, ...) -> ...` for a concrete conforming
  type `Foo` to express its type as `<Self: P> (Self, ...) -> ... for <Foo>`, preserving the relation
  to the protocol interface without relying on the pile of hacks that is the `witness_method`
  protocol.

- A bool for whether the generic signature of the function is "implied" by the substitutions.
  If true, the generic signature isn't really part of the calling convention of the function.
  This will allow closure types to distinguish a closure being passed to a generic function, like
  `<T, U> in (*T, *U) -> T for <Int, String>`, from the concrete type `(*Int, *String) -> Int`,
  which will make it easier for us to differentiate the representation of those as types, for
  instance by giving them different pointer authentication discriminators to harden arm64e
  code.

This patch is currently NFC, it just introduces the new APIs and takes a first pass at updating
code to use them. Much more work will need to be done once we start exercising these new
fields.

This does bifurcate some existing APIs:

- SILFunctionType now has two accessors to get its generic signature.
  `getSubstGenericSignature` gets the generic signature that is used to apply its
  substitution map, if any. `getInvocationGenericSignature` gets the generic signature
  used to invoke the function at apply sites. These differ if the generic signature is
  implied.
- SILParameterInfo and SILResultInfo values carry the unsubstituted types of the parameters
  and results of the function. They now have two APIs to get that type. `getInterfaceType`
  returns the unsubstituted type of the generic interface, and
  `getArgumentType`/`getReturnValueType` produce the substituted type that is used at
  apply sites.
2019-10-25 13:38:51 -07:00
Andrew Trick
bddc69c8a6 Organize SILOptimizer/Utils headers. Remove Local.h.
The XXOptUtils.h convention is already established and parallels
the SIL/XXUtils convention.

New:
- InstOptUtils.h
- CFGOptUtils.h
- BasicBlockOptUtils.h
- ValueLifetime.h

Removed:
- Local.h
- Two conflicting CFG.h files

This reorganization is helpful before I introduce more
utilities for block cloning similar to SinkAddressProjections.

Move the control flow utilies out of Local.h, which was an
unreadable, unprincipled mess. Rename it to InstOptUtils.h, and
confine it to small APIs for working with individual instructions.
These are the optimizer's additions to /SIL/InstUtils.h.

Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now
there is only SIL/CFG.h, resolving the naming conflict within the
swift project (this has always been a problem for source tools). Limit
this header to low-level APIs for working with branches and CFG edges.

Add BasicBlockOptUtils.h for block level transforms (it makes me sad
that I can't use BBOptUtils.h, but SIL already has
BasicBlockUtils.h). These are larger APIs for cloning or removing
whole blocks.
2019-10-02 11:34:54 -07:00
Michael Gottesman
5fc1d1d349 [ownership] Define a new instruction copy_unmanaged_value.
This provides a singular instruction for convert an unmanaged value to a ref,
then strong_retain it. I expanded the definition of UNCHECKED_REF_STORAGE to
include these copy like instructions. This instruction is valid in all SIL.

The reason why I am adding this instruction is that currently when we emit an
access to an unowned (unsafe) ivar, we use an unmanaged_to_ref and a strong
retain. This can look to the optimizer like a strong retain that can potentially
be optimized. By combining the two together into a new instruction, we can avoid
this potential problem since the pattern matching will break.
2019-08-25 21:26:40 -07:00
Davide Italiano
36b917b048 [SILInliner] Inherit SILBuilderContext when creating a new one.
Addresses Michael's feedback on my last commit.
2019-06-14 10:49:02 -07:00
Davide Italiano
0f1837c1fc [SILInliner] Also pass a SILBuilderContext.
Pointed out by Michael Gottesman.
2019-06-13 14:30:24 -07:00
Davide Italiano
15dd4fe4d1 [SILInliner] Set the correct scope for {begin,end}_borrow.
<rdar://problem/51512044>
2019-06-12 16:05:33 -07:00
Doug Gregor
c02ecf9859 [SE-0258] Rename to Property Wrappers 2019-05-29 22:17:50 -07:00
Arnold Schwaighofer
c187c8ac13 SIL: Replace uses of getReferencedFunction() by getReferencedFunctionOrNull() and getInitialReferencedFunction()
With the advent of dynamic_function_ref the actual callee of such a ref
my vary. Optimizations should not assume to know the content of a
function referenced by dynamic_function_ref. Introduce
getReferencedFunctionOrNull which will return null for such function
refs. And getInitialReferencedFunction to return the referenced
function.
Use as appropriate.

rdar://50959798
2019-05-26 08:58:14 -07:00
Jordan Rose
e8773b5e4d Add a PrettyStackTrace for SILInliner::inlineFunction (#24658) 2019-05-09 16:46:55 -07:00
Andrew Trick
aa6347c832 Merge pull request #24153 from atrick/fix-let-exclusivity
Add a SILGenCleanup pass and CanonicalizeInstruction utility.
2019-05-06 22:51:19 -07:00
Andrew Trick
ece096d91e Fix eraseFromParentWithdebugInsts to call a callback.
The recursivelyDeleteTriviallyDeadInstructions utility takes a
callBack to be called for every deleted instruction. However, it
wasn't passing this callBack to eraseFromParentWithdebugInsts. The
callback was used to update an iterator in some cases, so not calling
it resulted in iterator invalidation.

Doing this also cleans up the both APIs:
recursivelyDeleteTriviallyDeadInstructions and eraseFromParentWithdebugInsts.
2019-05-06 17:23:08 -07:00
Ravi Kandhadai
bed34d65ad [SIL Inlining] Extract out a reusable code snippet in PerformanceInliner
into a utility function in SILInliner.
2019-05-03 15:00:41 -07:00
Erik Eckstein
2e01b0edeb SIL: add assign_by_delegate instruction
Used for property delegates.
2019-04-23 11:32:28 -07:00
Slava Pestov
c791c4a137 SIL: SILUndef must be aware of the resilience expansion
The ownership kind is Any for trivial types, or Owned otherwise, but
whether a type is trivial or not will soon depend on the resilience
expansion.

This means that a SILModule now uniques two SILUndefs per type instead
of one, and serialization uses two distinct sentinel IDs for this
purpose as well.

For now, the resilience expansion is not actually used here, so this
change is NFC, other than changing the module format.
2019-03-12 00:30:35 -04:00
Erik Eckstein
767ad5e70a Inliner: fix a stack nesting problem when inlining coroutines
Beside fixing the compiler crash, this change also improves the stack-nesting correction mechanisms in the inliners:

* Instead of trying to correct the nesting after each inlining of a callee, correct the nesting once when inlining is finished for a caller function.
This fixes a potential compile time problem, because StackNesting iterates over the whole function.
In worst case this can lead to quadratic behavior in case many begin_apply instructions with overlapping stack locations are inlined.

* Because we are doing it only once for a caller, we can remove the complex logic for checking if it is necessary.
We can just do it unconditionally in case any coroutine gets inlined.
The inliners iterate over all instruction of a function anyway, so this does not increase the computational complexity (StackNesting is roughly linear with the number of instructions).

rdar://problem/47615442
2019-02-01 08:32:19 -08:00
Michael Gottesman
23378cc16f [sil] Rename QualifiedOwnership => Ownership.
Done using Xcode's refactoring engine.
2018-12-16 15:21:52 -08:00
Slava Pestov
aa747dcd81 Remove property behaviors 2018-12-07 20:38:33 -05: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
Andrew Trick
702981f775 Fix MandatoryInlining to not be quadratic.
Inlining has always been quadratic for no good reason. There was a
special hack for single-block callees that allowed linear inlining.

Instead, the now iterates over blocks and instructions in reverse,
splitting blocks as it inlines. There no longer needs to be special
case for single block callees, and the inliner is linear for all kinds
of callees.

This further simplifies and cleans up the code. There are just a few
basic invariants that the common inliner needs to provide about how
blocks are split and laid out. We can do this if we don't add hacks
for special cases within the inliner. Those invariants allow the
inliner clients to be much simpler and more efficient.

PerformanceInliner still needs to be fixed.

Fixes SR-9223: Inliner exhibits slow compilation time with a large
static array.
2018-11-26 09:41:28 -08:00
Andrew Trick
9c46b2a053 Fix block merging after inlining to help avoid quadratic inlining.
A recent SILCloner rewrite removed a special case hack for single
basic block callee functions:

commit c6865c0dff
Merge: 76e6c4157e 9e440d13a6
Author: Andrew Trick <atrick@apple.com>
Date:   Thu Oct 11 14:23:32 2018

    Merge pull request #19786 from atrick/silcloner-cleanup

    SILCloner and SILInliner rewrite.

Instead, the new inliner simply merges trivial unconditional branches
after inlining the return block. This way, the CFG is always in
canonical state after inlining. This is more robust, and avoids
interfering with subsequent SIL passes when non-single-block callees
are inlined.

The problem is that inlining a series of calls within a large block
could result in interleaved block splitting and merging operations,
which is quadratic in the block size. This showed up when inlining the
tens of thousands of array subscript calls emitted for a large array
initialization.

The first half of the fix is to simply defer block merging until all
calls are inlined. We can't expect SimplifyCFG to run immediately
after inlining, nor would we want to do that, *especially* for
mandatory inlining. This fix instead exposes block merging as a
trivial utility.

Note: by eliminating some unconditional branches, this change could
reduce the number of debug locations emitted. This does not
fundamentally change any debug information guarantee, and I was unable
to observe any behavior difference in the debugger.
2018-11-26 09:41:28 -08:00
Arnold Schwaighofer
7e32c68e1d Add new SIL instruction for calling dynamically_replaceable funtions
%0 = dynamic_function_ref @dynamically_replaceable_function
  apply %0()
  Calls a [dynamically_replaceable] function.

  %0 = prev_dynamic_function_ref @dynamic_replacement_function
  apply %0
  Calls the previous implementation that dynamic_replacement_function
  replaced.
2018-11-06 09:53:22 -08:00
Arnold Schwaighofer
5f4e183302 Add [dynamically_replacable] to SILFunctions
'dynamic' functions are marked as [dynamically_replaceable].
2018-11-06 09:53:21 -08:00
John McCall
18a8ed6090 Fix a stack-discipline bug with inlining coroutines. 2018-11-05 17:14:29 -05:00
Andrew Trick
1446952521 Merge pull request #20111 from atrick/critedge-util
NFC: SILBasicBlock utilties for handling critical edges.
2018-10-29 15:42:07 -07:00
Andrew Trick
2aa8427dc6 SILCloner: rename 'remapValue' to 'getMappedValue' to avoid confusion.
A follow up commit adds an API for SILCloner clients to set mapped
values. Calling the map lookup "remap" would be unacceptably misleading.
2018-10-27 16:30:37 -07:00
Jason Mittertreiner
39f1767859 Fix SILInliner Compilation on MSVC
SILBuilder contains a SILBuilderContext which contains a SILModule which
has a deleted operator=. Assigning an Optional<BeginApplySite> causes MSVC
to attempt to create operator= for SILBuilder which fails due to the
deleted operator=. This changes BeginApplySite to use a SILBuilder*
instead of a SILBuilder& to get around it.
2018-10-26 11:44:57 -07:00
Andrew Trick
c781d78782 Fix #includes. Arnold's review. 2018-10-09 22:36:33 -07:00
Andrew Trick
bd28b0ea1b SILCloner and SILInliner rewrite.
Mostly functionally neutral:
- may fix latent bugs.
- may reduce useless basic blocks after inlining.

This rewrite encapsulates the cloner's internal state, providing a
clean API for the CRTP subclasses. The subclasses are rewritten to use
the exposed API and extension points. This makes it much easier to
understand, work with, and extend SIL cloners, which are central to
many optimization passes. Basic SIL invariants are now clearly
expressed and enforced. There is no longer a intricate dance between
multiple levels of subclasses operating on underlying low-level data
structures. All of the logic needed to keep the original SIL in a
consistent state is contained within the SILCloner itself. Subclasses
only need to be responsible for their own modifications.

The immediate motiviation is to make CFG updates self-contained so
that SIL remains in a valid state. This will allow the removal of
critical edge splitting hacks and will allow general SIL utilities to
take advantage of the fact that we don't allow critical edges.

This rewrite establishes a simple principal that should be followed
everywhere: aside from the primitive mutation APIs on SIL data types,
each SIL utility is responsibile for leaving SIL in a valid state and
the logic for doing so should exist in one central location.

This includes, for example:
- Generating a valid CFG, splitting edges if needed.
- Returning a valid instruction iterator if any instructions are removed.
- Updating dominance.
- Updating SSA (block arguments).

(Dominance info and SSA properties are fundamental to SIL verification).

LoopInfo is also somewhat fundamental to SIL, and should generally be
updated, but it isn't required.

This also fixes some latent bugs related to iterator invalidation in
recursivelyDeleteTriviallyDeadInstructions and SILInliner. Note that
the SILModule deletion callback should be avoided. It can be useful as
a simple cache invalidation mechanism, but it is otherwise bug prone,
too limited to be very useful, and basically bad design. Utilities
that mutate should return a valid instruction iterator and provide
their own deletion callbacks.
2018-10-08 19:30:09 -07:00
Michael Gottesman
d57a88af0d [gardening] Rename references to SILPHIArgument => SILPhiArgument. 2018-09-25 22:23:34 -07:00
swift-ci
cc329fee03 Merge pull request #19141 from aschwaighofer/remove_constant_string_literal 2018-09-10 15:51:47 -07:00
Michael Gottesman
0290cd4323 [sil] Eliminate end_borrow_argument now that end_borrow has a single operand.
I changed all of the places that used end_borrow_argument to use end_borrow.

NOTE: I discovered in the process of this patch that we are not verifying
guaranteed block arguments completely. I disabled the tests here that show this
bad behavior and am going to re-enable them with more tests in a separate PR.
This has not been a problem since SILGen does not emit any such arguments as
guaranteed today. But once I do the SILGenPattern work this will change.

rdar://33440767
2018-09-06 14:04:57 -07:00
Arnold Schwaighofer
73df12c09f Remove dead constant_string_literal
constant_string_literal was added to support a one word representation
of String that never materialized.
2018-09-05 12:13:57 -07:00
Erik Eckstein
99a9ed5535 SIL: remove the pinning instructions: strong_pin, strong_unpin, is_unique_or_pinned
They are not used anymore after removing the pinning addressors.
2018-08-23 12:47:56 -07:00
John McCall
656aba19ea Rename "canInlineBeginApply" to just "canInline"; NFC. 2018-08-21 03:44:08 -04:00
John McCall
8613761487 Fix some edge cases when inlining coroutines.
The current inlining strategy doesn't support inlining coroutines
when there are multiple end_apply or abort_apply instructions in
the caller, so refuse to inline such cases.  Also, handle the case
where there are no yield instructions in the callee, which can
happen if e.g. the callee calls a no-return function.

I also simplified the code somewhat by removing the vestiges of the
code that tried to unify control flow with switches.

As an unrelated fix, suppress function signature optimization for
coroutines for now.
2018-08-20 19:23:11 -04:00
Michael Gottesman
f500f007f8 [sil] Add a template parameter to TypeSubstCloner so that subclasses can inject a SILFunctionBuilder composition class.
This works around a potential circular dependence issue where TypeSubstCloner
needs access to SILOptFunctionBuilder but is in libswiftSIL.

rdar://42301529
2018-08-06 13:40:25 -07:00