-
Notifications
You must be signed in to change notification settings - Fork 13.3k
reuse allocation for always_storage_live_locals bitset #107927
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ use std::mem; | |
use either::{Either, Left, Right}; | ||
|
||
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; | ||
use rustc_index::bit_set::GrowableBitSet; | ||
use rustc_index::vec::IndexVec; | ||
use rustc_middle::mir; | ||
use rustc_middle::mir::interpret::{ErrorHandled, InterpError, InvalidProgramInfo}; | ||
|
@@ -46,6 +47,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { | |
|
||
/// The recursion limit (cached from `tcx.recursion_limit(())`) | ||
pub recursion_limit: Limit, | ||
|
||
// reuse allocation for bit set | ||
always_live_locals_cache: GrowableBitSet<mir::Local>, | ||
} | ||
|
||
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread | ||
|
@@ -408,6 +412,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
param_env, | ||
memory: Memory::new(), | ||
recursion_limit: tcx.recursion_limit(), | ||
always_live_locals_cache: Default::default(), | ||
} | ||
} | ||
|
||
|
@@ -705,13 +710,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
let mut locals = IndexVec::from_elem(dummy, &body.local_decls); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is ~60% total allocated memory for At first, i tried to cache it too, but it saved later at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah that test involves a lot of CTFE stack variables. But I don't think this is worth optimizing for. This is totally unrealistic for real code. We shouldn't make rustc harder to maintain just for the sake of meaningless benchmarks -- that is not the purpose of these stress tests. |
||
|
||
// Now mark those locals as live that have no `Storage*` annotations. | ||
let always_live = always_storage_live_locals(self.body()); | ||
// and take cached allocation for bitset ... | ||
let mut always_live = mem::take(&mut self.always_live_locals_cache); | ||
always_storage_live_locals(self.body(), &mut always_live); | ||
|
||
for local in locals.indices() { | ||
if always_live.contains(local) { | ||
locals[local].value = LocalValue::Live(Operand::Immediate(Immediate::Uninit)); | ||
} | ||
} | ||
// done | ||
// ... and place it back | ||
self.always_live_locals_cache = always_live; | ||
|
||
self.frame_mut().locals = locals; | ||
M::after_stack_push(self)?; | ||
self.frame_mut().loc = Left(mir::Location::START); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,12 @@ | ||
use rustc_index::bit_set::BitSet; | ||
use rustc_index::bit_set::GrowableBitSet; | ||
use rustc_middle::mir::{self, Local}; | ||
|
||
/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations. | ||
/// | ||
/// These locals have fixed storage for the duration of the body. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment should explain the unconventional signature for this function, and what the caller is supposed to pass for the |
||
pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet<Local> { | ||
let mut always_live_locals = BitSet::new_filled(body.local_decls.len()); | ||
pub fn always_storage_live_locals(body: &mir::Body<'_>, locals: &mut GrowableBitSet<Local>) { | ||
locals.fill(body.local_decls.len()); | ||
let always_live_locals = locals; | ||
|
||
for block in &*body.basic_blocks { | ||
for statement in &block.statements { | ||
|
@@ -15,6 +16,4 @@ pub fn always_storage_live_locals(body: &mir::Body<'_>) -> BitSet<Local> { | |
} | ||
} | ||
} | ||
|
||
always_live_locals | ||
} |
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.
Don't know good place for this, any suggestions?
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.
This is probably the most global state you can add it to.
However note that this InterpCx is re-created per constant, so if there are many constants to evaluate, then each will still do their own thing. I am also concerned that we might keep large buffers around for longer than we have to.