Created
April 8, 2020 18:27
-
-
Save jonas-schievink/81897788c04417b035a307ce716e6b63 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! NRVO on acyclic CFGs. | |
use crate::transform::{MirPass, MirSource}; | |
use rustc_middle::mir::visit::Visitor; | |
use rustc_middle::mir::{ | |
read_only, Body, BodyAndCache, Constant, Local, LocalKind, Location, Operand, Place, Rvalue, | |
StatementKind, Statement, | |
}; | |
use rustc_middle::ty::TyCtxt; | |
use rustc_index::vec::IndexVec; | |
pub struct Nrvo; | |
impl<'tcx> MirPass<'tcx> for Nrvo { | |
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { | |
// We only run when the MIR optimization level is > 1. | |
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { | |
return; | |
} | |
// We do not handle cyclic CFGs yet. | |
if body.is_cfg_cyclic() { | |
return; | |
} | |
// Determine candidate pairs of locals. | |
let find = FindCandidates::new(body); | |
find.visit_body(body); | |
for candidate in find.into_candidate_iter() { | |
} | |
} | |
} | |
struct CandidateAssignment { | |
dest: Local, | |
src: Local, | |
loc: Location, | |
} | |
struct FindCandidates { | |
/// Collects assignments of the form `dest = src;`. | |
local_assignments: IndexVec<Local, Vec<(Local, Location)>>, | |
} | |
impl FindCandidates { | |
fn new(body: &Body<'_>) -> Self { | |
Self { | |
local_assignments: IndexVec::from_elem_n(Vec::new(), body.local_decls.len()), | |
} | |
} | |
fn into_candidate_iter(self) -> impl Iterator<Item = CandidateAssignment> { | |
self.local_assignments.into_iter_enumerated().flat_map(|(dest, vec)| { | |
vec.into_iter().map(move |(src, loc)| CandidateAssignment { | |
dest, src, loc, | |
}) | |
}) | |
} | |
} | |
impl<'tcx> Visitor<'tcx> for FindCandidates { | |
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { | |
match &statement.kind { | |
StatementKind::Assign(box (dest, Rvalue::Use(operand))) => { | |
if let Some(src) = operand.place() { | |
// We only care about direct local-to-local assignments. | |
if dest.projection.is_empty() && src.projection.is_empty() { | |
self.local_assignments[dest.local].push((src.local, location)); | |
} | |
} | |
} | |
_ => {} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment