Commit Graph

397 Commits

Author SHA1 Message Date
Joe Groff
3691991374 IRGen: Redesign enum codegen to break payloads into word-sized chunks.
Using LLVM large integers to represent enum payloads has been causing compiler performance and code size problems with large types, and has also exposed a long tail of backend bugs. Replace them with an "EnumPayload" abstraction that manages breaking a large opaque binary value into chunks, along with masking, testing, and extracting typed data from the binary blob. For now, use a word-sized chunking schema always, though the architecture here is set up to eventually allow the use of an arbitrary explosion schema, which would benefit single-payload enums by allowing the payload to follow the explosion schema of the contained value.

Swift SVN r28982
2015-05-24 05:23:23 +00:00
Slava Pestov
e6dbc2a171 IRGen: Don't emit enum case names for C-compatible enums
Until we start saving the rawValue to case name mapping, we can't
do anything with this.

Swift SVN r28428
2015-05-11 18:21:38 +00:00
Joe Groff
03cff119f5 IRGen: Don't try to pack a nonexistent empty payload from a single-payload enum nested into an outer enum.
Fixes rdar://problem/20882920.

Swift SVN r28405
2015-05-11 00:20:45 +00:00
Joe Groff
2d3eba9e0d IRGen: Reuse value witness table projections.
Don't project every value witness from the metadata every time we need one; this wastes code size in a way LLVM can't really optimize since it doesn't know the metadata is immutable. The code size wins on the standard library are disappointingly small (stdlib only shrinks by 4KB), but this makes generic IR a lot more compact and easier to read.

Swift SVN r28095
2015-05-03 05:00:40 +00:00
Andrew Trick
a174aa4dfe Add AST and SILGen support for Builtin.isUnique.
Preparation to fix <rdar://problem/18151694> Add Builtin.checkUnique
to avoid lost Array copies.

This adds the following new builtins:

    isUnique : <T> (inout T[?]) -> Int1
    isUniqueOrPinned : <T> (inout T[?]) -> Int1

These builtins take an inout object reference and return a
boolean. Passing the reference inout forces the optimizer to preserve
a retain distinct from what’s required to maintain lifetime for any of
the reference's source-level copies, because the called function is
allowed to replace the reference, thereby releasing the referent.

Before this change, the API entry points for uniqueness checking
already took an inout reference. However, after full inlining, it was
possible for two source-level variables that reference the same object
to appear to be the same variable from the optimizer's perspective
because an address to the variable was longer taken at the point of
checking uniqueness. Consequently the optimizer could remove
"redundant" copies which were actually needed to implement
copy-on-write semantics. With a builtin, the variable whose reference
is being checked for uniqueness appears mutable at the level of an
individual SIL instruction.

The kind of reference count checking that Builtin.isUnique performs
depends on the argument type:

    - Native object types are directly checked by reading the
      strong reference count:
      (Builtin.NativeObject, known native class reference)

    - Objective-C object types require an additional check that the
      dynamic object type uses native swift reference counting:
      (Builtin.UnknownObject, unknown class reference, class existential)

    - Bridged object types allow the dymanic object type check to be
      bypassed based on the pointer encoding:
      (Builtin.BridgeObject)

Any of the above types may also be wrapped in an optional.  If the
static argument type is optional, then a null check is also performed.

Thus, isUnique only returns true for non-null, native swift object
references with a strong reference count of one.

isUniqueOrPinned has the same semantics as isUnique except that it
also returns true if the object is marked pinned regardless of the
reference count. This allows for simultaneous non-structural
modification of multiple subobjects.

In some cases, the standard library can dynamically determine that it
has a native reference even though the static type is a bridge or
unknown object. Unsafe variants of the builtin are available to allow
the additional pointer bit mask and dynamic class lookup to be
bypassed in these cases:

    isUnique_native : <T> (inout T[?]) -> Int1
    isUniqueOrPinned_native : <T> (inout T[?]) -> Int1

These builtins perform an implicit cast to NativeObject before
checking uniqueness. There’s no way at SIL level to cast the address
of a reference, so we need to encapsulate this operation as part of
the builtin.

Swift SVN r27887
2015-04-28 22:54:24 +00:00
Joe Groff
bdac5fe1c8 IRGen: Implement emitIndirectCaseTest for dynamic multi-payload enums.
The last little bit of unimplemented code for dynamic enums.

Swift SVN r27814
2015-04-27 19:37:18 +00:00
Joe Groff
889b8d3826 IRGen: Fix implementation of emitValueCaseTest for multi-payload enums.
Empty cases are packed into the payload under a minimal number of tags, instead of having once case per tag, as for payload cases.

Swift SVN r27813
2015-04-27 19:37:18 +00:00
Joe Groff
0126311e23 Enable dynamic multi-payload enums.
Fixes rdar://problem/15666173.

Swift SVN r27792
2015-04-27 00:35:13 +00:00
Joe Groff
3dafb24b5d IRGen: Call the runtime to initialize dynamic multi-payload enum metadata.
Emit a call to a third and final to-be-implemented runtime function to help instantiate the metadata of a dynamic multi-payload enum.

Swift SVN r27790
2015-04-27 00:35:07 +00:00
Joe Groff
0b339b9a46 IRGen: Populate nominal type descriptor metadata for enums.
Store the number of payload and no-payload cases, the case names, and a lazy case type accessor function for enums, like we do for stored properties of structs and classes. This will be useful for multi-payload runtime support, and should also be enough info to hack together a reflection implementation for enums.

For dynamic multi-payload enums to not be ridiculously inefficient, we'll need to track the size of the payload area in the enum, like we do the field offsets of generic structs and classes, so hack off a byte in the payload case count to track the offset of that field in metadata records. 16 million payloads ought to be enough for anyone, right? (and 256 words between the enum metadata's address point and the payload size offset)

Swift SVN r27789
2015-04-27 00:35:04 +00:00
Joe Groff
6349fd7726 IRGen: Bitwise-take peepholes for multi-payload enums.
Do initializeWithTake by bitwise-copy on multi-payload enums when possible.

Swift SVN r27788
2015-04-27 00:34:59 +00:00
Joe Groff
fbf7c9c3c8 IRGen: Value semantics for dynamic multi-payload enums.
Refactor some things so that the copy_addr implementation for multi-payload enums works with dynamic as well as fixed cases.

Swift SVN r27787
2015-04-27 00:34:56 +00:00
Joe Groff
ff2d1df7af IRGen: Switching for dynamic multi-payload enums.
Use a different yet-to-be-implemented runtime call to extract the tag from a dynamic-layout enum so we can switch it.

Swift SVN r27786
2015-04-27 00:34:54 +00:00
Joe Groff
27266ff08a IRGen: Codegen for dynamic multi-payload tag injections.
Emit a call to an as-yet-unwritten runtime function that will perform the injection.

Swift SVN r27784
2015-04-27 00:34:49 +00:00
Joe Groff
c3bb5e7451 IRGen: Handle empty payloads in multi-payload enum layout.
This can come up now when generic multi-payload enums substitute in empty types for all their payloads. It's also an opportunity to factor things a bit so that they're easier to extend to dynamic cases.

Swift SVN r27783
2015-04-27 00:34:47 +00:00
Joe Groff
723697f421 IRGen: Don't use spare bits in fixed instances of dependent multi-payload enums.
We don't want to wait to revamp the runtime to track spare bits in order to get multi-payload enum cases working, so when lowering an enum, track when the generic enum type's layout is dependent, and constrain our use of spare bits when it is.

Swift SVN r27781
2015-04-27 00:34:38 +00:00
Joe Groff
e4e0f35aed IRGen: Implement an @_alignment attribute.
This is an internal-only affordance for the numerics team to be able to work on SIMD-compatible types. For now, it can only increase alignment of fixed-layout structs and enums; dynamic layout, classes, and other obvious extensions are left to another day when we can design a proper layout control design.

Swift SVN r27323
2015-04-15 17:23:30 +00:00
Chris Lattner
c1bc639d7b add an IRGen peephole for lowering certain switch_enum's that commonly
come up when pattern matching on optional.  Instead of expanding to a
switch with a default and one case, expand to an icmp and condbr.



Swift SVN r26090
2015-03-13 05:14:49 +00:00
Dmitri Hrybenko
61286f0260 Fix warnings produced by a newer version of Clang
Swift SVN r25257
2015-02-12 23:50:47 +00:00
Joe Groff
00f0286886 IRGen: Mask the payload of nested single-payload enum payloads.
Fixes rdar://problem/18841262.

Swift SVN r24908
2015-02-02 23:29:21 +00:00
Jordan Rose
4fae1f664f [IRGen] Remove the AST walk that looks for local type decls.
Per the previous commit we are no longer using this. Minor save in
simplicity and maybe a bit of compilation time as well.

In the long run IRGen probably shouldn't be pulling information from the
AST at all; the SILModule should be able to tell it what types it needs
to emit information for. But this is still an improvement for now.

No functionality change (that was the previous commit).

Swift SVN r24840
2015-01-30 03:54:08 +00:00
Chris Lattner
5ddc776efa The Payload case of SinglePayloadEnumImplStrategy is more complicated than
I thought.  Apparently there is no way to directly test whether a general
enum contains the payload without testing against each of the potential 
inhabitant cases with a switch.  Instead of solving this open problem, just
optimize the case where we're testing for a single non-payload case, and 
special case enums with one payload and one non-payload case (hello optional!)
by testing for the non-payload case and inverting the result.  This resolves
the miscompilations I was seeing before with my full patch set, but is still
NFC since the code that uses this isn't included yet.




Swift SVN r24365
2015-01-11 22:33:01 +00:00
Chris Lattner
2ea05c3adb Add new entry points to the enum implementation strategy for testing an enum against a
specific case and returning an i1 result.  This can be done a lot more efficiently (in
terms of generated LLVM IR) than doing a general switch over the cases.  This will be used
to implement rdar://19404937, but there is a miscompilation here that I'm tracking down.

Until it is working, I'm not committing the code to use these entrypoints, which wires it
into IRGen of SelectEnumInst and SelectEnumAddrInst.  Since that part isn't included, this
is NFC.


Swift SVN r24362
2015-01-11 07:36:53 +00:00
John McCall
275ef489d4 Switch IRGen to use ClusteredBitVector.
IRGen uses a typedef, SpareBitVector, for its principal
purpose of tracking spare bits.  Other uses should not
use this typedef, and I've tried to follow that, but I
did this rewrite mostly with sed and may have missed
some fixups.

This should be almost completely NFC.  There may be
some subtle changes in spare bits for witness tables
and other off-beat pointer types.  I also fixed a bug
where IRGen thought that thin functions were two
pointers wide, but this wouldn't have affected anything
because we never store thin functions anyway, since
they're not a valid AST type.

This commit repplies r24305 with two fixes:

  - It fixes the computation of spare bits for unusual
    integer types to use the already-agreed-upon type
    size instead of recomputing it.  This fixes the
    i386 stdlib build.  Joe and I agreed that we should
    also change the size to use the LLVM alloc size
    instead of the next power of 2, but this patch
    does not do that yet.

  - It changes the spare bits in function types back
    to the empty set.  I'll be changing this in a
    follow-up, but it needs to be tied to runtime
    changes.  This fixes the regression test failures.

Swift SVN r24324
2015-01-09 21:06:37 +00:00
Dmitri Hrybenko
4caca5d098 Revert "Switch IRGen to use ClusteredBitVector."
This reverts commit r24305.  It broke the standard library build.

Swift SVN r24318
2015-01-09 18:25:21 +00:00
John McCall
6e41b3c742 Switch IRGen to use ClusteredBitVector.
IRGen uses a typedef, SpareBitVector, for its principal
purpose of tracking spare bits.  Other uses should not
use this typedef, and I've tried to follow that, but I
did this rewrite mostly with sed and may have missed
some fixups.

This should be almost completely NFC.  There may be
some subtle changes in spare bits for witness tables
and other off-beat pointer types.  I also fixed a bug
where IRGen thought that thin functions were two
pointers wide, but this wouldn't have affected anything
because we never store thin functions anyway, since
they're not a valid AST type.

