]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_mir/transform/instcombine.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_mir / transform / instcombine.rs
index 6ccc886577ac664a1a90f6cbe9ddc261217c7551..290915763e275671df529077793a6d3231c0d73e 100644 (file)
@@ -1,29 +1,19 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
 //! Performs various peephole optimizations.
 
-use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
-use rustc::mir::transform::{MirPass, MirSource};
+use rustc::mir::{Constant, Location, Place, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
-use rustc::ty::TyCtxt;
-use rustc::util::nodemap::FxHashSet;
+use rustc::ty::{TyCtxt, TyKind};
+use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
+use crate::transform::{MirPass, MirSource};
 
 pub struct InstCombine;
 
 impl MirPass for InstCombine {
     fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          _: MirSource,
+                          _: MirSource<'tcx>,
                           mir: &mut Mir<'tcx>) {
         // We only run when optimizing MIR (at any level).
         if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
@@ -32,7 +22,7 @@ impl MirPass for InstCombine {
 
         // First, find optimization opportunities. This is done in a pre-pass to keep the MIR
         // read-only so that we can do global analyses on the MIR in the process (e.g.
-        // `Lvalue::ty()`).
+        // `Place::ty()`).
         let optimizations = {
             let mut optimization_finder = OptimizationFinder::new(mir, tcx);
             optimization_finder.visit_mir(mir);
@@ -44,22 +34,27 @@ impl MirPass for InstCombine {
     }
 }
 
-pub struct InstCombineVisitor {
-    optimizations: OptimizationList,
+pub struct InstCombineVisitor<'tcx> {
+    optimizations: OptimizationList<'tcx>,
 }
 
-impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
+impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor<'tcx> {
     fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
         if self.optimizations.and_stars.remove(&location) {
             debug!("Replacing `&*`: {:?}", rvalue);
-            let new_lvalue = match *rvalue {
-                Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => {
+            let new_place = match *rvalue {
+                Rvalue::Ref(_, _, Place::Projection(ref mut projection)) => {
                     // Replace with dummy
-                    mem::replace(&mut projection.base, Lvalue::Local(Local::new(0)))
+                    mem::replace(&mut projection.base, Place::Local(Local::new(0)))
                 }
                 _ => bug!("Detected `&*` but didn't find `&*`!"),
             };
-            *rvalue = Rvalue::Use(Operand::Consume(new_lvalue))
+            *rvalue = Rvalue::Use(Operand::Copy(new_place))
+        }
+
+        if let Some(constant) = self.optimizations.arrays_lengths.remove(&location) {
+            debug!("Replacing `Len([_; N])`: {:?}", rvalue);
+            *rvalue = Rvalue::Use(Operand::Constant(box constant));
         }
 
         self.super_rvalue(rvalue, location)
@@ -70,7 +65,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
 struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
     mir: &'b Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    optimizations: OptimizationList,
+    optimizations: OptimizationList<'tcx>,
 }
 
 impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
@@ -85,7 +80,7 @@ impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
 
 impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        if let Rvalue::Ref(_, _, Lvalue::Projection(ref projection)) = *rvalue {
+        if let Rvalue::Ref(_, _, Place::Projection(ref projection)) = *rvalue {
             if let ProjectionElem::Deref = projection.elem {
                 if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
                     self.optimizations.and_stars.insert(location);
@@ -93,11 +88,22 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
             }
         }
 
+        if let Rvalue::Len(ref place) = *rvalue {
+            let place_ty = place.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
+            if let TyKind::Array(_, len) = place_ty.sty {
+                let span = self.mir.source_info(location).span;
+                let ty = self.tcx.types.usize;
+                let constant = Constant { span, ty, literal: len, user_ty: None };
+                self.optimizations.arrays_lengths.insert(location, constant);
+            }
+        }
+
         self.super_rvalue(rvalue, location)
     }
 }
 
 #[derive(Default)]
-struct OptimizationList {
+struct OptimizationList<'tcx> {
     and_stars: FxHashSet<Location>,
+    arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
 }