@@ -5,6 +5,7 @@ use tracing::trace;
55use crate :: patch:: MirPatch ;
66
77pub ( super ) enum SimplifyConstCondition {
8+ AfterInstSimplify ,
89 AfterConstProp ,
910 Final ,
1011}
@@ -13,6 +14,9 @@ pub(super) enum SimplifyConstCondition {
1314impl < ' tcx > crate :: MirPass < ' tcx > for SimplifyConstCondition {
1415 fn name ( & self ) -> & ' static str {
1516 match self {
17+ SimplifyConstCondition :: AfterInstSimplify => {
18+ "SimplifyConstCondition-after-inst-simplify"
19+ }
1620 SimplifyConstCondition :: AfterConstProp => "SimplifyConstCondition-after-const-prop" ,
1721 SimplifyConstCondition :: Final => "SimplifyConstCondition-final" ,
1822 }
@@ -23,12 +27,33 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
2327 let typing_env = body. typing_env ( tcx) ;
2428 let mut patch = MirPatch :: new ( body) ;
2529
30+ fn try_get_const < ' tcx , ' a > (
31+ operand : & ' a Operand < ' tcx > ,
32+ has_place_const : Option < ( Place < ' tcx > , & ' a ConstOperand < ' tcx > ) > ,
33+ ) -> Option < & ' a ConstOperand < ' tcx > > {
34+ match operand {
35+ Operand :: Constant ( const_operand) => Some ( const_operand) ,
36+ // `has_place_const` must be the LHS of the previous statement.
37+ // Soundness: There is nothing can modify the place, as there are no statements between the two statements.
38+ Operand :: Copy ( place) | Operand :: Move ( place)
39+ if let Some ( ( place_const, const_operand) ) = has_place_const
40+ && place_const == * place =>
41+ {
42+ Some ( const_operand)
43+ }
44+ Operand :: Copy ( _) | Operand :: Move ( _) => None ,
45+ }
46+ }
47+
2648 ' blocks: for ( bb, block) in body. basic_blocks . iter_enumerated ( ) {
49+ let mut pre_place_const: Option < ( Place < ' tcx > , & ConstOperand < ' tcx > ) > = None ;
50+
2751 for ( statement_index, stmt) in block. statements . iter ( ) . enumerate ( ) {
52+ let has_place_const = pre_place_const. take ( ) ;
2853 // Simplify `assume` of a known value: either a NOP or unreachable.
2954 if let StatementKind :: Intrinsic ( box ref intrinsic) = stmt. kind
3055 && let NonDivergingIntrinsic :: Assume ( discr) = intrinsic
31- && let Operand :: Constant ( c) = discr
56+ && let Some ( c) = try_get_const ( discr, has_place_const )
3257 && let Some ( constant) = c. const_ . try_eval_bool ( tcx, typing_env)
3358 {
3459 if constant {
@@ -37,28 +62,29 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
3762 patch. patch_terminator ( bb, TerminatorKind :: Unreachable ) ;
3863 continue ' blocks;
3964 }
65+ } else if let StatementKind :: Assign ( box ( lhs, ref rvalue) ) = stmt. kind
66+ && let Rvalue :: Use ( Operand :: Constant ( c) ) = rvalue
67+ {
68+ pre_place_const = Some ( ( lhs, c) ) ;
4069 }
4170 }
4271
4372 let terminator = block. terminator ( ) ;
4473 let terminator = match terminator. kind {
45- TerminatorKind :: SwitchInt {
46- discr : Operand :: Constant ( ref c) , ref targets, ..
47- } => {
48- let constant = c. const_ . try_eval_bits ( tcx, typing_env) ;
49- if let Some ( constant) = constant {
50- let target = targets. target_for_value ( constant) ;
51- TerminatorKind :: Goto { target }
52- } else {
53- continue ;
54- }
74+ TerminatorKind :: SwitchInt { ref discr, ref targets, .. }
75+ if let Some ( c) = try_get_const ( discr, pre_place_const. take ( ) )
76+ && let Some ( constant) = c. const_ . try_eval_bits ( tcx, typing_env) =>
77+ {
78+ let target = targets. target_for_value ( constant) ;
79+ TerminatorKind :: Goto { target }
80+ }
81+ TerminatorKind :: Assert { target, ref cond, expected, .. }
82+ if let Some ( c) = try_get_const ( & cond, pre_place_const. take ( ) )
83+ && let Some ( constant) = c. const_ . try_eval_bool ( tcx, typing_env)
84+ && constant == expected =>
85+ {
86+ TerminatorKind :: Goto { target }
5587 }
56- TerminatorKind :: Assert {
57- target, cond : Operand :: Constant ( ref c) , expected, ..
58- } => match c. const_ . try_eval_bool ( tcx, typing_env) {
59- Some ( v) if v == expected => TerminatorKind :: Goto { target } ,
60- _ => continue ,
61- } ,
6288 _ => continue ,
6389 } ;
6490 patch. patch_terminator ( bb, terminator) ;
0 commit comments