Skip to content

Commit 93efb75

Browse files
committed
wip
1 parent c296b2d commit 93efb75

File tree

3 files changed

+264
-0
lines changed

3 files changed

+264
-0
lines changed

src/librustc_mir/transform/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod cleanup_post_borrowck;
1818
pub mod check_consts;
1919
pub mod check_unsafety;
2020
pub mod simplify_branches;
21+
pub mod simplify_try;
2122
pub mod simplify;
2223
pub mod erase_regions;
2324
pub mod no_landing_pads;
@@ -276,6 +277,8 @@ fn run_optimization_passes<'tcx>(
276277
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
277278
&remove_noop_landing_pads::RemoveNoopLandingPads,
278279
&simplify::SimplifyCfg::new("final"),
280+
&simplify_try::SimplifyArmIdentity,
281+
&simplify_try::SimplifyBranchSame,
279282
&simplify::SimplifyLocals,
280283

281284
&add_call_guards::CriticalCallEdges,
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use crate::transform::{MirPass, MirSource};
2+
use rustc::ty::{TyCtxt, Ty};
3+
use rustc::mir::*;
4+
use rustc_target::abi::VariantIdx;
5+
6+
/// Simplifies arms of form `Variant(x) => x` to just `x`.
7+
///
8+
/// This is done by transforming basic blocks where the statements match:
9+
///
10+
/// ```rust
11+
/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
12+
/// ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP;
13+
/// discriminant(_LOCAL_0) = VAR_IDX;
14+
/// ```
15+
///
16+
/// into:
17+
///
18+
/// ```rust
19+
/// _LOCAL_0 = move _LOCAL_1
20+
/// ```
21+
pub struct SimplifyArmIdentity;
22+
23+
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
24+
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) {
25+
for (idx, bb) in body.basic_blocks_mut().iter_mut().enumerate() {
26+
debug!("SimplifyArmIdentity - bb{} = {:?}", idx, bb);
27+
28+
// Need 3 statements:
29+
let (s0, s1, s2) = match &mut *bb.statements {
30+
[s0, s1, s2] => (s0, s1, s2),
31+
_ => continue,
32+
};
33+
debug!("SimplifyArmIdentity - found three stmts");
34+
35+
// Pattern match on the form we want:
36+
let (local_tmp_s0, local_1, vf_s0) = match match_get_variant_field(s0) {
37+
None => continue,
38+
Some(x) => x,
39+
};
40+
debug!("SimplifyArmIdentity - get");
41+
let (local_tmp_s1, local_0, vf_s1) = match match_set_variant_field(s1) {
42+
None => continue,
43+
Some(x) => x,
44+
};
45+
debug!("SimplifyArmIdentity - set");
46+
if local_tmp_s0 != local_tmp_s1 || vf_s0 != vf_s1 {
47+
continue;
48+
}
49+
match match_set_discr(s2) {
50+
Some((local, var_idx)) if local == local_0 && var_idx == vf_s0.var_idx => {}
51+
_ => continue,
52+
}
53+
debug!("SimplifyArmIdentity - set_discr");
54+
55+
// Right shape; transform!
56+
match &mut s0.kind {
57+
StatementKind::Assign(box (place, rvalue)) => {
58+
*place = local_0.into();
59+
*rvalue = Rvalue::Use(Operand::Move(local_1.into()));
60+
}
61+
_ => unreachable!(),
62+
}
63+
s1.kind = StatementKind::Nop;
64+
s2.kind = StatementKind::Nop;
65+
}
66+
}
67+
}
68+
69+
/// Match on:
70+
/// ```rust
71+
/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
72+
/// ```
73+
fn match_get_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
74+
match &stmt.kind {
75+
StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
76+
Rvalue::Use(Operand::Copy(pf)) | Rvalue::Use(Operand::Move(pf)) => {
77+
let local_into = place_into.as_local()?;
78+
let (local_from, vf) = match_variant_field_place(&pf)?;
79+
Some((local_into, local_from, vf))
80+
}
81+
_ => None,
82+
},
83+
_ => None,
84+
}
85+
}
86+
87+
/// Match on:
88+
/// ```rust
89+
/// ((_LOCAL_FROM as Variant).FIELD: TY) = move _LOCAL_INTO;
90+
/// ```
91+
fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
92+
match &stmt.kind {
93+
StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
94+
Rvalue::Use(Operand::Move(place_into)) => {
95+
let local_into = place_into.as_local()?;
96+
let (local_from, vf) = match_variant_field_place(&place_from)?;
97+
Some((local_into, local_from, vf))
98+
}
99+
_ => None,
100+
},
101+
_ => None,
102+
}
103+
}
104+
105+
/// Match on:
106+
/// ```rust
107+
/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
108+
/// ```
109+
fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> {
110+
match &stmt.kind {
111+
StatementKind::SetDiscriminant { place, variant_index } => Some((
112+
place.as_local()?,
113+
*variant_index
114+
)),
115+
_ => None,
116+
}
117+
}
118+
119+
#[derive(PartialEq)]
120+
struct VarField<'tcx> {
121+
field: Field,
122+
field_ty: Ty<'tcx>,
123+
var_idx: VariantIdx,
124+
}
125+
126+
/// Match on `((_LOCAL as Variant).FIELD: TY)`.
127+
fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
128+
match place.as_ref() {
129+
PlaceRef {
130+
base: &PlaceBase::Local(local),
131+
projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
132+
} => Some((local, VarField { field, field_ty: ty, var_idx })),
133+
_ => None,
134+
}
135+
}
136+
137+
pub struct SimplifyBranchSame;
138+
139+
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
140+
fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, _body: &mut Body<'tcx>) {
141+
//debug!("SimplifyBranchSame - simplifying {:?}", _body);
142+
}
143+
}

src/test/mir-opt/simplify_try.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
2+
let y = x?;
3+
Ok(y)
4+
}
5+
6+
fn main() {
7+
let _ = try_identity(Ok(0));
8+
}
9+
10+
// END RUST SOURCE
11+
// START rustc.try_identity.SimplifyArmIdentity.before.mir
12+
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
13+
// let mut _0: std::result::Result<u32, i32>;
14+
// let _2: u32;
15+
// let mut _3: std::result::Result<u32, i32>;
16+
// let mut _4: std::result::Result<u32, i32>;
17+
// let mut _5: isize;
18+
// let _6: i32;
19+
// let mut _7: !;
20+
// let mut _8: i32;
21+
// let mut _9: i32;
22+
// let _10: u32;
23+
// let mut _11: u32;
24+
// scope 1 {
25+
// }
26+
// scope 2 {
27+
// scope 3 {
28+
// scope 7 {
29+
// }
30+
// scope 8 {
31+
// let mut _12: i32;
32+
// }
33+
// }
34+
// }
35+
// scope 4 {
36+
// scope 5 {
37+
// }
38+
// }
39+
// scope 6 {
40+
// }
41+
// bb0: {
42+
// _5 = discriminant(_1);
43+
// switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
44+
// }
45+
// bb1: {
46+
// unreachable;
47+
// }
48+
// bb2: {
49+
// _6 = ((_1 as Err).0: i32);
50+
// ((_0 as Err).0: i32) = move _6;
51+
// discriminant(_0) = 1;
52+
// goto -> bb3;
53+
// }
54+
// bb3: {
55+
// return;
56+
// }
57+
// bb4: {
58+
// _10 = ((_1 as Ok).0: u32);
59+
// ((_0 as Ok).0: u32) = move _10;
60+
// discriminant(_0) = 0;
61+
// goto -> bb3;
62+
// }
63+
// }
64+
// END rustc.try_identity.SimplifyArmIdentity.before.mir
65+
// START rustc.try_identity.SimplifyArmIdentity.after.mir
66+
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
67+
// let mut _0: std::result::Result<u32, i32>;
68+
// let _2: u32;
69+
// let mut _3: std::result::Result<u32, i32>;
70+
// let mut _4: std::result::Result<u32, i32>;
71+
// let mut _5: isize;
72+
// let _6: i32;
73+
// let mut _7: !;
74+
// let mut _8: i32;
75+
// let mut _9: i32;
76+
// let _10: u32;
77+
// let mut _11: u32;
78+
// scope 1 {
79+
// }
80+
// scope 2 {
81+
// scope 3 {
82+
// scope 7 {
83+
// }
84+
// scope 8 {
85+
// let mut _12: i32;
86+
// }
87+
// }
88+
// }
89+
// scope 4 {
90+
// scope 5 {
91+
// }
92+
// }
93+
// scope 6 {
94+
// }
95+
// bb0: {
96+
// _5 = discriminant(_1);
97+
// switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
98+
// }
99+
// bb1: {
100+
// unreachable;
101+
// }
102+
// bb2: {
103+
// _0 = move _1;
104+
// nop;
105+
// nop;
106+
// goto -> bb3;
107+
// }
108+
// bb3: {
109+
// return;
110+
// }
111+
// bb4: {
112+
// _0 = move _1;
113+
// nop;
114+
// nop;
115+
// goto -> bb3;
116+
// }
117+
// }
118+
// END rustc.try_identity.SimplifyArmIdentity.after.mir

0 commit comments

Comments
 (0)