1
- use rustc_index:: IndexVec ;
1
+ use rustc_index:: IndexSlice ;
2
+ use rustc_middle:: mir:: patch:: MirPatch ;
2
3
use rustc_middle:: mir:: * ;
3
4
use rustc_middle:: ty:: { ParamEnv , ScalarInt , Ty , TyCtxt } ;
4
5
use std:: iter;
@@ -16,9 +17,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
16
17
let def_id = body. source . def_id ( ) ;
17
18
let param_env = tcx. param_env_reveal_all_normalized ( def_id) ;
18
19
19
- let bbs = body. basic_blocks . as_mut ( ) ;
20
20
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) ;
22
24
if !tcx. consider_optimizing ( || format ! ( "MatchBranchSimplification {def_id:?} " ) ) {
23
25
continue ;
24
26
}
@@ -34,12 +36,11 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
34
36
_ => continue ,
35
37
} ;
36
38
37
- if SimplifyToIf . simplify ( tcx, & mut body. local_decls , bbs , bb_idx, param_env) {
39
+ if SimplifyToIf . simplify ( tcx, body, bb_idx, param_env) {
38
40
should_cleanup = true ;
39
41
continue ;
40
42
}
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) {
43
44
should_cleanup = true ;
44
45
continue ;
45
46
}
@@ -57,43 +58,42 @@ trait SimplifyMatch<'tcx> {
57
58
fn simplify (
58
59
& mut self ,
59
60
tcx : TyCtxt < ' tcx > ,
60
- local_decls : & mut IndexVec < Local , LocalDecl < ' tcx > > ,
61
- bbs : & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
61
+ body : & mut Body < ' tcx > ,
62
62
switch_bb_idx : BasicBlock ,
63
63
param_env : ParamEnv < ' tcx > ,
64
64
) -> bool {
65
+ let bbs = & body. basic_blocks ;
65
66
let ( discr, targets) = match bbs[ switch_bb_idx] . terminator ( ) . kind {
66
67
TerminatorKind :: SwitchInt { ref discr, ref targets, .. } => ( discr, targets) ,
67
68
_ => unreachable ! ( ) ,
68
69
} ;
69
70
70
- let discr_ty = discr. ty ( local_decls, tcx) ;
71
+ // let local_decls = body.local_decls();
72
+ let discr_ty = discr. ty ( body. local_decls ( ) , tcx) ;
71
73
if !self . can_simplify ( tcx, targets, param_env, bbs, discr_ty) {
72
74
return false ;
73
75
}
74
76
77
+ let mut patch = MirPatch :: new ( body) ;
78
+
75
79
// Take ownership of items now that we know we can optimize.
76
80
let discr = discr. clone ( ) ;
77
81
78
82
// Introduce a temporary for the discriminant value.
79
83
let source_info = bbs[ switch_bb_idx] . terminator ( ) . source_info ;
80
- let discr_local = local_decls . push ( LocalDecl :: new ( discr_ty, source_info. span ) ) ;
84
+ let discr_local = patch . new_temp ( discr_ty, source_info. span ) ;
81
85
82
86
// We already checked that targets are different blocks,
83
87
// 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) ;
85
88
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 ( ) ;
89
+ let statement_index = bbs[ switch_bb_idx] . statements . len ( ) ;
90
+ let parent_end = Location { block : switch_bb_idx, statement_index } ;
91
+ patch. add_statement ( parent_end, StatementKind :: StorageLive ( discr_local) ) ;
92
+ patch. add_assign ( parent_end, Place :: from ( discr_local) , Rvalue :: Use ( discr) ) ;
93
+ self . new_stmts ( tcx, targets, param_env, & mut patch, parent_end, bbs, discr_local, discr_ty) ;
94
+ patch. add_statement ( parent_end, StatementKind :: StorageDead ( discr_local) ) ;
95
+ patch. patch_terminator ( switch_bb_idx, bbs[ first] . terminator ( ) . kind . clone ( ) ) ;
96
+ patch. apply ( body) ;
97
97
true
98
98
}
99
99
@@ -102,7 +102,7 @@ trait SimplifyMatch<'tcx> {
102
102
tcx : TyCtxt < ' tcx > ,
103
103
targets : & SwitchTargets ,
104
104
param_env : ParamEnv < ' tcx > ,
105
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
105
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
106
106
discr_ty : Ty < ' tcx > ,
107
107
) -> bool ;
108
108
@@ -111,10 +111,12 @@ trait SimplifyMatch<'tcx> {
111
111
tcx : TyCtxt < ' tcx > ,
112
112
targets : & SwitchTargets ,
113
113
param_env : ParamEnv < ' tcx > ,
114
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
114
+ patch : & mut MirPatch < ' tcx > ,
115
+ parent_end : Location ,
116
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
115
117
discr_local : Local ,
116
118
discr_ty : Ty < ' tcx > ,
117
- ) -> Vec < Statement < ' tcx > > ;
119
+ ) ;
118
120
}
119
121
120
122
struct SimplifyToIf ;
@@ -156,7 +158,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
156
158
tcx : TyCtxt < ' tcx > ,
157
159
targets : & SwitchTargets ,
158
160
param_env : ParamEnv < ' tcx > ,
159
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
161
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
160
162
_discr_ty : Ty < ' tcx > ,
161
163
) -> bool {
162
164
if targets. iter ( ) . len ( ) != 1 {
@@ -207,20 +209,23 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
207
209
tcx : TyCtxt < ' tcx > ,
208
210
targets : & SwitchTargets ,
209
211
param_env : ParamEnv < ' tcx > ,
210
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
212
+ patch : & mut MirPatch < ' tcx > ,
213
+ parent_end : Location ,
214
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
211
215
discr_local : Local ,
212
216
discr_ty : Ty < ' tcx > ,
213
- ) -> Vec < Statement < ' tcx > > {
217
+ ) {
214
218
let ( val, first) = targets. iter ( ) . next ( ) . unwrap ( ) ;
215
219
let second = targets. otherwise ( ) ;
216
220
// We already checked that first and second are different blocks,
217
221
// and bb_idx has a different terminator from both of them.
218
222
let first = & bbs[ first] ;
219
223
let second = & bbs[ second] ;
220
-
221
- let new_stmts = iter:: zip ( & first. statements , & second. statements ) . map ( |( f, s) | {
224
+ for ( f, s) in iter:: zip ( & first. statements , & second. statements ) {
222
225
match ( & f. kind , & s. kind ) {
223
- ( f_s, s_s) if f_s == s_s => ( * f) . clone ( ) ,
226
+ ( f_s, s_s) if f_s == s_s => {
227
+ patch. add_statement ( parent_end, f. kind . clone ( ) ) ;
228
+ }
224
229
225
230
(
226
231
StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
@@ -231,7 +236,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
231
236
let s_b = s_c. const_ . try_eval_bool ( tcx, param_env) . unwrap ( ) ;
232
237
if f_b == s_b {
233
238
// Same value in both blocks. Use statement as is.
234
- ( * f ) . clone ( )
239
+ patch . add_statement ( parent_end , f . kind . clone ( ) ) ;
235
240
} else {
236
241
// Different value between blocks. Make value conditional on switch condition.
237
242
let size = tcx. layout_of ( param_env. and ( discr_ty) ) . unwrap ( ) . size ;
@@ -246,17 +251,13 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
246
251
op,
247
252
Box :: new ( ( Operand :: Copy ( Place :: from ( discr_local) ) , const_cmp) ) ,
248
253
) ;
249
- Statement {
250
- source_info : f. source_info ,
251
- kind : StatementKind :: Assign ( Box :: new ( ( * lhs, rhs) ) ) ,
252
- }
254
+ patch. add_assign ( parent_end, * lhs, rhs) ;
253
255
}
254
256
}
255
257
256
258
_ => unreachable ! ( ) ,
257
259
}
258
- } ) ;
259
- new_stmts. collect ( )
260
+ }
260
261
}
261
262
}
262
263
@@ -333,7 +334,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
333
334
tcx : TyCtxt < ' tcx > ,
334
335
targets : & SwitchTargets ,
335
336
param_env : ParamEnv < ' tcx > ,
336
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
337
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
337
338
discr_ty : Ty < ' tcx > ,
338
339
) -> bool {
339
340
if targets. iter ( ) . len ( ) < 2 || targets. iter ( ) . len ( ) > 64 {
@@ -467,16 +468,20 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
467
468
_tcx : TyCtxt < ' tcx > ,
468
469
targets : & SwitchTargets ,
469
470
_param_env : ParamEnv < ' tcx > ,
470
- bbs : & IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
471
+ patch : & mut MirPatch < ' tcx > ,
472
+ parent_end : Location ,
473
+ bbs : & IndexSlice < BasicBlock , BasicBlockData < ' tcx > > ,
471
474
discr_local : Local ,
472
475
discr_ty : Ty < ' tcx > ,
473
- ) -> Vec < Statement < ' tcx > > {
476
+ ) {
474
477
let ( _, first) = targets. iter ( ) . next ( ) . unwrap ( ) ;
475
478
let first = & bbs[ first] ;
476
479
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 ( ) ,
480
+ for ( t, s) in iter:: zip ( & self . transfrom_types , & first. statements ) {
481
+ match ( t, & s. kind ) {
482
+ ( TransfromType :: Same , _) | ( TransfromType :: Eq , _) => {
483
+ patch. add_statement ( parent_end, s. kind . clone ( ) ) ;
484
+ }
480
485
(
481
486
TransfromType :: Discr ,
482
487
StatementKind :: Assign ( box ( lhs, Rvalue :: Use ( Operand :: Constant ( f_c) ) ) ) ,
@@ -487,13 +492,10 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
487
492
} else {
488
493
Rvalue :: Cast ( CastKind :: IntToInt , operand, f_c. const_ . ty ( ) )
489
494
} ;
490
- Statement {
491
- source_info : s. source_info ,
492
- kind : StatementKind :: Assign ( Box :: new ( ( * lhs, r_val) ) ) ,
493
- }
495
+ patch. add_assign ( parent_end, * lhs, r_val) ;
494
496
}
495
497
_ => unreachable ! ( ) ,
496
- } ) ;
497
- new_stmts . collect ( )
498
+ }
499
+ }
498
500
}
499
501
}
0 commit comments