about summary refs log tree commit diff
path: root/src/librustc_codegen_ssa
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2019-07-01 23:30:38 +0200
committerSantiago Pastorino <spastorino@gmail.com>2019-07-20 05:08:38 +0200
commit98d232487533c5ce157d2a1101bdc401253af82c (patch)
treef7a8f1f1703bc25e8746ef98aa3731cc62496416 /src/librustc_codegen_ssa
parentd0accade3e094d3196dfdda94dee7d4a359fc130 (diff)
downloadrust-98d232487533c5ce157d2a1101bdc401253af82c.tar.gz
rust-98d232487533c5ce157d2a1101bdc401253af82c.zip
Avoid cloning place in LocalAnalyzer visitor
Diffstat (limited to 'src/librustc_codegen_ssa')
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs141
1 files changed, 85 insertions, 56 deletions
diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs
index be02a2ac179..053b28e003c 100644
--- a/src/librustc_codegen_ssa/mir/analyze.rs
+++ b/src/librustc_codegen_ssa/mir/analyze.rs
@@ -92,6 +92,86 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
             self.first_assignment[local] = location;
         }
     }
+
+    fn process_place(&mut self,
+                     place_ref: &mir::PlaceRef<'_, 'tcx>,
+                     context: PlaceContext,
+                     location: Location) {
+        let cx = self.fx.cx;
+
+        if let Some(proj) = place_ref.projection {
+            // Allow uses of projections that are ZSTs or from scalar fields.
+            let is_consume = match context {
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
+                _ => false
+            };
+            if is_consume {
+                let base_ty =
+                    mir::Place::ty_from(place_ref.base, &proj.base, self.fx.mir, cx.tcx());
+                let base_ty = self.fx.monomorphize(&base_ty);
+
+                // ZSTs don't require any actual memory access.
+                let elem_ty = base_ty
+                    .projection_ty(cx.tcx(), &proj.elem)
+                    .ty;
+                let elem_ty = self.fx.monomorphize(&elem_ty);
+                if cx.layout_of(elem_ty).is_zst() {
+                    return;
+                }
+
+                if let mir::ProjectionElem::Field(..) = proj.elem {
+                    let layout = cx.layout_of(base_ty.ty);
+                    if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
+                        // Recurse with the same context, instead of `Projection`,
+                        // potentially stopping at non-operand projections,
+                        // which would trigger `not_ssa` on locals.
+                        self.process_place(
+                            &mir::PlaceRef {
+                                base: place_ref.base,
+                                projection: &proj.base,
+                            },
+                            context,
+                            location,
+                        );
+                        return;
+                    }
+                }
+            }
+
+            // A deref projection only reads the pointer, never needs the place.
+            if let mir::ProjectionElem::Deref = proj.elem {
+                self.process_place(
+                    &mir::PlaceRef {
+                        base: place_ref.base,
+                        projection: &proj.base,
+                    },
+                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+                    location
+                );
+                return;
+            }
+        }
+
+        // FIXME this is super_place code, is repeated here to avoid cloning place or changing
+        // visit_place API
+        let mut context = context;
+
+        if place_ref.projection.is_some() {
+            context = if context.is_mutating_use() {
+                PlaceContext::MutatingUse(MutatingUseContext::Projection)
+            } else {
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
+            };
+        }
+
+        self.visit_place_base(place_ref.base, context, location);
+
+        if let Some(box proj) = place_ref.projection {
+            self.visit_projection(place_ref.base, proj, context, location);
+        }
+    }
+
 }
 
 impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
@@ -158,63 +238,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
                    context: PlaceContext,
                    location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
-        let cx = self.fx.cx;
-
-        if let Some(proj) = &place.projection {
-            // Allow uses of projections that are ZSTs or from scalar fields.
-            let is_consume = match context {
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) |
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => true,
-                _ => false
-            };
-            if is_consume {
-                let base_ty = mir::Place::ty_from(&place.base, &proj.base, self.fx.mir, cx.tcx());
-                let base_ty = self.fx.monomorphize(&base_ty);
-
-                // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty
-                    .projection_ty(cx.tcx(), &proj.elem)
-                    .ty;
-                let elem_ty = self.fx.monomorphize(&elem_ty);
-                if cx.layout_of(elem_ty).is_zst() {
-                    return;
-                }
-
-                if let mir::ProjectionElem::Field(..) = proj.elem {
-                    let layout = cx.layout_of(base_ty.ty);
-                    if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
-                        // Recurse with the same context, instead of `Projection`,
-                        // potentially stopping at non-operand projections,
-                        // which would trigger `not_ssa` on locals.
-                        self.visit_place(
-                            // FIXME do not clone
-                            &mir::Place {
-                                base: place.base.clone(),
-                                projection: proj.base.clone(),
-                            },
-                            context,
-                            location,
-                        );
-                        return;
-                    }
-                }
-            }
-
-            // A deref projection only reads the pointer, never needs the place.
-            if let mir::ProjectionElem::Deref = proj.elem {
-                return self.visit_place(
-                    // FIXME do not clone
-                    &mir::Place {
-                        base: place.base.clone(),
-                        projection: proj.base.clone(),
-                    },
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                    location
-                );
-            }
-        }
 
-        self.super_place(place, context, location);
+        let place_ref = mir::PlaceRef {
+            base: &place.base,
+            projection: &place.projection,
+        };
+        self.process_place(&place_ref, context, location);
     }
 
     fn visit_local(&mut self,