Commit Graph

208 Commits

Author SHA1 Message Date
Michael Gottesman
9f6688e185 [sil-combine] Use high level ARC APIs instead of low level ARC APIs in a few cases to make code work in ossa and non-ossa. 2020-12-10 16:50:26 -08:00
Erik Eckstein
28220ff259 SILCombine: make the alloc_stack-enum optimization a bit more tolerant.
When eliminating an enum from an alloc_stack, accept "dead" inject_enum_addr instructions, which inject different enum cases.
2020-09-30 16:44:58 +02:00
Andrew Trick
5ae231eaab Rename getFieldNo() to getFieldIndex().
Do I really need to justify this?
2020-09-24 22:44:13 -07:00
Erik Eckstein
b9612b2edb SILCombine: fix an assertion crash in SILCombine when casting AnyClass to Any
This caused a problem when propagating the concrete type of an existential: if the concrete type is itself an opened existential, it was not added to the OpenedArchetypeTracker.

https://bugs.swift.org/browse/SR-13444
rdar://problem/68077098
2020-09-01 14:53:48 +02:00
Erik Eckstein
662f03ec4c SILCombine: optimize casts of existential boxes.
Optimize the unconditional_checked_cast_addr in this pattern:

   %box = alloc_existential_box $Error, $ConcreteError
   %a = project_existential_box $ConcreteError in %b : $Error
   store %value to %a : $*ConcreteError
   %err = alloc_stack $Error
   store %box to %err : $*Error
   %dest = alloc_stack $ConcreteError
   unconditional_checked_cast_addr Error in %err : $*Error to ConcreteError in %dest : $*ConcreteError

to:
   ...
   retain_value %value : $ConcreteError
   destroy_addr %err : $*Error
   store %value to %dest $*ConcreteError

This lets the alloc_existential_box become dead and it can be removed in following optimizations.
The same optimization is also done for conditional_checked_cast_addr.

There is also an implication for debugging:
Each "throw" in the code calls the runtime function swift_willThrow. The function is used by the debugger to set a breakpoint and also add hooks.
This optimization can completely eliminate a "throw", including the runtime call.
So, with optimized code, the user might not see the program to break at a throw, whereas in the source code it is actually throwing.
On the other hand, eliminating the existential box is a significant performance win and we don't guarantee any debugging behavior for optimized code anyway. So I think this is a reasonable trade-off.
I added an option "-Xllvm -keep-will-throw-call" to keep the runtime call which can be used if someone want's to reliably break on "throw" in optimized builds.

rdar://problem/66055678
2020-07-29 21:57:51 +02:00
Erik Eckstein
fc3e68a9d5 SILCombine: optimize a load from global static let
Propagate a value from a static "let" global variable.
This optimization is also done by GlobalOpt, but not with de-serialized globals, which can occur with cross-module optimization.
2020-06-22 16:49:26 +02:00
Erik Eckstein
6a9d08793a SILCombine: a peephole optimization to optimize alloc_stack of enums.
Replaces an alloc_stack of an enum by an alloc_stack of the payload if only one enum case (with payload) is stored to that location.

For example:

  %loc = alloc_stack $Optional<T>
  %payload = init_enum_data_addr %loc
  store %value to %payload
  ...
  %take_addr = unchecked_take_enum_data_addr %loc
  %l = load %take_addr

is transformed to

  %loc = alloc_stack $T
  store %value to %loc
  ...
  %l = load %loc

https://bugs.swift.org/browse/SR-12710
2020-06-10 09:23:37 +02:00
Anthony Latsis
9fd1aa5d59 [NFC] Pre- increment and decrement where possible 2020-06-01 15:39:29 +03:00
Erik Eckstein
33c8e16ce0 SIL optimizer: Support begin_cow_mutation and end_cow_mutation in some optimizations.
Mostly this is about "looking through" a begin_cow_mutation or end_cow_mutation.
2020-05-26 18:01:17 +02:00
Saleem Abdulrasool
fa46f7131c sprinkle some llvm_unreachable for MSVC (NFC)
MSVC does not realize that the switch is exhaustive and requires that
the path is explicitly marked as unreachable.  This silences the C4715
warning ("not all control paths return a value").
2020-04-24 18:59:07 -07:00
David Zarzycki
e2c4aa13ed [SILOptimizer] Do not hardcode unowned for loadable ref storage types 2020-04-17 10:40:59 -04:00
swift-ci
22d7267899 Merge pull request #30625 from zoecarver/fix/sil-combine-empty-visitors 2020-03-25 00:04:09 -07:00
swift-ci
0eeefaea05 Merge pull request #30559 from zoecarver/ossa/sil-combine 2020-03-24 22:02:43 -07:00
zoecarver
56d5c8aa4a [nfc] remove empty visitors in silcombine
Remove visitors in SILCombine that only return nullptr.
2020-03-24 20:03:59 -07:00
zoecarver
d3a01131d7 Update all relevant visitors in SILCombine to skip ownership functions.
Instead of bailing on ownership functions in SILCombine::run, we will
bail in individual visitors. This way, as SILCombine is updated we can
paritially support ownership across the pass.
2020-03-24 19:55:08 -07:00
Erik Eckstein
95cacf84b7 SILCombine: optimize creating enums with tuple payloads.
Convert sequences of

  %payload_addr = init_enum_data_addr %enum_addr
  %elem0_addr = tuple_element_addr %payload_addr, 0
  %elem1_addr = tuple_element_addr %payload_addr, 1
  ...
  store %payload0 to %elem0_addr
  store %payload1 to %elem1_addr
  ...
  inject_enum_addr %enum_addr, $EnumType.case

to

  %tuple = tuple (%payload0, %payload1, ...)
  %enum = enum $EnumType, $EnumType.case, %tuple
  store %enum to %enum_addr

Such patterns are generated for example when using the stdlib enumarated() function.

Part of rdar://problem/33438123
2020-03-19 19:07:11 +01:00
Michael Gottesman
5237bcd3b1 [silcombine] Eliminate mark_dependence whose base is a trivial object.
This pattern comes up when faking a base using
Builtin.convertUnsafeUnownedToGuaranteed.

rdar://59735604
2020-02-25 12:32:24 -08:00
Erik Eckstein
2afa1210b0 SILCombine: remove dead unchecked_take_enum_data_addr instructions. 2020-02-18 19:23:17 +01:00
Erik Eckstein
a89340c7b3 SILCombine: fix a miscompile in the alloc_stack optimization which causes a use-after-free.
A "copy_addr [take] %src to [initialization] %alloc_stack" is replaced by a "destroy_addr %src" if the alloc_stack is otherwise dead.
This is okay as long as the "moved" object is kept alive otherwise.
This can break if a retain of %src is moved after the copy_addr. It cannot happen with OSSA.
So as soon as we have OSSA, we can remove the check again.

rdar://problem/59509229
2020-02-17 16:04:40 +01:00
Erik Eckstein
966d617625 SIL optimizer: propagate count and capacity from empty Array/Set/Dictionary singletons.
Constant-propagate the 0 value when loading "count" or "capacity" from the empty Array, Set or Dictionary storage.
On high-level SIL this optimization is also done by the ArrayCountPropagation pass, but only for Array.
And even for Array it's sometimes needed to propagate the empty-array count when high-level semantics function are already inlined.

Fixes an optimization deficiency for empty OptionSet literals.

https://bugs.swift.org/browse/SR-12046
rdar://problem/58861171
2020-01-24 14:47:30 +01:00
David Zarzycki
f185dd66f1 [QoI] Fix -Wrange-loop-analysis warnings 2020-01-19 13:29:23 -05:00
Slava Pestov
53bfc767a3 SIL: Track target formal type for casts
SIL type lowering erases DynamicSelfType, so we generate
incorrect code when casting to DynamicSelfType. Fixing this
requires a fair amount of plumbing, but most of the
changes are mechanical.

Note that the textual SIL syntax for casts has changed
slightly; the target type is now a formal type without a '$',
not a SIL type.

Also, the unconditional_checked_cast_value and
checked_cast_value_br instructions now take the _source_
formal type as well, just like the *_addr forms they are
intended to replace.
2019-11-20 21:30:28 -05: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
Erik Eckstein
71b8c5617e SILCombine: fix a miscompile in dead alloc_existential_box removal
The miscompile results in a use-after-free crash.

rdar://problem/50759056
2019-05-16 15:05:44 -07:00
Andrew Trick
320759227a Canonicalize stores in the CanonicalizeInstruction utility.
This is the complement to load canonicalization. Although store
canonicalization is not required before diagnostics, it should be
defined in the same utility.
2019-05-09 13:00:39 -07:00
Andrew Trick
f395f86039 Canonicalize loads in SILGenCleanup.
Reimplement load instruction canonicalization as part of the
CanonicalizeInstruction utility.
2019-05-06 13:31:35 -07:00
Slava Pestov
16d5716e71 SIL: Use the best resilience expansion when lowering types
This is a large patch; I couldn't split it up further while still
keeping things working. There are four things being changed at
once here:

