Skip to content

Commit 2ae4287

Browse files
committed
wip
1 parent 93efb75 commit 2ae4287

File tree

9 files changed

+239
-23
lines changed

9 files changed

+239
-23
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,6 +3664,7 @@ dependencies = [
36643664
"arena",
36653665
"either",
36663666
"graphviz",
3667+
"itertools 0.8.0",
36673668
"log",
36683669
"log_settings",
36693670
"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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,10 @@ fn run_optimization_passes<'tcx>(
276276
&copy_prop::CopyPropagation,
277277
&simplify_branches::SimplifyBranches::new("after-copy-prop"),
278278
&remove_noop_landing_pads::RemoveNoopLandingPads,
279-
&simplify::SimplifyCfg::new("final"),
279+
&simplify::SimplifyCfg::new("after-remove-noo-landing-pads"),
280280
&simplify_try::SimplifyArmIdentity,
281281
&simplify_try::SimplifyBranchSame,
282+
&simplify::SimplifyCfg::new("final"),
282283
&simplify::SimplifyLocals,
283284

284285
&add_call_guards::CriticalCallEdges,

src/librustc_mir/transform/simplify_try.rs

Lines changed: 150 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
use crate::transform::{MirPass, MirSource};
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};
213
use rustc::ty::{TyCtxt, Ty};
314
use rustc::mir::*;
415
use rustc_target::abi::VariantIdx;
16+
use itertools::Itertools as _;
517

6-
/// Simplifies arms of form `Variant(x) => x` to just `x`.
18+
/// Simplifies arms of form `Variant(x) => Variant(x)` to just a move.
719
///
820
/// This is done by transforming basic blocks where the statements match:
921
///
@@ -21,10 +33,8 @@ use rustc_target::abi::VariantIdx;
2133
pub struct SimplifyArmIdentity;
2234

2335
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-
36+
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
37+
for bb in body.basic_blocks_mut() {
2838
// Need 3 statements:
2939
let (s0, s1, s2) = match &mut *bb.statements {
3040
[s0, s1, s2] => (s0, s1, s2),
@@ -46,9 +56,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
4656
if local_tmp_s0 != local_tmp_s1 || vf_s0 != vf_s1 {
4757
continue;
4858
}
49-
match match_set_discr(s2) {
50-
Some((local, var_idx)) if local == local_0 && var_idx == vf_s0.var_idx => {}
51-
_ => continue,
59+
if Some((local_0, vf_s0.var_idx)) != match_set_discr(s2) {
60+
continue;
5261
}
5362
debug!("SimplifyArmIdentity - set_discr");
5463

@@ -60,8 +69,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
6069
}
6170
_ => unreachable!(),
6271
}
63-
s1.kind = StatementKind::Nop;
64-
s2.kind = StatementKind::Nop;
72+
s1.make_nop();
73+
s2.make_nop();
6574
}
6675
}
6776
}
@@ -134,10 +143,138 @@ fn match_variant_field_place<'tcx>(place: &Place<'tcx>) -> Option<(Local, VarFie
134143
}
135144
}
136145

146+
/// Simplifies `SwitchInt(_) -> [targets]`,
147+
/// where all the `targets` have the same form,
148+
/// into `goto -> target_first`.
137149
pub struct SimplifyBranchSame;
138150