Swift SVN r24305
2015-01-09 10:05:51 +00:00
Joe Groff
0c05600caa IRGen: Lay out @objc enums in a C-compatible way.
Swift SVN r23424
2014-11-19 04:03:09 +00:00
Erik Eckstein
ec4accfda8 Optimize IRGen of select_num which maps the enum tag trivially to an int value.
This generates a simple int-cast instead of a switch.



Swift SVN r23117
2014-11-05 15:43:10 +00:00
Joe Groff
9205bf64cf SIL: Remove enum_is_tag.
Swift SVN r22616
2014-10-09 05:03:43 +00:00
Jordan Rose
3fcdfd40e9 Remove the "swift/Basic/Optional.h" header.
llvm::Optional lives in "llvm/ADT/Optional.h". Like Clang, we can get
Optional in the 'swift' namespace by including "swift/Basic/LLVM.h".

We're now fully switched over to llvm::Optional!

Swift SVN r22477
2014-10-02 18:51:45 +00:00
Jordan Rose
2a76f18e4b Drop uses of Optional::cache.
In preparation for the switch to llvm::Optional, which doesn't have a 'cache'
method. Given how long we spent bikeshedding over the name and how few places
we ended up using it, I didn't feel like trying to push it through on the
LLVM side.

Swift SVN r22471
2014-10-02 18:51:36 +00:00
Joe Groff
1c4e08a9c8 Fix up a tangle of issues related to reabstraction.
- A spot fix in SILGen for reabstracting the result of a downcast, which fixes checked casts to function types.
- Associate the layout information in type metadata records with the most abstract representation of the type. This is the correct thing to do in cases where we need the metadata as a tag for an opaque value--if we store a value in an Any, or pass it as an unconstrained generic parameter, we must maximally reabstract it. This fixes the value semantics of existentials containing trivial metatypes.
- To ensure that we get runtime layout of structs and enums correct when they contain reabstractable types, introduce a "metadata for layout" concept, which doesn't need to describe the canonical metadata for the type, but only needs to describe a type with equivalent layout and value semantics. This is a correctness fix that allows us to correctly lay out generic types containing dependent tuples and functions, and although we don't really take advantage of it here, it's also a potential runtime performance win down the road, because we could potentially produce direct metadata for a primitive type that's layout-equivalent with a runtime-instantiated type. To aid in type safety here, push SILType deeper into IRGen in places where we potentially care about specific representations of types.
- Finally, fix an inconsistency between the runtime and IRGen's concept of what spare bits unmanaged references and thick metatypes have.

Together, these fixes address rdar://problem/16406907, rdar://problem/17822208, rdar://problem/18189508, and likely many other related issues, and also fixes crash suite cases 012 and 024.

Swift SVN r21963
2014-09-16 01:44:34 +00:00
Michael Gottesman
e0b0744215 Remove trailing whitespace. NFC.
Swift SVN r21719
2014-09-04 21:53:19 +00:00
Michael Gottesman
9514ba5a7d [irgen] Lower fix_lifetime => swift_keepAlive().
I introduced a function swift_keepAlive2() which has a different signature from
swift_keepAlive() until I can verify that the stdlib is using the new
infrastructure.

The difference in signature is that swift_keepAlive2 takes just a pointer while
swift_keepAlive also takes a metadata value that is not necessary for our
purposes anymore.

Swift SVN r21718
2014-09-04 21:53:18 +00:00
Joe Groff
713712f731 IRGen: Don't special-case retain/release for multi-payload enums with multiple simple cases.
The simple cases after the first one end up getting assigned invalid non-null pointer representations that *_retain and *_release aren't written to expect. We checked for this case incorrectly by checking the size of vector arguments that had been std::move'd from. Oops. Fixes rdar://problem/18118396.

Swift SVN r21612
2014-08-31 00:34:29 +00:00
John McCall
0ddc7ee5b6 Resilience expansion is not an IR-generation concept.
If a type has to be passed or returned resiliently, it
will necessarily be passed indirectly, which is already
represented in SILFunctionType.  There is no need to
represent this as a separate channel of information.

NFC. Also fixes a problem where the signature cache
for ExtraData::Block was writing past the end of an
array (but into the storage for an adjacent array
which was fortunately never used).

ExtraData should also disappear as a concept, but we're
still relying on that for existential protocol witnesses.

Swift SVN r21548
2014-08-28 23:07:50 +00:00
John McCall
0934cf59a6 Test for a generic context, not just whether an enum has
ts own generic arguments.  Noticed by inspection; no test
case.

Swift SVN r21347
2014-08-21 08:01:34 +00:00
Joe Groff
b4f1db9da5 IRGen: Stub out an UnimplementedTypeInfo class.
This allows IRGen to complain about types it doesn't know how to lower yet, while still recovering well enough not to take the compiler down with it. This reduces the common "unimplemented enum layout" error to be a mere error instead of a compiler crash.

Swift SVN r20773
2014-07-30 20:50:50 +00:00
Joe Groff
fb9defc4dd IRGen: Add a "getBitMaskForNoPayloadElements" accessor for enum layout.
LLDB needs this in order to accurately test enums that use extra inhabitants of aggregates, for which we don't guarantee that we set all of the bits to an exact value. Allows lldb to address <rdar://problem/17787682>. Now with no test crashes.

Swift SVN r20545
2014-07-25 16:47:32 +00:00
Ben Langmuir
77f31139d4 Revert "IRGen: Add a "getBitMaskForNoPayloadElements" accessor for enum layout."
This was asserting in a bunch of tests.

This reverts commit r20527

Swift SVN r20533
2014-07-25 03:42:19 +00:00
Joe Groff
fe5da5bc43 IRGen: Add a "getBitMaskForNoPayloadElements" accessor for enum layout.
LLDB needs this in order to accurately test enums that use extra inhabitants of aggregates, for which we don't guarantee that we set all of the bits to an exact value. Allows lldb to address <rdar://problem/17787682>.

Swift SVN r20527
2014-07-24 23:53:59 +00:00
Pete Cooper
d6877f60a4 Add enum_is_tag instruction.
This returns an i1 given an enum and enum element, and allows us to check the tag without the control flow required by switch_enum

Note, the following -O3 performance numbers are with r20242 reverted.

benchmark      ,  baserun0  ,  optrun0   ,  delta,   speedup
2Sum           ,  1613.00   ,  1656.00   ,  43.00    ,        -2.6%
Ackermann      ,  4560.00   ,  4473.00   ,  87.00    ,        1.9%
DeltaBlue      ,  22122.00  ,  22181.00  ,  59.00    ,        -0.3%
Dictionary     ,  927.00    ,  898.00    ,  29.00    ,        3.2%
EditDistance   ,  1573.00   ,  1564.00   ,  9.00     ,        0.6%
ForLoops       ,  2122.00   ,  2142.00   ,  20.00    ,        -0.9%
Forest         ,  1131.00   ,  1130.00   ,  1.00     ,        0.1%
GlobalClass    ,  2926.00   ,  2712.00   ,  214.00   ,        7.9%
Hash           ,  1970.00   ,  1280.00   ,  690.00   ,        53.9%
Histogram      ,  1860.00   ,  1606.00   ,  254.00   ,        15.8%
Life           ,  1669.00   ,  1750.00   ,  81.00    ,        -4.6%
LinkedList     ,  1555.00   ,  1558.00   ,  3.00     ,        -0.2%
Memset         ,  328.00    ,  333.00    ,  5.00     ,        -1.5%
NBody          ,  114.00    ,  46.00     ,  68.00    ,        147.8%
Phonebook      ,  1434.00   ,  1379.00   ,  55.00    ,        4.0%
Prims          ,  1833.00   ,  1669.00   ,  164.00   ,        9.8%
QuickSort      ,  107.00    ,  106.00    ,  1.00     ,        0.9%
R17315246      ,  1103.00   ,  817.00    ,  286.00   ,        35.0%
RC4            ,  884.00    ,  57.00     ,  827.00   ,        1450.9%
Rectangles     ,  1624.00   ,  1624.00   ,  0.00     ,        0.0%
SmallPT        ,  1067.00   ,  1012.00   ,  55.00    ,        5.4%
StringBuilder  ,  942.00    ,  921.00    ,  21.00    ,        2.3%
StringWalk     ,  1253.00   ,  1260.00   ,  7.00     ,        -0.6%
Totals         ,  55770.00  ,  52317.00  ,  3453.00  ,        6.6%

