Skip to content

Commit cf0e78b

Browse files
committed
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.
1 parent 2e7034e commit cf0e78b

File tree

2 files changed

+49
-164
lines changed

2 files changed

+49
-164
lines changed

compiler/rustc_mir_dataflow/src/elaborate_drops.rs

+32-101
Original file line numberDiff line numberDiff line change
@@ -655,26 +655,20 @@ where
655655
///
656656
/// ```text
657657
/// loop-block:
658-
/// can_go = cur == length_or_end
658+
/// can_go = cur == len
659659
/// if can_go then succ else drop-block
660660
/// drop-block:
661-
/// if ptr_based {
662-
/// ptr = cur
663-
/// cur = cur.offset(1)
664-
/// } else {
665-
/// ptr = &raw mut P[cur]
666-
/// cur = cur + 1
667-
/// }
661+
/// ptr = &raw mut P[cur]
662+
/// cur = cur + 1
668663
/// drop(ptr)
669664
/// ```
670665
fn drop_loop(
671666
&mut self,
672667
succ: BasicBlock,
673668
cur: Local,
674-
length_or_end: Place<'tcx>,
669+
len: Local,
675670
ety: Ty<'tcx>,
676671
unwind: Unwind,
677-
ptr_based: bool,
678672
) -> BasicBlock {
679673
let copy = |place: Place<'tcx>| Operand::Copy(place);
680674
let move_ = |place: Place<'tcx>| Operand::Move(place);
@@ -683,22 +677,19 @@ where
683677
let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mut });
684678
let ptr = Place::from(self.new_temp(ptr_ty));
685679
let can_go = Place::from(self.new_temp(tcx.types.bool));
686-
687680
let one = self.constant_usize(1);
688-
let (ptr_next, cur_next) = if ptr_based {
689-
(
690-
Rvalue::Use(copy(cur.into())),
691-
Rvalue::BinaryOp(BinOp::Offset, Box::new((move_(cur.into()), one))),
692-
)
693-
} else {
694-
(
695-
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
696-
Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
697-
)
698-
};
699681

