Skip to content

Commit 75b7447

Browse files
committed
Introduce TerminatorKind::as_goto
1 parent e3b8d5c commit 75b7447

File tree

2 files changed

+50
-46
lines changed

2 files changed

+50
-46
lines changed

compiler/rustc_middle/src/mir/terminator.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,13 @@ impl<'tcx> TerminatorKind<'tcx> {
416416
_ => None,
417417
}
418418
}
419+
420+
pub fn as_goto(&self) -> Option<BasicBlock> {
421+
match self {
422+
TerminatorKind::Goto { target } => Some(*target),
423+
_ => None,
424+
}
425+
}
419426
}
420427

421428
impl<'tcx> Debug for TerminatorKind<'tcx> {

compiler/rustc_mir/src/transform/const_goto.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -53,57 +53,54 @@ impl<'tcx> MirPass<'tcx> for ConstGoto {
5353
impl<'a, 'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'a, 'tcx> {
5454
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
5555
let _:Option<_> = try {
56-
match terminator.kind {
57-
TerminatorKind::Goto { target } => {
58-
// We only apply this optimization if the last statement is a const assignment
59-
let last_statement =
60-
self.body.basic_blocks()[location.block].statements.last()?;
56+
let target = terminator.kind.as_goto()?;
57+
// We only apply this optimization if the last statement is a const assignment
58+
let last_statement =
59+
self.body.basic_blocks()[location.block].statements.last()?;
6160

62-
if let Some(box (place, Rvalue::Use(op))) = last_statement.kind.as_assign(){
63-
let _const = op.constant()?;
64-
// We found a constant being assigned to `place`.
65-
// Now check that the target of this Goto switches on this place.
66-
let target_bb = &self.body.basic_blocks()[target];
67-
// FIXME(simonvandel): We are conservative here when we don't allow
68-
// any statements in the target basic block.
69-
// This could probably be relaxed to allow `StorageDead`s which could be
70-
// copied to the predecessor of this block.
71-
if !target_bb.statements.is_empty() {
72-
None?
73-
}
61+
if let Some(box (place, Rvalue::Use(op))) = last_statement.kind.as_assign(){
62+
let _const = op.constant()?;
63+
// We found a constant being assigned to `place`.
64+
// Now check that the target of this Goto switches on this place.
65+
let target_bb = &self.body.basic_blocks()[target];
66+
67+
// FIXME(simonvandel): We are conservative here when we don't allow
68+
// any statements in the target basic block.
69+
// This could probably be relaxed to allow `StorageDead`s which could be
70+
// copied to the predecessor of this block.
71+
if !target_bb.statements.is_empty() {
72+
None?
73+
}
7474

75-
let target_bb_terminator = target_bb.terminator();
76-
let (discr, switch_ty, targets) = target_bb_terminator.kind.as_switch()?;
77-
if discr.place() == Some(*place) {
78-
// We now know that the Switch matches on the const place, and it is statementless
79-
// Now find which value in the Switch matches the const value.
80-
let const_value = _const.literal.try_eval_bits(
81-
self.tcx,
82-
self.param_env,
83-
switch_ty,
84-
)?;
85-
let found_value_idx_option = targets
86-
.iter()
87-
.enumerate()
88-
.find(|(_, x)| const_value == x.0)
89-
.map(|(idx, _)| idx);
75+
let target_bb_terminator = target_bb.terminator();
76+
let (discr, switch_ty, targets) = target_bb_terminator.kind.as_switch()?;
77+
if discr.place() == Some(*place) {
78+
// We now know that the Switch matches on the const place, and it is statementless
79+
// Now find which value in the Switch matches the const value.
80+
let const_value = _const.literal.try_eval_bits(
81+
self.tcx,
82+
self.param_env,
83+
switch_ty,
84+
)?;
85+
let found_value_idx_option = targets
86+
.iter()
87+
.enumerate()
88+
.find(|(_, x)| const_value == x.0)
89+
.map(|(idx, _)| idx);
9090

91-
let target_to_use_in_goto =
92-
if let Some(found_value_idx) = found_value_idx_option {
93-
targets.iter().nth(found_value_idx).unwrap().1
94-
} else {
95-
// If we did not find the const value in values, it must be the otherwise case
96-
targets.otherwise()
97-
};
91+
let target_to_use_in_goto =
92+
if let Some(found_value_idx) = found_value_idx_option {
93+
targets.iter().nth(found_value_idx).unwrap().1
94+
} else {
95+
// If we did not find the const value in values, it must be the otherwise case
96+
targets.otherwise()
97+
};
9898

99-
self.optimizations.push(OptimizationToApply {
100-
bb_with_goto: location.block,
101-
target_to_use_in_goto,
102-
});
103-
}
104-
}
99+
self.optimizations.push(OptimizationToApply {
100+
bb_with_goto: location.block,
101+
target_to_use_in_goto,
102+
});
105103
}
106-
_ => {}
107104
}
108105
Some(())
109106
};

0 commit comments

Comments
 (0)