@@ -4,14 +4,9 @@ use crate::transform::MirPass;
4
4
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
5
5
use rustc_hir:: Mutability ;
6
6
use rustc_index:: vec:: Idx ;
7
+ use rustc_middle:: mir:: visit:: { MutVisitor , Visitor } ;
7
8
use rustc_middle:: mir:: {
8
- visit:: PlaceContext ,
9
- visit:: { MutVisitor , Visitor } ,
10
- Statement ,
11
- } ;
12
- use rustc_middle:: mir:: {
13
- BinOp , Body , BorrowKind , Constant , Local , Location , Operand , Place , PlaceRef , ProjectionElem ,
14
- Rvalue ,
9
+ BinOp , Body , Constant , Local , Location , Operand , Place , PlaceRef , ProjectionElem , Rvalue ,
15
10
} ;
16
11
use rustc_middle:: ty:: { self , TyCtxt } ;
17
12
use std:: mem;
@@ -90,38 +85,10 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
90
85
}
91
86
}
92
87
93
- if let Some ( place) = self . optimizations . unneeded_deref . remove ( & location) {
94
- if self . should_combine ( rvalue, location) {
95
- debug ! ( "unneeded_deref: replacing {:?} with {:?}" , rvalue, place) ;
96
- * rvalue = Rvalue :: Use ( Operand :: Copy ( place) ) ;
97
- }
98
- }
99
-
100
88
// We do not call super_rvalue as we are not interested in any other parts of the tree
101
89
}
102
90
}
103
91
104
- struct MutatingUseVisitor {
105
- has_mutating_use : bool ,
106
- local_to_look_for : Local ,
107
- }
108
-
109
- impl MutatingUseVisitor {
110
- fn has_mutating_use_in_stmt ( local : Local , stmt : & Statement < ' tcx > , location : Location ) -> bool {
111
- let mut _self = Self { has_mutating_use : false , local_to_look_for : local } ;
112
- _self. visit_statement ( stmt, location) ;
113
- _self. has_mutating_use
114
- }
115
- }
116
-
117
- impl < ' tcx > Visitor < ' tcx > for MutatingUseVisitor {
118
- fn visit_local ( & mut self , local : & Local , context : PlaceContext , _: Location ) {
119
- if * local == self . local_to_look_for {
120
- self . has_mutating_use |= context. is_mutating_use ( ) ;
121
- }
122
- }
123
- }
124
-
125
92
/// Finds optimization opportunities on the MIR.
126
93
struct OptimizationFinder < ' b , ' tcx > {
127
94
body : & ' b Body < ' tcx > ,
@@ -134,103 +101,6 @@ impl OptimizationFinder<'b, 'tcx> {
134
101
OptimizationFinder { body, tcx, optimizations : OptimizationList :: default ( ) }
135
102
}
136
103
137
- fn find_deref_of_address ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) -> Option < ( ) > {
138
- // FIXME(#78192): This optimization can result in unsoundness.
139
- if !self . tcx . sess . opts . debugging_opts . unsound_mir_opts {
140
- return None ;
141
- }
142
-
143
- // Look for the sequence
144
- //
145
- // _2 = &_1;
146
- // ...
147
- // _5 = (*_2);
148
- //
149
- // which we can replace the last statement with `_5 = _1;` to avoid the load of `_2`.
150
- if let Rvalue :: Use ( op) = rvalue {
151
- let local_being_derefed = match op. place ( ) ?. as_ref ( ) {
152
- PlaceRef { local, projection : [ ProjectionElem :: Deref ] } => Some ( local) ,
153
- _ => None ,
154
- } ?;
155
-
156
- let mut dead_locals_seen = vec ! [ ] ;
157
-
158
- let stmt_index = location. statement_index ;
159
- // Look behind for statement that assigns the local from a address of operator.
160
- // 6 is chosen as a heuristic determined by seeing the number of times
161
- // the optimization kicked in compiling rust std.
162
- let lower_index = stmt_index. saturating_sub ( 6 ) ;
163
- let statements_to_look_in = self . body . basic_blocks ( ) [ location. block ] . statements
164
- [ lower_index..stmt_index]
165
- . iter ( )
166
- . rev ( ) ;
167
- for stmt in statements_to_look_in {
168
- match & stmt. kind {
169
- // Exhaustive match on statements to detect conditions that warrant we bail out of the optimization.
170
- rustc_middle:: mir:: StatementKind :: Assign ( box ( l, r) )
171
- if l. local == local_being_derefed =>
172
- {
173
- match r {
174
- // Looking for immutable reference e.g _local_being_deref = &_1;
175
- Rvalue :: Ref (
176
- _,
177
- // Only apply the optimization if it is an immutable borrow.
178
- BorrowKind :: Shared ,
179
- place_taken_address_of,
180
- ) => {
181
- // Make sure that the place has not been marked dead
182
- if dead_locals_seen. contains ( & place_taken_address_of. local ) {
183
- return None ;
184
- }
185
-
186
- self . optimizations
187
- . unneeded_deref
188
- . insert ( location, * place_taken_address_of) ;
189
- return Some ( ( ) ) ;
190
- }
191
-
192
- // We found an assignment of `local_being_deref` that is not an immutable ref, e.g the following sequence
193
- // _2 = &_1;
194
- // _3 = &5
195
- // _2 = _3; <-- this means it is no longer valid to replace the last statement with `_5 = _1;`
196
- // _5 = (*_2);
197
- _ => return None ,
198
- }
199
- }
200
-
201
- // Inline asm can do anything, so bail out of the optimization.
202
- rustc_middle:: mir:: StatementKind :: LlvmInlineAsm ( _) => return None ,
203
-
204
- // Remember `StorageDead`s, as the local being marked dead could be the
205
- // place RHS we are looking for, in which case we need to abort to avoid UB
206
- // using an uninitialized place
207
- rustc_middle:: mir:: StatementKind :: StorageDead ( dead) => {
208
- dead_locals_seen. push ( * dead)
209
- }
210
-
211
- // Check that `local_being_deref` is not being used in a mutating way which can cause misoptimization.
212
- rustc_middle:: mir:: StatementKind :: Assign ( box ( _, _) )
213
- | rustc_middle:: mir:: StatementKind :: Coverage ( _)
214
- | rustc_middle:: mir:: StatementKind :: Nop
215
- | rustc_middle:: mir:: StatementKind :: FakeRead ( _, _)
216
- | rustc_middle:: mir:: StatementKind :: StorageLive ( _)
217
- | rustc_middle:: mir:: StatementKind :: Retag ( _, _)
218
- | rustc_middle:: mir:: StatementKind :: AscribeUserType ( _, _)
219
- | rustc_middle:: mir:: StatementKind :: SetDiscriminant { .. } => {
220
- if MutatingUseVisitor :: has_mutating_use_in_stmt (
221
- local_being_derefed,
222
- stmt,
223
- location,
224
- ) {
225
- return None ;
226
- }
227
- }
228
- }
229
- }
230
- }
231
- Some ( ( ) )
232
- }
233
-
234
104
fn find_unneeded_equality_comparison ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
235
105
// find Ne(_place, false) or Ne(false, _place)
236
106
// or Eq(_place, true) or Eq(true, _place)
@@ -295,8 +165,6 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
295
165
}
296
166
}
297
167
298
- let _ = self . find_deref_of_address ( rvalue, location) ;
299
-
300
168
self . find_unneeded_equality_comparison ( rvalue, location) ;
301
169
302
170
// We do not call super_rvalue as we are not interested in any other parts of the tree
@@ -308,22 +176,15 @@ struct OptimizationList<'tcx> {
308
176
and_stars : FxHashSet < Location > ,
309
177
arrays_lengths : FxHashMap < Location , Constant < ' tcx > > ,
310
178
unneeded_equality_comparison : FxHashMap < Location , Operand < ' tcx > > ,
311
- unneeded_deref : FxHashMap < Location , Place < ' tcx > > ,
312
179
}
313
180
314
181
impl < ' tcx > OptimizationList < ' tcx > {
315
182
fn is_empty ( & self ) -> bool {
316
183
match self {
317
- OptimizationList {
318
- and_stars,
319
- arrays_lengths,
320
- unneeded_equality_comparison,
321
- unneeded_deref,
322
- } => {
184
+ OptimizationList { and_stars, arrays_lengths, unneeded_equality_comparison } => {
323
185
and_stars. is_empty ( )
324
186
&& arrays_lengths. is_empty ( )
325
187
&& unneeded_equality_comparison. is_empty ( )
326
- && unneeded_deref. is_empty ( )
327
188
}
328
189
}
329
190
}
0 commit comments