Skip to content

Commit 06a53dd

Browse files
committed
Auto merge of #113758 - cjgillot:move-dse, r=JakobDegen,oli-obk
Turn copy into moves during DSE. Dead store elimination computes whether removing a direct store to an unborrowed place is allowed. Where removing a store is allowed, writing `uninit` is too. This means that we can use this pass to transform `copy` operands into `move` operands. This is only interesting in call terminators, so we only handle those. Special care is taken for the `use_both(_1, _1)` case: - moving the second argument is ok, as `_1` is not live after the call; - moving the first argument is not, as the second argument reads `_1`. Fixes #75993 Fixes #108068 r? `@RalfJung` cc `@JakobDegen`
2 parents 6b53175 + 254bf60 commit 06a53dd

File tree

32 files changed

+130
-31
lines changed

32 files changed

+130
-31
lines changed

Diff for: compiler/rustc_mir_dataflow/src/impls/liveness.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
8888
}
8989
}
9090

91-
struct TransferFunction<'a, T>(&'a mut T);
91+
pub struct TransferFunction<'a, T>(pub &'a mut T);
9292

9393
impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T>
9494
where

Diff for: compiler/rustc_mir_dataflow/src/impls/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub use self::borrowed_locals::borrowed_locals;
2626
pub use self::borrowed_locals::MaybeBorrowedLocals;
2727
pub use self::liveness::MaybeLiveLocals;
2828
pub use self::liveness::MaybeTransitiveLiveLocals;
29+
pub use self::liveness::TransferFunction as LivenessTransferFunction;
2930
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
3031

3132
/// `MaybeInitializedPlaces` tracks all places that might be

Diff for: compiler/rustc_mir_transform/src/dead_store_elimination.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
//!
1414
1515
use rustc_index::bit_set::BitSet;
16+
use rustc_middle::mir::visit::Visitor;
1617
use rustc_middle::mir::*;
1718
use rustc_middle::ty::TyCtxt;
18-
use rustc_mir_dataflow::impls::{borrowed_locals, MaybeTransitiveLiveLocals};
19+
use rustc_mir_dataflow::impls::{
20+
borrowed_locals, LivenessTransferFunction, MaybeTransitiveLiveLocals,
21+
};
1922
use rustc_mir_dataflow::Analysis;
2023

2124
/// Performs the optimization on the body
@@ -28,8 +31,33 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
2831
.iterate_to_fixpoint()
2932
.into_results_cursor(body);
3033

34+
// For blocks with a call terminator, if an argument copy can be turned into a move,
35+
// record it as (block, argument index).
36+
let mut call_operands_to_move = Vec::new();
3137
let mut patch = Vec::new();
38+
3239
for (bb, bb_data) in traversal::preorder(body) {
40+
if let TerminatorKind::Call { ref args, .. } = bb_data.terminator().kind {
41+
let loc = Location { block: bb, statement_index: bb_data.statements.len() };
42+
43+
// Position ourselves between the evaluation of `args` and the write to `destination`.
44+
live.seek_to_block_end(bb);
45+
let mut state = live.get().clone();
46+
47+
for (index, arg) in args.iter().enumerate().rev() {
48+
if let Operand::Copy(place) = *arg
49+
&& !place.is_indirect()
50+
&& !borrowed.contains(place.local)
51+
&& !state.contains(place.local)
52+
{
53+
call_operands_to_move.push((bb, index));
54+
}
55+
56+
// Account that `arg` is read from, so we don't promote another argument to a move.
57+
LivenessTransferFunction(&mut state).visit_operand(arg, loc);
58+
}
59+
}
60+
3361
for (statement_index, statement) in bb_data.statements.iter().enumerate().rev() {
3462
let loc = Location { block: bb, statement_index };
3563
if let StatementKind::Assign(assign) = &statement.kind {
@@ -64,14 +92,22 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
6492
}
6593
}
6694

67-
if patch.is_empty() {
95+
if patch.is_empty() && call_operands_to_move.is_empty() {
6896
return;
6997
}
7098

7199
let bbs = body.basic_blocks.as_mut_preserves_cfg();
72100
for Location { block, statement_index } in patch {
73101
bbs[block].statements[statement_index].make_nop();
74102
}
103+
for (block, argument_index) in call_operands_to_move {
104+
let TerminatorKind::Call { ref mut args, .. } = bbs[block].terminator_mut().kind else {
105+
bug!()
106+
};
107+
let arg = &mut args[argument_index];
108+
let Operand::Copy(place) = *arg else { bug!() };
109+
*arg = Operand::Move(place);
110+
}
75111

76112
crate::simplify::simplify_locals(body, tcx)
77113
}

Diff for: tests/codegen/iter-repeat-n-trivial-drop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop
3333

3434
// CHECK: [[EMPTY]]:
3535
// CHECK-NOT: br
36-
// CHECK: phi i16 [ %[[VAL]], %[[NOT_EMPTY]] ], [ undef, %start ]
36+
// CHECK: phi i16
3737
// CHECK-NOT: br
3838
// CHECK: ret
3939

Diff for: tests/codegen/move-operands.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// compile-flags: -C no-prepopulate-passes -Zmir-enable-passes=+DestinationPropagation,-CopyProp
1+
// Verify that optimized MIR only copies `a` once.
2+
// compile-flags: -O -C no-prepopulate-passes
23

34
#![crate_type = "lib"]
45

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
- // MIR for `move_simple` before DeadStoreElimination
2+
+ // MIR for `move_simple` after DeadStoreElimination
3+
4+
fn move_simple(_1: i32) -> () {
5+
debug x => _1;
6+
let mut _0: ();
7+
let _2: ();
8+
- let mut _3: i32;
9+
- let mut _4: i32;
10+
11+
bb0: {
12+
StorageLive(_2);
13+
- _2 = use_both(_1, _1) -> [return: bb1, unwind unreachable];
14+
+ _2 = use_both(_1, move _1) -> [return: bb1, unwind unreachable];
15+
}
16+
17+
bb1: {
18+
StorageDead(_2);
19+
_0 = const ();
20+
return;
21+
}
22+
}
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
- // MIR for `move_simple` before DeadStoreElimination
2+
+ // MIR for `move_simple` after DeadStoreElimination
3+
4+
fn move_simple(_1: i32) -> () {
5+
debug x => _1;
6+
let mut _0: ();
7+
let _2: ();
8+
- let mut _3: i32;
9+
- let mut _4: i32;
10+
11+
bb0: {
12+
StorageLive(_2);
13+
- _2 = use_both(_1, _1) -> [return: bb1, unwind continue];
14+
+ _2 = use_both(_1, move _1) -> [return: bb1, unwind continue];
15+
}
16+
17+
bb1: {
18+
StorageDead(_2);
19+
_0 = const ();
20+
return;
21+
}
22+
}
23+
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
2+
// unit-test: DeadStoreElimination
3+
// compile-flags: -Zmir-enable-passes=+CopyProp
4+
5+
#[inline(never)]
6+
fn use_both(_: i32, _: i32) {}
7+
8+
// EMIT_MIR call_arg_copy.move_simple.DeadStoreElimination.diff
9+
fn move_simple(x: i32) {
10+
use_both(x, x);
11+
}
12+
13+
fn main() {
14+
move_simple(1);
15+
}

Diff for: tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind unreachable];
3333
+ StorageLive(_5);
3434
+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize));
35-
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> [return: bb2, unwind unreachable];
35+
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _5) -> [return: bb2, unwind unreachable];
3636
}
3737

3838
bb2: {

Diff for: tests/mir-opt/inline/dyn_trait.get_query.Inline.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> [return: bb2, unwind continue];
3333
+ StorageLive(_5);
3434
+ _5 = _4 as &dyn Cache<V = <Q as Query>::V> (PointerCoercion(Unsize));
35-
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> [return: bb2, unwind continue];
35+
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _5) -> [return: bb2, unwind continue];
3636
}
3737

3838
bb2: {

Diff for: tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
_2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize));
1818
StorageDead(_3);
1919
- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind unreachable];
20-
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> [return: bb1, unwind unreachable];
20+
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _2) -> [return: bb1, unwind unreachable];
2121
}
2222

2323
bb1: {

Diff for: tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
_2 = move _3 as &dyn Cache<V = <C as Cache>::V> (PointerCoercion(Unsize));
1818
StorageDead(_3);
1919
- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> [return: bb1, unwind continue];
20-
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> [return: bb1, unwind continue];
20+
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _2) -> [return: bb1, unwind continue];
2121
}
2222

2323
bb1: {

Diff for: tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@
134134
+ StorageDead(_14);
135135
+ StorageLive(_9);
136136
+ _13 = const _;
137-
+ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb5, unwind unreachable];
137+
+ _9 = std::alloc::Global::alloc_impl(move _13, _8, const false) -> [return: bb5, unwind unreachable];
138138
}
139139

140140
bb1: {
@@ -144,7 +144,7 @@
144144
}
145145

146146
bb2: {
147-
+ _12 = handle_alloc_error(_8) -> unwind unreachable;
147+
+ _12 = handle_alloc_error(move _8) -> unwind unreachable;
148148
+ }
149149
+
150150
+ bb3: {

Diff for: tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@
134134
+ StorageDead(_14);
135135
+ StorageLive(_9);
136136
+ _13 = const _;
137-
+ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb7, unwind: bb3];
137+
+ _9 = std::alloc::Global::alloc_impl(move _13, _8, const false) -> [return: bb7, unwind: bb3];
138138
}
139139

