Skip to content

Commit 0e9eee6

Browse files
committed
Auto merge of #96451 - JakobDegen:dest-prop, r=tmiasko
Fix Dest Prop Closes #82678, #79191 . This was not originally a total re-write of the pass but is has gradually turned into one. Notable changes: 1. Significant improvements to documentation all around. The top of the file has been extended with a more precise argument for soundness. The code should be fairly readable, and I've done my best to add useful comments wherever possible. I would very much like for the bus factor to not be one on this code. 3. Improved handling of conflicts that are not visible in normal dataflow. This was the cause of #79191. Handling this correctly requires us to make decision about the semantics and specifically evaluation order of basically all MIR constructs (see specifically #68364 #71117. The way this is implemented is based on my preferred resolution to these questions around the semantics of assignment statements. 4. Some re-architecting to improve performance. More details below. 5. Possible future improvements to this optimization are documented, and the code is written with the needs of those improvements in mind. The hope is that adding support for more precise analyses will not require a full re-write of this opt, but just localized changes. ### Regarding Performance The previous approach had some performance issues; letting `l` be the number of locals and `s` be the number of statements/terminators, the runtime of the pass was `O(l^2 * s)`, both in theory and in practice. This version is smarter about not calculating unnecessary things and doing more caching. Our runtime is now dominated by one invocation of `MaybeLiveLocals` for each "round," and the number of rounds is less than 5 in over 90% of cases. This means it's linear-ish in practice. r? `@oli-obk` who reviewed the last version of this, but review from anyone else would be more than welcome
2 parents faf1891 + 245c607 commit 0e9eee6

File tree

40 files changed

+1039
-1224
lines changed

40 files changed

+1039
-1224
lines changed

compiler/rustc_mir_dataflow/src/impls/init_locals.rs

-122
This file was deleted.

compiler/rustc_mir_dataflow/src/impls/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ use crate::{drop_flag_effects, on_all_children_bits};
1919
use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis};
2020

2121
mod borrowed_locals;
22-
mod init_locals;
2322
mod liveness;
2423
mod storage_liveness;
2524

2625
pub use self::borrowed_locals::borrowed_locals;
2726
pub use self::borrowed_locals::MaybeBorrowedLocals;
28-
pub use self::init_locals::MaybeInitializedLocals;
2927
pub use self::liveness::MaybeLiveLocals;
3028
pub use self::liveness::MaybeTransitiveLiveLocals;
3129
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};

compiler/rustc_mir_transform/src/dead_store_elimination.rs

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
7070
for Location { block, statement_index } in patch {
7171
bbs[block].statements[statement_index].make_nop();
7272
}
73+
74+
crate::simplify::SimplifyLocals.run_pass(tcx, body)
7375
}
7476

7577
pub struct DeadStoreElimination;

compiler/rustc_mir_transform/src/deduce_param_attrs.rs

+10-38
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,16 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
110110

111111
if let TerminatorKind::Call { ref args, .. } = terminator.kind {
112112
for arg in args {
113-
if let Operand::Move(_) = *arg {
114-
// ArgumentChecker panics if a direct move of an argument from a caller to a
115-
// callee was detected.
116-
//
117-
// If, in the future, MIR optimizations cause arguments to be moved directly
118-
// from callers to callees, change the panic to instead add the argument in
119-
// question to `mutating_uses`.
120-
ArgumentChecker::new(self.mutable_args.domain_size())
121-
.visit_operand(arg, location)
113+
if let Operand::Move(place) = *arg {
114+
let local = place.local;
115+
if place.is_indirect()
116+
|| local == RETURN_PLACE
117+
|| local.index() > self.mutable_args.domain_size()
118+
{
119+
continue;
120+
}
121+
122+
self.mutable_args.insert(local.index() - 1);
122123
}
123124
}
124125
};
@@ -127,35 +128,6 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
127128
}
128129
}
129130

130-
/// A visitor that simply panics if a direct move of an argument from a caller to a callee was
131-
/// detected.
132-
struct ArgumentChecker {
133-
/// The number of arguments to the calling function.
134-
arg_count: usize,
135-
}
136-
137-
impl ArgumentChecker {
138-
/// Creates a new ArgumentChecker.
139-
fn new(arg_count: usize) -> Self {
140-
Self { arg_count }
141-
}
142-
}
143-
144-
impl<'tcx> Visitor<'tcx> for ArgumentChecker {
145-
fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
146-
// Check to make sure that, if this local is an argument, we didn't move directly from it.
147-
if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move))
148-
&& local != RETURN_PLACE
149-
&& local.index() <= self.arg_count
150-
{
151-
// If, in the future, MIR optimizations cause arguments to be moved directly from
152-
// callers to callees, change this panic to instead add the argument in question to
153-
// `mutating_uses`.
154-
panic!("Detected a direct move from a caller's argument to a callee's argument!")
155-
}
156-
}
157-
}
158-
159131
/// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
160132
fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
161133
matches!(

0 commit comments

Comments
 (0)