1
Fork 0

rename BitSet to DenseBitSet

This should make it clearer that this bitset is dense, with the
advantages and disadvantages that it entails.
This commit is contained in:
Rémy Rakic 2025-01-07 15:19:05 +00:00
parent 7e4077d06f
commit a13354bea0
67 changed files with 367 additions and 356 deletions

View file

@ -1,17 +1,17 @@
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
/// Return the set of locals that appear in debuginfo.
pub fn debuginfo_locals(body: &Body<'_>) -> BitSet<Local> {
let mut visitor = DebuginfoLocals(BitSet::new_empty(body.local_decls.len()));
pub fn debuginfo_locals(body: &Body<'_>) -> DenseBitSet<Local> {
let mut visitor = DebuginfoLocals(DenseBitSet::new_empty(body.local_decls.len()));
for debuginfo in body.var_debug_info.iter() {
visitor.visit_var_debug_info(debuginfo);
}
visitor.0
}
struct DebuginfoLocals(BitSet<Local>);
struct DebuginfoLocals(DenseBitSet<Local>);
impl Visitor<'_> for DebuginfoLocals {
fn visit_local(&mut self, local: Local, _: PlaceContext, _: Location) {

View file

@ -4,7 +4,7 @@ use std::cmp::Ordering;
use std::ops::{Deref, DerefMut};
#[cfg(debug_assertions)]
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::{self, BasicBlock, Location};
use super::{Analysis, Direction, Effect, EffectIndex, Results};
@ -71,7 +71,7 @@ where
state_needs_reset: bool,
#[cfg(debug_assertions)]
reachable_blocks: BitSet<BasicBlock>,
reachable_blocks: DenseBitSet<BasicBlock>,
}
impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>

View file

@ -4,7 +4,7 @@
use std::fmt;
use rustc_index::Idx;
use rustc_index::bit_set::{BitSet, ChunkedBitSet, MixedBitSet};
use rustc_index::bit_set::{ChunkedBitSet, DenseBitSet, MixedBitSet};
use super::lattice::MaybeReachable;
@ -73,7 +73,7 @@ where
// Impls
impl<T, C> DebugWithContext<C> for BitSet<T>
impl<T, C> DebugWithContext<C> for DenseBitSet<T>
where
T: Idx + DebugWithContext<C>,
{

View file

@ -9,7 +9,7 @@ use std::{io, ops, str};
use regex::Regex;
use rustc_hir::def_id::DefId;
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::{
self, BasicBlock, Body, Location, create_dump_file, dump_enabled, graphviz_safe_def_name,
traversal,
@ -205,7 +205,7 @@ where
// the operations that involve the mutation, i.e. within the `borrow_mut`.
cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
style: OutputStyle,
reachable: BitSet<BasicBlock>,
reachable: DenseBitSet<BasicBlock>,
}
impl<'mir, 'tcx, A> Formatter<'mir, 'tcx, A>

View file

@ -39,7 +39,7 @@
//! [poset]: https://en.wikipedia.org/wiki/Partially_ordered_set
use rustc_index::Idx;
use rustc_index::bit_set::{BitSet, MixedBitSet};
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
use crate::framework::BitSetExt;
@ -68,10 +68,10 @@ pub trait HasTop {
const TOP: Self;
}
/// A `BitSet` represents the lattice formed by the powerset of all possible values of
/// the index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices,
/// one for each possible value of `T`.
impl<T: Idx> JoinSemiLattice for BitSet<T> {
/// A `DenseBitSet` represents the lattice formed by the powerset of all possible values of the
/// index type `T` ordered by inclusion. Equivalently, it is a tuple of "two-point" lattices, one
/// for each possible value of `T`.
impl<T: Idx> JoinSemiLattice for DenseBitSet<T> {
fn join(&mut self, other: &Self) -> bool {
self.union(other)
}

View file

@ -35,7 +35,7 @@
use std::cmp::Ordering;
use rustc_data_structures::work_queue::WorkQueue;
use rustc_index::bit_set::{BitSet, MixedBitSet};
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges, traversal};
@ -65,7 +65,7 @@ pub trait BitSetExt<T> {
fn contains(&self, elem: T) -> bool;
}
impl<T: Idx> BitSetExt<T> for BitSet<T> {
impl<T: Idx> BitSetExt<T> for DenseBitSet<T> {
fn contains(&self, elem: T) -> bool {
self.contains(elem)
}
@ -334,7 +334,7 @@ pub trait GenKill<T> {
}
}
impl<T: Idx> GenKill<T> for BitSet<T> {
impl<T: Idx> GenKill<T> for DenseBitSet<T> {
fn gen_(&mut self, elem: T) {
self.insert(elem);
}

View file

@ -84,13 +84,13 @@ impl<D: Direction> MockAnalysis<'_, D> {
/// The entry set for each `BasicBlock` is the ID of that block offset by a fixed amount to
/// avoid colliding with the statement/terminator effects.
fn mock_entry_set(&self, bb: BasicBlock) -> BitSet<usize> {
fn mock_entry_set(&self, bb: BasicBlock) -> DenseBitSet<usize> {
let mut ret = self.bottom_value(self.body);
ret.insert(Self::BASIC_BLOCK_OFFSET + bb.index());
ret
}
fn mock_entry_states(&self) -> IndexVec<BasicBlock, BitSet<usize>> {
fn mock_entry_states(&self) -> IndexVec<BasicBlock, DenseBitSet<usize>> {
let empty = self.bottom_value(self.body);
let mut ret = IndexVec::from_elem(empty, &self.body.basic_blocks);
@ -121,7 +121,7 @@ impl<D: Direction> MockAnalysis<'_, D> {
/// For example, the expected state when calling
/// `seek_before_primary_effect(Location { block: 2, statement_index: 2 })`
/// would be `[102, 0, 1, 2, 3, 4]`.
fn expected_state_at_target(&self, target: SeekTarget) -> BitSet<usize> {
fn expected_state_at_target(&self, target: SeekTarget) -> DenseBitSet<usize> {
let block = target.block();
let mut ret = self.bottom_value(self.body);
ret.insert(Self::BASIC_BLOCK_OFFSET + block.index());
@ -155,13 +155,13 @@ impl<D: Direction> MockAnalysis<'_, D> {
}
impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
type Domain = BitSet<usize>;
type Domain = DenseBitSet<usize>;
type Direction = D;
const NAME: &'static str = "mock";
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
BitSet::new_empty(Self::BASIC_BLOCK_OFFSET + body.basic_blocks.len())
DenseBitSet::new_empty(Self::BASIC_BLOCK_OFFSET + body.basic_blocks.len())
}
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {

View file

@ -1,4 +1,4 @@
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
@ -21,12 +21,12 @@ impl MaybeBorrowedLocals {
}
impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
const NAME: &'static str = "maybe_borrowed_locals";
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
// bottom = unborrowed
BitSet::new_empty(body.local_decls().len())
DenseBitSet::new_empty(body.local_decls().len())
}
fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
@ -137,8 +137,8 @@ where
}
/// The set of locals that are borrowed at some point in the MIR body.
pub fn borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
struct Borrowed(BitSet<Local>);
pub fn borrowed_locals(body: &Body<'_>) -> DenseBitSet<Local> {
struct Borrowed(DenseBitSet<Local>);
impl GenKill<Local> for Borrowed {
#[inline]
@ -151,7 +151,7 @@ pub fn borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
}
}
let mut borrowed = Borrowed(BitSet::new_empty(body.local_decls.len()));
let mut borrowed = Borrowed(DenseBitSet::new_empty(body.local_decls.len()));
TransferFunction { trans: &mut borrowed }.visit_body(body);
borrowed.0
}

View file

@ -2,7 +2,7 @@ use std::assert_matches::assert_matches;
use rustc_abi::VariantIdx;
use rustc_index::Idx;
use rustc_index::bit_set::{BitSet, MixedBitSet};
use rustc_index::bit_set::{DenseBitSet, MixedBitSet};
use rustc_middle::bug;
use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges};
use rustc_middle::ty::util::Discr;
@ -207,7 +207,7 @@ pub struct MaybeUninitializedPlaces<'a, 'tcx> {
move_data: &'a MoveData<'tcx>,
mark_inactive_variants_as_uninit: bool,
skip_unreachable_unwind: BitSet<mir::BasicBlock>,
skip_unreachable_unwind: DenseBitSet<mir::BasicBlock>,
}
impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
@ -217,7 +217,7 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
body,
move_data,
mark_inactive_variants_as_uninit: false,
skip_unreachable_unwind: BitSet::new_empty(body.basic_blocks.len()),
skip_unreachable_unwind: DenseBitSet::new_empty(body.basic_blocks.len()),
}
}
@ -233,7 +233,7 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
pub fn skipping_unreachable_unwind(
mut self,
unreachable_unwind: BitSet<mir::BasicBlock>,
unreachable_unwind: DenseBitSet<mir::BasicBlock>,
) -> Self {
self.skip_unreachable_unwind = unreachable_unwind;
self

View file

@ -1,4 +1,4 @@
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{
self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges,
@ -26,14 +26,14 @@ use crate::{Analysis, Backward, GenKill};
pub struct MaybeLiveLocals;
impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
type Direction = Backward;
const NAME: &'static str = "liveness";
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
// bottom = not live
BitSet::new_empty(body.local_decls.len())
DenseBitSet::new_empty(body.local_decls.len())
}
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
@ -81,7 +81,7 @@ impl<'tcx> Analysis<'tcx> for MaybeLiveLocals {
}
}
pub struct TransferFunction<'a>(pub &'a mut BitSet<Local>);
pub struct TransferFunction<'a>(pub &'a mut DenseBitSet<Local>);
impl<'tcx> Visitor<'tcx> for TransferFunction<'_> {
fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
@ -117,7 +117,7 @@ impl<'tcx> Visitor<'tcx> for TransferFunction<'_> {
}
}
struct YieldResumeEffect<'a>(&'a mut BitSet<Local>);
struct YieldResumeEffect<'a>(&'a mut DenseBitSet<Local>);
impl<'tcx> Visitor<'tcx> for YieldResumeEffect<'_> {
fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
@ -137,7 +137,7 @@ enum DefUse {
}
impl DefUse {
fn apply(state: &mut BitSet<Local>, place: Place<'_>, context: PlaceContext) {
fn apply(state: &mut DenseBitSet<Local>, place: Place<'_>, context: PlaceContext) {
match DefUse::for_place(place, context) {
Some(DefUse::Def) => state.kill(place.local),
Some(DefUse::Use) => state.gen_(place.local),
@ -204,7 +204,7 @@ impl DefUse {
///
/// All of the caveats of `MaybeLiveLocals` apply.
pub struct MaybeTransitiveLiveLocals<'a> {
always_live: &'a BitSet<Local>,
always_live: &'a DenseBitSet<Local>,
}
impl<'a> MaybeTransitiveLiveLocals<'a> {
@ -212,20 +212,20 @@ impl<'a> MaybeTransitiveLiveLocals<'a> {
/// considered live.
///
/// This should include at least all locals that are ever borrowed.
pub fn new(always_live: &'a BitSet<Local>) -> Self {
pub fn new(always_live: &'a DenseBitSet<Local>) -> Self {
MaybeTransitiveLiveLocals { always_live }
}
}
impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
type Direction = Backward;
const NAME: &'static str = "transitive liveness";
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
// bottom = not live
BitSet::new_empty(body.local_decls.len())
DenseBitSet::new_empty(body.local_decls.len())
}
fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {

View file

@ -1,6 +1,6 @@
use std::borrow::Cow;
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@ -10,8 +10,8 @@ use crate::{Analysis, GenKill, ResultsCursor};
/// The set of locals in a MIR body that do not have `StorageLive`/`StorageDead` annotations.
///
/// These locals have fixed storage for the duration of the body.
pub fn always_storage_live_locals(body: &Body<'_>) -> BitSet<Local> {
let mut always_live_locals = BitSet::new_filled(body.local_decls.len());
pub fn always_storage_live_locals(body: &Body<'_>) -> DenseBitSet<Local> {
let mut always_live_locals = DenseBitSet::new_filled(body.local_decls.len());
for block in &*body.basic_blocks {
for statement in &block.statements {
@ -25,23 +25,23 @@ pub fn always_storage_live_locals(body: &Body<'_>) -> BitSet<Local> {
}
pub struct MaybeStorageLive<'a> {
always_live_locals: Cow<'a, BitSet<Local>>,
always_live_locals: Cow<'a, DenseBitSet<Local>>,
}
impl<'a> MaybeStorageLive<'a> {
pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
pub fn new(always_live_locals: Cow<'a, DenseBitSet<Local>>) -> Self {
MaybeStorageLive { always_live_locals }
}
}
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
const NAME: &'static str = "maybe_storage_live";
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
// bottom = dead
BitSet::new_empty(body.local_decls.len())
DenseBitSet::new_empty(body.local_decls.len())
}
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
@ -67,23 +67,23 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageLive<'a> {
}
pub struct MaybeStorageDead<'a> {
always_live_locals: Cow<'a, BitSet<Local>>,
always_live_locals: Cow<'a, DenseBitSet<Local>>,
}
impl<'a> MaybeStorageDead<'a> {
pub fn new(always_live_locals: Cow<'a, BitSet<Local>>) -> Self {
pub fn new(always_live_locals: Cow<'a, DenseBitSet<Local>>) -> Self {
MaybeStorageDead { always_live_locals }
}
}
impl<'a, 'tcx> Analysis<'tcx> for MaybeStorageDead<'a> {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
const NAME: &'static str = "maybe_storage_dead";
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
// bottom = live
BitSet::new_empty(body.local_decls.len())
DenseBitSet::new_empty(body.local_decls.len())
}
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
@ -125,13 +125,13 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
}
impl<'tcx> Analysis<'tcx> for MaybeRequiresStorage<'_, 'tcx> {
type Domain = BitSet<Local>;
type Domain = DenseBitSet<Local>;
const NAME: &'static str = "requires_storage";
fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
// bottom = dead
BitSet::new_empty(body.local_decls.len())
DenseBitSet::new_empty(body.local_decls.len())
}
fn initialize_start_block(&self, body: &Body<'tcx>, state: &mut Self::Domain) {
@ -304,7 +304,7 @@ impl<'tcx> MaybeRequiresStorage<'_, 'tcx> {
struct MoveVisitor<'a, 'mir, 'tcx> {
borrowed_locals: &'a mut BorrowedLocalsResults<'mir, 'tcx>,
state: &'a mut BitSet<Local>,
state: &'a mut DenseBitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for MoveVisitor<'_, '_, 'tcx> {

View file

@ -1,4 +1,4 @@
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::interval::SparseIntervalMatrix;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::{self, BasicBlock, Body, Location};
@ -102,7 +102,7 @@ pub fn save_as_intervals<'tcx, N, A>(
) -> SparseIntervalMatrix<N, PointIndex>
where
N: Idx,
A: Analysis<'tcx, Domain = BitSet<N>>,
A: Analysis<'tcx, Domain = DenseBitSet<N>>,
{
let values = SparseIntervalMatrix::new(elements.num_points());
let mut visitor = Visitor { elements, values };
@ -122,7 +122,7 @@ struct Visitor<'a, N: Idx> {
impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N>
where
A: Analysis<'tcx, Domain = BitSet<N>>,
A: Analysis<'tcx, Domain = DenseBitSet<N>>,
N: Idx,
{
fn visit_after_primary_statement_effect(

View file

@ -6,7 +6,7 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet, StdEntry};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_index::IndexVec;
use rustc_index::bit_set::BitSet;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@ -399,7 +399,7 @@ impl<'tcx> Map<'tcx> {
&mut self,
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
exclude: BitSet<Local>,
exclude: DenseBitSet<Local>,
value_limit: Option<usize>,
) {
// Start by constructing the places for each bare local.
@ -912,9 +912,9 @@ pub fn iter_fields<'tcx>(
}
/// Returns all locals with projections that have their reference or address taken.
pub fn excluded_locals(body: &Body<'_>) -> BitSet<Local> {
pub fn excluded_locals(body: &Body<'_>) -> DenseBitSet<Local> {
struct Collector {
result: BitSet<Local>,
result: DenseBitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for Collector {
@ -932,7 +932,7 @@ pub fn excluded_locals(body: &Body<'_>) -> BitSet<Local> {
}
}
let mut collector = Collector { result: BitSet::new_empty(body.local_decls.len()) };
let mut collector = Collector { result: DenseBitSet::new_empty(body.local_decls.len()) };
collector.visit_body(body);
collector.result
}