InstCombine Len([_; N]) => const N in MIR

This commit is contained in:
Scott McMurray 2017-11-25 11:59:16 -08:00
parent ca8ef26293
commit 62391c8c86
2 changed files with 58 additions and 8 deletions

View File

@ -10,10 +10,10 @@
//! Performs various peephole optimizations. //! Performs various peephole optimizations.
use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local}; use rustc::mir::{Constant, Literal, Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
use rustc::mir::visit::{MutVisitor, Visitor}; use rustc::mir::visit::{MutVisitor, Visitor};
use rustc::ty::TyCtxt; use rustc::ty::{TyCtxt, TypeVariants};
use rustc::util::nodemap::FxHashSet; use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use std::mem; use std::mem;
use transform::{MirPass, MirSource}; use transform::{MirPass, MirSource};
@ -44,11 +44,11 @@ impl MirPass for InstCombine {
} }
} }
pub struct InstCombineVisitor { pub struct InstCombineVisitor<'tcx> {
optimizations: OptimizationList, 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) { fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
if self.optimizations.and_stars.remove(&location) { if self.optimizations.and_stars.remove(&location) {
debug!("Replacing `&*`: {:?}", rvalue); debug!("Replacing `&*`: {:?}", rvalue);
@ -62,6 +62,11 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
*rvalue = Rvalue::Use(Operand::Consume(new_lvalue)) *rvalue = Rvalue::Use(Operand::Consume(new_lvalue))
} }
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) self.super_rvalue(rvalue, location)
} }
} }
@ -70,7 +75,7 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> { struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> {
mir: &'b Mir<'tcx>, mir: &'b Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
optimizations: OptimizationList, optimizations: OptimizationList<'tcx>,
} }
impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> { impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> {
@ -93,11 +98,23 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
} }
} }
if let Rvalue::Len(ref lvalue) = *rvalue {
let lvalue_ty = lvalue.ty(&self.mir.local_decls, self.tcx).to_ty(self.tcx);
if let TypeVariants::TyArray(_, len) = lvalue_ty.sty {
let span = self.mir.source_info(location).span;
let ty = self.tcx.types.usize;
let literal = Literal::Value { value: len };
let constant = Constant { span, ty, literal };
self.optimizations.arrays_lengths.insert(location, constant);
}
}
self.super_rvalue(rvalue, location) self.super_rvalue(rvalue, location)
} }
} }
#[derive(Default)] #[derive(Default)]
struct OptimizationList { struct OptimizationList<'tcx> {
and_stars: FxHashSet<Location>, and_stars: FxHashSet<Location>,
arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
} }

View File

@ -0,0 +1,33 @@
// Copyright 2017 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.
fn norm2(x: [f32; 2]) -> f32 {
let a = x[0];
let b = x[1];
a*a + b*b
}
fn main() {
assert_eq!(norm2([3.0, 4.0]), 5.0*5.0);
}
// END RUST SOURCE
// START rustc.norm2.InstCombine.before.mir
// _5 = Len(_1);
// ...
// _10 = Len(_1);
// END rustc.norm2.InstCombine.before.mir
// START rustc.norm2.InstCombine.after.mir
// _5 = const 2usize;
// ...
// _10 = const 2usize;
// END rustc.norm2.InstCombine.after.mir