1- use rustc_index:: IndexVec ;
1+ use rustc_index:: IndexSlice ;
2+ use rustc_middle:: mir:: patch:: MirPatch ;
23use rustc_middle:: mir:: * ;
34use rustc_middle:: ty:: { ParamEnv , ScalarInt , Ty , TyCtxt } ;
45use std:: iter;
@@ -16,9 +17,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
1617 let def_id = body. source . def_id ( ) ;
1718 let param_env = tcx. param_env_reveal_all_normalized ( def_id) ;
1819
19- let bbs = body. basic_blocks . as_mut ( ) ;
2020 let mut should_cleanup = false ;
21- for bb_idx in bbs. indices ( ) {
21+ for i in 0 ..body. basic_blocks . len ( ) {
22+ let bbs = & * body. basic_blocks ;
23+ let bb_idx = BasicBlock :: from_usize ( i) ;
2224 if !tcx. consider_optimizing ( || format ! ( "MatchBranchSimplification {def_id:?} " ) ) {
2325 continue ;
2426 }
@@ -34,12 +36,11 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
3436 _ => continue ,
3537 } ;
3638
37- if SimplifyToIf . simplify ( tcx, & mut body. local_decls , bbs , bb_idx, param_env) {
39+ if SimplifyToIf . simplify ( tcx, body, bb_idx, param_env) {
3840 should_cleanup = true ;
3941 continue ;
4042 }
41- if SimplifyToExp :: default ( ) . simplify ( tcx, & mut body. local_decls , bbs, bb_idx, param_env)
42- {
43+ if SimplifyToExp :: default ( ) . simplify ( tcx, body, bb_idx, param_env) {
4344 should_cleanup = true ;
4445 continue ;
4546 }
@@ -57,43 +58,41 @@ trait SimplifyMatch<'tcx> {
5758 fn simplify (
5859 & mut self ,
5960 tcx : TyCtxt < ' tcx > ,
60- local_decls : & mut IndexVec < Local , LocalDecl < ' tcx > > ,
61- bbs : & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
61+ body : & mut Body < ' tcx > ,
6262 switch_bb_idx : BasicBlock ,
6363 param_env : ParamEnv < ' tcx > ,
6464 ) -> bool {
65+ let bbs = & body. basic_blocks ;
6566 let ( discr, targets) = match bbs[ switch_bb_idx] . terminator ( ) . kind {
6667 TerminatorKind :: SwitchInt { ref discr, ref targets, .. } => ( discr, targets) ,
6768 _ => unreachable ! ( ) ,
6869 } ;
6970
70- let discr_ty = discr. ty ( local_decls, tcx) ;
71+ let discr_ty = discr. ty ( body . local_decls ( ) , tcx) ;
7172 if !self . can_simplify ( tcx, targets, param_env, bbs, discr_ty) {
7273 return false ;
7374 }
7475
76+ let mut patch = MirPatch :: new ( body) ;
77+
7578 // Take ownership of items now that we know we can optimize.
7679 let discr = discr. clone ( ) ;
7780
7881 // Introduce a temporary for the discriminant value.
7982 let source_info = bbs[ switch_bb_idx] . terminator ( ) . source_info ;
80- let discr_local = local_decls . push ( LocalDecl :: new ( discr_ty, source_info. span ) ) ;
83+ let discr_local = patch . new_temp ( discr_ty, source_info. span ) ;
8184
8285 // We already checked that targets are different blocks,
8386 // and bb_idx has a different terminator from both of them.
84- let new_stmts = self . new_stmts ( tcx, targets, param_env, bbs, discr_local, discr_ty) ;
8587 let ( _, first) = targets. iter ( ) . next ( ) . unwrap ( ) ;
86- let ( from, first) = bbs. pick2_mut ( switch_bb_idx, first) ;
87- from. statements
88- . push ( Statement { source_info, kind : StatementKind :: StorageLive ( discr_local) } ) ;
89- from. statements . push ( Statement {
90- source_info,
91- kind : StatementKind :: Assign ( Box :: new ( ( Place :: from ( discr_local) , Rvalue :: Use ( discr) ) ) ) ,
92- } ) ;
93- from. statements . extend ( new_stmts) ;
94- from. statements
95- . push ( Statement { source_info, kind : StatementKind :: StorageDead ( discr_local) } ) ;
96- from. terminator_mut ( ) . kind = first. terminator ( ) . kind . clone ( ) ;
88+ let statement_index = bbs[ switch_bb_idx] . statements . len ( ) ;
89+ let parent_end = Location { block : switch_bb_idx, statement_index } ;
90+ patch. add_statement ( parent_end, StatementKind :: StorageLive ( discr_local) ) ;
91+ patch. add_assign ( parent_end, Place :: from ( discr_local) , Rvalue :: Use ( discr) ) ;
92+ self . new_stmts ( tcx, targets, param_env, & mut patch, parent_end, bbs, discr_local, discr_ty) ;
93+ patch. add_statement ( parent_end, StatementKind :: StorageDead ( discr_local) ) ;
94+ patch. patch_terminator ( switch_bb_idx, bbs[ first] . terminator ( ) . kind . clone ( ) ) ;
95+ patch. apply ( body) ;
9796 true
9897 }
9998
@@ -102,7 +101,7 @@ trait SimplifyMatch<'tcx> {
102101 tcx : TyCtxt < ' tcx > ,
103102 targets : & SwitchTargets ,
104103 param_env : ParamEnv < ' tcx > ,
105- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
104+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
106105 discr_ty : Ty < ' tcx > ,
107106 ) -> bool ;
108107
@@ -111,10 +110,12 @@ trait SimplifyMatch<'tcx> {
111110 tcx : TyCtxt < ' tcx > ,
112111 targets : & SwitchTargets ,
113112 param_env : ParamEnv < ' tcx > ,
114- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
113+ patch : & mut MirPatch < ' tcx > ,
114+ parent_end : Location ,
115+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
115116 discr_local : Local ,
116117 discr_ty : Ty < ' tcx > ,
117- ) -> Vec < Statement < ' tcx > > ;
118+ ) ;
118119}
119120
120121struct SimplifyToIf ;
@@ -156,7 +157,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
156157 tcx : TyCtxt < ' tcx > ,
157158 targets : & SwitchTargets ,
158159 param_env : ParamEnv < ' tcx > ,
159- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
160+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
160161 _discr_ty : Ty < ' tcx > ,
161162 ) -> bool {
162163 if targets. iter ( ) . len ( ) != 1 {
@@ -207,20 +208,23 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
207208 tcx : TyCtxt < ' tcx > ,
208209 targets : & SwitchTargets ,
209210 param_env : ParamEnv < ' tcx > ,
210- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
211+ patch : & mut MirPatch < ' tcx > ,
212+ parent_end : Location ,
213+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
211214 discr_local : Local ,
212215 discr_ty : Ty < ' tcx > ,
213- ) -> Vec < Statement < ' tcx > > {
216+ ) {
214217 let ( val, first) = targets. iter ( ) . next ( ) . unwrap ( ) ;
215218 let second = targets. otherwise ( ) ;
216219 // We already checked that first and second are different blocks,
217220 // and bb_idx has a different terminator from both of them.
218221 let first = & bbs[ first] ;
219222 let second = & bbs[ second] ;
220-
221- let new_stmts = iter:: zip ( & first. statements , & second. statements ) . map ( |( f, s) | {
223+ for ( f, s) in iter:: zip ( & first. statements , & second. statements ) {
222224 match ( & f. kind , & s. kind ) {
223- ( f_s, s_s) if f_s == s_s => ( * f) . clone ( ) ,
225+ ( f_s, s_s) if f_s == s_s => {
226+ patch. add_statement ( parent_end, f. kind . clone ( ) ) ;
227+ }
224228
225229 (
226230 StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
@@ -231,7 +235,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
231235 let s_b = s_c. const_ . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
232236 if f_b == s_b {
233237 // Same value in both blocks. Use statement as is.
234- ( * f ) . clone ( )
238+ patch . add_statement ( parent_end , f . kind . clone ( ) ) ;
235239 } else {
236240 // Different value between blocks. Make value conditional on switch condition.
237241 let size = tcx. layout_of ( param_env. and ( discr_ty) ) . unwrap ( ) . size ;
@@ -246,17 +250,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
246250 op,
247251 Box :: new ( ( Operand :: Copy ( Place :: from ( discr_local) ) , const_cmp) ) ,
248252 ) ;
249- Statement {
250- source_info : f. source_info ,
251- kind : StatementKind :: Assign ( Box :: new ( ( * lhs, rhs) ) ) ,
252- }
253+ patch. add_assign ( parent_end, * lhs, rhs) ;
253254 }
254255 }
255256
256257 _ => unreachable ! ( ) ,
257258 }
258- } ) ;
259- new_stmts. collect ( )
259+ }
260260 }
261261}
262262
@@ -333,7 +333,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
333333 tcx : TyCtxt < ' tcx > ,
334334 targets : & SwitchTargets ,
335335 param_env : ParamEnv < ' tcx > ,
336- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
336+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
337337 discr_ty : Ty < ' tcx > ,
338338 ) -> bool {
339339 if targets. iter ( ) . len ( ) < 2 || targets. iter ( ) . len ( ) > 64 {
@@ -467,16 +467,20 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
467467 _tcx : TyCtxt < ' tcx > ,
468468 targets : & SwitchTargets ,
469469 _param_env : ParamEnv < ' tcx > ,
470- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
470+ patch : & mut MirPatch < ' tcx > ,
471+ parent_end : Location ,
472+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
471473 discr_local : Local ,
472474 discr_ty : Ty < ' tcx > ,
473- ) -> Vec < Statement < ' tcx > > {
475+ ) {
474476 let ( _, first) = targets. iter ( ) . next ( ) . unwrap ( ) ;
475477 let first = & bbs[ first] ;
476478
477- let new_stmts =
478- iter:: zip ( & self . transfrom_types , & first. statements ) . map ( |( t, s) | match ( t, & s. kind ) {
479- ( TransfromType :: Same , _) | ( TransfromType :: Eq , _) => ( * s) . clone ( ) ,
479+ for ( t, s) in iter:: zip ( & self . transfrom_types , & first. statements ) {
480+ match ( t, & s. kind ) {
481+ ( TransfromType :: Same , _) | ( TransfromType :: Eq , _) => {
482+ patch. add_statement ( parent_end, s. kind . clone ( ) ) ;
483+ }
480484 (
481485 TransfromType :: Discr ,
482486 StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
@@ -487,13 +491,10 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
487491 } else {
488492 Rvalue :: Cast ( CastKind :: IntToInt , operand, f_c. const_ . ty ( ) )
489493 } ;
490- Statement {
491- source_info : s. source_info ,
492- kind : StatementKind :: Assign ( Box :: new ( ( * lhs, r_val) ) ) ,
493- }
494+ patch. add_assign ( parent_end, * lhs, r_val) ;
494495 }
495496 _ => unreachable ! ( ) ,
496- } ) ;
497- new_stmts . collect ( )
497+ }
498+ }
498499 }
499500}
0 commit comments