Skip to content

rustc generates a lot of llvm ir for small programs due to inline generated drops #38827

Open

Description

@jrmuizel

Building https://github.com/jrmuizel/webrender/blob/sample-min/sample-min/src/main.rs ends up generating 12MB of LLVM IR (25MB of LLVM IR with debug info turned on). This seems like an excessive amount and it has a big impact on build times.

Activity

  1. jonas-schievink commented on Jan 4, 2017

    @jonas-schievink
    Contributor

    webrender marks a lot of functions as #[inline] for performance, which causes their IR to be included in your crate. #[inline] has always been problematic for build times.

  2. jrmuizel commented on Jan 4, 2017

    @jrmuizel
    ContributorAuthor

    But shouldn't those inline functions only be emitted if they are used by main.rs?

  3. RReverser commented on Jan 4, 2017

    @RReverser
    Contributor

    @jrmuizel I think you need to use lto = true for final binary if you want such cross-crate optimizations (dead line code elimination, inlining etc.) to happen correctly.

  4. jrmuizel commented on Jan 4, 2017

    @jrmuizel
    ContributorAuthor

    I'm not really looking for cross-crate optimizations so lto seems inappropriate.

    Why do we need to re-emit the ir for unused inline functions? How could these functions ever be used?

  5. jonas-schievink commented on Jan 4, 2017

    @jonas-schievink
    Contributor

    They are used by the functions used by main.rs. All inline-functions transitively used by your code will be included in the crate's LLVM module IIRC. This gives LLVM the ability to inline all of them (if it decides to do so) into your code.

  6. jrmuizel commented on Jan 5, 2017

    @jrmuizel
    ContributorAuthor

    So it looks like the bulk of this code is from the drop function implementations. i.e. mem::forgetting the return values from renderer::Renderer::new(opts) and compiling with -C panic=abort drops the IR size to 1.3MB. Is there a reason the drop functions need to be inline?

  7. RReverser commented on Jan 5, 2017

    @RReverser
    Contributor

    I'm not really looking for cross-crate optimizations so lto seems inappropriate.
    Why do we need to re-emit the ir for unused inline functions?

    Well, you're looking for dead code elimination (not emitting functions from other crate that are unused), so you do want cross-crate optimization.

  8. bluss commented on Jan 5, 2017

    @bluss
    Contributor

    One reason is that automatically generated drop (like for Renderer) can not be marked inline explicitly, so it would limit programs to not have them inlineable by default.

  9. jrmuizel commented on Jan 5, 2017

    @jrmuizel
    ContributorAuthor

    It seems like we could avoid having inline generated drop functions in debug builds though.

  10. changed the title [-]rustc generates a lot of llvm ir for small programs[/-] [+]rustc generates a lot of llvm ir for small programs due to inline generated drops[/+] on Jan 5, 2017
  11. jrmuizel commented on Apr 5, 2017

    @jrmuizel
    ContributorAuthor

    It looks like the majority of the code is being added because of monomorphization caused by the inline drop.

  12. added
    I-compiletimeIssue: Problems and improvements with respect to compile times.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 20, 2017
  13. jrmuizel commented on Jul 11, 2017

    @jrmuizel
    ContributorAuthor

    running RUST_LOG=rustc_trans rustc on this example shows 4614 functions being translated. I wonder if it would be pursuing polymorphic code gen so that we don't get hammered with monomorphization.

  14. scottmcm commented on Feb 23, 2022

    @scottmcm
    Member

    This codegen test suggests that drop glue is not marked for inlining by default:
    4ea25da#diff-d13eb81c7eec73d0e1f5f62e9c15e987b7fac6b90e1924401152d1146200b92fR1-R2

  15. jrmuizel commented on Feb 23, 2022

    @jrmuizel
    ContributorAuthor

    Indeed. As I understand it, the problem is not that code is marked as inline it's that it's generic code that gets a monomorphized version generated for it instead of sharing it. See #68414 and #84175

  16. jrmuizel commented on May 15, 2022

    @jrmuizel
    ContributorAuthor

    More specifically, for an example like:

    struct A(String);
    
    fn a(_: A) {}

    becomes something like:

    a(x: A) {
       core::ptr::drop_in_place::<A>(&x);
    }

    which even though it's not being inlined gets codegened in place because of monomorphization.

  17. added
    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such
    on Oct 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationA-destructorsArea: Destructors (`Drop`, …)C-enhancementCategory: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-compiletimeIssue: Problems and improvements with respect to compile times.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions