Skip to content

Commit be3cc06

Browse files
committedMar 9, 2020
Auto merge of #69756 - wesleywiser:simplify_try, r=<try>
[WIP] Modify SimplifyArmIdentity so it can trigger on mir-opt-level=1 r? @ghost
2 parents 2cb0b85 + f0d5e44 commit be3cc06

File tree

5 files changed

+719
-80
lines changed

5 files changed

+719
-80
lines changed
 

‎src/librustc_mir/transform/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,12 @@ fn run_optimization_passes<'tcx>(
311311
&const_prop::ConstProp,
312312
&simplify_branches::SimplifyBranches::new("after-const-prop"),
313313
&deaggregator::Deaggregator,
314+
&simplify_try::SimplifyArmIdentity,
315+
&simplify_try::SimplifyBranchSame,
314316
&copy_prop::CopyPropagation,
315317
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
316318
&remove_noop_landing_pads::RemoveNoopLandingPads,
317319
&simplify::SimplifyCfg::new("after-remove-noop-landing-pads"),
318-
&simplify_try::SimplifyArmIdentity,
319-
&simplify_try::SimplifyBranchSame,
320320
&simplify::SimplifyCfg::new("final"),
321321
&simplify::SimplifyLocals,
322322
&add_call_guards::CriticalCallEdges,

‎src/librustc_mir/transform/simplify_try.rs

+244-39
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,19 @@ use crate::transform::{simplify, MirPass, MirSource};
1313
use itertools::Itertools as _;
1414
use rustc::mir::*;
1515
use rustc::ty::{Ty, TyCtxt};
16+
use rustc_index::vec::IndexVec;
1617
use rustc_target::abi::VariantIdx;
18+
use std::iter::{Enumerate, Peekable};
19+
use std::slice::Iter;
1720

1821
/// Simplifies arms of form `Variant(x) => Variant(x)` to just a move.
1922
///
2023
/// This is done by transforming basic blocks where the statements match:
2124
///
2225
/// ```rust
2326
/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
24-
/// ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP;
27+
/// _TMP_2 = _LOCAL_TMP;
28+
/// ((_LOCAL_0 as Variant).FIELD: TY) = move _TMP_2;
2529
/// discriminant(_LOCAL_0) = VAR_IDX;
2630
/// ```
2731
///
@@ -32,50 +36,251 @@ use rustc_target::abi::VariantIdx;
3236
/// ```
3337
pub struct SimplifyArmIdentity;
3438

39+
#[derive(Debug)]
40+
struct ArmIdentityInfo<'tcx> {
41+
/// Storage location for the variant's field
42+
local_temp_0: Local,
43+
/// Storage location holding the varient being read from
44+
local_1: Local,
45+
/// The varient field being read from
46+
vf_s0: VarField<'tcx>,
47+
48+
/// Tracks each assignment to a temporary of the varient's field
49+
field_tmp_assignments: Vec<(Local, Local)>,
50+
51+
/// Storage location holding the variant's field that was read from
52+
local_tmp_s1: Local,
53+
/// Storage location holding the enum that we are writing to
54+
local_0: Local,
55+
/// The varient field being written to
56+
vf_s1: VarField<'tcx>,
57+
58+
/// Storage location that the discrimentant is being set to
59+
set_discr_local: Local,
60+
/// The variant being written
61+
set_discr_var_idx: VariantIdx,
62+
63+
/// Index of the statement that should be overwritten as a move
64+
stmt_to_overwrite: usize,
65+
/// SourceInfo for the new move
66+
source_info: SourceInfo,
67+
68+
/// Indexes of matching Storage{Live,Dead} statements encountered.
69+
/// (StorageLive index,, StorageDead index, Local)
70+
storage_stmts: Vec<(usize, usize, Local)>,
71+
72+
/// The statements that should be removed (turned into nops)
73+
stmts_to_remove: Vec<usize>,
74+
}
75+
76+
fn get_arm_identity_info<'a, 'tcx>(stmts: &'a [Statement<'tcx>]) -> Option<ArmIdentityInfo<'tcx>> {
77+
let mut tmp_assigns = Vec::new();
78+
let mut nop_stmts = Vec::new();
79+
let mut storage_stmts = Vec::new();
80+
let mut storage_live_stmts = Vec::new();
81+
let mut storage_dead_stmts = Vec::new();
82+
83+
type StmtIter<'a, 'tcx> = Peekable<Enumerate<Iter<'a, Statement<'tcx>>>>;
84+
85+
fn is_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool {
86+
matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_))
87+
}
88+
89+
fn try_eat_storage_stmts<'a, 'tcx>(
90+
stmt_iter: &mut StmtIter<'a, 'tcx>,
91+
storage_live_stmts: &mut Vec<(usize, Local)>,
92+
storage_dead_stmts: &mut Vec<(usize, Local)>,
93+
) {
94+
while stmt_iter.peek().map(|(_, stmt)| is_storage_stmt(stmt)).unwrap_or(false) {
95+
let (idx, stmt) = stmt_iter.next().unwrap();
96+
97+
if let StatementKind::StorageLive(l) = stmt.kind {
98+
storage_live_stmts.push((idx, l));
99+
} else if let StatementKind::StorageDead(l) = stmt.kind {
100+
storage_dead_stmts.push((idx, l));
101+
}
102+
}
103+
}
104+
105+
fn is_tmp_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool {
106+
if let StatementKind::Assign(box (place, Rvalue::Use(op))) = &stmt.kind {
107+
if let Operand::Copy(p) | Operand::Move(p) = op {
108+
return place.as_local().is_some() && p.as_local().is_some();
109+
}
110+
}
111+
112+
false
113+
}
114+
115+
fn try_eat_assign_tmp_stmts<'a, 'tcx>(
116+
stmt_iter: &mut StmtIter<'a, 'tcx>,
117+
tmp_assigns: &mut Vec<(Local, Local)>,
118+
nop_stmts: &mut Vec<usize>,
119+
) {
120+
while stmt_iter.peek().map(|(_, stmt)| is_tmp_storage_stmt(stmt)).unwrap_or(false) {
121+
let (idx, stmt) = stmt_iter.next().unwrap();
122+
123+
if let StatementKind::Assign(box (place, Rvalue::Use(op))) = &stmt.kind {
124+
if let Operand::Copy(p) | Operand::Move(p) = op {
125+
tmp_assigns.push((place.as_local().unwrap(), p.as_local().unwrap()));
126+
nop_stmts.push(idx);
127+
}
128+
}
129+
}
130+
}
131+
132+
let mut stmt_iter = stmts.iter().enumerate().peekable();
133+
134+
try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
135+
136+
let (starting_stmt, stmt) = stmt_iter.next()?;
137+
let (local_tmp_s0, local_1, vf_s0) = match_get_variant_field(stmt)?;
138+
139+
try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
140+
141+
try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts);
142+
143+
try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
144+
145+
try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts);
146+
147+
let (idx, stmt) = stmt_iter.next()?;
148+
let (local_tmp_s1, local_0, vf_s1) = match_set_variant_field(stmt)?;
149+
nop_stmts.push(idx);
150+
151+
let (idx, stmt) = stmt_iter.next()?;
152+
let (set_discr_local, set_discr_var_idx) = match_set_discr(stmt)?;
153+
let discr_stmt_source_info = stmt.source_info;
154+
nop_stmts.push(idx);
155+
156+
try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts);
157+
158+
for (live_idx, live_local) in storage_live_stmts {
159+
if let Some(i) = storage_dead_stmts.iter().rposition(|(_, l)| *l == live_local) {
160+
let (dead_idx, _) = storage_dead_stmts.swap_remove(i);
161+
storage_stmts.push((live_idx, dead_idx, live_local));
162+
}
163+
}
164+
165+
Some(ArmIdentityInfo {
166+
local_temp_0: local_tmp_s0,
167+
local_1,
168+
vf_s0,
169+
field_tmp_assignments: tmp_assigns,
170+
local_tmp_s1,
171+
local_0,
172+
vf_s1,
173+
set_discr_local,
174+
set_discr_var_idx,
175+
stmt_to_overwrite: starting_stmt,
176+
source_info: discr_stmt_source_info,
177+
storage_stmts,
178+
stmts_to_remove: nop_stmts,
179+
})
180+
}
181+
182+
fn optimization_applies<'tcx>(
183+
opt_info: &ArmIdentityInfo<'tcx>,
184+
local_decls: &IndexVec<Local, LocalDecl<'tcx>>,
185+
) -> bool {
186+
trace!("testing if optimization applies...");
187+
188+
if opt_info.local_0 == opt_info.local_1 {
189+
trace!("NO: moving into ourselves");
190+
return false;
191+
} else if opt_info.vf_s0 != opt_info.vf_s1 {
192+
trace!("NO: the field-and-variant information do not match");
193+
return false;
194+
} else if local_decls[opt_info.local_0].ty != local_decls[opt_info.local_1].ty {
195+
// FIXME(Centril,oli-obk): possibly relax ot same layout?
196+
trace!("NO: source and target locals have different types");
197+
return false;
198+
} else if (opt_info.local_0, opt_info.vf_s0.var_idx)
199+
!= (opt_info.set_discr_local, opt_info.set_discr_var_idx)
200+
{
201+
trace!("NO: the discriminants do not match");
202+
return false;
203+
}
204+
205+
// Verify the assigment chain consists of the form b = a; c = b; d = c; etc...
206+
if opt_info.field_tmp_assignments.len() == 0 {
207+
trace!("NO: no assignments found");
208+
}
209+
let mut last_assigned_to = opt_info.field_tmp_assignments[0].1;
210+
let source_local = last_assigned_to;
211+
for (l, r) in &opt_info.field_tmp_assignments {
212+
if *r != last_assigned_to {
213+
trace!("NO: found unexpected assignment {:?} = {:?}", l, r);
214+
return false;
215+
}
216+
217+
last_assigned_to = *l;
218+
}
219+
220+
if source_local != opt_info.local_temp_0 {
221+
trace!(
222+
"NO: start of assignment chain does not match enum variant temp: {:?} != {:?}",
223+
source_local,
224+
opt_info.local_temp_0
225+
);
226+
return false;
227+
} else if last_assigned_to != opt_info.local_tmp_s1 {
228+
trace!(
229+
"NO: end of assignemnt chain does not match written enum temp: {:?} != {:?}",
230+
last_assigned_to,
231+
opt_info.local_tmp_s1
232+
);
233+
return false;
234+
}
235+
236+
trace!("SUCCESS: optimization applies!");
237+
return true;
238+
}
239+
35240
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
36-
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
241+
fn run_pass(&self, _: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
242+
trace!("running SimplifyArmIdentity on {:?}", source);
37243
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
38244
for bb in basic_blocks {
39-
// Need 3 statements:
40-
let (s0, s1, s2) = match &mut *bb.statements {
41-
[s0, s1, s2] => (s0, s1, s2),
42-
_ => continue,
43-
};
245+
trace!("bb is {:?}", bb.statements);
44246

45-
// Pattern match on the form we want:
46-
let (local_tmp_s0, local_1, vf_s0) = match match_get_variant_field(s0) {
47-
None => continue,
48-
Some(x) => x,
49-
};
50-
let (local_tmp_s1, local_0, vf_s1) = match match_set_variant_field(s1) {
51-
None => continue,
52-
Some(x) => x,
53-
};
54-
if local_tmp_s0 != local_tmp_s1
55-
// Avoid moving into ourselves.
56-
|| local_0 == local_1
57-
// The field-and-variant information match up.
58-
|| vf_s0 != vf_s1
59-
// Source and target locals have the same type.
60-
// FIXME(Centril | oli-obk): possibly relax to same layout?
61-
|| local_decls[local_0].ty != local_decls[local_1].ty
62-
// We're setting the discriminant of `local_0` to this variant.
63-
|| Some((local_0, vf_s0.var_idx)) != match_set_discr(s2)
64-
{
65-
continue;
66-
}
247+
if let Some(mut opt_info) = get_arm_identity_info(&bb.statements) {
248+
trace!("got opt_info = {:#?}", opt_info);
249+
if !optimization_applies(&opt_info, local_decls) {
250+
debug!("optimization skipped for {:?}", source);
251+
continue;
252+
}
253+
254+
// Also remove unused Storage{Live,Dead} statements which correspond
255+
// to temps used previously.
256+
for (left, right) in opt_info.field_tmp_assignments {
257+
for (live_idx, dead_idx, local) in &opt_info.storage_stmts {
258+
if *local == left || *local == right {
259+
opt_info.stmts_to_remove.push(*live_idx);
260+
opt_info.stmts_to_remove.push(*dead_idx);
261+
}
262+
}
263+
}
67264

68-
// Right shape; transform!
69-
s0.source_info = s2.source_info;
70-
match &mut s0.kind {
71-
StatementKind::Assign(box (place, rvalue)) => {
72-
*place = local_0.into();
73-
*rvalue = Rvalue::Use(Operand::Move(local_1.into()));
265+
// Right shape; transform!
266+
let stmt = &mut bb.statements[opt_info.stmt_to_overwrite];
267+
stmt.source_info = opt_info.source_info;
268+
match &mut stmt.kind {
269+
StatementKind::Assign(box (place, rvalue)) => {
270+
*place = opt_info.local_0.into();
271+
*rvalue = Rvalue::Use(Operand::Move(opt_info.local_1.into()));
272+
}
273+
_ => unreachable!(),
74274
}
75-
_ => unreachable!(),
275+
276+
for stmt_idx in opt_info.stmts_to_remove {
277+
bb.statements[stmt_idx].make_nop();
278+
}
279+
280+
bb.statements.retain(|stmt| stmt.kind != StatementKind::Nop);
281+
282+
trace!("block is now {:?}", bb.statements);
76283
}
77-
s1.make_nop();
78-
s2.make_nop();
79284
}
80285
}
81286
}
@@ -129,7 +334,7 @@ fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)>
129334
}
130335
}
131336

132-
#[derive(PartialEq)]
337+
#[derive(PartialEq, Debug)]
133338
struct VarField<'tcx> {
134339
field: Field,
135340
field_ty: Ty<'tcx>,

‎src/test/mir-opt/simplify-arm-identity.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,14 @@ fn main() {
3939
// }
4040
// ...
4141
// bb3: {
42+
// StorageLive(_4);
4243
// _4 = ((_1 as Foo).0: u8);
43-
// ((_2 as Foo).0: u8) = move _4;
44+
// StorageLive(_5);
45+
// _5 = _4;
46+
// ((_2 as Foo).0: u8) = move _5;
4447
// discriminant(_2) = 0;
48+
// StorageDead(_5);
49+
// StorageDead(_4);
4550
// goto -> bb4;
4651
// }
4752
// ...
@@ -65,9 +70,14 @@ fn main() {
6570
// }
6671
// ...
6772
// bb3: {
73+
// StorageLive(_4);
6874
// _4 = ((_1 as Foo).0: u8);
69-
// ((_2 as Foo).0: u8) = move _4;
75+
// StorageLive(_5);
76+
// _5 = _4;
77+
// ((_2 as Foo).0: u8) = move _5;
7078
// discriminant(_2) = 0;
79+
// StorageDead(_5);
80+
// StorageDead(_4);
7181
// goto -> bb4;
7282
// }
7383
// ...

‎src/test/mir-opt/simplify-arm.rs

+380
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
// compile-flags: -Z mir-opt-level=1
2+
3+
fn id(o: Option<u8>) -> Option<u8> {
4+
match o {
5+
Some(v) => Some(v),
6+
None => None,
7+
}
8+
}
9+
10+
fn id_result(r: Result<u8, i32>) -> Result<u8, i32> {
11+
match r {
12+
Ok(x) => Ok(x),
13+
Err(y) => Err(y),
14+
}
15+
}
16+
17+
fn id_try(r: Result<u8, i32>) -> Result<u8, i32> {
18+
let x = r?;
19+
Ok(x)
20+
}
21+
22+
fn main() {
23+
id(None);
24+
id_result(Ok(4));
25+
id_try(Ok(4));
26+
}
27+
28+
// END RUST SOURCE
29+
// START rustc.id.SimplifyArmIdentity.before.mir
30+
// debug o => _1;
31+
// let mut _0: std::option::Option<u8>;
32+
// let mut _2: isize;
33+
// let _3: u8;
34+
// let mut _4: u8;
35+
// scope 1 {
36+
// debug v => _3;
37+
// }
38+
// bb0: {
39+
// _2 = discriminant(_1);
40+
// switchInt(move _2) -> [0isize: bb1, 1isize: bb3, otherwise: bb2];
41+
// }
42+
// bb1: {
43+
// discriminant(_0) = 0;
44+
// goto -> bb4;
45+
// }
46+
// bb2: {
47+
// unreachable;
48+
// }
49+
// bb3: {
50+
// StorageLive(_3);
51+
// _3 = ((_1 as Some).0: u8);
52+
// StorageLive(_4);
53+
// _4 = _3;
54+
// ((_0 as Some).0: u8) = move _4;
55+
// discriminant(_0) = 1;
56+
// StorageDead(_4);
57+
// StorageDead(_3);
58+
// goto -> bb4;
59+
// }
60+
// bb4: {
61+
// return;
62+
// }
63+
// END rustc.id.SimplifyArmIdentity.before.mir
64+
// START rustc.id.SimplifyArmIdentity.after.mir
65+
// debug o => _1;
66+
// let mut _0: std::option::Option<u8>;
67+
// let mut _2: isize;
68+
// let _3: u8;
69+
// let mut _4: u8;
70+
// scope 1 {
71+
// debug v => _3;
72+
// }
73+
// bb0: {
74+
// _2 = discriminant(_1);
75+
// switchInt(move _2) -> [0isize: bb1, 1isize: bb3, otherwise: bb2];
76+
// }
77+
// bb1: {
78+
// discriminant(_0) = 0;
79+
// goto -> bb4;
80+
// }
81+
// bb2: {
82+
// unreachable;
83+
// }
84+
// bb3: {
85+
// _0 = move _1;
86+
// goto -> bb4;
87+
// }
88+
// bb4: {
89+
// return;
90+
// }
91+
// END rustc.id.SimplifyArmIdentity.after.mir
92+
93+
// START rustc.id_result.SimplifyArmIdentity.before.mir
94+
// debug r => _1;
95+
// let mut _0: std::result::Result<u8, i32>;
96+
// let mut _2: isize;
97+
// let _3: u8;
98+
// let mut _4: u8;
99+
// let _5: i32;
100+
// let mut _6: i32;
101+
// scope 1 {
102+
// debug x => _3;
103+
// }
104+
// scope 2 {
105+
// debug y => _5;
106+
// }
107+
// bb0: {
108+
// _2 = discriminant(_1);
109+
// switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2];
110+
// }
111+
// bb1: {
112+
// StorageLive(_5);
113+
// _5 = ((_1 as Err).0: i32);
114+
// StorageLive(_6);
115+
// _6 = _5;
116+
// ((_0 as Err).0: i32) = move _6;
117+
// discriminant(_0) = 1;
118+
// StorageDead(_6);
119+
// StorageDead(_5);
120+
// goto -> bb4;
121+
// }
122+
// bb2: {
123+
// unreachable;
124+
// }
125+
// bb3: {
126+
// StorageLive(_3);
127+
// _3 = ((_1 as Ok).0: u8);
128+
// StorageLive(_4);
129+
// _4 = _3;
130+
// ((_0 as Ok).0: u8) = move _4;
131+
// discriminant(_0) = 0;
132+
// StorageDead(_4);
133+
// StorageDead(_3);
134+
// goto -> bb4;
135+
// }
136+
// bb4: {
137+
// return;
138+
// }
139+
// END rustc.id_result.SimplifyArmIdentity.before.mir
140+
// START rustc.id_result.SimplifyArmIdentity.after.mir
141+
// debug r => _1;
142+
// let mut _0: std::result::Result<u8, i32>;
143+
// let mut _2: isize;
144+
// let _3: u8;
145+
// let mut _4: u8;
146+
// let _5: i32;
147+
// let mut _6: i32;
148+
// scope 1 {
149+
// debug x => _3;
150+
// }
151+
// scope 2 {
152+
// debug y => _5;
153+
// }
154+
// bb0: {
155+
// _2 = discriminant(_1);
156+
// switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2];
157+
// }
158+
// bb1: {
159+
// _0 = move _1;
160+
// goto -> bb4;
161+
// }
162+
// bb2: {
163+
// unreachable;
164+
// }
165+
// bb3: {
166+
// _0 = move _1;
167+
// goto -> bb4;
168+
// }
169+
// bb4: {
170+
// return;
171+
// }
172+
// END rustc.id_result.SimplifyArmIdentity.after.mir
173+
// START rustc.id_result.SimplifyBranchSame.before.mir
174+
// debug r => _1;
175+
// let mut _0: std::result::Result<u8, i32>;
176+
// let mut _2: isize;
177+
// let _3: u8;
178+
// let mut _4: u8;
179+
// let _5: i32;
180+
// let mut _6: i32;
181+
// scope 1 {
182+
// debug x => _3;
183+
// }
184+
// scope 2 {
185+
// debug y => _5;
186+
// }
187+
// bb0: {
188+
// _2 = discriminant(_1);
189+
// switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2];
190+
// }
191+
// bb1: {
192+
// _0 = move _1;
193+
// goto -> bb4;
194+
// }
195+
// bb2: {
196+
// unreachable;
197+
// }
198+
// bb3: {
199+
// _0 = move _1;
200+
// goto -> bb4;
201+
// }
202+
// bb4: {
203+
// return;
204+
// }
205+
// END rustc.id_result.SimplifyBranchSame.before.mir
206+
// START rustc.id_result.SimplifyBranchSame.after.mir
207+
// debug r => _1;
208+
// let mut _0: std::result::Result<u8, i32>;
209+
// let mut _2: isize;
210+
// let _3: u8;
211+
// let mut _4: u8;
212+
// let _5: i32;
213+
// let mut _6: i32;
214+
// scope 1 {
215+
// debug x => _3;
216+
// }
217+
// scope 2 {
218+
// debug y => _5;
219+
// }
220+
// bb0: {
221+
// _2 = discriminant(_1);
222+
// goto -> bb1;
223+
// }
224+
// bb1: {
225+
// _0 = move _1;
226+
// goto -> bb2;
227+
// }
228+
// bb2: {
229+
// return;
230+
// }
231+
// END rustc.id_result.SimplifyBranchSame.after.mir
232+
233+
// START rustc.id_try.SimplifyArmIdentity.before.mir
234+
// debug r => _1;
235+
// let mut _0: std::result::Result<u8, i32>;
236+
// let _2: u8;
237+
// let mut _3: std::result::Result<u8, i32>;
238+
// let mut _4: std::result::Result<u8, i32>;
239+
// let mut _5: isize;
240+
// let _6: i32;
241+
// let mut _7: !;
242+
// let mut _8: i32;
243+
// let mut _9: i32;
244+
// let _10: u8;
245+
// let mut _11: u8;
246+
// scope 1 {
247+
// debug x => _2;
248+
// }
249+
// scope 2 {
250+
// debug err => _6;
251+
// scope 3 {
252+
// }
253+
// }
254+
// scope 4 {
255+
// debug val => _10;
256+
// scope 5 {
257+
// }
258+
// }
259+
// bb0: {
260+
// StorageLive(_2);
261+
// StorageLive(_3);
262+
// StorageLive(_4);
263+
// _4 = _1;
264+
// _3 = const <std::result::Result<u8, i32> as std::ops::Try>::into_result(move _4) -> bb1;
265+
// }
266+
// bb1: {
267+
// StorageDead(_4);
268+
// _5 = discriminant(_3);
269+
// switchInt(move _5) -> [0isize: bb2, 1isize: bb4, otherwise: bb3];
270+
// }
271+
// bb2: {
272+
// StorageLive(_10);
273+
// _10 = ((_3 as Ok).0: u8);
274+
// _2 = _10;
275+
// StorageDead(_10);
276+
// StorageDead(_3);
277+
// StorageLive(_11);
278+
// _11 = _2;
279+
// ((_0 as Ok).0: u8) = move_ 11;
280+
// discriminant(_0) = 0;
281+
// StorageDead(_11);
282+
// StorageDead(_2);
283+
// goto -> bb5;
284+
// }
285+
// bb3: {
286+
// unreachable;
287+
// }
288+
// bb4: {
289+
// StorageLive(_6);
290+
// _6 = ((_3 as Err).0: i32);
291+
// StorageLive(_8);
292+
// StorageLive(_9);
293+
// _9 = _6;
294+
// _8 = const <i32 as std::convert::From<i32>>::from(move _9) -> bb6;
295+
// }
296+
// bb5: {
297+
// return;
298+
// }
299+
// bb6: {
300+
// StorageDead(_9);
301+
// _0 = const <std::result::Result<u8, i32> as std::ops::Try>::from_error(move _8) -> bb7;
302+
// }
303+
// bb7: {
304+
// StorageDead(_8);
305+
// StorageDead(_6);
306+
// StorageDead(_3);
307+
// StorageDead(_2);
308+
// goto -> bb5;
309+
// }
310+
// END rustc.id_try.SimplifyArmIdentity.before.mir
311+
// START rustc.id_try.SimplifyArmIdentity.after.mir
312+
// debug r => _1;
313+
// let mut _0: std::result::Result<u8, i32>;
314+
// let _2: u8;
315+
// let mut _3: std::result::Result<u8, i32>;
316+
// let mut _4: std::result::Result<u8, i32>;
317+
// let mut _5: isize;
318+
// let _6: i32;
319+
// let mut _7: !;
320+
// let mut _8: i32;
321+
// let mut _9: i32;
322+
// let _10: u8;
323+
// let mut _11: u8;
324+
// scope 1 {
325+
// debug x => _2;
326+
// }
327+
// scope 2 {
328+
// debug err => _6;
329+
// scope 3 {
330+
// }
331+
// }
332+
// scope 4 {
333+
// debug val => _10;
334+
// scope 5 {
335+
// }
336+
// }
337+
// bb0: {
338+
// StorageLive(_2);
339+
// StorageLive(_3);
340+
// StorageLive(_4);
341+
// _4 = _1;
342+
// _3 = const <std::result::Result<u8, i32> as std::ops::Try>::into_result(move _4) -> bb1;
343+
// }
344+
// bb1: {
345+
// StorageDead(_4);
346+
// _5 = discriminant(_3);
347+
// switchInt(move _5) -> [0isize: bb2, 1isize: bb4, otherwise: bb3];
348+
// }
349+
// bb2: {
350+
// _0 = move _3;
351+
// StorageDead(_3);
352+
// StorageDead(_2);
353+
// goto -> bb5;
354+
// }
355+
// bb3: {
356+
// unreachable;
357+
// }
358+
// bb4: {
359+
// StorageLive(_6);
360+
// _6 = ((_3 as Err).0: i32);
361+
// StorageLive(_8);
362+
// StorageLive(_9);
363+
// _9 = _6;
364+
// _8 = const <i32 as std::convert::From<i32>>::from(move _9) -> bb6;
365+
// }
366+
// bb5: {
367+
// return;
368+
// }
369+
// bb6: {
370+
// StorageDead(_9);
371+
// _0 = const <std::result::Result<u8, i32> as std::ops::Try>::from_error(move _8) -> bb7;
372+
// }
373+
// bb7: {
374+
// StorageDead(_8);
375+
// StorageDead(_6);
376+
// StorageDead(_3);
377+
// StorageDead(_2);
378+
// goto -> bb5;
379+
// }
380+
// END rustc.id_try.SimplifyArmIdentity.after.mir

‎src/test/mir-opt/simplify_try.rs

+81-37
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ fn main() {
2323
// let _10: u32;
2424
// let mut _11: u32;
2525
// scope 1 {
26-
// debug y => _10;
26+
// debug y => _2;
2727
// }
2828
// scope 2 {
2929
// debug err => _6;
3030
// scope 3 {
3131
// scope 7 {
32-
// debug t => _6;
32+
// debug t => _9;
3333
// }
3434
// scope 8 {
35-
// debug v => _6;
35+
// debug v => _8;
3636
// let mut _12: i32;
3737
// }
3838
// }
@@ -43,22 +43,49 @@ fn main() {
4343
// }
4444
// }
4545
// scope 6 {
46-
// debug self => _1;
46+
// debug self => _4;
4747
// }
4848
// bb0: {
49-
// _5 = discriminant(_1);
49+
// StorageLive(_2);
50+
// StorageLive(_3);
51+
// StorageLive(_4);
52+
// _4 = _1;
53+
// _3 = move _4;
54+
// StorageDead(_4);
55+
// _5 = discriminant(_3);
5056
// switchInt(move _5) -> [0isize: bb1, otherwise: bb2];
5157
// }
5258
// bb1: {
53-
// _10 = ((_1 as Ok).0: u32);
54-
// ((_0 as Ok).0: u32) = move _10;
59+
// StorageLive(_10);
60+
// _10 = ((_3 as Ok).0: u32);
61+
// _2 = _10;
62+
// StorageDead(_10);
63+
// StorageDead(_3);
64+
// StorageLive(_11);
65+
// _11 = _2;
66+
// ((_0 as Ok).0: u32) = move _11;
5567
// discriminant(_0) = 0;
68+
// StorageDead(_11);
69+
// StorageDead(_2);
5670
// goto -> bb3;
5771
// }
5872
// bb2: {
59-
// _6 = ((_1 as Err).0: i32);
60-
// ((_0 as Err).0: i32) = move _6;
73+
// StorageLive(_6);
74+
// _6 = ((_3 as Err).0: i32);
75+
// StorageLive(_8);
76+
// StorageLive(_9);
77+
// _9 = _6;
78+
// _8 = move _9;
79+
// StorageDead(_9);
80+
// StorageLive(_12);
81+
// _12 = move _8;
82+
// ((_0 as Err).0: i32) = move _12;
6183
// discriminant(_0) = 1;
84+
// StorageDead(_12);
85+
// StorageDead(_8);
86+
// StorageDead(_6);
87+
// StorageDead(_3);
88+
// StorageDead(_2);
6289
// goto -> bb3;
6390
// }
6491
// bb3: {
@@ -82,16 +109,16 @@ fn main() {
82109
// let _10: u32;
83110
// let mut _11: u32;
84111
// scope 1 {
85-
// debug y => _10;
112+
// debug y => _2;
86113
// }
87114
// scope 2 {
88115
// debug err => _6;
89116
// scope 3 {
90117
// scope 7 {
91-
// debug t => _6;
118+
// debug t => _9;
92119
// }
93120
// scope 8 {
94-
// debug v => _6;
121+
// debug v => _8;
95122
// let mut _12: i32;
96123
// }
97124
// }
@@ -102,22 +129,28 @@ fn main() {
102129
// }
103130
// }
104131
// scope 6 {
105-
// debug self => _1;
132+
// debug self => _4;
106133
// }
107134
// bb0: {
108-
// _5 = discriminant(_1);
135+
// StorageLive(_2);
136+
// StorageLive(_3);
137+
// StorageLive(_4);
138+
// _4 = _1;
139+
// _3 = move _4;
140+
// StorageDead(_4);
141+
// _5 = discriminant(_3);
109142
// switchInt(move _5) -> [0isize: bb1, otherwise: bb2];
110143
// }
111144
// bb1: {
112-
// _0 = move _1;
113-
// nop;
114-
// nop;
145+
// _0 = move _3;
146+
// StorageDead(_3);
147+
// StorageDead(_2);
115148
// goto -> bb3;
116149
// }
117150
// bb2: {
118-
// _0 = move _1;
119-
// nop;
120-
// nop;
151+
// _0 = move _3;
152+
// StorageDead(_3);
153+
// StorageDead(_2);
121154
// goto -> bb3;
122155
// }
123156
// bb3: {
@@ -141,16 +174,16 @@ fn main() {
141174
// let _10: u32;
142175
// let mut _11: u32;
143176
// scope 1 {
144-
// debug y => _10;
177+
// debug y => _2;
145178
// }
146179
// scope 2 {
147180
// debug err => _6;
148181
// scope 3 {
149182
// scope 7 {
150-
// debug t => _6;
183+
// debug t => _9;
151184
// }
152185
// scope 8 {
153-
// debug v => _6;
186+
// debug v => _8;
154187
// let mut _12: i32;
155188
// }
156189
// }
@@ -161,16 +194,22 @@ fn main() {
161194
// }
162195
// }
163196
// scope 6 {
164-
// debug self => _1;
197+
// debug self => _4;
165198
// }
166199
// bb0: {
167-
// _5 = discriminant(_1);
200+
// StorageLive(_2);
201+
// StorageLive(_3);
202+
// StorageLive(_4);
203+
// _4 = _1;
204+
// _3 = move _4;
205+
// StorageDead(_4);
206+
// _5 = discriminant(_3);
168207
// goto -> bb1;
169208
// }
170209
// bb1: {
171-
// _0 = move _1;
172-
// nop;
173-
// nop;
210+
// _0 = move _3;
211+
// StorageDead(_3);
212+
// StorageDead(_2);
174213
// goto -> bb2;
175214
// }
176215
// bb2: {
@@ -183,34 +222,39 @@ fn main() {
183222
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
184223
// debug x => _1;
185224
// let mut _0: std::result::Result<u32, i32>;
186-
// let mut _2: isize;
187-
// let _3: i32;
188-
// let _4: u32;
225+
// let _2: u32;
226+
// let mut _3: isize;
227+
// let _4: i32;
228+
// let mut _5: i32;
229+
// let mut _6: i32;
230+
// let _7: u32;
189231
// scope 1 {
190-
// debug y => _4;
232+
// debug y => _2;
191233
// }
192234
// scope 2 {
193-
// debug err => _3;
235+
// debug err => _4;
194236
// scope 3 {
195237
// scope 7 {
196-
// debug t => _3;
238+
// debug t => _6;
197239
// }
198240
// scope 8 {
199-
// debug v => _3;
241+
// debug v => _5;
200242
// }
201243
// }
202244
// }
203245
// scope 4 {
204-
// debug val => _4;
246+
// debug val => _7;
205247
// scope 5 {
206248
// }
207249
// }
208250
// scope 6 {
209251
// debug self => _1;
210252
// }
211253
// bb0: {
212-
// _2 = discriminant(_1);
254+
// StorageLive(_2);
255+
// _3 = discriminant(_1);
213256
// _0 = move _1;
257+
// StorageDead(_2);
214258
// return;
215259
// }
216260
// }

0 commit comments

Comments
 (0)
Please sign in to comment.