]> git.lizzy.rs Git - rust.git/commitdiff
Use IndexVec instead of FxHashMap
authorOliver Schneider <public.oliver.schneider@kit.edu>
Mon, 29 Jan 2018 14:12:45 +0000 (15:12 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 8 Mar 2018 07:34:14 +0000 (08:34 +0100)
src/librustc_mir/transform/const_prop.rs

index 35fce184bebe8e610fe702cda8bda91df4b422a7..e1a1c47373015c25fcd1cb892ba6a1d767206533 100644 (file)
 
 use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local};
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
-use rustc::mir::TerminatorKind;
+use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo};
 use rustc::mir::visit::Visitor;
+use rustc::ty::layout::LayoutOf;
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, PrimVal, GlobalId};
 use interpret::{eval_body_with_mir, eval_body, mk_borrowck_eval_cx, unary_op, ValTy};
-use rustc::util::nodemap::FxHashMap;
 use transform::{MirPass, MirSource};
 use syntax::codemap::Span;
 use rustc::ty::subst::Substs;
+use rustc_data_structures::indexed_vec::IndexVec;
 
 pub struct ConstProp;
 
@@ -35,9 +36,10 @@ fn run_pass<'a, 'tcx>(&self,
                           mir: &mut Mir<'tcx>) {
         trace!("ConstProp starting for {:?}", source.def_id);
 
-        // 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.
-        // `Place::ty()`).
+        // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
+        // constants, instead of just checking for const-folding succeeding.
+        // That would require an uniform one-def no-mutation analysis
+        // and RPO (or recursing when needing the value of a local).
         let mut optimization_finder = OptimizationFinder::new(mir, tcx, source);
         optimization_finder.visit_mir(mir);
 
@@ -52,7 +54,7 @@ struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
     mir: &'b Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     source: MirSource,
-    places: FxHashMap<Local, Const<'tcx>>,
+    places: IndexVec<Local, Option<Const<'tcx>>>,
 }
 
 impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
@@ -65,7 +67,7 @@ fn new(
             mir,
             tcx,
             source,
-            places: FxHashMap::default(),
+            places: IndexVec::from_elem(None, &mir.local_decls),
         }
     }
 
@@ -117,7 +119,7 @@ fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
         match *op {
             Operand::Constant(ref c) => self.eval_constant(c),
             Operand::Move(ref place) | Operand::Copy(ref place) => match *place {
-                Place::Local(loc) => self.places.get(&loc).cloned(),
+                Place::Local(loc) => self.places[loc].clone(),
                 // FIXME(oli-obk): field and index projections
                 Place::Projection(_) => None,
                 _ => None,
@@ -129,8 +131,9 @@ fn const_prop(
         &mut self,
         rvalue: &Rvalue<'tcx>,
         place_ty: ty::Ty<'tcx>,
-        span: Span,
+        source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
+        let span = source_info.span;
         match *rvalue {
             // No need to overwrite an already evaluated constant
             Rvalue::Use(Operand::Constant(box Constant {
@@ -213,20 +216,12 @@ fn const_prop(
                 let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
                 let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
-                let param_env = ParamEnv::empty(traits::Reveal::All);
-                let bits = (self.tcx, param_env).layout_of(left.ty).unwrap().size.bits();
-                if r >= bits as u128 {
-                    let data = &self.mir[location.block];
-                    let stmt_idx = location.statement_index;
-                    let source_info = if stmt_idx < data.statements.len() {
-                        data.statements[stmt_idx].source_info
-                    } else {
-                        data.terminator().source_info
-                    };
-                    let span = source_info.span;
+                let param_env = self.tcx.param_env(self.source.def_id);
+                let bits = (self.tcx, param_env).layout_of(left.1).unwrap().size.bits();
+                if r.to_bytes().ok()? >= bits as u128 {
                     let scope_info = match self.mir.visibility_scope_info {
                         ClearCrossCrate::Set(ref data) => data,
-                        ClearCrossCrate::Clear => return,
+                        ClearCrossCrate::Clear => return None,
                     };
                     let node_id = scope_info[source_info.scope].lint_root;
                     self.tcx.lint_node(
@@ -369,13 +364,13 @@ fn visit_statement(
             let place_ty = place
                 .ty(&self.mir.local_decls, self.tcx)
                 .to_ty(self.tcx);
-            let span = statement.source_info.span;
-            if let Some(value) = self.const_prop(rval, place_ty, span) {
+            if let Some(value) = self.const_prop(rval, place_ty, statement.source_info) {
                 if let Place::Local(local) = *place {
                     if self.mir.local_kind(local) == LocalKind::Temp
                         && CanConstProp::check(local, self.mir) {
                         trace!("storing {:?} to {:?}", value, local);
-                        assert!(self.places.insert(local, value).is_none());
+                        assert!(self.places[local].is_none());
+                        self.places[local] = Some(value);
                     }
                 }
             }