-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
safely transmute<&List<Ty<'tcx>>, &List<GenericArg<'tcx>>>
#93505
Conversation
Some changes occurred in src/tools/clippy. cc @rust-lang/clippy |
(rust-highfive has picked a reviewer for you, use r? to override) |
@bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit 443bbb12b2f09a19a08527640a9988d13e56203d with merge c462201b7d359b74f466604390e92b54810fe960... |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💔 Test failed - checks-actions |
@bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit e4d2a5f747ca4fa5ec9a1ec042e1ae4d006da63d with merge a70d158d75abc4ec966880549ca103eb120f8cb8... |
☀️ Try build successful - checks-actions |
Queued a70d158d75abc4ec966880549ca103eb120f8cb8 with parent 415c9f9, future comparison URL. |
// Can't use the macros as we have reuse the `substs` here. | ||
impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> { | ||
type Lifted = &'tcx List<Ty<'tcx>>; | ||
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the transmute inside it, in instances such as this one, I personally like to spell out the aliases explicitly:
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { | |
fn lift_to_tcx(self: &'a List<Ty<'a>>, tcx: TyCtxt<'tcx>) -> Option<&'tcx List<Ty<'tcx>>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i generally agree, though, considering that all other Lift
impls also don't do that i am going to keep the code as is for now.
Finished benchmarking commit (a70d158d75abc4ec966880549ca103eb120f8cb8): comparison url. Summary: This benchmark run shows 18 relevant improvements 🎉 but 13 relevant regressions 😿 to instruction counts.
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR led to changes in compiler perf. Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @bors rollup=never |
e4d2a5f
to
4a1a0ed
Compare
💔 Test failed - checks-actions |
seems spurious again? 🤔 @bors retry |
☀️ Test successful - checks-actions |
Finished benchmarking commit (03a8cc7): comparison url. Summary: This benchmark run shows 17 relevant improvements 🎉 but 48 relevant regressions 😿 to instruction counts.
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression |
that perf impact is worse then the previous run, going to look into that a bit xx |
@@ -208,6 +233,17 @@ pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>; | |||
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; | |||
|
|||
impl<'a, 'tcx> InternalSubsts<'tcx> { | |||
/// Checks whether all elements of this list are types, if so, transmute. | |||
pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> { | |||
if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe checking the pointer tag directly would make it possible for LLVM to optimize this? Something like self.iter().all(|arg| arg.ptr.get() & TAG_MASK == TYPE_TAG)
?
Adding #[inline]
to this method is a good idea in any case.
…ster inline `tuple_fields` more rust-lang#93505 fun, after this i have no idea what might be causing the perf impact.
update `hash_stable` for `List<Ty<'tcx>>` cc rust-lang#93505 (comment) this is the hottest part changed since the pre-merge perf run
…errors Don't transmute `&List<GenericArg>` <-> `&List<Ty>` In rust-lang#93505 we allowed safely transmuting between `&List<GenericArg<'_>>` and `&List<Ty<'_>>`. This was possible because `GenericArg` is a tagged pointer and the tag for types is `0b00`, such that a `GenericArg` with a type inside has the same layout as `Ty`. While this was meant as an optimization, it doesn't look like it was actually any perf or max-rss win (see rust-lang#94799 (comment), rust-lang#94841, rust-lang#110496 (comment)). Additionally the way it was done is quite fragile — `unsafe` code was not properly documented or contained in a module, types were not marked as `repr(C)` (making the transmutes possibly unsound). All of this makes the code maintenance harder and blocks other possible optimizations (as an example I've found out about these `transmutes` when my change caused them to sigsegv compiler). Thus, I think we can safely (pun intended) remove those transmutes, making maintenance easier, optimizations possible, code less cursed, etc. r? `@compiler-errors`
…errors Don't transmute `&List<GenericArg>` <-> `&List<Ty>` In rust-lang#93505 we allowed safely transmuting between `&List<GenericArg<'_>>` and `&List<Ty<'_>>`. This was possible because `GenericArg` is a tagged pointer and the tag for types is `0b00`, such that a `GenericArg` with a type inside has the same layout as `Ty`. While this was meant as an optimization, it doesn't look like it was actually any perf or max-rss win (see rust-lang#94799 (comment), rust-lang#94841, rust-lang#110496 (comment)). Additionally the way it was done is quite fragile — `unsafe` code was not properly documented or contained in a module, types were not marked as `repr(C)` (making the transmutes possibly unsound). All of this makes the code maintenance harder and blocks other possible optimizations (as an example I've found out about these `transmutes` when my change caused them to sigsegv compiler). Thus, I think we can safely (pun intended) remove those transmutes, making maintenance easier, optimizations possible, code less cursed, etc. r? `@compiler-errors`
This PR has 3 relevant steps which are is split in distinct commits.
The first commit now interns
List<Ty<'tcx>>
andList<GenericArg<'tcx>>
together, potentially reusing memory while allowing free conversions between these two usingList<Ty<'tcx>>::as_substs()
andSubstsRef<'tcx>::try_as_type_list()
.Using this, we then use
&'tcx List<Ty<'tcx>>
instead of aSubstsRef<'tcx>
for tuple fields, simplifying a bunch of code.Finally, as tuple fields and other generic arguments now use a different
TypeFoldable<'tcx>
impl, we optimize the impl forList<Ty<'tcx>>
improving perf by slightly less than 1% in tuple heavy benchmarks.