Rewrite dest prop.
This fixes a number of correctness issues from the previous version. Additionally, we use a new strategy which has much better performance charactersitics and also finds more opportunities to apply the optimization.
This commit is contained in:
parent
80a96467ec
commit
245c60749a
40 changed files with 1046 additions and 1231 deletions
|
@ -70,6 +70,8 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
|
|||
for Location { block, statement_index } in patch {
|
||||
bbs[block].statements[statement_index].make_nop();
|
||||
}
|
||||
|
||||
crate::simplify::SimplifyLocals.run_pass(tcx, body)
|
||||
}
|
||||
|
||||
pub struct DeadStoreElimination;
|
||||
|
|
|
@ -110,15 +110,16 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
|
|||
|
||||
if let TerminatorKind::Call { ref args, .. } = terminator.kind {
|
||||
for arg in args {
|
||||
if let Operand::Move(_) = *arg {
|
||||
// ArgumentChecker panics if a direct move of an argument from a caller to a
|
||||
// callee was detected.
|
||||
//
|
||||
// If, in the future, MIR optimizations cause arguments to be moved directly
|
||||
// from callers to callees, change the panic to instead add the argument in
|
||||
// question to `mutating_uses`.
|
||||
ArgumentChecker::new(self.mutable_args.domain_size())
|
||||
.visit_operand(arg, location)
|
||||
if let Operand::Move(place) = *arg {
|
||||
let local = place.local;
|
||||
if place.is_indirect()
|
||||
|| local == RETURN_PLACE
|
||||
|| local.index() > self.mutable_args.domain_size()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
self.mutable_args.insert(local.index() - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -127,35 +128,6 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
|
|||
}
|
||||
}
|
||||
|
||||
/// A visitor that simply panics if a direct move of an argument from a caller to a callee was
|
||||
/// detected.
|
||||
struct ArgumentChecker {
|
||||
/// The number of arguments to the calling function.
|
||||
arg_count: usize,
|
||||
}
|
||||
|
||||
impl ArgumentChecker {
|
||||
/// Creates a new ArgumentChecker.
|
||||
fn new(arg_count: usize) -> Self {
|
||||
Self { arg_count }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ArgumentChecker {
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
|
||||
// Check to make sure that, if this local is an argument, we didn't move directly from it.
|
||||
if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move))
|
||||
&& local != RETURN_PLACE
|
||||
&& local.index() <= self.arg_count
|
||||
{
|
||||
// If, in the future, MIR optimizations cause arguments to be moved directly from
|
||||
// callers to callees, change this panic to instead add the argument in question to
|
||||
// `mutating_uses`.
|
||||
panic!("Detected a direct move from a caller's argument to a callee's argument!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
|
||||
fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
|
||||
matches!(
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue