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

cg_llvm: fewer_names in uncached_llvm_type #76030

Merged
merged 1 commit into from
Aug 31, 2020

Conversation

davidtwco
Copy link
Member

This PR changes uncached_llvm_type so that a named struct type (with an empty name) is always created when the fewer_names option is enabled. By skipping the generation of names, we can improve perf. Giving LLVMStructCreateNamed an empty name works because LLVM will perform random renames to avoid collisions. Needs a perf run!

cc @eddyb (whom I've discussed this with)

@rust-highfive
Copy link
Collaborator

r? @eddyb

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 28, 2020
@Mark-Simulacrum
Copy link
Member

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Aug 28, 2020

⌛ Trying commit 2a36ad0fba34ca0971bd0de139958cb2f2f7fa11 with merge bb00eaa22b9a71d4409837350e6428ad8cca832c...

@davidtwco
Copy link
Member Author

@bors try (after fixing the use of fewer_names)

@bors
Copy link
Contributor

bors commented Aug 28, 2020

⌛ Trying commit 3be8dca04d7021e24a236f7feb841226daa647c5 with merge d71677e4467122732f2d745104d4f694320de5cf...

@bors
Copy link
Contributor

bors commented Aug 28, 2020

☀️ Try build successful - checks-actions, checks-azure
Build commit: d71677e4467122732f2d745104d4f694320de5cf (d71677e4467122732f2d745104d4f694320de5cf)

@rust-timer
Copy link
Collaborator

Queued d71677e4467122732f2d745104d4f694320de5cf with parent 3e3c552, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (d71677e4467122732f2d745104d4f694320de5cf): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never

@wesleywiser
Copy link
Member

The wins seem to be almost exclusively in the incremental tests (there are a few 0-2% wins in the FULL tests). Is that expected? Do we know why that is?

@eddyb
Copy link
Member

eddyb commented Aug 28, 2020

@wesleywiser most of what incr-patched rebuilds do is generate LLVM for everything in a CGU, most of which isn't actually changed, but we have no way to partially update the LLVM module corresponding to the CGU (I don't even think we keep the pre-optimization LLVM module bitcode anyway).

So what this is showing is that codegen and/or LLVM optimizations are faster. The 0-2% wins in full/incr-full are probably the same, there's just the regular Rust compilation as well, so it's much less of the total.


Although looking at the absolute values, I'm starting to doubt that, maybe the dep graph has less (false?) edges thanks to not looking at the types in full detail?

Maybe we could figure out if it's that, by using a FmtWriter with a fmt::Write implementation with a noop write_str, and still passing String::new() to LLVM, so that most of the effect is making all of the queries in ty::print::pretty.
(or I guess the old ty::print::obsolete? not sure if that was more/less expensive, in terms of the dep graph)

@eddyb
Copy link
Member

eddyb commented Aug 29, 2020

@bors try @rust-timer queue (we now allow deduplication of non-ty::Adt LLVM types)

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Aug 29, 2020

⌛ Trying commit 0100c83c0743ba0164edbb931ba513dedbd26c69 with merge b86ce2d9e7d96d5a001f3d8fbd61161e351c4f60...

@bors
Copy link
Contributor

bors commented Aug 29, 2020

☀️ Try build successful - checks-actions, checks-azure
Build commit: b86ce2d9e7d96d5a001f3d8fbd61161e351c4f60 (b86ce2d9e7d96d5a001f3d8fbd61161e351c4f60)

@rust-timer
Copy link
Collaborator

Queued b86ce2d9e7d96d5a001f3d8fbd61161e351c4f60 with parent 7b1dd61, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking try commit (b86ce2d9e7d96d5a001f3d8fbd61161e351c4f60): comparison url.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. Please note that if the perf results are neutral, you should likely undo the rollup=never given below by specifying rollup- to bors.

Importantly, though, if the results of this run are non-neutral do not roll this PR up -- it will mask other regressions or improvements in the roll up.

@bors rollup=never

@eddyb
Copy link
Member

eddyb commented Aug 29, 2020

I was excited about the difference between the two perf runs but we didn't do it soon enough and 3 PRs landed in between, which seem to account for all the wins except clap-rs-debug.

So overall I feel like the final version is an improvement, even if slight.

@davidtwco
Copy link
Member Author

Merge failure looks spurious?

@davidtwco
Copy link
Member Author

Re-approving, previous merge failure has been seen on other PRs so is likely spurious.

@bors r=eddyb

@bors
Copy link
Contributor

bors commented Aug 31, 2020

📌 Commit fa01ce8 has been approved by eddyb

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 31, 2020
@jyn514 jyn514 added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. labels Aug 31, 2020
@bors
Copy link
Contributor

bors commented Aug 31, 2020

⌛ Testing commit fa01ce8 with merge 1d22f75...

@bors
Copy link
Contributor

bors commented Aug 31, 2020

☀️ Test successful - checks-actions, checks-azure
Approved by: eddyb
Pushing 1d22f75 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 31, 2020
@bors bors merged commit 1d22f75 into rust-lang:master Aug 31, 2020
@davidtwco davidtwco deleted the fewer-names-llvm-type-of branch August 31, 2020 21:24
wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this pull request Nov 24, 2020
Clean up some of the pkgsrc Makefile, there's still lots in here that
should just be deleted though.  Switch SunOS to the illumos bootstrap
by default.

Version 1.48.0 (2020-11-19)
==========================

Language
--------

- [The `unsafe` keyword is now syntactically permitted on modules.][75857] This
  is still rejected *semantically*, but can now be parsed by procedural macros.

Compiler
--------
- [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158] This tells
  `rustc` whether to link its own C runtime and libraries or to rely on a external
  linker to find them. (Supported only on `windows-gnu`, `linux-musl`, and `wasi` platforms.)
- [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.][77386]
  Note: If you're using cargo you must explicitly pass the `--target` flag.
- [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420]

\* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
---------
- [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`,
  and `&Stderr`.][76275]
- [All arrays of any length now implement `TryFrom<Vec<T>>`.][76310]
- [The `matches!` macro now supports having a trailing comma.][74880]
- [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194]
- [The `RefCell::{replace, replace_with, clone}` methods now all use `#[track_caller]`.][77055]

Stabilized APIs
---------------
- [`slice::as_ptr_range`]
- [`slice::as_mut_ptr_range`]
- [`VecDeque::make_contiguous`]
- [`future::pending`]
- [`future::ready`]

The following previously stable methods are now `const fn`'s:

- [`Option::is_some`]
- [`Option::is_none`]
- [`Option::as_ref`]
- [`Result::is_ok`]
- [`Result::is_err`]
- [`Result::as_ref`]
- [`Ordering::reverse`]
- [`Ordering::then`]

Cargo
-----

Rustdoc
-------
- [You can now link to items in `rustdoc` using the intra-doc link
  syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate
  a link to `std::future`'s documentation. See ["Linking to items by
  name"][intradoc-links] for more information.
- [You can now specify `#[doc(alias = "<alias>")]` on items to add search aliases
  when searching through `rustdoc`'s UI.][75740]

Compatibility Notes
-------------------
- [Promotion of references to `'static` lifetime inside `const fn` now follows the
  same rules as inside a `fn` body.][75502] In particular, `&foo()` will not be
  promoted to `'static` lifetime any more inside `const fn`s.
- [Associated type bindings on trait objects are now verified to meet the bounds
  declared on the trait when checking that they implement the trait.][27675]
- [When trait bounds on associated types or opaque types are ambiguous, the
  compiler no longer makes an arbitrary choice on which bound to use.][54121]
- [Fixed recursive nonterminals not being expanded in macros during
  pretty-print/reparse check.][77153] This may cause errors if your macro wasn't
  correctly handling recursive nonterminal tokens.
- [`&mut` references to non zero-sized types are no longer promoted.][75585]
- [`rustc` will now warn if you use attributes like `#[link_name]` or `#[cold]`
  in places where they have no effect.][73461]
- [Updated `_mm256_extract_epi8` and `_mm256_extract_epi16` signatures in
  `arch::{x86, x86_64}` to return `i32` to match the vendor signatures.][73166]
- [`mem::uninitialized` will now panic if any inner types inside a struct or enum
  disallow zero-initialization.][71274]
- [`#[target_feature]` will now error if used in a place where it has no effect.][78143]
- [Foreign exceptions are now caught by `catch_unwind` and will cause an abort.][70212]
  Note: This behaviour is not guaranteed and is still considered undefined behaviour,
  see the [`catch_unwind`] documentation for further information.

Internal Only
-------------
These changes provide no direct user facing benefits, but represent significant
improvements to the internals and overall performance of rustc and
related tools.
- [Building `rustc` from source now uses `ninja` by default over `make`.][74922]
  You can continue building with `make` by setting `ninja=false` in
  your `config.toml`.
- [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030]
- [Made `ensure_sufficient_stack()` non-generic][76680]

[78143]: rust-lang/rust#78143
[76680]: rust-lang/rust#76680
[76030]: rust-lang/rust#76030
[70212]: rust-lang/rust#70212
[27675]: rust-lang/rust#27675
[54121]: rust-lang/rust#54121
[71274]: rust-lang/rust#71274
[77386]: rust-lang/rust#77386
[77153]: rust-lang/rust#77153
[77055]: rust-lang/rust#77055
[76275]: rust-lang/rust#76275
[76310]: rust-lang/rust#76310
[76420]: rust-lang/rust#76420
[76158]: rust-lang/rust#76158
[75857]: rust-lang/rust#75857
[75585]: rust-lang/rust#75585
[75740]: rust-lang/rust#75740
[75502]: rust-lang/rust#75502
[74880]: rust-lang/rust#74880
[74922]: rust-lang/rust#74922
[74430]: rust-lang/rust#74430
[74194]: rust-lang/rust#74194
[73461]: rust-lang/rust#73461
[73166]: rust-lang/rust#73166
[intradoc-links]: https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html
[`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
[`Option::is_some`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_some
[`Option::is_none`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none
[`Option::as_ref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref
[`Result::is_ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok
[`Result::is_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err
[`Result::as_ref`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref
[`Ordering::reverse`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.reverse
[`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then
[`slice::as_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range
[`slice::as_mut_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range
[`VecDeque::make_contiguous`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.make_contiguous
[`future::pending`]: https://doc.rust-lang.org/std/future/fn.pending.html
[`future::ready`]: https://doc.rust-lang.org/std/future/fn.ready.html
bors added a commit to rust-lang-ci/rust that referenced this pull request Dec 17, 2020
Revert "cg_llvm: `fewer_names` in `uncached_llvm_type`"

Fixes rust-lang#76213 and fixes rust-lang#79564.

This PR temporarily reverts commit fa01ce8 from rust-lang#76030 to until the root issue can be resolved. Requested [in t-compiler meeting](https://rust-lang.zulipchat.com/#narrow/stream/238009-t-compiler.2Fmeetings/topic/.5Bweekly.20meeting.5D.202020-12-17.20.2354818/near/220261541).

*Note*: I was seeing some failing debuginfo-gdb tests locally but I wasn't sure if they were spurious.
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Jan 1, 2021
Pkgsrc changes:
 * Compensate for files being moved around upstream.
 * Introduce optional, on-by-default semi-static building of cargo,
   using the internal curl and openssl sources.  This reduces the dynamic
   dependencies of cargo and therefore the rust package itself.
   Ref. options.mk.
 * The 1.47.0 bootstrap kits have been re-built with the above option
   turned on, so no longer depends on curl or openssl from pkgsrc and/or
   from earlier OS or pkgsrc versions.  This should hopefully fix
   installation of rust with non-default PREFIX, ref. PR#54453.


Upstream changes:

Version 1.48.0 (2020-11-19)
==========================

Language
--------
- [The `unsafe` keyword is now syntactically permitted on modules.][75857] This
  is still rejected *semantically*, but can now be parsed by procedural macros.

Compiler
--------
- [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158]
  This tells `rustc` whether to link its own C runtime and libraries
  or to rely on a external linker to find them. (Supported only on
  `windows-gnu`, `linux-musl`, and `wasi` platforms.)
- [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.]
  [77386]
  Note: If you're using cargo you must explicitly pass the `--target` flag.
- [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420]

\* Refer to Rust's [platform support page][forge-platform-support] for more
information on Rust's tiered platform support.

Libraries
---------
- [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`,
  and `&Stderr`.][76275]
- [All arrays of any length now implement `TryFrom<Vec<T>>`.][76310]
- [The `matches!` macro now supports having a trailing comma.][74880]
- [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194]
- [The `RefCell::{replace, replace_with, clone}` methods now all use
  `#[track_caller]`.][77055]

Stabilized APIs
---------------
- [`slice::as_ptr_range`]
- [`slice::as_mut_ptr_range`]
- [`VecDeque::make_contiguous`]
- [`future::pending`]
- [`future::ready`]

The following previously stable methods are now `const fn`'s:

- [`Option::is_some`]
- [`Option::is_none`]
- [`Option::as_ref`]
- [`Result::is_ok`]
- [`Result::is_err`]
- [`Result::as_ref`]
- [`Ordering::reverse`]
- [`Ordering::then`]

Cargo
-----

Rustdoc
-------
- [You can now link to items in `rustdoc` using the intra-doc link
  syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate
  a link to `std::future`'s documentation. See ["Linking to items by
  name"][intradoc-links] for more information.
- [You can now specify `#[doc(alias = "<alias>")]` on items to add
  search aliases when searching through `rustdoc`'s UI.][75740]

Compatibility Notes
-------------------
- [Promotion of references to `'static` lifetime inside `const fn`
  now follows the same rules as inside a `fn` body.][75502] In
  particular, `&foo()` will not be promoted to `'static` lifetime
  any more inside `const fn`s.
- [Associated type bindings on trait objects are now verified to meet the bounds
  declared on the trait when checking that they implement the trait.][27675]
- [When trait bounds on associated types or opaque types are ambiguous, the
  compiler no longer makes an arbitrary choice on which bound to use.][54121]
- [Fixed recursive nonterminals not being expanded in macros during
  pretty-print/reparse check.][77153] This may cause errors if your macro wasn't
  correctly handling recursive nonterminal tokens.
- [`&mut` references to non zero-sized types are no longer promoted.][75585]
- [`rustc` will now warn if you use attributes like `#[link_name]` or `#[cold]`
  in places where they have no effect.][73461]
- [Updated `_mm256_extract_epi8` and `_mm256_extract_epi16` signatures in
  `arch::{x86, x86_64}` to return `i32` to match the vendor signatures.][73166]
- [`mem::uninitialized` will now panic if any inner types inside
  a struct or enum disallow zero-initialization.][71274]
- [`#[target_feature]` will now error if used in a place where it
  has no effect.][78143]
- [Foreign exceptions are now caught by `catch_unwind` and will
  cause an abort.][70212] Note: This behaviour is not guaranteed
  and is still considered undefined behaviour, see the [`catch_unwind`]
  documentation for further information.

Internal Only
-------------
These changes provide no direct user facing benefits, but represent significant
improvements to the internals and overall performance of rustc and
related tools.

- [Building `rustc` from source now uses `ninja` by default over `make`.][74922]
  You can continue building with `make` by setting `ninja=false` in
  your `config.toml`.
- [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030]
- [Made `ensure_sufficient_stack()` non-generic][76680]

[78143]: rust-lang/rust#78143
[76680]: rust-lang/rust#76680
[76030]: rust-lang/rust#76030
[70212]: rust-lang/rust#70212
[27675]: rust-lang/rust#27675
[54121]: rust-lang/rust#54121
[71274]: rust-lang/rust#71274
[77386]: rust-lang/rust#77386
[77153]: rust-lang/rust#77153
[77055]: rust-lang/rust#77055
[76275]: rust-lang/rust#76275
[76310]: rust-lang/rust#76310
[76420]: rust-lang/rust#76420
[76158]: rust-lang/rust#76158
[75857]: rust-lang/rust#75857
[75585]: rust-lang/rust#75585
[75740]: rust-lang/rust#75740
[75502]: rust-lang/rust#75502
[74880]: rust-lang/rust#74880
[74922]: rust-lang/rust#74922
[74430]: rust-lang/rust#74430
[74194]: rust-lang/rust#74194
[73461]: rust-lang/rust#73461
[73166]: rust-lang/rust#73166
[intradoc-links]: https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html
[`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
[`Option::is_some`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_some
[`Option::is_none`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none
[`Option::as_ref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref
[`Result::is_ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok
[`Result::is_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err
[`Result::as_ref`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref
[`Ordering::reverse`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.reverse
[`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then
[`slice::as_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range
[`slice::as_mut_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range
[`VecDeque::make_contiguous`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.make_contiguous
[`future::pending`]: https://doc.rust-lang.org/std/future/fn.pending.html
[`future::ready`]: https://doc.rust-lang.org/std/future/fn.ready.html
@tmiasko
Copy link
Contributor

tmiasko commented Jan 8, 2021

Giving LLVMStructCreateNamed an empty name works because LLVM will perform random renames to avoid collisions

The renaming scheme applies only if type name is non-empty, It might be plausible to try landing this again with a fixed with non-empty string.

There is also additional subtle side effect of this changes. For LTO, the merged codegen unit contains substantially more bitcasts than before (since type names between different units are unrelated). While bitcasts, shouldn't be significant, it wouldn't be exactly surprising if they have some effect, at least until migration to opaque pointer is complete in LLVM.

@tgnottingham
Copy link
Contributor

tgnottingham commented Jan 20, 2021

@tmiasko, I applied your suggestion of using a fixed non-empty string ("x" in particular -- does it matter?) and ran benchmarks locally. Results were still impressive:

fewer_names_p2

I'll leave this to you or @davidtwco to apply, since I'm just drive-by benchmarking.

Other than the bitcasting issue tmiasko mentioned, is there any reason we shouldn't do this, and should try to optimize name generation instead?

I also don't understand why this seems to have huge effects on some benchmarks, and no effect on similar benchmarks. E.g. why should this have 0% change on cargo-debug incr-full, but give a ~60% improvement on cargo-debug incr-patched-println?

@tgnottingham
Copy link
Contributor

tgnottingham commented Feb 8, 2021

@eddyb

I didn't go as far as what you suggested in #76030 (comment), but I did look at the CGU reuse for the cargo-debug incr-patched-println benchmark before and after this change.

Before the change, there were 16 CGUs whose artifacts couldn't be reused. After the change, there were only 2. This likely explains why this change only had a dramatic effect on incr-patched builds. It also potentially suggests that there are false edges in the dependency graph, which you alluded to. Finally, it goes to show how much profit we might derive from improving the CGU invalidation situation.

Also, this change made it so that the name is set to None for types like Closure, Foreign, etc. when fewer_names is enabled. Was that intended? Edit: Oh, just saw the code review comment that talked about this. Don't quite understand, but at least I know it was intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. merged-by-bors This PR was explicitly merged by bors. relnotes-perf Performance improvements that should be mentioned in the release notes S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet