-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 #123259 - scottmcm:tweak-if-const, r=<try>
Fixup `if T::CONST` in MIR r? ghost
- Loading branch information
Showing
13 changed files
with
467 additions
and
350 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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//! A pass that makes `SwitchInt`-on-`const` more obvious to later code. | ||
use rustc_middle::mir::*; | ||
use rustc_middle::ty::TyCtxt; | ||
|
||
/// A `MirPass` for simplifying `if T::CONST`. | ||
/// | ||
/// Today, MIR building for things like `if T::IS_ZST` introduce a constant | ||
/// for the copy of the bool, so it ends up in MIR as | ||
/// `_1 = CONST; switchInt (move _1)` or `_2 = CONST; switchInt (_2)`. | ||
/// | ||
/// This pass is very specifically targeted at *exactly* those patterns. | ||
/// It can absolutely be replaced with a more general pass should we get one that | ||
/// we can run in low optimization levels, but at the time of writing even in | ||
/// optimized builds this wasn't simplified. | ||
#[derive(Default)] | ||
pub struct SwitchConst; | ||
|
||
impl<'tcx> MirPass<'tcx> for SwitchConst { | ||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { | ||
for block in body.basic_blocks.as_mut_preserves_cfg() { | ||
let switch_local = if let TerminatorKind::SwitchInt { discr, .. } = | ||
&block.terminator().kind | ||
&& let Some(place) = discr.place() | ||
&& let Some(local) = place.as_local() | ||
{ | ||
local | ||
} else { | ||
continue; | ||
}; | ||
|
||
let new_operand = if let Some(statement) = block.statements.last() | ||
&& let StatementKind::Assign(place_and_rvalue) = &statement.kind | ||
&& let Some(local) = place_and_rvalue.0.as_local() | ||
&& local == switch_local | ||
&& let Rvalue::Use(operand) = &place_and_rvalue.1 | ||
&& let Operand::Constant(_) = operand | ||
{ | ||
operand.clone() | ||
} else { | ||
continue; | ||
}; | ||
|
||
if !tcx.consider_optimizing(|| format!("SwitchConst: switchInt(move {switch_local:?}")) | ||
{ | ||
break; | ||
} | ||
|
||
let TerminatorKind::SwitchInt { discr, .. } = &mut block.terminator_mut().kind else { | ||
bug!("Somehow wasn't a switchInt any more?") | ||
}; | ||
*discr = new_operand; | ||
} | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
tests/mir-opt/pre-codegen/if_associated_const.check_bool.PreCodegen.after.mir
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,23 @@ | ||
// MIR for `check_bool` after PreCodegen | ||
|
||
fn check_bool() -> u32 { | ||
let mut _0: u32; | ||
|
||
bb0: { | ||
switchInt(const <T as TraitWithBool>::FLAG) -> [0: bb1, otherwise: bb2]; | ||
} | ||
|
||
bb1: { | ||
_0 = const 456_u32; | ||
goto -> bb3; | ||
} | ||
|
||
bb2: { | ||
_0 = const 123_u32; | ||
goto -> bb3; | ||
} | ||
|
||
bb3: { | ||
return; | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
tests/mir-opt/pre-codegen/if_associated_const.check_int.PreCodegen.after.mir
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,33 @@ | ||
// MIR for `check_int` after PreCodegen | ||
|
||
fn check_int() -> u32 { | ||
let mut _0: u32; | ||
|
||
bb0: { | ||
switchInt(const <T as TraitWithInt>::VALUE) -> [1: bb1, 2: bb2, 3: bb3, otherwise: bb4]; | ||
} | ||
|
||
bb1: { | ||
_0 = const 123_u32; | ||
goto -> bb5; | ||
} | ||
|
||
bb2: { | ||
_0 = const 456_u32; | ||
goto -> bb5; | ||
} | ||
|
||
bb3: { | ||
_0 = const 789_u32; | ||
goto -> bb5; | ||
} | ||
|
||
bb4: { | ||
_0 = const 0_u32; | ||
goto -> bb5; | ||
} | ||
|
||
bb5: { | ||
return; | ||
} | ||
} |
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,27 @@ | ||
// skip-filecheck | ||
//@ compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2 | ||
|
||
#![crate_type = "lib"] | ||
|
||
pub trait TraitWithBool { | ||
const FLAG: bool; | ||
} | ||
|
||
// EMIT_MIR if_associated_const.check_bool.PreCodegen.after.mir | ||
pub fn check_bool<T: TraitWithBool>() -> u32 { | ||
if T::FLAG { 123 } else { 456 } | ||
} | ||
|
||
pub trait TraitWithInt { | ||
const VALUE: i32; | ||
} | ||
|
||
// EMIT_MIR if_associated_const.check_int.PreCodegen.after.mir | ||
pub fn check_int<T: TraitWithInt>() -> u32 { | ||
match T::VALUE { | ||
1 => 123, | ||
2 => 456, | ||
3 => 789, | ||
_ => 0, | ||
} | ||
} |
Oops, something went wrong.