Swift SVN r20361
2014-07-23 02:53:43 +00:00
Joe Groff
5e9e346e78 IRGen: Lower enum payload types before classifying them for layout.
Fixes a crash when enums contained AST-only types such as functions or metatypes as payloads.

Swift SVN r19969
2014-07-15 02:29:54 +00:00
Joe Groff
ac903bf943 IRGen: Make our use of spare bits in heap objects tagged-pointer-safe.
Don't use spare bits on platforms that use ObjC tagged pointers when an enum payload involves a class-constrained existential, archetype, or ObjC-defined class type. If a payload is of a Swift-defined class type, we can still assume it's a real pointer and use its spare bits. Add an @unsafe_no_objc_tagged_pointer attribute that can be applied to protocols to denote that existentials bounded by that protocol can use spare bits; this is necessary to preserve the layout of bridged Array and Dictionary types, which should not be bound to tagged pointer types in practice (fingers crossed). Fixes <rdar://problem/16270219>.

Swift SVN r18781
2014-06-10 17:07:47 +00:00
Joe Groff
e4a048a5f6 IRGen: Fix miscomputation in single-payload enum 'switch'.
We were miscalculating the number of empty-payload cases representable by each tag value and failing to lower cases after the first two. Fixes <rdar://problem/17025341>.

Swift SVN r18620
2014-05-24 17:32:41 +00:00
Joe Groff
dd92b14b59 IRGen: Fix getExtraInhabitants codegen for no-payload enums.
We were getting this wrong by zext-ing a signed value. Oops. Fixes <rdar://problem/16887421>.

Swift SVN r18016
2014-05-13 19:22:31 +00:00
John McCall
c57dac63ae Use the first element of structs and tuples as a source
for extra inhabitants.

For structs in particular, this eliminates a major source
of abstraction penatlies.  For example, an optional struct
containing an object pointer is now represented the same
way as an optional object pointer, which is critical for
correctly importing CF types as Unmanaged<T>!.

In time, we should generalize this to consider all elements
as sources for extra inhabitants, as well as exploiting
spare bits in the representation, but getting the
single-element case right really provides the bulk of the
benefit.

This commit restores r17242 and r17243 with a fix to use
value witnesses that actually forward the right type metadata
down.  We were already generating these value witnesses in
the dependent struct VWT pattern, but I was being too clever
and trying to use the underlying value witness directly.

Swift SVN r17267
2014-05-02 20:17:14 +00:00
Joe Groff
05a9a266e4 Revert "Use the first element of an enum as a source for"
This reverts commit r17242. We can't simply forward tuple element extra
inhabitant witnesses for the same reason laid out in the previous commit.

Swift SVN r17252
2014-05-02 16:22:44 +00:00
Joe Groff
0e6ec12b57 Revert "Use the first element of a struct as a source for"
This reverts commit r17243. We can't just forward the extra inhabitant payloads
from a field, because they will end up receiving metadata for the incorrect
type and crashing.

Swift SVN r17251
2014-05-02 16:22:41 +00:00
John McCall
c0e4242bec Use the first element of a struct as a source for
extra inhabitants.

Obviously this should eventually be generalized to
take from any element, but this is good enough to
give us zero-cost abstraction via single-field structs.

Contains some bugfixes for the tuple-extra-inhabitant
changes as well, because test coverage for optional
structs is obviously quite a bit richer than for
optional tuples.

All of this is leading towards unblocking IRGen for
importing CFStringRef as Unmanaged<CFString>!.

Swift SVN r17243
2014-05-02 10:29:55 +00:00