]>
Commit | Line | Data |
---|---|---|
9e0c209e SL |
1 | // Copyright 2016 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Performs various peephole optimizations. | |
12 | ||
c30ab7b3 | 13 | use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local}; |
9e0c209e SL |
14 | use rustc::mir::visit::{MutVisitor, Visitor}; |
15 | use rustc::ty::TyCtxt; | |
476ff2be | 16 | use rustc::util::nodemap::FxHashSet; |
c30ab7b3 | 17 | use rustc_data_structures::indexed_vec::Idx; |
9e0c209e | 18 | use std::mem; |
abe05a73 | 19 | use transform::{MirPass, MirSource}; |
9e0c209e | 20 | |
7cac9316 | 21 | pub struct InstCombine; |
9e0c209e | 22 | |
7cac9316 XL |
23 | impl MirPass for InstCombine { |
24 | fn run_pass<'a, 'tcx>(&self, | |
25 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
26 | _: MirSource, | |
27 | mir: &mut Mir<'tcx>) { | |
9e0c209e | 28 | // We only run when optimizing MIR (at any level). |
476ff2be | 29 | if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { |
9e0c209e SL |
30 | return |
31 | } | |
32 | ||
33 | // First, find optimization opportunities. This is done in a pre-pass to keep the MIR | |
34 | // read-only so that we can do global analyses on the MIR in the process (e.g. | |
35 | // `Lvalue::ty()`). | |
7cac9316 | 36 | let optimizations = { |
9e0c209e SL |
37 | let mut optimization_finder = OptimizationFinder::new(mir, tcx); |
38 | optimization_finder.visit_mir(mir); | |
7cac9316 XL |
39 | optimization_finder.optimizations |
40 | }; | |
9e0c209e SL |
41 | |
42 | // Then carry out those optimizations. | |
7cac9316 | 43 | MutVisitor::visit_mir(&mut InstCombineVisitor { optimizations }, mir); |
9e0c209e SL |
44 | } |
45 | } | |
46 | ||
7cac9316 XL |
47 | pub struct InstCombineVisitor { |
48 | optimizations: OptimizationList, | |
49 | } | |
50 | ||
51 | impl<'tcx> MutVisitor<'tcx> for InstCombineVisitor { | |
9e0c209e SL |
52 | fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { |
53 | if self.optimizations.and_stars.remove(&location) { | |
54 | debug!("Replacing `&*`: {:?}", rvalue); | |
55 | let new_lvalue = match *rvalue { | |
56 | Rvalue::Ref(_, _, Lvalue::Projection(ref mut projection)) => { | |
c30ab7b3 SL |
57 | // Replace with dummy |
58 | mem::replace(&mut projection.base, Lvalue::Local(Local::new(0))) | |
9e0c209e SL |
59 | } |
60 | _ => bug!("Detected `&*` but didn't find `&*`!"), | |
61 | }; | |
62 | *rvalue = Rvalue::Use(Operand::Consume(new_lvalue)) | |
63 | } | |
64 | ||
65 | self.super_rvalue(rvalue, location) | |
66 | } | |
67 | } | |
68 | ||
69 | /// Finds optimization opportunities on the MIR. | |
70 | struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> { | |
71 | mir: &'b Mir<'tcx>, | |
72 | tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
73 | optimizations: OptimizationList, | |
74 | } | |
75 | ||
76 | impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> { | |
77 | fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> { | |
78 | OptimizationFinder { | |
3b2f2976 XL |
79 | mir, |
80 | tcx, | |
9e0c209e SL |
81 | optimizations: OptimizationList::default(), |
82 | } | |
83 | } | |
84 | } | |
85 | ||
86 | impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> { | |
87 | fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { | |
88 | if let Rvalue::Ref(_, _, Lvalue::Projection(ref projection)) = *rvalue { | |
89 | if let ProjectionElem::Deref = projection.elem { | |
90 | if projection.base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() { | |
91 | self.optimizations.and_stars.insert(location); | |
92 | } | |
93 | } | |
94 | } | |
95 | ||
96 | self.super_rvalue(rvalue, location) | |
97 | } | |
98 | } | |
99 | ||
100 | #[derive(Default)] | |
101 | struct OptimizationList { | |
476ff2be | 102 | and_stars: FxHashSet<Location>, |
9e0c209e | 103 | } |