- Places that call SILType::isAddressOnly()/isLoadable() now call
  the SILFunction overload and not the SILModule one.

- SILFunction's overloads of getTypeLowering() and getLoweredType()
  now pass the function's resilience expansion down, instead of
  hardcoding ResilienceExpansion::Minimal.

- Various other places with '// FIXME: Expansion' now use a better
  resilience expansion.

- A few tests were updated to reflect SILGen's improved code
  generation, and some new tests are added to cover more code paths
  that previously were uncovered and only manifested themselves as
  standard library build failures while I was working on this change.
2019-04-26 22:47:59 -04:00
Slava Pestov
8915f96e3e SIL: Replace SILType::isTrivial(SILModule) with isTrivial(SILFunction) 2019-03-12 01:16:04 -04:00
Slava Pestov
903721cdc5 SIL: Remove SILType::getMetatypeInstanceType() 2019-03-01 02:07:16 -05:00
Michael Gottesman
cf43a93d3e [silcombine] (store (struct_gep addr) value) -> (store addr (struct value)) for single field structs. 2019-01-11 12:23:13 -08:00
Erik Eckstein
5c17f0f6f8 SILCombine: peephole to propagate resilient enum cases
Basically the pattern to optimize is:
    inject_enum_addr %stackloc, #SomeCase
    switch_enum_addr %stackloc ...

This works even if the enum is resilient and the case does not have a payload. As long as we don't have opaque values in SIL we need this peephole to optimize the pattern.
This change fixes the code generation for Float.rounded().

rdar://problem/46353885
2018-12-10 16:14:15 -08:00
Robert Widmann
014fd952ef [NFC] Silence a bunch of Wunused-variable diagnostics 2018-08-24 15:16:40 -07:00
Dante Broggi
43f79dfba8 fix a code example found looking through commits 2018-06-08 06:54:57 -04:00
Erik Eckstein
bb5fe18300 Add/fix comments as a follow-up to the string constants optimization changes. 2018-06-07 16:22:04 -07:00
Erik Eckstein
71b6c82230 SILCombine: optimize loading bytes from a string literal 2018-06-07 13:43:34 -07:00
Arnold Schwaighofer
65e9593216 SILCombine: Can't replace a alloc_ref_dynamic with an alloc_ref if the metatype is generic
rdar://40853265
SR-7896
2018-06-06 12:04:32 -07:00
Erik Eckstein
a2b0e8f96b SILCombine: make the value_to_bridge_object peephole less conservative.
We can always eliminate ARC operations on the result of a value_to_bridge_object instruction.
There is no need to restrict the operand to a specific SIL pattern.
2018-05-29 11:01:03 -07:00
David Zarzycki
8c0c55539f [SIL] NFC: Rename misleading getSwiftRValueType() to getASTType()
Reference storage types are not RValues. Also, use more SILType helper
methods to avoid line wrap.
2018-05-04 08:14:38 -04:00
Davide Italiano
b4d563802b [SILInstruction] Introduce isDebugInstruction().
This is a property of an instruction and should be a member
function of `SILInstruction` and not a free function in
`DebugUtils`. Discussed with Adrian.
2018-04-11 10:14:21 -07:00
Dante Broggi
943033ef32 Fix typo in assert: Excted to Expected (#14619) 2018-02-13 18:21:14 -08:00
Joe Shajrawi
3675019184 [SILCombiner] Remove strong retains and strong releases of tagged strings. A retain/release of a string literal is a no-op. 2018-02-13 11:45:01 +02:00
Erik Eckstein
4167fa00d5 SILCombiner: fix a non-determinism in a peephole optimization for load instructions. 2018-02-01 12:15:46 -08:00
Chris Lattner
415cd50ba2 Reduce array abstraction on apple platforms dealing with literals (#13665)
* Reduce array abstraction on apple platforms dealing with literals

Part of the ongoing quest to reduce swift array literal abstraction
penalties: make the SIL optimizer able to eliminate bridging overhead
 when dealing with array literals.

Introduce a new classify_bridge_object SIL instruction to handle the
logic of extracting platform specific bits from a Builtin.BridgeObject
value that indicate whether it contains a ObjC tagged pointer object,
or a normal ObjC object. This allows the SIL optimizer to eliminate
these, which allows constant folding a ton of code. On the example
added to test/SILOptimizer/static_arrays.swift, this results in 4x
less SIL code, and also leads to a lot more commonality between linux
and apple platform codegen when passing an array literal.

This also introduces a couple of SIL combines for patterns that occur
in the array literal passing case.
2018-01-02 15:23:48 -08:00
Chris Lattner
3761ee3f1b Remove a transformation introduced in PR13652 which fails on the iOS
simulator in a way I can't repro.  Reimplement the important part of it
in a new way to achieve the same effect.
2018-01-01 07:45:54 -08:00
Chris Lattner
1e63108998 Speculative fix for a regression on the
"oss-swift_tools-RA_stdlib-RD_test-simulator" iOS simulator bot.
2017-12-31 20:13:58 -08:00
Chris Lattner
de289752fe Implement a few silcombine transformations for arrays (#13652)
* Implement a few silcombine transformations for arrays

 - Useless existential_ref <-> class conversions.
 - mark_dependence_inst depending on uninteresting instructions.
 - release(init_existential_ref(x)) -> release(x) when hasOneUse(x)
 - Update COWArrayOpt to handle the new forms generated by this.

these aren't massive performance wins, but do shrink the size of SIL when
dealing with arrays.

* Generalize testcase to work on linux and on mac when checking stdlib is enabled.
2017-12-30 22:30:37 -08:00
Andrew Trick
d369aa4070 Support @noescape SIL function types. (#12420)
Support for @noescape SILFunctionTypes.

These are the underlying SIL changes necessary to implement the new
closure capture ABI.

Note: This includes a change to function name mangling that
primarily affects reabstraction thunks.

The new ABI will allow stack allocation of non-escaping closures as a
simple optimization.

The new ABI, and the stack allocation optimization, also require
closure context to be @guaranteed. That will be implemented as the
next step.

Many SIL passes pattern match partial_apply sequences. These all
needed to be fixed to handle the convert_function that SILGen now
emits. The conversion is now needed whenever a function declaration,
which has an escaping type, is passed into a @NoEscape argument.

In addition to supporting new SIL patterns, some optimizations like
inlining and SIL combine are now stronger which could perturb some
benchmark results.

These underlying SIL changes should be merged now to avoid conflicting
with other work. Minor benchmark discrepancies can be investigated as part of
the stack-allocation work.

* Add a noescape attribute to SILFunctionType.

And set this attribute correctly when lowering formal function types to SILFunctionTypes based on @escaping.

This will allow stack allocation of closures, and unblock a related ABI change.

* Flip the polarity on @noescape on SILFunctionType and clarify that
we don't default it.

* Emit withoutActuallyEscaping using a convert_function instruction.

It might be better to use a specialized instruction here, but I'll leave that up to Andy.

Andy: And I'll leave that to Arnold who is implementing SIL support for guaranteed ownership of thick function types.

* Fix SILGen and SIL Parsing.

* Fix the LoadableByAddress pass.

* Fix ClosureSpecializer.

* Fix performance inliner constant propagation.

* Fix the PartialApplyCombiner.

* Adjust SILFunctionType for thunks.

* Add mangling for @noescape/@escaping.

* Fix test cases for @noescape attribute, mangling, convert_function, etc.

* Fix exclusivity test cases.

* Fix AccessEnforcement.

* Fix SILCombine of convert_function -> apply.

* Fix ObjC bridging thunks.

* Various MandatoryInlining fixes.

* Fix SILCombine optimizeApplyOfConvertFunction.

* Fix more test cases after merging (again).

* Fix ClosureSpecializer. Hande convert_function cloning.

Be conservative when combining convert_function. Most of our code doesn't know
how to deal with function type mismatches yet.

* Fix MandatoryInlining.

Be conservative with function conversion. The inliner does not yet know how to
cast arguments or convert between throwing forms.

* Fix PartialApplyCombiner.
2017-10-17 13:07:25 -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
Roman Levenstein
f802fe4829 [sil-combine] Minor improvement to the peephole for removal of alloc_ref instructions that are only allocated and then deallocated 2017-08-01 15:23:23 -07:00
Saleem Abdulrasool
8e0b43afd0 SILOptimizer: include used header
Include headers that are used in the file.
2017-07-24 13:41:23 -07:00