Use index based drop loop for slices and arrays
Instead of building two kinds of drop pair loops, of which only one will be eventually used at runtime in a given monomorphization, always use index based loop.
This commit is contained in:
parent
2e7034ebf7
commit
cf0e78bd3b
@ -655,26 +655,20 @@ where
|
||||
///
|
||||
/// ```text
|
||||
/// loop-block:
|
||||
/// can_go = cur == length_or_end
|
||||
/// can_go = cur == len
|
||||
/// if can_go then succ else drop-block
|
||||
/// drop-block:
|
||||
/// if ptr_based {
|
||||
/// ptr = cur
|
||||
/// cur = cur.offset(1)
|
||||
/// } else {
|
||||
/// ptr = &raw mut P[cur]
|
||||
/// cur = cur + 1
|
||||
/// }
|
||||
/// ptr = &raw mut P[cur]
|
||||
/// cur = cur + 1
|
||||
/// drop(ptr)
|
||||
/// ```
|
||||
fn drop_loop(
|
||||
&mut self,
|
||||
succ: BasicBlock,
|
||||
cur: Local,
|
||||
length_or_end: Place<'tcx>,
|
||||
len: Local,
|
||||
ety: Ty<'tcx>,
|
||||
unwind: Unwind,
|
||||
ptr_based: bool,
|
||||
) -> BasicBlock {
|
||||
let copy = |place: Place<'tcx>| Operand::Copy(place);
|
||||
let move_ = |place: Place<'tcx>| Operand::Move(place);
|
||||
@ -683,22 +677,19 @@ where
|
||||
let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut });
|
||||
let ptr = Place::from(self.new_temp(ptr_ty));
|
||||
let can_go = Place::from(self.new_temp(tcx.types.bool));
|
||||
|
||||
let one = self.constant_usize(1);
|
||||
let (ptr_next, cur_next) = if ptr_based {
|
||||
(
|
||||
Rvalue::Use(copy(cur.into())),
|
||||
Rvalue::BinaryOp(BinOp::Offset, Box::new((move_(cur.into()), one))),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
|
||||
Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
|
||||
)
|
||||
};
|
||||
|
||||
let drop_block = BasicBlockData {
|
||||
statements: vec![self.assign(ptr, ptr_next), self.assign(Place::from(cur), cur_next)],
|
||||
statements: vec![
|
||||
self.assign(
|
||||
ptr,
|
||||
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
|
||||
),
|
||||
self.assign(
|
||||
cur.into(),
|
||||
Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
|
||||
),
|
||||
],
|
||||
is_cleanup: unwind.is_cleanup(),
|
||||
terminator: Some(Terminator {
|
||||
source_info: self.source_info,
|
||||
@ -711,10 +702,7 @@ where
|
||||
let loop_block = BasicBlockData {
|
||||
statements: vec![self.assign(
|
||||
can_go,
|
||||
Rvalue::BinaryOp(
|
||||
BinOp::Eq,
|
||||
Box::new((copy(Place::from(cur)), copy(length_or_end))),
|
||||
),
|
||||
Rvalue::BinaryOp(BinOp::Eq, Box::new((copy(Place::from(cur)), copy(len.into())))),
|
||||
)],
|
||||
is_cleanup: unwind.is_cleanup(),
|
||||
terminator: Some(Terminator {
|
||||
@ -738,13 +726,6 @@ where
|
||||
|
||||
fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock {
|
||||
debug!("open_drop_for_array({:?}, {:?})", ety, opt_size);
|
||||
|
||||
// if size_of::<ety>() == 0 {
|
||||
// index_based_loop
|
||||
// } else {
|
||||
// ptr_based_loop
|
||||
// }
|
||||
|
||||
let tcx = self.tcx();
|
||||
|
||||
if let Some(size) = opt_size {
|
||||
@ -770,86 +751,36 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
let move_ = |place: Place<'tcx>| Operand::Move(place);
|
||||
let elem_size = Place::from(self.new_temp(tcx.types.usize));
|
||||
let len = Place::from(self.new_temp(tcx.types.usize));
|
||||
|
||||
let base_block = BasicBlockData {
|
||||
statements: vec![
|
||||
self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
|
||||
self.assign(len, Rvalue::Len(self.place)),
|
||||
],
|
||||
is_cleanup: self.unwind.is_cleanup(),
|
||||
terminator: Some(Terminator {
|
||||
source_info: self.source_info,
|
||||
kind: TerminatorKind::SwitchInt {
|
||||
discr: move_(elem_size),
|
||||
targets: SwitchTargets::static_if(
|
||||
0,
|
||||
self.drop_loop_pair(ety, false, len),
|
||||
self.drop_loop_pair(ety, true, len),
|
||||
),
|
||||
},
|
||||
}),
|
||||
};
|
||||
self.elaborator.patch().new_block(base_block)
|
||||
self.drop_loop_pair(ety)
|
||||
}
|
||||
|
||||
/// Creates a pair of drop-loops of `place`, which drops its contents, even
|
||||
/// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
|
||||
/// otherwise create an index loop.
|
||||
fn drop_loop_pair(
|
||||
&mut self,
|
||||
ety: Ty<'tcx>,
|
||||
ptr_based: bool,
|
||||
length: Place<'tcx>,
|
||||
) -> BasicBlock {
|
||||
debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based);
|
||||
/// in the case of 1 panic.
|
||||
fn drop_loop_pair(&mut self, ety: Ty<'tcx>) -> BasicBlock {
|
||||
debug!("drop_loop_pair({:?})", ety);
|
||||
let tcx = self.tcx();
|
||||
let iter_ty = if ptr_based { tcx.mk_mut_ptr(ety) } else { tcx.types.usize };
|
||||
let len = self.new_temp(tcx.types.usize);
|
||||
let cur = self.new_temp(tcx.types.usize);
|
||||
|
||||
let cur = self.new_temp(iter_ty);
|
||||
let length_or_end = if ptr_based { Place::from(self.new_temp(iter_ty)) } else { length };
|
||||
let unwind =
|
||||
self.unwind.map(|unwind| self.drop_loop(unwind, cur, len, ety, Unwind::InCleanup));
|
||||
|
||||
let unwind = self.unwind.map(|unwind| {
|
||||
self.drop_loop(unwind, cur, length_or_end, ety, Unwind::InCleanup, ptr_based)
|
||||
});
|
||||
let loop_block = self.drop_loop(self.succ, cur, len, ety, unwind);
|
||||
|
||||
let loop_block = self.drop_loop(self.succ, cur, length_or_end, ety, unwind, ptr_based);
|
||||
|
||||
let cur = Place::from(cur);
|
||||
let drop_block_stmts = if ptr_based {
|
||||
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
|
||||
let tmp = Place::from(self.new_temp(tmp_ty));
|
||||
// tmp = &raw mut P;
|
||||
// cur = tmp as *mut T;
|
||||
// end = Offset(cur, len);
|
||||
let mir_cast_kind = ty::cast::mir_cast_kind(iter_ty, tmp_ty);
|
||||
vec![
|
||||
self.assign(tmp, Rvalue::AddressOf(Mutability::Mut, self.place)),
|
||||
self.assign(cur, Rvalue::Cast(mir_cast_kind, Operand::Move(tmp), iter_ty)),
|
||||
self.assign(
|
||||
length_or_end,
|
||||
Rvalue::BinaryOp(
|
||||
BinOp::Offset,
|
||||
Box::new((Operand::Copy(cur), Operand::Move(length))),
|
||||
),
|
||||
),
|
||||
]
|
||||
} else {
|
||||
// cur = 0 (length already pushed)
|
||||
let zero = self.constant_usize(0);
|
||||
vec![self.assign(cur, Rvalue::Use(zero))]
|
||||
};
|
||||
let drop_block = self.elaborator.patch().new_block(BasicBlockData {
|
||||
statements: drop_block_stmts,
|
||||
let zero = self.constant_usize(0);
|
||||
let block = BasicBlockData {
|
||||
statements: vec![
|
||||
self.assign(len.into(), Rvalue::Len(self.place)),
|
||||
self.assign(cur.into(), Rvalue::Use(zero)),
|
||||
],
|
||||
is_cleanup: unwind.is_cleanup(),
|
||||
terminator: Some(Terminator {
|
||||
source_info: self.source_info,
|
||||
kind: TerminatorKind::Goto { target: loop_block },
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
let drop_block = self.elaborator.patch().new_block(block);
|
||||
// FIXME(#34708): handle partially-dropped array/slice elements.
|
||||
let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind);
|
||||
self.drop_flag_test_block(reset_block, self.succ, unwind)
|
||||
|
@ -4,21 +4,13 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
|
||||
let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _4: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _14: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _4: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _5: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _6: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _7: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
|
||||
bb0: {
|
||||
goto -> bb15; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
goto -> bb8; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -30,72 +22,34 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
|
||||
}
|
||||
|
||||
bb3 (cleanup): {
|
||||
_5 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_5)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_4 = &raw mut (*_1)[_3]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_4)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb4 (cleanup): {
|
||||
_6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_5 = Eq(_3, _2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _5) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_7 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_6 = &raw mut (*_1)[_3]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_6)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb6: {
|
||||
_8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_7 = Eq(_3, _2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _7) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb7: {
|
||||
_4 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_2 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb7; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb9 (cleanup): {
|
||||
_11 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_11)) -> bb10; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb10 (cleanup): {
|
||||
_12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb11: {
|
||||
_13 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb12: {
|
||||
_14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb13: {
|
||||
_15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb14: {
|
||||
goto -> bb13; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
|
||||
bb15: {
|
||||
_2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user