jiebi/CodeConvo huggingface dataset:
Code change:
(cfg, _) => cfg.as_deref().cloned(), }; <del> debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.and_then(|p| p.cfg.as_ref()), cfg); </del> <ins> debug!( "Portability {:?} {:?} (parent: {:?}) - {:?} = {:?}", item.name, item.cfg, parent, parent.and_then(|p| p.cfg.as_ref()), cfg ); </ins> Some(format!("<div class="stab portability">{}</div>", cfg?.render_long_html())) }

Related discussion:
text: From Given the following Rust code with in-line annotations of the expected behaviour: On: does not seem to be able to generate feature requirement labels on types in private modules () that are publicly reexported (). The labels do not show up on the module overview nor page, but do propagate into items like functions for the given type. This renders the type without any feature requirement, neither in the module overview: ! Nor on the page: ! Note that the label is propagated onto (does not have an explicit ), at least understood that! It is supposed to render the feature requirement for like , both in the module overview above as on the page: ! It seems tricky to combine feature requirements on the and reexport. In the case above they are the same, but what if: The type is only publicly available when and are specified. Specifying is fine but makes the contents of unreachable through the current module, specifying only should result in a "module not found" error. CC
This also affects re-exports of entire crates. Unfortunately there the fix is not clear at all, since the "parent" crate is obviously not guaranteed to have the same features as the crate being re-exported.
Within the same crate as well; it's not about the features that are enabled (though it is relevant which are available) but about the combined restrictions that are placed on the definition and reexport. Simplest I can think of is a union of all features (but gets complicated quick when inversions and vs is used) and later perhaps simplifying based on feature relations (if implies there is no need to display as requirement, if either definition or reexport requires ). That's necessary to cleanly solve crate reexports, since you effectively want to ensure that the top-level crate feature implies feature and hide it. If the whole resolver is made smart enough (perhaps this already exists, I'm not too familiar with Cargo) it could even throw warnings when there exist feature combinations that would lead to a compiler error (ie. explicitly reexporting a symbol that is not available for a certain set of features).
I wonder if this is just an ordering issue of the passes: The private modules have disappeared by the point where we pass all the data down so we don't see them.
Code change:
(cfg, _) => cfg.as_deref().cloned(), }; <del> debug!("Portability {:?} - {:?} = {:?}", item.cfg, parent.and_then(|p| p.cfg.as_ref()), cfg); </del> <ins> debug!( "Portability {:?} {:?} (parent: {:?}) - {:?} = {:?}", item.name, item.cfg, parent, parent.and_then(|p| p.cfg.as_ref()), cfg ); </ins> Some(format!("<div class="stab portability">{}</div>", cfg?.render_long_html())) }

Related discussion:
text: Thanks for the suggestion - I moved before and (I've never built rustc/rustdoc from source, pleasantly surprised that only took just under 7min on a ThreadRipper :partyingface:) but it doesn't change anything to the generated output unfortunately :(
I observe this on public items as well: Does not show the badge at re-exports.
So from the following code: is stripped and then inlined. The stripped version contains all the correct information but the inlined one doesn't. Checking what's the best course here: either cloning the stripped item or propagating when inlining.
Code change:
msg: &str) -> DiagnosticBuilder<'a> { <del> let (level, src) = self.sets.get_lint_level(lint, self.cur); </del> <ins> let (level, src) = self.sets.get_lint_level(lint, self.cur, None); </ins> lint::struct_lint_level(self.sess, lint, level, src, span, msg) }

Related discussion:
text: The following snippet works fine before but now it reports a warning: Steps to reproduce: clone rustup override set nightly-2017-08-11 cargo test Is this an expected behavior, or a bug? Thank you!
cc -- probably related to the new lint implementation
Yes this was caused by The bug is on . The check for whether is in scope is not checking the current set of attributes being linted. For example this does not warn: but this warns: (as you've noticed) The fix is to just take the local variable into account which has the up-to-that-point set of lint attributes collected.
I've opened a PR for this at
Code change:
<ins> // assembly-output: emit-asm // # zen3 previously exhibited odd vectorization // compile-flags: --crate-type=lib -Ctarget-cpu=znver3 -O // only-x86_64 // ignore-sgx use std::iter; // previously this produced a long chain of // 56:  vpextrb $6, %xmm0, %ecx // 57:  orb %cl, 22(%rsi) // 58:  vpextrb $7, %xmm0, %ecx // 59:  orb %cl, 23(%rsi) // [...] // CHECK-LABEL: zip_arrays: #[no_mangle] pub fn zip_arrays(mut a: [u8; 32], b: [u8; 32]) -> [u8; 32] { // CHECK-NOT: vpextrb // CHECK-NOT: orb %cl // CHECK: vorps iter::zip(&mut a, b).for_each(|(a, b)| *a |= b); // CHECK: retq a } </ins>

Related discussion:
text: <!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code: I expected to see this happen: same codegen or similar in performance Instead, this happened: array has way worse codegen <details<summaryAssembly</summary<p</p</details<!-- Provide the most recent version this worked on, for example: It most recently worked on: Rust 1.47 --It most recently worked on: 1.64 <!-- Provide the version you are using that has the regression. --65 till now. Regressed in nightly-2022-08-13, maybe LLVM 15 ?: : <!-- Did the compiler crash? If so, please provide a backtrace. --<!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. -- modify labels: +regression-from-stable-to-stable -regression-untriaged <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
WG-prioritization assigning priority (). cc since this regressed in the LLVM 15 update label -I-prioritize +P-medium +T-compiler
I've seen llvm doing these strange 1-byte-at-a-time "vectorizations" in other places too. This might be a more general problem. In this case we can probably paper over it by implementing TrustedRandomAccess for the array iter.
Unfortunately, the array iterator is fundamentally worse right now, because indexing into it -- a fundamental part of being a by-value array iterator -- keeps it from SRoAing and thus doesn't optimize well. This is why when I was making better I ended up making to not have to use . Sadly, for the foreseeable future you're better off using the "weaker" slice iterator when you can.
My guess is that the SROA is missing something in the opaque pointer mode.
Code change:
<ins> // assembly-output: emit-asm // # zen3 previously exhibited odd vectorization // compile-flags: --crate-type=lib -Ctarget-cpu=znver3 -O // only-x86_64 // ignore-sgx use std::iter; // previously this produced a long chain of // 56:  vpextrb $6, %xmm0, %ecx // 57:  orb %cl, 22(%rsi) // 58:  vpextrb $7, %xmm0, %ecx // 59:  orb %cl, 23(%rsi) // [...] // CHECK-LABEL: zip_arrays: #[no_mangle] pub fn zip_arrays(mut a: [u8; 32], b: [u8; 32]) -> [u8; 32] { // CHECK-NOT: vpextrb // CHECK-NOT: orb %cl // CHECK: vorps iter::zip(&mut a, b).for_each(|(a, b)| *a |= b); // CHECK: retq a } </ins>

Related discussion:
text: claim
It's not about vectorization. This optimization can be restored by using . But highly unrecommended. Upstream issue:
The upstream issue is closed. claim
Code change:
) -> DefId { let body = tcx.mir_built(coroutine_def_id).borrow(); <ins> // If the typeck results are tainted, no need to make a by-ref body. if body.tainted_by_errors.is_some() { return coroutine_def_id.to_def_id(); } </ins> let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = tcx.coroutine_kind(coroutine_def_id) else {

Related discussion:
text: <!-- [31mICE[0m: Rustc '-Zunstable-options --edition=2024 -ooutputfile -Zdump-mir-dir=dir' 'error: internal compiler error: impossible case reached', 'error: internal compiler error: impossible case reached' File: --auto-reduced (treereduce-rust): original: Version information ` Command: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongProgram output</strong</summary<p</p</details<!-- query stack: [coroutinebymovebodydefid] looking up the coroutine by-move body for [analysis] running analysis passes on this crate -- label +F-asyncclosure
As a step of reducing your code examples, could you please ensure that is necessary to reproduce this ICE before mentioning it in the issue? This ICE reproduces on edition 2021, which is the current stable edition.
My project fails on nightly also while using edition 2021.
Yep, a fix is already up and it's waiting for approval. I recommend downgrading to a slightly older nightly until this is fixed.
Code change:
<del> error: lifetime may not live long enough --> $DIR/issue-16922.rs:4:5 | LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> { |                       - let's call the lifetime of this reference `'1` LL |     Box::new(value) as Box<dyn Any> |     ^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` | help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound | LL | fn foo<T: Any>(value: &T) -> Box<dyn Any + '_> { |                                          ++++ error: aborting due to previous error </del>

Related discussion:
text: we currently output The suggestion is incomplete and will not result in compilable code. Because the lifetime is coming from an argument of type , which is an unconstrained type parameter, itself will not have the needed lifetime and causes the obligation that we're trying to reverse by suggesting . The appropriate changes to the code would be either or , depending on whether appears in any other argument or not.
The suggested code .
Code change:
run_pass_manager(cgcx, tm, llmod, config, true); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm"); timeline.record("thin-done"); <ins> // FIXME: this is a hack around a bug in LLVM right now. Discovered in // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen // error if there's an available_externally function in the LLVM module. // Typically we don't actually use these functions but ThinLTO makes // heavy use of them when inlining across modules. // // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this // function call (and its definition on the C++ side of things) // shouldn't be necessary eventually and we can safetly delete these few // lines. llvm::LLVMRustThinLTORemoveAvailableExternally(llmod); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae"); timeline.record("no-ae"); </ins> Ok(mtrans) } }

Related discussion:
text: I'm opening this up to serve as a tracking issue for enabling multiple codegen units in release mode by default. I've written up a before but the tl;dr; is that multiple codegen units enables us to run optimization/code generation in parallel, making use of all available computing resources often speeding up compilations by more than 2x. Historically this has not been done due to claims of a loss in performance, but the is intended to assuage such concerns. The most viable route forward seems to be to enable multiple CGUs and ThinLTO at the same time in release mode. Blocking issues: [x] Enable for libstd on all platforms - - - - Potential blockers/bugs: - -
cc
Presumably this will remain a stable compiler flag, but what else will change by default? Is the plan to make this only affect , or is the plan to also make this affect ? Do we want to make continue to use only a single CGU, to hedge against regressions for people who are already willing to trade off compiler time for runtime?
I would specifically propose that any opt level greater than 1 uses 16 codegen units and ThinLTO enabled by default for those 16 codegen units.
This is very interesting. One would think that ThinLTO-driven inlining should always have to do less work when our much more conservative pre-LLVM inlining. But that doesn't always seem to be the case, as in the . Most tests on the seem to profit though. Overall it's still not a clear picture to me.
was that comment meant for a different thread? I forget which one as well though, so I'll respond here! As a "quick benchmark" I compiled the regex test suite with 16 CGUs + ThinLTO and then toggled inlining in all CGUs on/off. Surprisingly inlining in all CGUs was 5s faster to compile, and additionally . In those timings is where inlining is only in one CGU, where is inlining in all CGUs. One benchmark, , got twice as slow!
Yeah, the comment was in response to (rust-doom) but since that was closed already, I put it here.
Code change:
run_pass_manager(cgcx, tm, llmod, config, true); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm"); timeline.record("thin-done"); <ins> // FIXME: this is a hack around a bug in LLVM right now. Discovered in // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen // error if there's an available_externally function in the LLVM module. // Typically we don't actually use these functions but ThinLTO makes // heavy use of them when inlining across modules. // // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this // function call (and its definition on the C++ side of things) // shouldn't be necessary eventually and we can safetly delete these few // lines. llvm::LLVMRustThinLTORemoveAvailableExternally(llmod); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae"); timeline.record("no-ae"); </ins> Ok(mtrans) } }

Related discussion:
text: Regarding the compilation time difference between pre- and post-trans inlining, my hypothesis would be that sometimes pre-trans inlining will lead to more code being eliminated early on (as in the case of regex apparently) and sometimes it will have the opposite effect. I suspect that there's room for improvement by tuning which LLVM passes we run specifically for ThinLTO. Or do we do that already?
Heh it's true yeah, I'd imagine that there's always room for improvement in pass tuning in Rust :). Right now we perform (afaik) 0 customization of any pass manager in LLVM. All of the normal optimization passes, LTO optimization passes, and ThinLTO optimization passes are all the same as what's in LLVM itself.
I wanted to also take the time and tabulate all the results from the to make sure it's all visibile in one place. Note that all the timings below are comparing a release build to a release build with 16 CGUs and ThinLTO enabled Improvements All of the following compile times improved, sorted by most improved to least improved Regressions The following crates regressed in compile times, sorted from smallest regression to largest alexcrichton's attempt to reproduce the regressions Here I attempt to reproduce the regressions on my own machine with Unfortunately the only regression I was able to reproduce was the rust-belt regression. I'll be looking more into that.
Looking into , one interesting thing I've found is that the crate takes longer to compile with ThinLTO than it would otherwise. Looking at it appears that one codegen unit in this crate takes 99% of the time in LLVM. This codegen unit appears to be basically entirely dominated by . Almost all of the benefit of multiple codegen units is spreading out the work across all CPUs. Enabling ThinLTO to avoid losing any perf is fundamentally doing more work than what's already happening at , but we get speedups across the board in most cases. If we have one huge CGU, split it in two, and work on those in parallel then we've got 50% of the original time to run ThinLTO (in a perfect world). If ThinLTO takes more than 50% of the time then we'd have a build time regression, but that's almost never happening.
Code change:
run_pass_manager(cgcx, tm, llmod, config, true); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm"); timeline.record("thin-done"); <ins> // FIXME: this is a hack around a bug in LLVM right now. Discovered in // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen // error if there's an available_externally function in the LLVM module. // Typically we don't actually use these functions but ThinLTO makes // heavy use of them when inlining across modules. // // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this // function call (and its definition on the C++ side of things) // shouldn't be necessary eventually and we can safetly delete these few // lines. llvm::LLVMRustThinLTORemoveAvailableExternally(llmod); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae"); timeline.record("no-ae"); </ins> Ok(mtrans) } }

Related discussion:
text: What's happening here is that we have one huge CGU, but when we split it up we still have one huge CGU. This means that the CGU which may take ~1% less time in LLVM only gives us a tiny sliver of a window to run ThinLTO passes. In the case of the crate this means that adding ThinLTO passes is an overall build time regression. So generalizing even further, I think that enabling ThinLTO and multiple CGUs by default is going to regress compile time performance in any crate where our paritioning implementation doesn't actually partition very well. In the case of we've got one huge function which hogs almost all the optimization time (I think) and the entire crate is basically dominated by that one function. I would be willing to conclude, however, that such a situation is likely quite rare. Almost all other crates in the ecosystem will benefit from the partitioning which should basically evenly split up a crate. maybe you have thoughts on this though?
Thank you so much for collecting and analyzing such a large amount of data, Your conclusions make sense to me. Unevenly distributed CGU sizes are also a problem for incremental compilation; e.g. the test sees 90% CGU re-use, yet compile time is almost the same as from-scratch. In the non-incremental case it might be an option to detect the problematic case right after partitioning and then switch to non-LTO mode? I'm not sure it's worth the extra complexity though. For cases where there is one big CGU but that CGU contains multiple functions, we should be able to rather easily redistribute functions to other CGUs. We'd only need a metric for the size of a . The number of MIR instructions might be a sufficient heuristic here. That would not help for but it might help for other crates. In conclusion, judging from the table above, I think we should make the default sooner rather than later. Open questions I see: What to do about ? I would have thought that it would always be a clear win to disable this when ThinLTO is enabled but that doesn't seem to be the case. Are there hardware configurations where this never is a win? E.g. should we default to traditional compilation if ?
Code change:
run_pass_manager(cgcx, tm, llmod, config, true); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-pm"); timeline.record("thin-done"); <ins> // FIXME: this is a hack around a bug in LLVM right now. Discovered in // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen // error if there's an available_externally function in the LLVM module. // Typically we don't actually use these functions but ThinLTO makes // heavy use of them when inlining across modules. // // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this // function call (and its definition on the C++ side of things) // shouldn't be necessary eventually and we can safetly delete these few // lines. llvm::LLVMRustThinLTORemoveAvailableExternally(llmod); cgcx.save_temp_bitcode(&mtrans, "thin-lto-after-rm-ae"); timeline.record("no-ae"); </ins> Ok(mtrans) } }

Related discussion:
text: FWIW, as the author of , which is a made-for-fun Piston game, I am more than happy to take a small compile regression when it seems like vast majority of crates get huge real-time improvements!
This seems like a good thing to have in our back pocket, but I'm also wary of trying to do this by default. For example the case is one where we may wish to disable ThinLTO but the one massive function could also critically rely on a function in a different CGU being inlined? That sort of case would be difficult for us to determine... In any case though I agree that we probably don't need the complexity just yet so I think we can defer this for later. Agreed! So far all the crate's I've seen the O(instructions) has been quite a good metric for "how long this takes in all LLVM-related passes", so counting MIR sounds reasonable to me as well. Again though I also feel like this is ok to have in our back pocket. I'd want dig more into the minor change example, I'm curious how awry the CGU distribution is there and whether a heuristic like this would help. Quite surprisingly I've yet to see any data that it's beneficial to compile time in release mode or doesn't hurt runtime. (all data is that it hurts both compile time and runtime performance!) That being said we're seeing such big wins from ThinLTO on big projects today that we can probably just save this as a possible optimization for the future. On the topic of inline functions I recently dug up again (later closed in favor of , but the latter may no longer be true today). I suspect that may "fix" quite a bit of the compile time issue here without coming at a loss of performance? In any case possibly lots of interesting things we could do there. Also a good question! I find this to be a difficult one, however, because the CGU number will affect the output artifact, which means that if we do this sort of probing it'll be beneficial for performance but come at the cost of more difficult deterministic builds. You'd have to specify the CGUs manually or build on the same-ish hardware to get a deterministic build I think? I think though that if you have 1 CPU then this is universaly a huge regression.