-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Mir predecessors cache invalidate on terminators #64841
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
Mir predecessors cache invalidate on terminators #64841
Conversation
… predecessors_for to slice
…k, invalidate cache when accessing unique terminator
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
r? @oli-obk |
Not sure if it makes sense to have 2 branches, but I have it separate in case we want to explore another option. The base is shared with #64736 |
|
||
pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { | ||
self.predecessors_cache = None; | ||
/* |
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 was my first attempt at "smart" invalidation, though I doubted it quickly after writing it. I don't get the feeling that this will be faster than just wiping the whole cache since the recreation still has to re-walk everything. Maybe if we have a way to mark some basic blocks as "dirty" then the recreation could be faster. I'll either update this or remove it before moving the PR out of draft.
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 don't think we should be doing smart invalidation for now. We can leave that to the user and make them choose the appropriate function for their use case (thus not invalidating so much)
@@ -1336,6 +1383,10 @@ impl<'tcx> BasicBlockData<'tcx> { | |||
BasicBlockData { statements: vec![], terminator, is_cleanup: false } | |||
} | |||
|
|||
pub fn terminator_opt(&self) -> &Option<Terminator<'tcx>> { | |||
&self.terminator |
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.
Since I can't leave a comment outside of my changes...
I really wanted to make BasicBlockData::terminator
private, but that's not possible because Cfg
needs it in order to build up the BasicBlockData
initially. Would it make sense to make terminator
private and add a new method called something like terminator_for_cfg
and terminator_for_cfg_mut
that's intended only to be used by Cfg
? This would help ensure that all other mutable access to terminator
properly goes through Body
so the cache can be properly maintained. In the current form, it would be very easy for someone to access &mut terminator
directly without realizing it.
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.
yea, seems fine to makeit private and create a BasicBlockData::new
function that takes all values needed to construct a BasicBlockData
self.terminator.as_mut().expect("invalid terminator state") | ||
} | ||
|
||
// This can be public since changing the kind will not break the predecessors cache in Body | ||
pub fn terminator_kind_mut(&mut self) -> &mut TerminatorKind<'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.
Is this safe to do? TerminatorKind
doesn't affect successors, right?
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.
TerminatorKind
contains many BasicBlock
ids, and if you change them, the successors change
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@@ -210,17 +210,38 @@ impl<'tcx> Body<'tcx> { | |||
|
|||
#[inline] | |||
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'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.
this should still invalidate, or better not exist at all anymore
&mut self.basic_blocks | ||
} | ||
|
||
pub fn basic_block_terminator_opt_mut(&mut self, bb: BasicBlock) -> &mut Option<Terminator<'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.
this could just be called terminator_opt_mut
|
||
pub fn basic_block_terminator_mut(&mut self, bb: BasicBlock) -> &mut Terminator<'tcx> { | ||
self.predecessors_cache = None; | ||
/* |
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 don't think we should be doing smart invalidation for now. We can leave that to the user and make them choose the appropriate function for their use case (thus not invalidating so much)
src/librustc/mir/mod.rs
Outdated
#[inline] | ||
pub fn basic_blocks_and_local_decls_mut( | ||
&mut self, | ||
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) { | ||
self.predecessors_cache = None; |
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 still needs to invalidate, otherwise the cache is wrong.
@@ -1336,6 +1383,10 @@ impl<'tcx> BasicBlockData<'tcx> { | |||
BasicBlockData { statements: vec![], terminator, is_cleanup: false } | |||
} | |||
|
|||
pub fn terminator_opt(&self) -> &Option<Terminator<'tcx>> { | |||
&self.terminator |
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.
yea, seems fine to makeit private and create a BasicBlockData::new
function that takes all values needed to construct a BasicBlockData
self.terminator.as_mut().expect("invalid terminator state") | ||
} | ||
|
||
// This can be public since changing the kind will not break the predecessors cache in Body | ||
pub fn terminator_kind_mut(&mut self) -> &mut TerminatorKind<'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.
TerminatorKind
contains many BasicBlock
ids, and if you change them, the successors change
No description provided.