Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0113342

Browse files
committedNov 11, 2019
Auto merge of #66282 - Centril:simplify-try, r=<try>
[WIP] [mir-opt] asking `?`s in a more optimized fashion This PR works towards #66234 by providing two optimization passes meant to run in sequence: - `SimplifyArmIdentity` which transforms something like: ```rust _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY ); ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP; discriminant(_LOCAL_0) = VAR_IDX; ``` into: ```rust _LOCAL_0 = move _LOCAL_1 ``` - `SimplifyBranchSame` which transforms `SwitchInt`s to identical basic blocks into a `goto` to the first reachable target. Together, these are meant to simplify the following into just `res`: ```rust match res { Ok(x) => Ok(x), Err(x) => Err(x), } ``` It should be noted however that the desugaring of `?` includes a function call and so the first pass in this PR relies on inlining to substitute that function call for identity on `x`. Inlining requires `mir-opt-level=2` so this might not have any effect in perf-bot but let's find out. r? @oli-obk -- This is WIP, but I'd appreciate feedback. :)
2 parents e2fa952 + 657c945 commit 0113342

File tree

9 files changed

+485
-9
lines changed

9 files changed

+485
-9
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3668,6 +3668,7 @@ dependencies = [
36683668
"arena",
36693669
"either",
36703670
"graphviz",
3671+
"itertools 0.8.0",
36713672
"log",
36723673
"log_settings",
36733674
"polonius-engine",

‎src/librustc/hir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,7 +2101,7 @@ pub enum TyKind {
21012101
Err,
21022102
}
21032103

2104-
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
2104+
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
21052105
pub struct InlineAsmOutput {
21062106
pub constraint: Symbol,
21072107
pub is_rw: bool,
@@ -2111,7 +2111,7 @@ pub struct InlineAsmOutput {
21112111

21122112
// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
21132113
// it needs to be `Clone` and use plain `Vec<T>` instead of `HirVec<T>`.
2114-
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
2114+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
21152115
pub struct InlineAsm {
21162116
pub asm: Symbol,
21172117
pub asm_str_style: StrStyle,

‎src/librustc/mir/interpret/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
246246
}
247247
}
248248

249-
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
249+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
250250
pub enum PanicInfo<O> {
251251
Panic {
252252
msg: Symbol,

‎src/librustc/mir/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ pub struct Terminator<'tcx> {
10401040
pub kind: TerminatorKind<'tcx>,
10411041
}
10421042

1043-
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
1043+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
10441044
pub enum TerminatorKind<'tcx> {
10451045
/// Block should have one successor in the graph; we jump there.
10461046
Goto { target: BasicBlock },
@@ -1568,7 +1568,7 @@ impl Statement<'_> {
15681568
}
15691569
}
15701570

1571-
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
1571+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
15721572
pub enum StatementKind<'tcx> {
15731573
/// Write the RHS Rvalue to the LHS Place.
15741574
Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
@@ -1634,7 +1634,7 @@ pub enum RetagKind {
16341634
}
16351635

16361636
/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
1637-
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
1637+
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
16381638
pub enum FakeReadCause {
16391639
/// Inject a fake read of the borrowed input at the end of each guards
16401640
/// code.
@@ -1667,7 +1667,7 @@ pub enum FakeReadCause {
16671667
ForLet,
16681668
}
16691669

1670-
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
1670+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
16711671
pub struct InlineAsm<'tcx> {
16721672
pub asm: HirInlineAsm,
16731673
pub outputs: Box<[Place<'tcx>]>,
@@ -2105,7 +2105,7 @@ impl<'tcx> Operand<'tcx> {
21052105
///////////////////////////////////////////////////////////////////////////
21062106
/// Rvalues
21072107
2108-
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
2108+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
21092109
pub enum Rvalue<'tcx> {
21102110
/// x (either a move or copy, depending on type of x)
21112111
Use(Operand<'tcx>),
@@ -2487,7 +2487,7 @@ impl<'tcx> UserTypeProjections {
24872487
/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
24882488
/// `field[0]` (aka `.0`), indicating that the type of `s` is
24892489
/// determined by finding the type of the `.0` field from `T`.
2490-
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
2490+
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
24912491
pub struct UserTypeProjection {
24922492
pub base: UserTypeAnnotationIndex,
24932493
pub projs: Vec<ProjectionKind>,

‎src/librustc_mir/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ doctest = false
1313
arena = { path = "../libarena" }
1414
either = "1.5.0"
1515
dot = { path = "../libgraphviz", package = "graphviz" }
16+
itertools = "0.8"
1617
log = "0.4"
1718
log_settings = "0.1.1"
1819
polonius-engine = "0.10.0"

‎src/librustc_mir/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
1616
#![feature(decl_macro)]
1717
#![feature(drain_filter)]
1818
#![feature(exhaustive_patterns)]
19+
#![feature(iter_order_by)]
1920
#![feature(never_type)]
2021
#![feature(specialization)]
2122
#![feature(try_trait)]

‎src/librustc_mir/transform/mod.rs

Lines changed: 4 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;
@@ -275,6 +276,9 @@ fn run_optimization_passes<'tcx>(
275276
&copy_prop::CopyPropagation,
276277
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
277278
&remove_noop_landing_pads::RemoveNoopLandingPads,
279+
&simplify::SimplifyCfg::new("after-remove-noo-landing-pads"),
280+
&simplify_try::SimplifyArmIdentity,
281+
&simplify_try::SimplifyBranchSame,
278282
&simplify::SimplifyCfg::new("final"),
279283
&simplify::SimplifyLocals,
280284

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
//! The general point of the optimizations provided here is to simplify something like:
2+
//!
3+
//! ```rust
4+
//! match x {
5+
//! Ok(x) => Ok(x),
6+
//! Err(x) => Err(x)
7+
//! }
8+
//! ```
9+
//!
10+
//! into just `x`.
11+
12+
use crate::transform::{MirPass, MirSource, simplify};
13+
use rustc::ty::{TyCtxt, Ty};
14+
use rustc::mir::*;
15+
use rustc_target::abi::VariantIdx;
16+
use itertools::Itertools as _;
17+
18+
/// Simplifies arms of form `Variant(x) => Variant(x)` to just a move.
19+
///
20+
/// This is done by transforming basic blocks where the statements match:
21+
///
22+
/// ```rust
23+
/// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY );
24+
/// ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP;
25+
/// discriminant(_LOCAL_0) = VAR_IDX;
26+
/// ```
27+
///
28+
/// into:
29+
///
30+
/// ```rust
31+
/// _LOCAL_0 = move _LOCAL_1
32+
/// ```
33+
pub struct SimplifyArmIdentity;
34+
35+
impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
36+
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
37+
for bb in body.basic_blocks_mut() {
38+
// Need 3 statements:
39+
let (s0, s1, s2) = match &mut *bb.statements {
40+
[s0, s1, s2] => (s0, s1, s2),
41+
_ => continue,
42+
};
43+
44+
// Pattern match on the form we want:
45+
let (local_tmp_s0, local_1, vf_s0) = match match_get_variant_field(s0) {
46+
None => continue,
47+
Some(x) => x,
48+
};
49+
let (local_tmp_s1, local_0, vf_s1) = match match_set_variant_field(s1) {
50+
None => continue,
51+
Some(x) => x,
52+
};
53+
if local_tmp_s0 != local_tmp_s1
54+
|| vf_s0 != vf_s1
55+
|| Some((local_0, vf_s0.var_idx)) != match_set_discr(s2)
56+
{
57+
continue;
58+
}
59+
60+
// Right shape; transform!
61+
match &mut s0.kind {
62+
StatementKind::Assign(box (place, rvalue)) => {
63+
*place = local_0.into();
64+
*rvalue = Rvalue::Use(Operand::Move(local_1.into()));
65+
}
66+
_ => unreachable!(),
67+
}
68+
s1.make_nop();
69+
s2.make_nop();
70+
}
71+
}
72+
}
73+
74+
/// Match on:
75+
/// ```rust
76+
/// _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY);
77+
/// ```
78+
fn match_get_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
79+
match &stmt.kind {
80+
StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
81+
Rvalue::Use(Operand::Copy(pf)) | Rvalue::Use(Operand::Move(pf)) => {
82+
let local_into = place_into.as_local()?;
83+
let (local_from, vf) = match_variant_field_place(&pf)?;
84+
Some((local_into, local_from, vf))
85+
}
86+
_ => None,
87+
},
88+
_ => None,
89+
}
90+
}
91+
92+
/// Match on:
93+
/// ```rust
94+
/// ((_LOCAL_FROM as Variant).FIELD: TY) = move _LOCAL_INTO;
95+
/// ```
96+
fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
97+
match &stmt.kind {
98+
StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
99+
Rvalue::Use(Operand::Move(place_into)) => {
100+
let local_into = place_into.as_local()?;
101+
let (local_from, vf) = match_variant_field_place(&place_from)?;
102+
Some((local_into, local_from, vf))
103+
}
104+
_ => None,
105+
},
106+
_ => None,
107+
}
108+
}
109+
110+
/// Match on:
111+
/// ```rust
112+
/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
113+
/// ```
114+
fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> {
115+
match &stmt.kind {
116+
StatementKind::SetDiscriminant { place, variant_index } => Some((
117+
place.as_local()?,
118+
*variant_index
119+
)),
120+
_ => None,
121+
}
122+
}
123+
124+
#[derive(PartialEq)]
125+
struct VarField<'tcx> {
126+
field: Field,
127+
field_ty: Ty<'tcx>,
128+
var_idx: VariantIdx,
129+
}
130+
131+
/// Match on `((_LOCAL as Variant).FIELD: TY)`.
132+
fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarField<'tcx>)> {
133+
match place.as_ref() {
134+
PlaceRef {
135+
base: &PlaceBase::Local(local),
136+
projection: &[ProjectionElem::Downcast(_, var_idx), ProjectionElem::Field(field, ty)],
137+
} => Some((local, VarField { field, field_ty: ty, var_idx })),
138+
_ => None,
139+
}
140+
}
141+
142+
/// Simplifies `SwitchInt(_) -> [targets]`,
143+
/// where all the `targets` have the same form,
144+
/// into `goto -> target_first`.
145+
pub struct SimplifyBranchSame;
146+
147+
impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
148+
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
149+
let bbs = body.basic_blocks_mut();
150+
for bb_idx in bbs.indices() {
151+
let targets = match &bbs[bb_idx].terminator().kind {
152+
TerminatorKind::SwitchInt { targets, .. } => targets,
153+
_ => continue,
154+
};
155+
156+
// Reaching `unreachable` is UB so assume it doesn't happen.
157+
let mut iter_bbs_reachable = targets
158+
.iter()
159+
.map(|idx| (*idx, &bbs[*idx]))
160+
.filter(|(_, bb)| bb.terminator().kind != TerminatorKind::Unreachable)
161+
.peekable();
162+
163+
// We want to `goto -> bb_first`.
164+
let bb_first = iter_bbs_reachable
165+
.peek()
166+
.map(|(idx, _)| *idx)
167+
.unwrap_or(targets[0]);
168+
169+
// All successor basic blocks should have the exact same form.
170+
let all_successors_equivalent = iter_bbs_reachable
171+
.map(|(_, bb)| bb)
172+
.tuple_windows()
173+
.all(|(bb_l, bb_r)| {
174+
bb_l.is_cleanup == bb_r.is_cleanup
175+
&& bb_l.terminator().kind == bb_r.terminator().kind
176+
&& bb_l.statements.iter().eq_by(&bb_r.statements, |x, y| x.kind == y.kind)
177+
});
178+
179+
if all_successors_equivalent {
180+
// Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
181+
bbs[bb_idx].terminator_mut().kind = TerminatorKind::Goto { target: bb_first };
182+
}
183+
}
184+
185+
// We may have dead blocks now, so remvoe those.
186+
simplify::remove_dead_blocks(body);
187+
}
188+
}
189+
190+
/*
191+
192+
KEEPSAKE: REMOVE IF NOT NECESSARY!
193+
194+
fn statement_semantic_eq(sa: &StatementKind<'_>, sb: &StatementKind<'_>) -> bool {
195+
use StatementKind::*;
196+
match (sb, sa) {
197+
(AscribeUserType(pa, va), AscribeUserType(pb, vb)) => pa == pb && va == vb,
198+
(Assign(a), Assign(b)) => a == b,
199+
(FakeRead(fa, pa), FakeRead(fb, pb)) => fa == fb && pa == pb,
200+
(InlineAsm(a), InlineAsm(b)) => a == b,
201+
(Nop, StatementKind::Nop) => true,
202+
(Retag(ra, pa), Retag(rb, pb)) => ra == rb && pa == pb,
203+
(
204+
SetDiscriminant { place: pa, variant_index: va },
205+
SetDiscriminant { place: pb, variant_index: vb },
206+
) => pa == pb && va == vb,
207+
(StorageDead(a), StorageDead(b)) => a == b,
208+
(StorageLive(a), StorageLive(b)) => a == b,
209+
(AscribeUserType(..), _) | (_, AscribeUserType(..))
210+
| (StorageDead(..), _) | (_, StorageDead(..))
211+
| (Assign(..), _) | (_, Assign(..))
212+
| (FakeRead(..), _) | (_, FakeRead(..))
213+
| (InlineAsm(..), _) | (_, InlineAsm(..))
214+
| (Nop, _) | (_, Nop)
215+
| (Retag(..), _) | (_, Retag(..))
216+
| (SetDiscriminant { .. }, _) | (_, SetDiscriminant { .. }) => true,
217+
}
218+
}
219+
220+
fn terminator_semantic_eq(ta: &TerminatorKind<'_>, tb: &TerminatorKind<'_>) -> bool {
221+
use TerminatorKind::*;
222+
match (ta, tb) {
223+
(Goto { target: a }, Goto { target: b }) => a == b,
224+
(Resume, Resume)
225+
| (Abort, Abort)
226+
| (Return, Return)
227+
| (Unreachable, Unreachable)
228+
| (GeneratorDrop, GeneratorDrop) => true,
229+
(
230+
SwitchInt { discr: da, switch_ty: sa, targets: ta, values: _ },
231+
SwitchInt { discr: db, switch_ty: sb, targets: tb, values: _ },
232+
) => da == db && sa == sb && ta == tb,
233+
(
234+
Drop { location: la, target: ta, unwind: ua },
235+
Drop { location: lb, target: tb, unwind: ub },
236+
) => la == lb && ta == tb && ua == ub,
237+
(
238+
DropAndReplace { location: la, target: ta, unwind: ua, value: va },
239+
DropAndReplace { location: lb, target: tb, unwind: ub, value: vb },
240+
) => la == lb && ta == tb && ua == ub && va == vb,
241+
(
242+
Call { func: fa, args: aa, destination: da, cleanup: ca, from_hir_call: _ },
243+
Call { func: fb, args: ab, destination: db, cleanup: cb, from_hir_call: _ },
244+
) => fa == fb && aa == ab && da == db && ca == cb,
245+
(
246+
Assert { cond: coa, expected: ea, msg: ma, target: ta, cleanup: cla },
247+
Assert { cond: cob, expected: eb, msg: mb, target: tb, cleanup: clb },
248+
) => coa == cob && ea == eb && ma == mb && ta == tb && cla == clb,
249+
(
250+
Yield { value: va, resume: ra, drop: da },
251+
Yield { value: vb, resume: rb, drop: db },
252+
) => va == vb && ra == rb && da == db,
253+
(
254+
FalseEdges { real_target: ra, imaginary_target: ia },
255+
FalseEdges { real_target: rb, imaginary_target: ib },
256+
) => ra == rb && ia == ib,
257+
(
258+
FalseUnwind { real_target: ra, unwind: ua },
259+
FalseUnwind { real_target: rb, unwind: ub },
260+
) => ra == rb && ua == ub,
261+
(Goto { .. }, _) | (_, Goto { .. })
262+
| (Resume, _) | (_, Resume)
263+
| (Abort, _) | (_, Abort)
264+
| (Return, _) | (_, Return)
265+
| (Unreachable, _) | (_, Unreachable)
266+
| (GeneratorDrop, _) | (_, GeneratorDrop)
267+
| (SwitchInt { .. }, _) | (_, SwitchInt { .. })
268+
| (Drop { .. }, _) | (_, Drop { .. })
269+
| (DropAndReplace { .. }, _) | (_, DropAndReplace { .. })
270+
| (Call { .. }, _) | (_, Call { .. })
271+
| (Assert { .. }, _) | (_, Assert { .. })
272+
| (Yield { .. }, _) | (_, Yield { .. })
273+
| (FalseEdges { .. }, _) | (_, FalseEdges { .. }) => false,
274+
}
275+
}
276+
*/

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

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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+
66+
// START rustc.try_identity.SimplifyArmIdentity.after.mir
67+
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
68+
// let mut _0: std::result::Result<u32, i32>;
69+
// let _2: u32;
70+
// let mut _3: std::result::Result<u32, i32>;
71+
// let mut _4: std::result::Result<u32, i32>;
72+
// let mut _5: isize;
73+
// let _6: i32;
74+
// let mut _7: !;
75+
// let mut _8: i32;
76+
// let mut _9: i32;
77+
// let _10: u32;
78+
// let mut _11: u32;
79+
// scope 1 {
80+
// }
81+
// scope 2 {
82+
// scope 3 {
83+
// scope 7 {
84+
// }
85+
// scope 8 {
86+
// let mut _12: i32;
87+
// }
88+
// }
89+
// }
90+
// scope 4 {
91+
// scope 5 {
92+
// }
93+
// }
94+
// scope 6 {
95+
// }
96+
// bb0: {
97+
// _5 = discriminant(_1);
98+
// switchInt(move _5) -> [0isize: bb4, 1isize: bb2, otherwise: bb1];
99+
// }
100+
// bb1: {
101+
// unreachable;
102+
// }
103+
// bb2: {
104+
// _0 = move _1;
105+
// nop;
106+
// nop;
107+
// goto -> bb3;
108+
// }
109+
// bb3: {
110+
// return;
111+
// }
112+
// bb4: {
113+
// _0 = move _1;
114+
// nop;
115+
// nop;
116+
// goto -> bb3;
117+
// }
118+
// }
119+
// END rustc.try_identity.SimplifyArmIdentity.after.mir
120+
121+
// START rustc.try_identity.SimplifyBranchSame.after.mir
122+
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
123+
// let mut _0: std::result::Result<u32, i32>;
124+
// let _2: u32;
125+
// let mut _3: std::result::Result<u32, i32>;
126+
// let mut _4: std::result::Result<u32, i32>;
127+
// let mut _5: isize;
128+
// let _6: i32;
129+
// let mut _7: !;
130+
// let mut _8: i32;
131+
// let mut _9: i32;
132+
// let _10: u32;
133+
// let mut _11: u32;
134+
// scope 1 {
135+
// }
136+
// scope 2 {
137+
// scope 3 {
138+
// scope 7 {
139+
// }
140+
// scope 8 {
141+
// let mut _12: i32;
142+
// }
143+
// }
144+
// }
145+
// scope 4 {
146+
// scope 5 {
147+
// }
148+
// }
149+
// scope 6 {
150+
// }
151+
// bb0: {
152+
// _5 = discriminant(_1);
153+
// goto -> bb2;
154+
// }
155+
// bb1: {
156+
// return;
157+
// }
158+
// bb2: {
159+
// _0 = move _1;
160+
// nop;
161+
// nop;
162+
// goto -> bb1;
163+
// }
164+
// }
165+
// END rustc.try_identity.SimplifyBranchSame.after.mir
166+
167+
// START rustc.try_identity.SimplifyLocals.after.mir
168+
// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
169+
// let mut _0: std::result::Result<u32, i32>;
170+
// let mut _2: isize;
171+
// scope 1 {
172+
// }
173+
// scope 2 {
174+
// scope 3 {
175+
// scope 7 {
176+
// }
177+
// scope 8 {
178+
// }
179+
// }
180+
// }
181+
// scope 4 {
182+
// scope 5 {
183+
// }
184+
// }
185+
// scope 6 {
186+
// }
187+
// bb0: {
188+
// _2 = discriminant(_1);
189+
// _0 = move _1;
190+
// return;
191+
// }
192+
// }
193+
// END rustc.try_identity.SimplifyLocals.after.mir

0 commit comments

Comments
 (0)
Please sign in to comment.