Skip to content

Commit c8cbd4f

Browse files
Merge BitSetOperator and InitialFlow into one trait.
Since the value of `InitialFlow` defines the semantics of the `join` operation, there's no reason to have seperate traits for each. We can add a default impl of `join` which branches based on `BOTTOM_VALUE`. This should get optimized away.
1 parent c054186 commit c8cbd4f

File tree

6 files changed

+51
-115
lines changed

6 files changed

+51
-115
lines changed

src/librustc_data_structures/bit_set.rs

-5
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,6 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
273273
}
274274
}
275275

276-
pub trait BitSetOperator {
277-
/// Combine one bitset into another.
278-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool;
279-
}
280-
281276
#[inline]
282277
fn bitwise<Op>(out_vec: &mut [Word], in_vec: &[Word], op: Op) -> bool
283278
where Op: Fn(Word, Word) -> Word

src/librustc_mir/dataflow/impls/borrowed_locals.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,9 @@ impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
8383
}
8484
}
8585

86-
impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
87-
#[inline]
88-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
89-
inout_set.union(in_set) // "maybe" means we union effects of both preds
90-
}
91-
}
92-
93-
impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
94-
#[inline]
95-
fn bottom_value() -> bool {
96-
false // bottom = unborrowed
97-
}
86+
impl<'a, 'tcx> BottomValue for HaveBeenBorrowedLocals<'a, 'tcx> {
87+
// bottom = unborrowed
88+
const BOTTOM_VALUE: bool = false;
9889
}
9990

10091
struct BorrowedLocalsVisitor<'gk> {

src/librustc_mir/dataflow/impls/borrows.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ use rustc::mir::{self, Location, Place, PlaceBase, Body};
55
use rustc::ty::TyCtxt;
66
use rustc::ty::RegionVid;
77

8-
use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
8+
use rustc_data_structures::bit_set::BitSet;
99
use rustc_data_structures::fx::FxHashMap;
1010
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
1111

12-
use crate::dataflow::{BitDenotation, InitialFlow, GenKillSet};
12+
use crate::dataflow::{BitDenotation, BottomValue, GenKillSet};
1313
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
1414
use crate::borrow_check::nll::ToRegionVid;
1515
use crate::borrow_check::places_conflict;
@@ -331,16 +331,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for Borrows<'a, 'tcx> {
331331
}
332332
}
333333

334-
impl<'a, 'tcx> BitSetOperator for Borrows<'a, 'tcx> {
335-
#[inline]
336-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
337-
inout_set.union(in_set) // "maybe" means we union effects of both preds
338-
}
339-
}
340-
341-
impl<'a, 'tcx> InitialFlow for Borrows<'a, 'tcx> {
342-
#[inline]
343-
fn bottom_value() -> bool {
344-
false // bottom = nothing is reserved or activated yet
345-
}
334+
impl<'a, 'tcx> BottomValue for Borrows<'a, 'tcx> {
335+
/// bottom = nothing is reserved or activated yet;
336+
const BOTTOM_VALUE: bool = false;
346337
}

src/librustc_mir/dataflow/impls/mod.rs

+14-60
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
55
use rustc::ty::TyCtxt;
66
use rustc::mir::{self, Body, Location};
7-
use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
7+
use rustc_data_structures::bit_set::BitSet;
88
use rustc_data_structures::indexed_vec::Idx;
99

1010
use super::MoveDataParamEnv;
1111

1212
use crate::util::elaborate_drops::DropFlagState;
1313

1414
use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex, InitKind};
15-
use super::{BitDenotation, InitialFlow, GenKillSet};
15+
use super::{BitDenotation, BottomValue, GenKillSet};
1616

1717
use super::drop_flag_effects_for_function_entry;
1818
use super::drop_flag_effects_for_location;
@@ -505,68 +505,22 @@ impl<'a, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'tcx> {
505505
}
506506
}
507507

508-
impl<'a, 'tcx> BitSetOperator for MaybeInitializedPlaces<'a, 'tcx> {
509-
#[inline]
510-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
511-
inout_set.union(in_set) // "maybe" means we union effects of both preds
512-
}
513-
}
514-
515-
impl<'a, 'tcx> BitSetOperator for MaybeUninitializedPlaces<'a, 'tcx> {
516-
#[inline]
517-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
518-
inout_set.union(in_set) // "maybe" means we union effects of both preds
519-
}
520-
}
521-
522-
impl<'a, 'tcx> BitSetOperator for DefinitelyInitializedPlaces<'a, 'tcx> {
523-
#[inline]
524-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
525-
inout_set.intersect(in_set) // "definitely" means we intersect effects of both preds
526-
}
527-
}
528-
529-
impl<'a, 'tcx> BitSetOperator for EverInitializedPlaces<'a, 'tcx> {
530-
#[inline]
531-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
532-
inout_set.union(in_set) // inits from both preds are in scope
533-
}
534-
}
535-
536-
// The way that dataflow fixed point iteration works, you want to
537-
// start at bottom and work your way to a fixed point. Control-flow
538-
// merges will apply the `join` operator to each block entry's current
539-
// state (which starts at that bottom value).
540-
//
541-
// This means, for propagation across the graph, that you either want
542-
// to start at all-zeroes and then use Union as your merge when
543-
// propagating, or you start at all-ones and then use Intersect as
544-
// your merge when propagating.
545-
546-
impl<'a, 'tcx> InitialFlow for MaybeInitializedPlaces<'a, 'tcx> {
547-
#[inline]
548-
fn bottom_value() -> bool {
549-
false // bottom = uninitialized
550-
}
508+
impl<'a, 'tcx> BottomValue for MaybeInitializedPlaces<'a, 'tcx> {
509+
/// bottom = uninitialized
510+
const BOTTOM_VALUE: bool = false;
551511
}
552512

553-
impl<'a, 'tcx> InitialFlow for MaybeUninitializedPlaces<'a, 'tcx> {
554-
#[inline]
555-
fn bottom_value() -> bool {
556-
false // bottom = initialized (start_block_effect counters this at outset)
557-
}
513+
impl<'a, 'tcx> BottomValue for MaybeUninitializedPlaces<'a, 'tcx> {
514+
/// bottom = initialized (start_block_effect counters this at outset)
515+
const BOTTOM_VALUE: bool = false;
558516
}
559517

560-
impl<'a, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'tcx> {
561-
#[inline]
562-
fn bottom_value() -> bool {
563-
true // bottom = initialized (start_block_effect counters this at outset)
564-
}
518+
impl<'a, 'tcx> BottomValue for DefinitelyInitializedPlaces<'a, 'tcx> {
519+
/// bottom = initialized (start_block_effect counters this at outset)
520+
const BOTTOM_VALUE: bool = true;
565521
}
566522

567-
impl<'a, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'tcx> {
568-
#[inline]
569-
fn bottom_value() -> bool {
570-
false // bottom = no initialized variables by default
571-
}
523+
impl<'a, 'tcx> BottomValue for EverInitializedPlaces<'a, 'tcx> {
524+
/// bottom = no initialized variables by default
525+
const BOTTOM_VALUE: bool = false;
572526
}

src/librustc_mir/dataflow/impls/storage_liveness.rs

+3-12
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,7 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
5959
}
6060
}
6161

62-
impl<'a, 'tcx> BitSetOperator for MaybeStorageLive<'a, 'tcx> {
63-
#[inline]
64-
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
65-
inout_set.union(in_set) // "maybe" means we union effects of both preds
66-
}
67-
}
68-
69-
impl<'a, 'tcx> InitialFlow for MaybeStorageLive<'a, 'tcx> {
70-
#[inline]
71-
fn bottom_value() -> bool {
72-
false // bottom = dead
73-
}
62+
impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
63+
/// bottom = dead
64+
const BOTTOM_VALUE: bool = false;
7465
}

src/librustc_mir/dataflow/mod.rs

+26-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use syntax::ast::{self, MetaItem};
22
use syntax::symbol::{Symbol, sym};
33

4-
use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet};
4+
use rustc_data_structures::bit_set::{BitSet, HybridBitSet};
55
use rustc_data_structures::indexed_vec::Idx;
66
use rustc_data_structures::work_queue::WorkQueue;
77

@@ -552,25 +552,39 @@ impl<E:Idx> AllSets<E> {
552552
}
553553

554554
/// Parameterization for the precise form of data flow that is used.
555-
/// `InitialFlow` handles initializing the bitvectors before any
556-
/// code is inspected by the analysis. Analyses that need more nuanced
557-
/// initialization (e.g., they need to consult the results of some other
558-
/// dataflow analysis to set up the initial bitvectors) should not
559-
/// implement this.
560-
pub trait InitialFlow {
561-
/// Specifies the initial value for each bit in the `on_entry` set
562-
fn bottom_value() -> bool;
555+
///
556+
/// `BottomValue` determines whether the initial entry set for each basic block is empty or full.
557+
/// This also determines the semantics of the lattice `join` operator used to merge dataflow
558+
/// results, since dataflow works by starting at the bottom and moving monotonically to a fixed
559+
/// point.
560+
///
561+
/// This means, for propagation across the graph, that you either want to start at all-zeroes and
562+
/// then use Union as your merge when propagating, or you start at all-ones and then use Intersect
563+
/// as your merge when propagating.
564+
pub trait BottomValue {
565+
/// Specifies the initial value for each bit in the entry set for each basic block.
566+
const BOTTOM_VALUE: bool;
567+
568+
/// Merges `in_set` into `inout_set`, returning `true` if `inout_set` changed.
569+
#[inline]
570+
fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
571+
if Self::BOTTOM_VALUE == false {
572+
inout_set.union(in_set)
573+
} else {
574+
inout_set.intersect(in_set)
575+
}
576+
}
563577
}
564578

565579
/// A specific flavor of dataflow analysis.
566580
///
567581
/// To run a dataflow analysis, one sets up an initial state for the
568582
/// `START_BLOCK` via `start_block_effect` and a transfer function (`trans`)
569583
/// for each block individually. The entry set for all other basic blocks is
570-
/// initialized to `InitialFlow::bottom_value`. The dataflow analysis then
584+
/// initialized to `Self::BOTTOM_VALUE`. The dataflow analysis then
571585
/// iteratively modifies the various entry sets (but leaves the the transfer
572586
/// function unchanged).
573-
pub trait BitDenotation<'tcx>: BitSetOperator + InitialFlow {
587+
pub trait BitDenotation<'tcx>: BottomValue {
574588
/// Specifies what index type is used to access the bitvector.
575589
type Idx: Idx;
576590

@@ -688,7 +702,7 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation<'tcx>
688702
let bits_per_block = denotation.bits_per_block();
689703
let num_blocks = body.basic_blocks().len();
690704

691-
let on_entry = if D::bottom_value() {
705+
let on_entry = if D::BOTTOM_VALUE == true {
692706
vec![BitSet::new_filled(bits_per_block); num_blocks]
693707
} else {
694708
vec![BitSet::new_empty(bits_per_block); num_blocks]

0 commit comments

Comments
 (0)