From 05742ffb432adb0278bcb7262251cec9657d4067 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Jul 2018 10:34:21 +1000 Subject: [PATCH 1/3] Inline and remove `DataflowAnalysis::num_bits_overall()`. It has a single callsite, and duplicates some code from that callsite. The code is more concise and clearer this way. --- src/librustc_mir/dataflow/mod.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index e3b67b0a003..e59236c5168 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -736,7 +736,9 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation let bits_per_block = denotation.bits_per_block(); let usize_bits = mem::size_of::() * 8; let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; - let num_overall = Self::num_bits_overall(mir, bits_per_block); + let bits_per_block_rounded_up = words_per_block * usize_bits; // a multiple of word size + let num_blocks = mir.basic_blocks().len(); + let num_overall = num_blocks * bits_per_block_rounded_up; let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall)); let on_entry = Bits::new(if D::bottom_value() { @@ -774,18 +776,6 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation } } } - - fn num_bits_overall(mir: &Mir, bits_per_block: usize) -> usize { - let usize_bits = mem::size_of::() * 8; - let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; - - // (now rounded up to multiple of word size) - let bits_per_block = words_per_block * usize_bits; - - let num_blocks = mir.basic_blocks().len(); - let num_overall = num_blocks * bits_per_block; - num_overall - } } impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation From f0c67951d076db8272f7a52f4d2596ae77b3311d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Jul 2018 10:53:57 +1000 Subject: [PATCH 2/3] Make BitSlice's `Word` properly generic. Currently `Word` is `usize`, and there are various places in the code that assume this. This patch mostly just changes `usize` occurrences to `Word`. Most of the changes were found as compile errors when I changed `Word` to a type other than `usize`, but there was one non-obvious case in librustc_mir/dataflow/mod.rs that caused bounds check failures before I fixed it. --- src/librustc_data_structures/bitslice.rs | 14 +++++++------- src/librustc_mir/dataflow/impls/borrowed_locals.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 4 ++-- src/librustc_mir/dataflow/impls/mod.rs | 12 ++++++------ .../dataflow/impls/storage_liveness.rs | 2 +- src/librustc_mir/dataflow/mod.rs | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs index 2678861be06..5b5dd907cb7 100644 --- a/src/librustc_data_structures/bitslice.rs +++ b/src/librustc_data_structures/bitslice.rs @@ -79,7 +79,7 @@ fn bit_lookup(bit: usize) -> BitLookup { } -fn bit_str(bit: Word) -> String { +fn bit_str(bit: usize) -> String { let byte = bit >> 3; let lobits = 1 << (bit & 0b111); format!("[{}:{}-{:02x}]", bit, byte, lobits) @@ -116,8 +116,8 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String { } #[inline] -pub fn bitwise(out_vec: &mut [usize], - in_vec: &[usize], +pub fn bitwise(out_vec: &mut [Word], + in_vec: &[Word], op: &Op) -> bool { assert_eq!(out_vec.len(), in_vec.len()); let mut changed = false; @@ -132,21 +132,21 @@ pub fn bitwise(out_vec: &mut [usize], pub trait BitwiseOperator { /// Applies some bit-operation pointwise to each of the bits in the two inputs. - fn join(&self, pred1: usize, pred2: usize) -> usize; + fn join(&self, pred1: Word, pred2: Word) -> Word; } pub struct Intersect; impl BitwiseOperator for Intersect { #[inline] - fn join(&self, a: usize, b: usize) -> usize { a & b } + fn join(&self, a: Word, b: Word) -> Word { a & b } } pub struct Union; impl BitwiseOperator for Union { #[inline] - fn join(&self, a: usize, b: usize) -> usize { a | b } + fn join(&self, a: Word, b: Word) -> Word { a | b } } pub struct Subtract; impl BitwiseOperator for Subtract { #[inline] - fn join(&self, a: usize, b: usize) -> usize { a & !b } + fn join(&self, a: Word, b: Word) -> Word { a & !b } } diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 244e8b5ccd7..c7513ac8816 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // "maybe" means we union effects of both preds } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index a109389aa31..dbdf5b4e096 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -20,7 +20,7 @@ use rustc::ty::TyCtxt; use rustc::ty::{RegionKind, RegionVid}; use rustc::ty::RegionKind::ReScope; -use rustc_data_structures::bitslice::BitwiseOperator; +use rustc_data_structures::bitslice::{BitwiseOperator, Word}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_set::IdxSet; use rustc_data_structures::indexed_vec::IndexVec; @@ -370,7 +370,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // union effects of preds when computing reservations } } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index f64fd64b283..ee3bba840c6 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,7 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::{BitwiseOperator}; +use rustc_data_structures::bitslice::{BitwiseOperator, Word}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; @@ -663,35 +663,35 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // "maybe" means we union effects of both preds } } impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // "maybe" means we union effects of both preds } } impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 & pred2 // "definitely" means we intersect effects of both preds } } impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // moves from both preds are in scope } } impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // inits from both preds are in scope } } diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index dea61542ac4..29548051a4d 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> { impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> { #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { + fn join(&self, pred1: Word, pred2: Word) -> Word { pred1 | pred2 // "maybe" means we union effects of both preds } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index e59236c5168..f58609aa9a5 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -12,7 +12,7 @@ use syntax::ast::{self, MetaItem}; use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; -use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; +use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word}; use rustc_data_structures::work_queue::WorkQueue; use rustc::ty::{self, TyCtxt}; @@ -467,7 +467,7 @@ pub struct AllSets { bits_per_block: usize, /// Number of words associated with each block entry - /// equal to bits_per_block / usize::BITS, rounded up. + /// equal to bits_per_block / (mem::size_of:: * 8), rounded up. words_per_block: usize, /// For each block, bits generated by executing the statements in @@ -734,9 +734,9 @@ impl<'a, 'tcx, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation dead_unwinds: &'a IdxSet, denotation: D) -> Self where D: InitialFlow { let bits_per_block = denotation.bits_per_block(); - let usize_bits = mem::size_of::() * 8; - let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits; - let bits_per_block_rounded_up = words_per_block * usize_bits; // a multiple of word size + let bits_per_word = mem::size_of::() * 8; + let words_per_block = (bits_per_block + bits_per_word - 1) / bits_per_word; + let bits_per_block_rounded_up = words_per_block * bits_per_word; // a multiple of word size let num_blocks = mir.basic_blocks().len(); let num_overall = num_blocks * bits_per_block_rounded_up; From f2b0b6700ce984a38abd06e48e7884573688539b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 13 Jul 2018 13:05:22 +1000 Subject: [PATCH 3/3] Fix bitslice printing. In multiple ways: - Two calls to `bits_to_string()` passed in byte lengths rather than bit lengths, which meant only 1/8th of the `BitSlice` was printed. - `bit_str`'s purpose is entirely mysterious. I removed it and changed its callers to print the indices in the obvious way. - `bits_to_string`'s inner loop was totally wrong, such that it printed entirely bogus results. - `bits_to_string` now also adds a '|' between words, which makes the output easier to read, e.g.: `[ff-ff-ff-ff-ff-ff-ff-ff|ff-ff-ff-ff-ff-ff-ff-07]`. --- src/librustc_data_structures/bitslice.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/librustc_data_structures/bitslice.rs b/src/librustc_data_structures/bitslice.rs index 5b5dd907cb7..79435aa3987 100644 --- a/src/librustc_data_structures/bitslice.rs +++ b/src/librustc_data_structures/bitslice.rs @@ -28,9 +28,9 @@ impl BitSlice for [Word] { fn clear_bit(&mut self, idx: usize) -> bool { let words = self; debug!("clear_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); + bits_to_string(words, words.len() * mem::size_of::() * 8), idx); let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); - debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); + debug!("word={} bit_in_word={} bit_mask=0x{:x}", word, bit_in_word, bit_mask); let oldv = words[word]; let newv = oldv & !bit_mask; words[word] = newv; @@ -42,7 +42,7 @@ impl BitSlice for [Word] { fn set_bit(&mut self, idx: usize) -> bool { let words = self; debug!("set_bit: words={} idx={}", - bits_to_string(words, words.len() * mem::size_of::()), bit_str(idx)); + bits_to_string(words, words.len() * mem::size_of::() * 8), idx); let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); let oldv = words[word]; @@ -78,13 +78,6 @@ fn bit_lookup(bit: usize) -> BitLookup { BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask } } - -fn bit_str(bit: usize) -> String { - let byte = bit >> 3; - let lobits = 1 << (bit & 0b111); - format!("[{}:{}-{:02x}]", bit, byte, lobits) -} - pub fn bits_to_string(words: &[Word], bits: usize) -> String { let mut result = String::new(); let mut sep = '['; @@ -95,7 +88,7 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String { let mut i = 0; for &word in words.iter() { let mut v = word; - loop { // for each byte in `v`: + for _ in 0..mem::size_of::() { // for each byte in `v`: let remain = bits - i; // If less than a byte remains, then mask just that many bits. let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF }; @@ -110,6 +103,7 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String { i += 8; sep = '-'; } + sep = '|'; } result.push(']'); return result