@@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
48
48
ref targets,
49
49
ref values,
50
50
..
51
- } if targets. len ( ) == 2 && values. len ( ) == 1 => {
51
+ } if targets. len ( ) == 2 && values. len ( ) == 1 && targets [ 0 ] != targets [ 1 ] => {
52
52
( place, values[ 0 ] , switch_ty, targets[ 0 ] , targets[ 1 ] )
53
53
}
54
54
// Only optimize switch int statements
@@ -89,48 +89,45 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
89
89
// Take ownership of items now that we know we can optimize.
90
90
let discr = discr. clone ( ) ;
91
91
92
- let new_stmts = first_stmts
93
- . iter ( )
94
- . zip ( scnd_stmts. iter ( ) )
95
- . map ( |( f, s) | {
96
- match ( & f. kind , & s. kind ) {
97
- ( f_s, s_s) if f_s == s_s => ( * f) . clone ( ) ,
92
+ // We already checked that first and second are different blocks,
93
+ // and bb_idx has a different terminator from both of them.
94
+ let ( from, first, second) = bbs. pick3_mut ( bb_idx, first, second) ;
98
95
99
- (
100
- StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
101
- StatementKind :: Assign ( box ( _, Rvalue :: Use ( Operand :: Constant ( s_c) ) ) ) ,
102
- ) => {
103
- // From earlier loop we know that we are dealing with bool constants only:
104
- let f_b = f_c. literal . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
105
- let s_b = s_c. literal . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
106
- if f_b == s_b {
107
- // Same value in both blocks. Use statement as is.
108
- ( * f) . clone ( )
109
- } else {
110
- // Different value between blocks. Make value conditional on switch condition.
111
- let size = tcx. layout_of ( param_env. and ( switch_ty) ) . unwrap ( ) . size ;
112
- let const_cmp = Operand :: const_from_scalar (
113
- tcx,
114
- switch_ty,
115
- crate :: interpret:: Scalar :: from_uint ( val, size) ,
116
- rustc_span:: DUMMY_SP ,
117
- ) ;
118
- let op = if f_b { BinOp :: Eq } else { BinOp :: Ne } ;
119
- let rhs =
120
- Rvalue :: BinaryOp ( op, Operand :: Copy ( discr. clone ( ) ) , const_cmp) ;
121
- Statement {
122
- source_info : f. source_info ,
123
- kind : StatementKind :: Assign ( box ( * lhs, rhs) ) ,
124
- }
96
+ let new_stmts = first. statements . iter ( ) . zip ( second. statements . iter ( ) ) . map ( |( f, s) | {
97
+ match ( & f. kind , & s. kind ) {
98
+ ( f_s, s_s) if f_s == s_s => ( * f) . clone ( ) ,
99
+
100
+ (
101
+ StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
102
+ StatementKind :: Assign ( box ( _, Rvalue :: Use ( Operand :: Constant ( s_c) ) ) ) ,
103
+ ) => {
104
+ // From earlier loop we know that we are dealing with bool constants only:
105
+ let f_b = f_c. literal . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
106
+ let s_b = s_c. literal . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
107
+ if f_b == s_b {
108
+ // Same value in both blocks. Use statement as is.
109
+ ( * f) . clone ( )
110
+ } else {
111
+ // Different value between blocks. Make value conditional on switch condition.
112
+ let size = tcx. layout_of ( param_env. and ( switch_ty) ) . unwrap ( ) . size ;
113
+ let const_cmp = Operand :: const_from_scalar (
114
+ tcx,
115
+ switch_ty,
116
+ crate :: interpret:: Scalar :: from_uint ( val, size) ,
117
+ rustc_span:: DUMMY_SP ,
118
+ ) ;
119
+ let op = if f_b { BinOp :: Eq } else { BinOp :: Ne } ;
120
+ let rhs = Rvalue :: BinaryOp ( op, Operand :: Copy ( discr. clone ( ) ) , const_cmp) ;
121
+ Statement {
122
+ source_info : f. source_info ,
123
+ kind : StatementKind :: Assign ( box ( * lhs, rhs) ) ,
125
124
}
126
125
}
127
-
128
- _ => unreachable ! ( ) ,
129
126
}
130
- } )
131
- . collect :: < Vec < _ > > ( ) ;
132
127
133
- let ( from, first) = bbs. pick2_mut ( bb_idx, first) ;
128
+ _ => unreachable ! ( ) ,
129
+ }
130
+ } ) ;
134
131
from. statements . extend ( new_stmts) ;
135
132
from. terminator_mut ( ) . kind = first. terminator ( ) . kind . clone ( ) ;
136
133
}
0 commit comments