Skip to content

Analyse storage liveness and preserve it during generator transformation #44480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/librustc_data_structures/bitslice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ pub trait BitwiseOperator {
fn join(&self, pred1: usize, pred2: usize) -> usize;
}

pub struct Intersect;
impl BitwiseOperator for Intersect {
#[inline]
fn join(&self, a: usize, b: usize) -> usize { a & b }
}
pub struct Union;
impl BitwiseOperator for Union {
#[inline]
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_data_structures/indexed_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::mem;
use std::ops::{Deref, DerefMut, Range};
use std::slice;
use bitslice::{BitSlice, Word};
use bitslice::{bitwise, Union, Subtract};
use bitslice::{bitwise, Union, Subtract, Intersect};
use indexed_vec::Idx;

/// Represents a set (or packed family of sets), of some element type
Expand Down Expand Up @@ -164,6 +164,10 @@ impl<T: Idx> IdxSet<T> {
bitwise(self.words_mut(), other.words(), &Subtract)
}

pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
bitwise(self.words_mut(), other.words(), &Intersect)
}

pub fn iter(&self) -> Iter<T> {
Iter {
cur: None,
Expand Down
4 changes: 4 additions & 0 deletions src/librustc_mir/dataflow/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ use super::drop_flag_effects_for_function_entry;
use super::drop_flag_effects_for_location;
use super::on_lookup_result_bits;

mod storage_liveness;

pub use self::storage_liveness::*;

#[allow(dead_code)]
pub(super) mod borrows;

Expand Down
82 changes: 82 additions & 0 deletions src/librustc_mir/dataflow/impls/storage_liveness.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// 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.

pub use super::*;

use rustc::mir::*;
use dataflow::BitDenotation;

#[derive(Copy, Clone)]
pub struct MaybeStorageLive<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
}

impl<'a, 'tcx: 'a> MaybeStorageLive<'a, 'tcx> {
pub fn new(mir: &'a Mir<'tcx>)
-> Self {
MaybeStorageLive { mir: mir }
}

pub fn mir(&self) -> &Mir<'tcx> {
self.mir
}
}

impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
type Idx = Local;
fn name() -> &'static str { "maybe_storage_live" }
fn bits_per_block(&self) -> usize {
self.mir.local_decls.len()
}

fn start_block_effect(&self, _sets: &mut BlockSets<Local>) {
// Nothing is live on function entry
}

fn statement_effect(&self,
sets: &mut BlockSets<Local>,
loc: Location) {
let stmt = &self.mir[loc.block].statements[loc.statement_index];

match stmt.kind {
StatementKind::StorageLive(l) => sets.gen(&l),
StatementKind::StorageDead(l) => sets.kill(&l),
_ => (),
}
}

fn terminator_effect(&self,
_sets: &mut BlockSets<Local>,
_loc: Location) {
// Terminators have no effect
}

fn propagate_call_return(&self,
_in_out: &mut IdxSet<Local>,
_call_bb: mir::BasicBlock,
_dest_bb: mir::BasicBlock,
_dest_lval: &mir::Lvalue) {
// Nothing to do when a call returns successfully
}
}

impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> {
#[inline]
fn join(&self, pred1: usize, pred2: usize) -> usize {
pred1 | pred2 // "maybe" means we union effects of both preds
}
}

impl<'a, 'tcx> DataflowOperator for MaybeStorageLive<'a, 'tcx> {
#[inline]
fn bottom_value() -> bool {
false // bottom = dead
}
}
24 changes: 24 additions & 0 deletions src/librustc_mir/dataflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use std::mem;
use std::path::PathBuf;
use std::usize;

pub use self::impls::{MaybeStorageLive};
pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
pub use self::impls::{DefinitelyInitializedLvals};
pub use self::impls::borrows::{Borrows, BorrowData, BorrowIndex};
Expand Down Expand Up @@ -351,6 +352,29 @@ pub trait DataflowResultsConsumer<'a, 'tcx: 'a> {
flow_state: &mut Self::FlowState);
}

pub fn state_for_location<T: BitDenotation>(loc: Location,
analysis: &T,
result: &DataflowResults<T>)
-> IdxSetBuf<T::Idx> {
let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();

{
let mut sets = BlockSets {
on_entry: &mut entry.clone(),
kill_set: &mut entry.clone(),
gen_set: &mut entry,
};

for stmt in 0..loc.statement_index {
let mut stmt_loc = loc;
stmt_loc.statement_index = stmt;
analysis.statement_effect(&mut sets, stmt_loc);
}
}

entry
}

pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
{
flow_state: DataflowState<O>,
Expand Down
Loading