@@ -4,14 +4,9 @@ use crate::transform::MirPass;
44use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
55use rustc_hir:: Mutability ;
66use rustc_index:: vec:: Idx ;
7+ use rustc_middle:: mir:: visit:: { MutVisitor , Visitor } ;
78use 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 ,
1510} ;
1611use rustc_middle:: ty:: { self , TyCtxt } ;
1712use std:: mem;
@@ -90,38 +85,10 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
9085 }
9186 }
9287
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-
10088 // We do not call super_rvalue as we are not interested in any other parts of the tree
10189 }
10290}
10391
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-
12592/// Finds optimization opportunities on the MIR.
12693struct OptimizationFinder < ' b , ' tcx > {
12794 body : & ' b Body < ' tcx > ,
@@ -134,103 +101,6 @@ impl OptimizationFinder<'b, 'tcx> {
134101 OptimizationFinder { body, tcx, optimizations : OptimizationList :: default ( ) }
135102 }
136103
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-
234104 fn find_unneeded_equality_comparison ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
235105 // find Ne(_place, false) or Ne(false, _place)
236106 // or Eq(_place, true) or Eq(true, _place)
@@ -295,8 +165,6 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> {
295165 }
296166 }
297167
298- let _ = self . find_deref_of_address ( rvalue, location) ;
299-
300168 self . find_unneeded_equality_comparison ( rvalue, location) ;
301169
302170 // 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> {
308176 and_stars : FxHashSet < Location > ,
309177 arrays_lengths : FxHashMap < Location , Constant < ' tcx > > ,
310178 unneeded_equality_comparison : FxHashMap < Location , Operand < ' tcx > > ,
311- unneeded_deref : FxHashMap < Location , Place < ' tcx > > ,
312179}
313180
314181impl < ' tcx > OptimizationList < ' tcx > {
315182 fn is_empty ( & self ) -> bool {
316183 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 } => {
323185 and_stars. is_empty ( )
324186 && arrays_lengths. is_empty ( )
325187 && unneeded_equality_comparison. is_empty ( )
326- && unneeded_deref. is_empty ( )
327188 }
328189 }
329190 }
0 commit comments