139151
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);
152+
fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
153+
let bbs = body.basic_blocks_mut();
154+
for bb_idx in bbs.indices() {
155+
let targets = match &bbs[bb_idx].terminator().kind {
156+
TerminatorKind::SwitchInt { targets, .. } => targets,
157+
_ => continue,
158+
};
159+
160+
// Reaching `unreachable` is UB so assume it doesn't happen.
161+
let mut iter_bbs_reachable = targets
162+
.iter()
163+
.map(|idx| (*idx, &bbs[*idx]))
164+
.filter(|(_, bb)| bb.terminator().kind != TerminatorKind::Unreachable)
165+
.peekable();
166+
167+
// We want to `goto -> bb_first`.
168+
let bb_first = iter_bbs_reachable
169+
.peek()
170+
.map(|(idx, _)| *idx)
171+
.unwrap_or(targets[0]);
172+
173+
// All successor basic blocks should have the exact same form.
174+
let all_successors_equivalent = iter_bbs_reachable
175+
.map(|(_, bb)| bb)
176+
.tuple_windows()
177+
.all(|(bb_l, bb_r)| {
178+
bb_l.is_cleanup == bb_r.is_cleanup
179+
&& bb_l.terminator().kind == bb_r.terminator().kind
180+
&& bb_l.statements.iter().eq_by(&bb_r.statements, |x, y| x.kind == y.kind)
181+
});
182+
183+
if all_successors_equivalent {
184+
// Replace `SwitchInt(..) -> [bb_first, ..];` with a `goto -> bb_first;`.
185+
bbs[bb_idx].terminator_mut().kind = TerminatorKind::Goto { target: bb_first };
186+
}
187+
}
188+
189+
// We may have dead blocks now, so remvoe those.
190+
simplify::remove_dead_blocks(body);
191+
}
192+
}
193+
194+
/*
195+
196+
KEEPSAKE: TODO REMOVE IF NOT NECESSARY!
197+
198+
fn statement_semantic_eq(sa: &StatementKind<'_>, sb: &StatementKind<'_>) -> bool {
199+
use StatementKind::*;
200+
match (sb, sa) {
201+
(AscribeUserType(pa, va), AscribeUserType(pb, vb)) => pa == pb && va == vb,
202+
(Assign(a), Assign(b)) => a == b,
203+
(FakeRead(fa, pa), FakeRead(fb, pb)) => fa == fb && pa == pb,
204+
(InlineAsm(a), InlineAsm(b)) => a == b,
205+
(Nop, StatementKind::Nop) => true,
206+
(Retag(ra, pa), Retag(rb, pb)) => ra == rb && pa == pb,
207+
(
208+
SetDiscriminant { place: pa, variant_index: va },
209+
SetDiscriminant { place: pb, variant_index: vb },
210+
) => pa == pb && va == vb,
211+
(StorageDead(a), StorageDead(b)) => a == b,
212+
(StorageLive(a), StorageLive(b)) => a == b,
213+
(AscribeUserType(..), _) | (_, AscribeUserType(..))
214+
| (StorageDead(..), _) | (_, StorageDead(..))
215+
| (Assign(..), _) | (_, Assign(..))
216+
| (FakeRead(..), _) | (_, FakeRead(..))
217+
| (InlineAsm(..), _) | (_, InlineAsm(..))
218+
| (Nop, _) | (_, Nop)
219+
| (Retag(..), _) | (_, Retag(..))
220+
| (SetDiscriminant { .. }, _) | (_, SetDiscriminant { .. }) => true,
221+
}
222+
}
223+
224+
fn terminator_semantic_eq(ta: &TerminatorKind<'_>, tb: &TerminatorKind<'_>) -> bool {
225+
use TerminatorKind::*;
226+
match (ta, tb) {
227+
(Goto { target: a }, Goto { target: b }) => a == b,
228+
(Resume, Resume)
229+
| (Abort, Abort)
230+
| (Return, Return)
231+
| (Unreachable, Unreachable)
232+
| (GeneratorDrop, GeneratorDrop) => true,
233+
(
234+
SwitchInt { discr: da, switch_ty: sa, targets: ta, values: _ },
235+
SwitchInt { discr: db, switch_ty: sb, targets: tb, values: _ },
236+
) => da == db && sa == sb && ta == tb,
237+
(
238+
Drop { location: la, target: ta, unwind: ua },
239+
Drop { location: lb, target: tb, unwind: ub },
240+
) => la == lb && ta == tb && ua == ub,
241+
(
242+
DropAndReplace { location: la, target: ta, unwind: ua, value: va },
243+
DropAndReplace { location: lb, target: tb, unwind: ub, value: vb },
244+
) => la == lb && ta == tb && ua == ub && va == vb,
245+
(
246+
Call { func: fa, args: aa, destination: da, cleanup: ca, from_hir_call: _ },
247+
Call { func: fb, args: ab, destination: db, cleanup: cb, from_hir_call: _ },
248+
) => fa == fb && aa == ab && da == db && ca == cb,
249+
(
250+
Assert { cond: coa, expected: ea, msg: ma, target: ta, cleanup: cla },
251+
Assert { cond: cob, expected: eb, msg: mb, target: tb, cleanup: clb },
252+
) => coa == cob && ea == eb && ma == mb && ta == tb && cla == clb,
253+
(
254+
Yield { value: va, resume: ra, drop: da },
255+
Yield { value: vb, resume: rb, drop: db },
256+
) => va == vb && ra == rb && da == db,
257+
(
258+
FalseEdges { real_target: ra, imaginary_target: ia },
259+
FalseEdges { real_target: rb, imaginary_target: ib },
260+
) => ra == rb && ia == ib,
261+
(
262+
FalseUnwind { real_target: ra, unwind: ua },
263+
FalseUnwind { real_target: rb, unwind: ub },
264+
) => ra == rb && ua == ub,
265+
(Goto { .. }, _) | (_, Goto { .. })
266+
| (Resume, _) | (_, Resume)
267+
| (Abort, _) | (_, Abort)
268+
| (Return, _) | (_, Return)
269+
| (Unreachable, _) | (_, Unreachable)
270+
| (GeneratorDrop, _) | (_, GeneratorDrop)
271+
| (SwitchInt { .. }, _) | (_, SwitchInt { .. })
272+
| (Drop { .. }, _) | (_, Drop { .. })
273+
| (DropAndReplace { .. }, _) | (_, DropAndReplace { .. })
274+
| (Call { .. }, _) | (_, Call { .. })
275+
| (Assert { .. }, _) | (_, Assert { .. })
276+
| (Yield { .. }, _) | (_, Yield { .. })
277+
| (FalseEdges { .. }, _) | (_, FalseEdges { .. }) => false,
142278
}
143279
}
280+
*/

0 commit comments

Comments
 (0)