140140
bb1: {
@@ -161,7 +161,7 @@
161161
- bb4 (cleanup): {
162162
- resume;
163163
+ bb4: {
164-
+ _12 = handle_alloc_error(_8) -> bb3;
164+
+ _12 = handle_alloc_error(move _8) -> bb3;
165165
+ }
166166
+
167167
+ bb5: {

Diff for: tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn test2(_1: &dyn X) -> bool {
1515
_3 = &(*_1);
1616
_2 = move _3 as &dyn X (PointerCoercion(Unsize));
1717
StorageDead(_3);
18-
_0 = <dyn X as X>::y(_2) -> [return: bb1, unwind unreachable];
18+
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind unreachable];
1919
}
2020

2121
bb1: {

Diff for: tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn test2(_1: &dyn X) -> bool {
1515
_3 = &(*_1);
1616
_2 = move _3 as &dyn X (PointerCoercion(Unsize));
1717
StorageDead(_3);
18-
_0 = <dyn X as X>::y(_2) -> [return: bb1, unwind continue];
18+
_0 = <dyn X as X>::y(move _2) -> [return: bb1, unwind continue];
1919
}
2020

2121
bb1: {

Diff for: tests/mir-opt/issue_101973.inner.ConstProp.panic-abort.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
bb2: {
6767
_6 = Shl(move _7, const 1_i32);
6868
StorageDead(_7);
69-
_3 = rotate_right::<u32>(_4, _6) -> [return: bb3, unwind unreachable];
69+
_3 = rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
7070
}
7171

7272
bb3: {

Diff for: tests/mir-opt/issue_101973.inner.ConstProp.panic-unwind.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
bb2: {
6767
_6 = Shl(move _7, const 1_i32);
6868
StorageDead(_7);
69-
_3 = rotate_right::<u32>(_4, _6) -> [return: bb3, unwind unreachable];
69+
_3 = rotate_right::<u32>(move _4, move _6) -> [return: bb3, unwind unreachable];
7070
}
7171

7272
bb3: {

Diff for: tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn num_to_digit(_1: char) -> u32 {
3535

3636
bb2: {
3737
StorageLive(_4);
38-
_4 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb3, unwind unreachable];
38+
_4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
3939
}
4040

4141
bb3: {

Diff for: tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn num_to_digit(_1: char) -> u32 {
3535

3636
bb2: {
3737
StorageLive(_4);
38-
_4 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb3, unwind continue];
38+
_4 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue];
3939
}
4040

4141
bb3: {

Diff for: tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
4646
StorageDead(_4);
4747
_6 = Ge(_2, const _);
4848
StorageLive(_7);
49-
_7 = unlikely(_6) -> [return: bb1, unwind unreachable];
49+
_7 = unlikely(move _6) -> [return: bb1, unwind unreachable];
5050
}
5151

5252
bb1: {

Diff for: tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn int_range(_1: usize, _2: usize) -> () {
8888

8989
bb7: {
9090
_10 = ((_6 as Some).0: usize);
91-
_11 = opaque::<usize>(_10) -> [return: bb8, unwind continue];
91+
_11 = opaque::<usize>(move _10) -> [return: bb8, unwind continue];
9292
}
9393

9494
bb8: {

Diff for: tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
4242
StorageLive(_7);
4343
StorageLive(_6);
4444
_6 = &mut _5;
45-
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_6) -> [return: bb2, unwind unreachable];
45+
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
4646
}
4747

4848
bb2: {

Diff for: tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
4242
StorageLive(_7);
4343
StorageLive(_6);
4444
_6 = &mut _5;
45-
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_6) -> [return: bb2, unwind: bb8];
45+
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
4646
}
4747

4848
bb2: {

Diff for: tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
88
}
99

1010
bb0: {
11-
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_1) -> [return: bb1, unwind unreachable];
11+
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
1212
}
1313

1414
bb1: {

Diff for: tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
88
}
99

1010
bb0: {
11-
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(_1) -> [return: bb1, unwind continue];
11+
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
1212
}
1313

1414
bb1: {

Diff for: tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
1212

1313
bb0: {
1414
StorageLive(_3);
15-
_3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> [return: bb1, unwind unreachable];
15+
_3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, move _1) -> [return: bb1, unwind unreachable];
1616
}
1717

1818
bb1: {

Diff for: tests/mir-opt/pre-codegen/slice_index.slice_index_range.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
1212

1313
bb0: {
1414
StorageLive(_3);
15-
_3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, _1) -> [return: bb1, unwind continue];
15+
_3 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, move _1) -> [return: bb1, unwind continue];
1616
}
1717

1818
bb1: {

Diff for: tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut
55
let mut _0: std::option::Option<&mut T>;
66

77
bb0: {
8-
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(_1) -> [return: bb1, unwind unreachable];
8+
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind unreachable];
99
}
1010

1111
bb1: {

Diff for: tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut
55
let mut _0: std::option::Option<&mut T>;
66

77
bb0: {
8-
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(_1) -> [return: bb1, unwind continue];
8+
_0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind continue];
99
}
1010

1111
bb1: {

Diff for: tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> {
55
let mut _0: std::option::Option<&T>;
66

77
bb0: {
8-
_0 = <std::slice::Iter<'_, T> as Iterator>::next(_1) -> [return: bb1, unwind unreachable];
8+
_0 = <std::slice::Iter<'_, T> as Iterator>::next(move _1) -> [return: bb1, unwind unreachable];
99
}
1010

1111
bb1: {

0 commit comments

Comments
 (0)