Skip to content

Commit

Permalink
InstCombine Len([_; N]) => const N in MIR
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmcm committed Nov 25, 2017
1 parent ca8ef26 commit 62391c8
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 8 deletions.
33 changes: 25 additions & 8 deletions src/librustc_mir/transform/instcombine.rs
Expand Up @@ -10,10 +10,10 @@

//! 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::ty::TyCtxt;
use rustc::util::nodemap::FxHashSet;
use rustc::ty::{TyCtxt, TypeVariants};
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::Idx;
use std::mem;
use transform::{MirPass, MirSource};
Expand Down Expand Up @@ -44,11 +44,11 @@ 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);
Expand All @@ -62,6 +62,11 @@ impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor {
*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)
}
}
Expand All @@ -70,7 +75,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> {
Expand All @@ -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)
}
}

#[derive(Default)]
struct OptimizationList {
struct OptimizationList<'tcx> {
and_stars: FxHashSet<Location>,
arrays_lengths: FxHashMap<Location, Constant<'tcx>>,
}
33 changes: 33 additions & 0 deletions src/test/mir-opt/combine_array_len.rs
@@ -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

0 comments on commit 62391c8

Please sign in to comment.