700682
let drop_block = BasicBlockData {
701-
statements: vec![self.assign(ptr, ptr_next), self.assign(Place::from(cur), cur_next)],
683+
statements: vec![
684+
self.assign(
685+
ptr,
686+
Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place, cur)),
687+
),
688+
self.assign(
689+
cur.into(),
690+
Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))),
691+
),
692+
],
702693
is_cleanup: unwind.is_cleanup(),
703694
terminator: Some(Terminator {
704695
source_info: self.source_info,
@@ -711,10 +702,7 @@ where
711702
let loop_block = BasicBlockData {
712703
statements: vec![self.assign(
713704
can_go,
714-
Rvalue::BinaryOp(
715-
BinOp::Eq,
716-
Box::new((copy(Place::from(cur)), copy(length_or_end))),
717-
),
705+
Rvalue::BinaryOp(BinOp::Eq, Box::new((copy(Place::from(cur)), copy(len.into())))),
718706
)],
719707
is_cleanup: unwind.is_cleanup(),
720708
terminator: Some(Terminator {
@@ -738,13 +726,6 @@ where
738726

739727
fn open_drop_for_array(&mut self, ety: Ty<'tcx>, opt_size: Option<u64>) -> BasicBlock {
740728
debug!("open_drop_for_array({:?}, {:?})", ety, opt_size);
741-
742-
// if size_of::<ety>() == 0 {
743-
// index_based_loop
744-
// } else {
745-
// ptr_based_loop
746-
// }
747-
748729
let tcx = self.tcx();
749730

750731
if let Some(size) = opt_size {
@@ -770,86 +751,36 @@ where
770751
}
771752
}
772753

773-
let move_ = |place: Place<'tcx>| Operand::Move(place);
774-
let elem_size = Place::from(self.new_temp(tcx.types.usize));
775-
let len = Place::from(self.new_temp(tcx.types.usize));
776-
777-
let base_block = BasicBlockData {
778-
statements: vec![
779-
self.assign(elem_size, Rvalue::NullaryOp(NullOp::SizeOf, ety)),
780-
self.assign(len, Rvalue::Len(self.place)),
781-
],
782-
is_cleanup: self.unwind.is_cleanup(),
783-
terminator: Some(Terminator {
784-
source_info: self.source_info,
785-
kind: TerminatorKind::SwitchInt {
786-
discr: move_(elem_size),
787-
targets: SwitchTargets::static_if(
788-
0,
789-
self.drop_loop_pair(ety, false, len),
790-
self.drop_loop_pair(ety, true, len),
791-
),
792-
},
793-
}),
794-
};
795-
self.elaborator.patch().new_block(base_block)
754+
self.drop_loop_pair(ety)
796755
}
797756

798757
/// Creates a pair of drop-loops of `place`, which drops its contents, even
799-
/// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
800-
/// otherwise create an index loop.
801-
fn drop_loop_pair(
802-
&mut self,
803-
ety: Ty<'tcx>,
804-
ptr_based: bool,
805-
length: Place<'tcx>,
806-
) -> BasicBlock {
807-
debug!("drop_loop_pair({:?}, {:?})", ety, ptr_based);
758+
/// in the case of 1 panic.
759+
fn drop_loop_pair(&mut self, ety: Ty<'tcx>) -> BasicBlock {
760+
debug!("drop_loop_pair({:?})", ety);
808761
let tcx = self.tcx();
809-
let iter_ty = if ptr_based { tcx.mk_mut_ptr(ety) } else { tcx.types.usize };
762+
let len = self.new_temp(tcx.types.usize);
763+
let cur = self.new_temp(tcx.types.usize);
810764

811-
let cur = self.new_temp(iter_ty);
812-
let length_or_end = if ptr_based { Place::from(self.new_temp(iter_ty)) } else { length };
765+
let unwind =
766+
self.unwind.map(|unwind| self.drop_loop(unwind, cur, len, ety, Unwind::InCleanup));
813767

814-
let unwind = self.unwind.map(|unwind| {
815-
self.drop_loop(unwind, cur, length_or_end, ety, Unwind::InCleanup, ptr_based)
816-
});
768+
let loop_block = self.drop_loop(self.succ, cur, len, ety, unwind);
817769

818-
let loop_block = self.drop_loop(self.succ, cur, length_or_end, ety, unwind, ptr_based);
819-
820-
let cur = Place::from(cur);
821-
let drop_block_stmts = if ptr_based {
822-
let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place));
823-
let tmp = Place::from(self.new_temp(tmp_ty));
824-
// tmp = &raw mut P;
825-
// cur = tmp as *mut T;
826-
// end = Offset(cur, len);
827-
let mir_cast_kind = ty::cast::mir_cast_kind(iter_ty, tmp_ty);
828-
vec![
829-
self.assign(tmp, Rvalue::AddressOf(Mutability::Mut, self.place)),
830-
self.assign(cur, Rvalue::Cast(mir_cast_kind, Operand::Move(tmp), iter_ty)),
831-
self.assign(
832-
length_or_end,
833-
Rvalue::BinaryOp(
834-
BinOp::Offset,
835-
Box::new((Operand::Copy(cur), Operand::Move(length))),
836-
),
837-
),
838-
]
839-
} else {
840-
// cur = 0 (length already pushed)
841-
let zero = self.constant_usize(0);
842-
vec![self.assign(cur, Rvalue::Use(zero))]
843-
};
844-
let drop_block = self.elaborator.patch().new_block(BasicBlockData {
845-
statements: drop_block_stmts,
770+
let zero = self.constant_usize(0);
771+
let block = BasicBlockData {
772+
statements: vec![
773+
self.assign(len.into(), Rvalue::Len(self.place)),
774+
self.assign(cur.into(), Rvalue::Use(zero)),
775+
],
846776
is_cleanup: unwind.is_cleanup(),
847777
terminator: Some(Terminator {
848778
source_info: self.source_info,
849779
kind: TerminatorKind::Goto { target: loop_block },
850780
}),
851-
});
781+
};
852782

783+
let drop_block = self.elaborator.patch().new_block(block);
853784
// FIXME(#34708): handle partially-dropped array/slice elements.
854785
let reset_block = self.drop_flag_reset_block(DropFlagMode::Deep, drop_block, unwind);
855786
self.drop_flag_test_block(reset_block, self.succ, unwind)

tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir

+17-63
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,13 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
44
let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
55
let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
66
let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
7-
let mut _4: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
8-
let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
9-
let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
10-
let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
11-
let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
12-
let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
13-
let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
14-
let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
15-
let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
16-
let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
17-
let mut _14: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
18-
let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
7+
let mut _4: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
8+
let mut _5: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
9+
let mut _6: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
10+
let mut _7: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
1911

2012
bb0: {
21-
goto -> bb15; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
13+
goto -> bb8; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
2214
}
2315

2416
bb1: {
@@ -30,72 +22,34 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
3022
}
3123

3224
bb3 (cleanup): {
33-
_5 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
34-
_4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
35-
drop((*_5)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
25+
_4 = &raw mut (*_1)[_3]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
26+
_3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
27+
drop((*_4)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
3628
}
3729

3830
bb4 (cleanup): {
39-
_6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
40-
switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
31+
_5 = Eq(_3, _2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
32+
switchInt(move _5) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
4133
}
4234

4335
bb5: {
44-
_7 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
45-
_4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
46-
drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
36+
_6 = &raw mut (*_1)[_3]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
37+
_3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
38+
drop((*_6)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
4739
}
4840

4941
bb6: {
50-
_8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
51-
switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
42+
_7 = Eq(_3, _2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
43+
switchInt(move _7) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
5244
}
5345

5446
bb7: {
55-
_4 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
47+
_2 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
48+
_3 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
5649
goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
5750
}
5851

5952
bb8: {
6053
goto -> bb7; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
6154
}
62-
63-
bb9 (cleanup): {
64-
_11 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
65-
_9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
66-
drop((*_11)) -> bb10; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
67-
}
68-
69-
bb10 (cleanup): {
70-
_12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
71-
switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
72-
}
73-
74-
bb11: {
75-
_13 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
76-
_9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
77-
drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
78-
}
79-
80-
bb12: {
81-
_14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
82-
switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
83-
}
84-
85-
bb13: {
86-
_15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
87-
_9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
88-
_10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
89-
goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
90-
}
91-
92-
bb14: {
93-
goto -> bb13; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
94-
}
95-
96-
bb15: {
97-
_2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
98-
_3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
99-
switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
100-
}
10155
}

0 commit comments

Comments
 (0)