Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce -Zvirtual-function-elimination codegen flag #96285

Merged
merged 8 commits into from
Jun 15, 2022

Commits on Jun 14, 2022

  1. Add -Zvirtual-function-elimination flag

    Adds the virtual-function-elimination unstable compiler flag and a check
    that this flag is only used in combination with -Clto. LLVM can only
    apply this optimization with fat LTO.
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    def3fd8 View commit details
    Browse the repository at this point in the history
  2. Add LLVM module flags required for the VFE opt

    To apply the optimization the `Virtual Function Elim` module flag has to
    be set. To apply this optimization post-link the `LTOPostLink` module
    flag has to be set.
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    20f597f View commit details
    Browse the repository at this point in the history
  3. Add typeid_for_trait_ref function

    This function computes a Itanium-like typeid for a trait_ref. This is
    required for the VFE optimization in LLVM. It is used to map
    `llvm.type.checked.load` invocations, that is loading the function from
    a vtable, to the vtables this function could be from.
    
    It is important to note that `typeid`s are not unique. So multiple
    vtables of the same trait can share `typeid`s.
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    d55787a View commit details
    Browse the repository at this point in the history
  4. Add llvm.type.checked.load intrinsic

    Add the intrinsic
    
    declare {i8*, i1} @llvm.type.checked.load(i8* %ptr, i32 %offset, metadata %type)
    
    This is used in the VFE optimization when lowering loading functions
    from vtables to LLVM IR. The `metadata` is used to map the function to
    all vtables this function could belong to. This ensures that functions
    from vtables that might be used somewhere won't get removed.
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    e1c1d0f View commit details
    Browse the repository at this point in the history
  5. Add metadata generation for vtables when using VFE

    This adds the typeid and `vcall_visibility` metadata to vtables when the
    -Cvirtual-function-elimination flag is set.
    
    The typeid is generated in the same way as for the
    `llvm.type.checked.load` intrinsic from the trait_ref.
    
    The offset that is added to the typeid is always 0. This is because LLVM
    assumes that vtables are constructed according to the definition in the
    Itanium ABI. This includes an "address point" of the vtable. In C++ this
    is the offset in the vtable where information for RTTI is placed. Since
    there is no RTTI information in Rust's vtables, this "address point" is
    always 0. This "address point" in combination with the offset passed to
    the `llvm.type.checked.load` intrinsic determines the final function
    that should be loaded from the vtable in the
    `WholeProgramDevirtualization` pass in LLVM. That's why the
    `llvm.type.checked.load` intrinsics are generated with the typeid of the
    trait, rather than with that of the function that is called. This
    matches what `clang` does for C++.
    
    The vcall_visibility metadata depends on three factors:
    
    1. LTO level: Currently this is always fat LTO, because LLVM only
       supports this optimization with fat LTO.
    2. Visibility of the trait: If the trait is publicly visible, VFE
       can only act on its vtables after linking.
    3. Number of CGUs: if there is more than one CGU, also vtables with
       restricted visibility could be seen outside of the CGU, so VFE can
       only act on them after linking.
    
    To reflect this, there are three visibility levels: Public, LinkageUnit,
    and TranslationUnit.
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    e96e6e2 View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    996c6b7 View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    a93ea7e View commit details
    Browse the repository at this point in the history
  8. Add VFE test for 32 bit

    The offset in the llvm.type.checked.load intrinsic differs on 32 bit platforms
    flip1995 committed Jun 14, 2022
    Configuration menu
    Copy the full SHA
    195f208 View commit details
    Browse the repository at this point in the history