Skip to content

Struct DU emit redundant constructors with an unused parameter, initalization and zero-comparison can be improved #9767

Description

@abelbraaksma

Found this while investigating the performance issues with @cmeeren's implementation of Array.tryPickV, see #6781 (comment).

As an example, take the following code:

typeMyNormalDU=| Case1
| Case2
| Case3
| Case4
| Case5
| Case6
| Case7
| Case8
| Case9

This compiles into the following constructors (I removed attributes for ease of reading):

internalMyStructDU(int _tag,bool flag){this.Tag=_tag;}internalMyStructDU(int _tag,byte num){this.Tag=_tag;}internalMyStructDU(int _tag,sbyte num){this.Tag=_tag;}internalMyStructDU(int _tag,char chr){this.Tag=_tag;}internalMyStructDU(int _tag,short num){this.Tag=_tag;}internalMyStructDU(int _tag,int num){this.Tag=_tag;}internalMyStructDU(int _tag,ushort num){this.Tag=_tag;}internalMyStructDU(int _tag,uint num,bool flag){this.Tag=_tag;}internalMyStructDU(int _tag,uint num,byte num){this.Tag=_tag;}

There wasn't anything about this implementation detail in the relevant RFC, but my guess is this is to disambiguate constructors for same-type DU fields, as there's a clear "countable" use of all the build-in types up until 32 bit.

Optimization ideas for struct DUs

These redundant parameters lead to overhead in constructing the types, as the extra param needs to be put on the stack, even though it is always zero (false, '\0', 0uy etc). There used to be other optimization issues with overloaded constructors in structs w.r.t. JIT optimizations, but I haven't been able to verify that that is still the case.

Either way, I propose we improve this, which would consequently improve ValueOption as well:

  • These constructors are only ever called from a single place, we can emit simple struct-init code there instead with the proper value(s), if any
  • For no-value multi-case struct-DUs, only the _tag needs to be set, ctor overloads are not needed
  • Any top-case initialization without a value can be optimized to just init the struct to zero (i.e. ValueNone, or Case1 above)

If this is made possible, voption can be improved to issue the same null-check (i.e. br.false or br.true) as for option to check for ValueNone, which dramatically speeds up the current implementation which calls get_Tag() and compares it with 0.

This would also open the way to implement overlapping DU cases in an overlapping internal struct, which dramatically reduces space occupied by struct DUs.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    Done

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions