InstCombine Len([_; N]) => const N in MIR
This commit is contained in:
parent
ca8ef26293
commit
62391c8c86
@ -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>>,
|
||||||
}
|
}
|
||||||
|
33
src/test/mir-opt/combine_array_len.rs
Normal file
33
src/test/mir-opt/combine_array_len.rs
Normal 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
|
Loading…
Reference in New Issue
Block a user