You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sema models enum case constructors as ApplyExprs. Formerly SILGen
would emit a case constructor function for each enum case,
constructing the enum value in the constructor body. ApplyExprs
of case constructors were lowered like any other call.
This is nice and straightforward but has several downsides:
1) Case constructor functions are very repetitive and trivial,
in particular for no-payload cases. They were declared
@_transparent and so were inlined at call sites, but for
public enums they still had to be emitted into the final
object file.
2) If the enum is generic, the substituted type may be loadable
even if the unsubstituted type is not, but since the case
constructor is polymorphic we had to allocate stack buffers
anyway, to pass the payload and result at the right abstration
level. This meant that for example Optional.Some(foo)
generated less-efficient SIL than the equivalent implicit
conversion.
3) We were missing out on peephole optimization opportunities when
the payload of an indirect case or address-only enum could be
emitted directly into the destination buffer, avoiding a copy.
One example would be when an enum payload is the result of
calling a function that returns an address-only value indirectly.
It appears we had unnecessary copies and takes even with -O.
Again, optional implicit conversions special-cased this.
This patch implements a new approach where a fully-formed call to
a element constructor is handled via a special code path where
the 'enum' or 'init_enum_data_addr' / 'inject_enum_addr'
instructions are emitted directly. These always work on the
substituted type, avoiding stack allocations unless needed.
An additional optimization is that the ArgumentSource abstraction
is used to delay evaluation of the payload argument until the
indirect box or address-only payload was set up.
If a element constructor is partially applied, we still emit a
reference to the constant as before.
It may seem like case constructor functions are at least useful
for resilience, but case constructors are transparent, so making
them resilient would require a new "transparent but only in this
module, and don't serialize the SIL body" declaration.
@inline(always) is almost what we need here, but this affect
mandatory inlining, only the optimizer, so it would be a
regression for non-resilient enums, or usages of resilient enums
in the current module.
A better approach is to construct resilient enums with a new
destructiveInjectEnumTag value witness function, which is
coming soon, and the general improvement from that approach
is what prompted this patch.
0 commit comments