@@ -24,11 +24,7 @@ impl<'tcx> crate::MirPass<'tcx> for MergeBranchSimplification {
24
24
let param_env = tcx. param_env_reveal_all_normalized ( def_id) ;
25
25
26
26
let borrowed_locals = borrowed_locals ( body) ;
27
- let mut maybe_live: ResultsCursor < ' _ , ' _ , MaybeTransitiveLiveLocals < ' _ > > =
28
- MaybeTransitiveLiveLocals :: new ( & borrowed_locals)
29
- . into_engine ( tcx, body)
30
- . iterate_to_fixpoint ( )
31
- . into_results_cursor ( body) ;
27
+ let mut stmt_live_result = StatementLiveResult :: new ( tcx, body, & borrowed_locals) ;
32
28
for i in 0 ..body. basic_blocks . len ( ) {
33
29
let bbs = & * body. basic_blocks ;
34
30
let switch_bb_idx = BasicBlock :: from_usize ( i) ;
@@ -75,8 +71,7 @@ impl<'tcx> crate::MirPass<'tcx> for MergeBranchSimplification {
75
71
targets,
76
72
src_place,
77
73
src_ty,
78
- & borrowed_locals,
79
- & mut maybe_live,
74
+ & mut stmt_live_result,
80
75
) {
81
76
let statement_index = bbs[ switch_bb_idx] . statements . len ( ) ;
82
77
let parent_end = Location { block : switch_bb_idx, statement_index } ;
@@ -93,6 +88,33 @@ impl<'tcx> crate::MirPass<'tcx> for MergeBranchSimplification {
93
88
}
94
89
}
95
90
91
+ struct StatementLiveResult < ' tcx , ' mir , ' a > {
92
+ tcx : TyCtxt < ' tcx > ,
93
+ body : & ' mir Body < ' tcx > ,
94
+ result : Option < ResultsCursor < ' mir , ' tcx , MaybeTransitiveLiveLocals < ' a > > > ,
95
+ borrowed_locals : & ' a BitSet < Local > ,
96
+ }
97
+
98
+ impl < ' tcx , ' mir , ' a > StatementLiveResult < ' tcx , ' mir , ' a > {
99
+ fn new ( tcx : TyCtxt < ' tcx > , body : & ' mir Body < ' tcx > , borrowed_locals : & ' a BitSet < Local > ) -> Self {
100
+ Self { tcx, body, result : None , borrowed_locals }
101
+ }
102
+
103
+ fn is_live ( & mut self , loc : Location , local : Local ) -> bool {
104
+ if self . borrowed_locals . contains ( local) {
105
+ return true ;
106
+ }
107
+ let maybe_live = self . result . get_or_insert_with ( || {
108
+ MaybeTransitiveLiveLocals :: new ( & self . borrowed_locals )
109
+ . into_engine ( self . tcx , self . body )
110
+ . iterate_to_fixpoint ( )
111
+ . into_results_cursor ( self . body )
112
+ } ) ;
113
+ maybe_live. seek_before_primary_effect ( loc) ;
114
+ maybe_live. get ( ) . contains ( local)
115
+ }
116
+ }
117
+
96
118
/// The GVN simplified
97
119
/// ```ignore (syntax-highlighting-only)
98
120
/// match a {
@@ -116,22 +138,11 @@ fn can_simplify_to_copy<'tcx>(
116
138
targets : & SwitchTargets ,
117
139
src_place : Place < ' tcx > ,
118
140
src_ty : tcx:: PlaceTy < ' tcx > ,
119
- borrowed_locals : & BitSet < Local > ,
120
- maybe_live : & mut ResultsCursor < ' _ , ' tcx , MaybeTransitiveLiveLocals < ' _ > > ,
141
+ stmt_live_result : & mut StatementLiveResult < ' tcx , ' _ , ' _ > ,
121
142
) -> Option < Place < ' tcx > > {
122
143
let mut targets_iter = targets. iter ( ) ;
123
144
let dest_place = targets_iter. next ( ) . and_then ( |( index, target) | {
124
- find_copy_assign (
125
- tcx,
126
- param_env,
127
- body,
128
- index,
129
- target,
130
- src_place,
131
- src_ty,
132
- borrowed_locals,
133
- maybe_live,
134
- )
145
+ find_copy_assign ( tcx, param_env, body, index, target, src_place, src_ty, stmt_live_result)
135
146
} ) ?;
136
147
let dest_ty = dest_place. ty ( body. local_decls ( ) , tcx) ;
137
148
if dest_ty. ty != src_ty. ty || dest_ty. variant_index . is_some ( ) {
@@ -147,8 +158,7 @@ fn can_simplify_to_copy<'tcx>(
147
158
other_target,
148
159
src_place,
149
160
src_ty,
150
- borrowed_locals,
151
- maybe_live,
161
+ stmt_live_result,
152
162
)
153
163
} ) {
154
164
return None ;
@@ -164,8 +174,7 @@ fn find_copy_assign<'tcx>(
164
174
target_block : BasicBlock ,
165
175
src_place : Place < ' tcx > ,
166
176
src_ty : tcx:: PlaceTy < ' tcx > ,
167
- borrowed_locals : & BitSet < Local > ,
168
- maybe_live : & mut ResultsCursor < ' _ , ' tcx , MaybeTransitiveLiveLocals < ' _ > > ,
177
+ stmt_live_result : & mut StatementLiveResult < ' tcx , ' _ , ' _ > ,
169
178
) -> Option < Place < ' tcx > > {
170
179
let statements = & body. basic_blocks [ target_block] . statements ;
171
180
if statements. is_empty ( ) {
@@ -190,11 +199,10 @@ fn find_copy_assign<'tcx>(
190
199
StatementKind :: Assign ( box ( dest_place, _) )
191
200
| StatementKind :: SetDiscriminant { place : box dest_place, .. }
192
201
| StatementKind :: Deinit ( box dest_place) => {
193
- if dest_place. is_indirect ( ) || borrowed_locals . contains ( dest_place . local ) {
202
+ if dest_place. is_indirect ( ) {
194
203
return None ;
195
204
}
196
- maybe_live. seek_before_primary_effect ( loc) ;
197
- if !maybe_live. get ( ) . contains ( dest_place. local ) {
205
+ if !stmt_live_result. is_live ( loc, dest_place. local ) {
198
206
lived_stmts. remove ( statement_index) ;
199
207
} else if matches ! ( statement. kind, StatementKind :: Assign ( _) )
200
208
&& expected_assign_stmt. is_none ( )
0 commit comments