@@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
4848 ref targets,
4949 ref values,
5050 ..
51- } if targets. len ( ) == 2 && values. len ( ) == 1 => {
51+ } if targets. len ( ) == 2 && values. len ( ) == 1 && targets [ 0 ] != targets [ 1 ] => {
5252 ( place, values[ 0 ] , switch_ty, targets[ 0 ] , targets[ 1 ] )
5353 }
5454 // Only optimize switch int statements
@@ -89,48 +89,45 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
8989 // Take ownership of items now that we know we can optimize.
9090 let discr = discr. clone ( ) ;
9191
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) ;
9895
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) ) ,
125124 }
126125 }
127-
128- _ => unreachable ! ( ) ,
129126 }
130- } )
131- . collect :: < Vec < _ > > ( ) ;
132127
133- let ( from, first) = bbs. pick2_mut ( bb_idx, first) ;
128+ _ => unreachable ! ( ) ,
129+ }
130+ } ) ;
134131 from. statements . extend ( new_stmts) ;
135132 from. terminator_mut ( ) . kind = first. terminator ( ) . kind . clone ( ) ;
136133 }
0 commit comments