Auto merge of #109008 - clubby789:drop-elaborate-array, r=davidtwco
Drop array patterns using subslices Fixes #109004 Drops contiguous subslices of an array when moving elements out with a pattern, which improves perf for large arrays r? `@compiler-errors`
This commit is contained in:
commit
a5a690cf4b
2 changed files with 70 additions and 18 deletions
|
@ -729,23 +729,59 @@ where
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
if let Some(size) = opt_size {
|
if let Some(size) = opt_size {
|
||||||
let fields: Vec<(Place<'tcx>, Option<D::Path>)> = (0..size)
|
enum ProjectionKind<Path> {
|
||||||
.map(|i| {
|
Drop(std::ops::Range<u64>),
|
||||||
(
|
Keep(u64, Path),
|
||||||
tcx.mk_place_elem(
|
}
|
||||||
self.place,
|
// Previously, we'd make a projection for every element in the array and create a drop
|
||||||
ProjectionElem::ConstantIndex {
|
// ladder if any `array_subpath` was `Some`, i.e. moving out with an array pattern.
|
||||||
offset: i,
|
// This caused huge memory usage when generating the drops for large arrays, so we instead
|
||||||
min_length: size,
|
// record the *subslices* which are dropped and the *indexes* which are kept
|
||||||
from_end: false,
|
let mut drop_ranges = vec![];
|
||||||
},
|
let mut dropping = true;
|
||||||
),
|
let mut start = 0;
|
||||||
self.elaborator.array_subpath(self.path, i, size),
|
for i in 0..size {
|
||||||
)
|
let path = self.elaborator.array_subpath(self.path, i, size);
|
||||||
})
|
if dropping && path.is_some() {
|
||||||
.collect();
|
drop_ranges.push(ProjectionKind::Drop(start..i));
|
||||||
|
dropping = false;
|
||||||
if fields.iter().any(|(_, path)| path.is_some()) {
|
} else if !dropping && path.is_none() {
|
||||||
|
dropping = true;
|
||||||
|
start = i;
|
||||||
|
}
|
||||||
|
if let Some(path) = path {
|
||||||
|
drop_ranges.push(ProjectionKind::Keep(i, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !drop_ranges.is_empty() {
|
||||||
|
if dropping {
|
||||||
|
drop_ranges.push(ProjectionKind::Drop(start..size));
|
||||||
|
}
|
||||||
|
let fields = drop_ranges
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.map(|p| {
|
||||||
|
let (project, path) = match p {
|
||||||
|
ProjectionKind::Drop(r) => (
|
||||||
|
ProjectionElem::Subslice {
|
||||||
|
from: r.start,
|
||||||
|
to: r.end,
|
||||||
|
from_end: false,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
&ProjectionKind::Keep(offset, path) => (
|
||||||
|
ProjectionElem::ConstantIndex {
|
||||||
|
offset,
|
||||||
|
min_length: size,
|
||||||
|
from_end: false,
|
||||||
|
},
|
||||||
|
Some(path),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
(tcx.mk_place_elem(self.place, project), path)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let (succ, unwind) = self.drop_ladder_bottom();
|
let (succ, unwind) = self.drop_ladder_bottom();
|
||||||
return self.drop_ladder(fields, succ, unwind).0;
|
return self.drop_ladder(fields, succ, unwind).0;
|
||||||
}
|
}
|
||||||
|
@ -824,7 +860,7 @@ where
|
||||||
let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
|
let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
|
||||||
self.open_drop_for_array(*ety, size)
|
self.open_drop_for_array(*ety, size)
|
||||||
}
|
}
|
||||||
ty::Slice(ety) => self.open_drop_for_array(*ety, None),
|
ty::Slice(ety) => self.drop_loop_pair(*ety),
|
||||||
|
|
||||||
_ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
|
_ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
|
||||||
}
|
}
|
||||||
|
|
16
tests/ui/mir/issue-109004-drop-large-array.rs
Normal file
16
tests/ui/mir/issue-109004-drop-large-array.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
const SZ: usize = 64_000_000;
|
||||||
|
type BigDrop = [String; SZ];
|
||||||
|
|
||||||
|
fn f(_dropme: BigDrop) {}
|
||||||
|
|
||||||
|
fn f2(_moveme: BigDrop) -> String {
|
||||||
|
let [a, ..] = _moveme;
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f(std::array::from_fn(|_| String::new()));
|
||||||
|
f2(std::array::from_fn(|_| String::new()));
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue