Skip to content

Commit

Permalink
Auto merge of #109085 - tmiasko:index-based, r=WaffleLapkin
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Mar 17, 2023
2 parents 511364e + cf0e78b commit 2d64f22
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 164 deletions.
133 changes: 32 additions & 101 deletions compiler/rustc_mir_dataflow/src/elaborate_drops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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
}
}

0 comments on commit 2d64f22

Please sign in to comment.