forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#137702 - scottmcm:deconstruct-options, r=<try>
[nothing to see here] this is probably a bad idea but I'm curious r? ghost
- Loading branch information
Showing
12 changed files
with
596 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
use std::mem; | ||
|
||
use rustc_index::IndexVec; | ||
use rustc_middle::bug; | ||
use rustc_middle::mir::*; | ||
use rustc_middle::ty::TyCtxt; | ||
use tracing::{debug, instrument, trace}; | ||
|
||
pub(super) struct BranchDuplicator; | ||
|
||
impl<'tcx> crate::MirPass<'tcx> for BranchDuplicator { | ||
fn is_enabled(&self, sess: &rustc_session::Session) -> bool { | ||
sess.mir_opt_level() >= 2 | ||
} | ||
|
||
#[instrument(skip_all level = "debug")] | ||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | ||
let def_id = body.source.def_id(); | ||
debug!(?def_id); | ||
|
||
// Optimizing coroutines creates query cycles. | ||
if tcx.is_coroutine(def_id) { | ||
trace!("Skipped for coroutine {:?}", def_id); | ||
return; | ||
} | ||
|
||
let is_branch = |targets: &SwitchTargets| { | ||
targets.all_targets().len() == 2 | ||
|| (targets.all_values().len() == 2 | ||
&& body.basic_blocks[targets.otherwise()].is_empty_unreachable()) | ||
}; | ||
|
||
let mut candidates = Vec::new(); | ||
for (bb, bbdata) in body.basic_blocks.iter_enumerated() { | ||
if let TerminatorKind::SwitchInt { targets, .. } = &bbdata.terminator().kind | ||
&& is_branch(targets) | ||
&& let Ok(preds) = | ||
<[BasicBlock; 2]>::try_from(body.basic_blocks.predecessors()[bb].as_slice()) | ||
&& preds.iter().copied().all(|p| { | ||
matches!(body.basic_blocks[p].terminator().kind, TerminatorKind::Goto { .. }) | ||
}) | ||
&& bbdata.statements.iter().all(|x| is_negligible(&x.kind)) | ||
{ | ||
candidates.push((bb, preds)); | ||
} | ||
} | ||
|
||
if candidates.is_empty() { | ||
return; | ||
} | ||
|
||
let basic_blocks = body.basic_blocks.as_mut(); | ||
for (bb, [p0, p1]) in candidates { | ||
let bbdata = &mut basic_blocks[bb]; | ||
let statements = mem::take(&mut bbdata.statements); | ||
let unreachable = Terminator { | ||
source_info: bbdata.terminator().source_info, | ||
kind: TerminatorKind::Unreachable, | ||
}; | ||
let terminator = mem::replace(bbdata.terminator_mut(), unreachable); | ||
|
||
let pred0data = &mut basic_blocks[p0]; | ||
pred0data.statements.extend(statements.iter().cloned()); | ||
*pred0data.terminator_mut() = terminator.clone(); | ||
|
||
let pred1data = &mut basic_blocks[p1]; | ||
pred1data.statements.extend(statements); | ||
*pred1data.terminator_mut() = terminator; | ||
} | ||
} | ||
|
||
fn is_required(&self) -> bool { | ||
false | ||
} | ||
} | ||
|
||
fn is_negligible<'tcx>(stmt: &StatementKind<'tcx>) -> bool { | ||
use Rvalue::*; | ||
use StatementKind::*; | ||
match stmt { | ||
StorageLive(..) | StorageDead(..) => true, | ||
Assign(place_and_rvalue) => match &place_and_rvalue.1 { | ||
Ref(..) | RawPtr(..) | Discriminant(..) | NullaryOp(..) => true, | ||
_ => false, | ||
}, | ||
_ => false, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.BranchDuplicator.panic-abort.diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
- // MIR for `use_checked_sub` before BranchDuplicator | ||
+ // MIR for `use_checked_sub` after BranchDuplicator | ||
|
||
fn use_checked_sub(_1: u32, _2: u32) -> () { | ||
debug x => _1; | ||
debug rhs => _2; | ||
let mut _0: (); | ||
let mut _3: std::option::Option<u32>; | ||
let mut _4: u32; | ||
let mut _5: u32; | ||
let mut _6: isize; | ||
let _8: (); | ||
let mut _9: u32; | ||
scope 1 { | ||
debug delta => _7; | ||
let _7: u32; | ||
scope 2 (inlined core::num::<impl u32>::checked_sub) { | ||
let mut _10: bool; | ||
let mut _11: u32; | ||
} | ||
} | ||
|
||
bb0: { | ||
StorageLive(_3); | ||
StorageLive(_4); | ||
_4 = copy _1; | ||
StorageLive(_5); | ||
_5 = copy _2; | ||
StorageLive(_10); | ||
_10 = Lt(copy _4, copy _5); | ||
switchInt(move _10) -> [0: bb5, otherwise: bb4]; | ||
} | ||
|
||
bb1: { | ||
StorageLive(_7); | ||
_7 = copy ((_3 as Some).0: u32); | ||
StorageLive(_9); | ||
_9 = copy _7; | ||
_8 = do_something(move _9) -> [return: bb2, unwind unreachable]; | ||
} | ||
|
||
bb2: { | ||
StorageDead(_9); | ||
StorageDead(_7); | ||
goto -> bb3; | ||
} | ||
|
||
bb3: { | ||
StorageDead(_3); | ||
return; | ||
} | ||
|
||
bb4: { | ||
_3 = const Option::<u32>::None; | ||
- goto -> bb6; | ||
+ StorageDead(_10); | ||
+ StorageDead(_5); | ||
+ StorageDead(_4); | ||
+ _6 = discriminant(_3); | ||
+ switchInt(move _6) -> [1: bb1, 0: bb3, otherwise: bb7]; | ||
} | ||
|
||
bb5: { | ||
StorageLive(_11); | ||
_11 = SubUnchecked(copy _4, copy _5); | ||
_3 = Option::<u32>::Some(move _11); | ||
StorageDead(_11); | ||
- goto -> bb6; | ||
- } | ||
- | ||
- bb6: { | ||
StorageDead(_10); | ||
StorageDead(_5); | ||
StorageDead(_4); | ||
_6 = discriminant(_3); | ||
switchInt(move _6) -> [1: bb1, 0: bb3, otherwise: bb7]; | ||
+ } | ||
+ | ||
+ bb6: { | ||
+ unreachable; | ||
} | ||
|
||
bb7: { | ||
unreachable; | ||
} | ||
} | ||
|
||
ALLOC0 (size: 8, align: 4) { | ||
00 00 00 00 __ __ __ __ │ ....░░░░ | ||
} | ||
|
91 changes: 91 additions & 0 deletions
91
tests/mir-opt/pre-codegen/checked_ops.use_checked_sub.BranchDuplicator.panic-unwind.diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
- // MIR for `use_checked_sub` before BranchDuplicator | ||
+ // MIR for `use_checked_sub` after BranchDuplicator | ||
|
||
fn use_checked_sub(_1: u32, _2: u32) -> () { | ||
debug x => _1; | ||
debug rhs => _2; | ||
let mut _0: (); | ||
let mut _3: std::option::Option<u32>; | ||
let mut _4: u32; | ||
let mut _5: u32; | ||
let mut _6: isize; | ||
let _8: (); | ||
let mut _9: u32; | ||
scope 1 { | ||
debug delta => _7; | ||
let _7: u32; | ||
scope 2 (inlined core::num::<impl u32>::checked_sub) { | ||
let mut _10: bool; | ||
let mut _11: u32; | ||
} | ||
} | ||
|
||
bb0: { | ||
StorageLive(_3); | ||
StorageLive(_4); | ||
_4 = copy _1; | ||
StorageLive(_5); | ||
_5 = copy _2; | ||
StorageLive(_10); | ||
_10 = Lt(copy _4, copy _5); | ||
switchInt(move _10) -> [0: bb5, otherwise: bb4]; | ||
} | ||
|
||
bb1: { | ||
StorageLive(_7); | ||
_7 = copy ((_3 as Some).0: u32); | ||
StorageLive(_9); | ||
_9 = copy _7; | ||
_8 = do_something(move _9) -> [return: bb2, unwind continue]; | ||
} | ||
|
||
bb2: { | ||
StorageDead(_9); | ||
StorageDead(_7); | ||
goto -> bb3; | ||
} | ||
|
||
bb3: { | ||
StorageDead(_3); | ||
return; | ||
} | ||
|
||
bb4: { | ||
_3 = const Option::<u32>::None; | ||
- goto -> bb6; | ||
+ StorageDead(_10); | ||
+ StorageDead(_5); | ||
+ StorageDead(_4); | ||
+ _6 = discriminant(_3); | ||
+ switchInt(move _6) -> [1: bb1, 0: bb3, otherwise: bb7]; | ||
} | ||
|
||
bb5: { | ||
StorageLive(_11); | ||
_11 = SubUnchecked(copy _4, copy _5); | ||
_3 = Option::<u32>::Some(move _11); | ||
StorageDead(_11); | ||
- goto -> bb6; | ||
- } | ||
- | ||
- bb6: { | ||
StorageDead(_10); | ||
StorageDead(_5); | ||
StorageDead(_4); | ||
_6 = discriminant(_3); | ||
switchInt(move _6) -> [1: bb1, 0: bb3, otherwise: bb7]; | ||
+ } | ||
+ | ||
+ bb6: { | ||
+ unreachable; | ||
} | ||
|
||
bb7: { | ||
unreachable; | ||
} | ||
} | ||
|
||
ALLOC0 (size: 8, align: 4) { | ||
00 00 00 00 __ __ __ __ │ ....░░░░ | ||
} | ||
|
Oops, something went wrong.