From 99695a324c1198a721a6f18d1aa377cfac73c689 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 26 Feb 2022 11:17:02 -0500 Subject: [PATCH 1/5] Expand IntervalSet APIs This extends the functionality available on IntervalSet to provide more flexible access needed for the InitMask abstraction (and, likely, more generally useful as code wishes to migrate between the various Idx-based set abstractions available in rustc_index). --- .../src/stable_hasher.rs | 7 + compiler/rustc_index/src/interval.rs | 81 +++++++- compiler/rustc_index/src/interval/tests.rs | 185 ++++++++++++++++++ 3 files changed, 272 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 31d6a42cf2884..f6a0ae3bbfded 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -1,5 +1,6 @@ use crate::sip128::SipHasher128; use rustc_index::bit_set; +use rustc_index::interval; use rustc_index::vec; use smallvec::SmallVec; use std::hash::{BuildHasher, Hash, Hasher}; @@ -510,6 +511,12 @@ impl HashStable for bit_set::BitSet { } } +impl HashStable for interval::IntervalSet { + fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); + } +} + impl HashStable for bit_set::BitMatrix { fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index ed504938e8aa7..78655a491b8a6 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -5,13 +5,14 @@ use std::ops::RangeBounds; use crate::vec::Idx; use crate::vec::IndexVec; +use rustc_macros::{Decodable, Encodable}; use smallvec::SmallVec; #[cfg(test)] mod tests; /// Stores a set of intervals on the indices. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct IntervalSet { // Start, end map: SmallVec<[(u32, u32); 4]>, @@ -43,6 +44,17 @@ impl IntervalSet { IntervalSet { map: SmallVec::new(), domain, _data: PhantomData } } + /// Ensure that the set's domain is at least `min_domain_size`. + pub fn ensure(&mut self, min_domain_size: usize) { + if self.domain < min_domain_size { + self.domain = min_domain_size; + } + } + + pub fn domain_size(&self) -> usize { + self.domain + } + pub fn clear(&mut self) { self.map.clear(); } @@ -67,6 +79,10 @@ impl IntervalSet { self.insert_range(point..=point) } + pub fn remove(&mut self, point: I) { + self.remove_range(point..=point); + } + /// Returns true if we increased the number of elements present. pub fn insert_range(&mut self, range: impl RangeBounds + Clone) -> bool { let start = inclusive_start(range.clone()); @@ -134,6 +150,31 @@ impl IntervalSet { } } + pub fn remove_range(&mut self, range: impl RangeBounds + Clone) { + let start = inclusive_start(range.clone()); + let Some(end) = inclusive_end(self.domain, range.clone()) else { + // empty range + return; + }; + if start > end { + return; + } + // We insert the range, so that any previous gaps are merged into just one large + // range, which we can then split in the next step (either inserting a + // smaller range after or not). + self.insert_range(range); + // Find the range we just inserted. + let idx = self.map.partition_point(|r| r.0 <= end).checked_sub(1).unwrap(); + let (prev_start, prev_end) = self.map.remove(idx); + // The range we're looking at contains the range we're removing completely. + assert!(prev_start <= start && end <= prev_end); + self.insert_range(I::new(prev_start as usize)..I::new(start as usize)); + self.insert_range(( + Bound::Excluded(I::new(end as usize)), + Bound::Included(I::new(prev_end as usize)), + )); + } + pub fn contains(&self, needle: I) -> bool { let needle = needle.index() as u32; let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else { @@ -157,6 +198,44 @@ impl IntervalSet { self.map.is_empty() } + /// Returns the minimum (first) element present in the set from `range`. + pub fn first_set_in(&self, range: impl RangeBounds + Clone) -> Option { + let start = inclusive_start(range.clone()); + let Some(end) = inclusive_end(self.domain, range) else { + // empty range + return None; + }; + if start > end { + return None; + } + let range = self.map.get(self.map.partition_point(|r| r.1 < start))?; + if range.0 > end { None } else { Some(I::new(std::cmp::max(range.0, start) as usize)) } + } + + /// Returns the minimum (first) element **not** present in the set from `range`. + pub fn first_gap_in(&self, range: impl RangeBounds + Clone) -> Option { + let start = inclusive_start(range.clone()); + let Some(end) = inclusive_end(self.domain, range) else { + // empty range + return None; + }; + if start > end { + return None; + } + let Some(range) = self.map.get(self.map.partition_point(|r| r.1 < start)) else { + return Some(I::new(start as usize)); + }; + if start < range.0 { + return Some(I::new(start as usize)); + } else if range.1 as usize + 1 < self.domain { + if range.1 + 1 <= end { + return Some(I::new(range.1 as usize + 1)); + } + } + + None + } + /// Returns the maximum (last) element present in the set from `range`. pub fn last_set_in(&self, range: impl RangeBounds + Clone) -> Option { let start = inclusive_start(range.clone()); diff --git a/compiler/rustc_index/src/interval/tests.rs b/compiler/rustc_index/src/interval/tests.rs index d90b449f32609..848feaca4768d 100644 --- a/compiler/rustc_index/src/interval/tests.rs +++ b/compiler/rustc_index/src/interval/tests.rs @@ -118,6 +118,61 @@ fn insert_range() { } } +#[test] +fn remove_range() { + fn check(insert: A, remove: B) + where + A: RangeBounds + Clone + IntoIterator + std::fmt::Debug, + B: RangeBounds + Clone + IntoIterator + std::fmt::Debug, + { + let mut set = IntervalSet::new(300); + set.insert_range(insert.clone()); + set.remove_range(remove.clone()); + for i in set.iter() { + assert!(insert.contains(&i) && !remove.contains(&i)); + } + for i in insert.clone() { + if i >= 300 { + break; + } + if remove.contains(&i) { + assert!(!set.contains(i)); + } else { + assert!(set.contains(i)); + } + } + set.insert_range(insert.clone()); + for i in set.iter() { + assert!(insert.contains(&i)); + } + for i in insert.clone() { + if i >= 300 { + break; + } + assert!(set.contains(i)); + } + } + for a in 0..10 { + for b in a..10 { + for i in 0..10 { + for j in i..10 { + check(a..b, i..j); + check(a..=b, i..j); + check(a.., i..j); + + check(a..b, i..=j); + check(a..=b, i..=j); + check(a.., i..=j); + + check(a..b, i..); + check(a..=b, i..); + check(a.., i..); + } + } + } + } +} + #[test] fn insert_range_dual() { let mut set = IntervalSet::::new(300); @@ -193,6 +248,136 @@ fn last_set_in() { cmp(&set, i..); cmp(&set, i..j); cmp(&set, i..=j); + set.insert(k / 2); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + } + } + } +} + +#[test] +fn first_set_in() { + fn easy(set: &IntervalSet, needle: impl RangeBounds) -> Option { + for e in set.iter() { + if needle.contains(&e) { + return Some(e); + } + } + None + } + + #[track_caller] + fn cmp(set: &IntervalSet, needle: impl RangeBounds + Clone + std::fmt::Debug) { + assert_eq!( + set.first_set_in(needle.clone()), + easy(set, needle.clone()), + "{:?} in {:?}", + needle, + set + ); + } + let mut set = IntervalSet::new(300); + cmp(&set, 50..=50); + set.insert(64); + cmp(&set, 64..=64); + set.insert(64 - 1); + cmp(&set, 0..=64 - 1); + cmp(&set, 0..=5); + cmp(&set, 10..100); + set.insert(100); + cmp(&set, 100..110); + cmp(&set, 99..100); + cmp(&set, 99..=100); + + for i in 0..=30 { + for j in i..=30 { + for k in 0..30 { + let mut set = IntervalSet::new(100); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k / 2); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert_range(k / 2..k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + } + } + } +} + +#[test] +fn first_gap_in() { + fn easy(set: &IntervalSet, needle: impl RangeBounds) -> Option { + for point in 0..set.domain_size() { + if needle.contains(&point) && !set.contains(point) { + return Some(point); + } + } + None + } + + #[track_caller] + fn cmp(set: &IntervalSet, needle: impl RangeBounds + Clone + std::fmt::Debug) { + eprintln!("comparing"); + assert_eq!( + set.first_gap_in(needle.clone()), + easy(set, needle.clone()), + "{:?} in {:?}", + needle, + set + ); + } + let mut set = IntervalSet::new(300); + cmp(&set, 50..=50); + set.insert(64); + cmp(&set, 64..=64); + set.insert(64 - 1); + cmp(&set, 0..=64 - 1); + cmp(&set, 0..=5); + cmp(&set, 10..100); + set.insert(100); + cmp(&set, 100..110); + cmp(&set, 99..100); + cmp(&set, 99..=100); + + for i in 0..=30 { + for j in i..=30 { + for k in 0..30 { + let mut set = IntervalSet::new(100); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k / 2); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert_range(k / 2..k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); } } } From e540587d0259e305da7303f5dd0c7f5e7dfc7065 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Feb 2022 21:53:49 -0500 Subject: [PATCH 2/5] Use IntervalSet in InitMask rather than the custom bitset impl --- .../src/mir/interpret/allocation.rs | 319 ++---------------- 1 file changed, 34 insertions(+), 285 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5de119f956282..f95b7490e2bc4 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -1,13 +1,12 @@ //! The virtual memory representation of the MIR interpreter. use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; -use std::iter; use std::ops::{Deref, Range}; use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::sorted_map::SortedMap; +use rustc_index::interval::IntervalSet; use rustc_span::DUMMY_SP; use rustc_target::abi::{Align, HasDataLayout, Size}; @@ -567,323 +566,73 @@ impl Allocation { // Uninitialized byte tracking //////////////////////////////////////////////////////////////////////////////// -type Block = u64; - /// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte /// is initialized. If it is `false` the byte is uninitialized. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct InitMask { - blocks: Vec, - len: Size, + set: IntervalSet, } -impl InitMask { - pub const BLOCK_SIZE: u64 = 64; - - #[inline] - fn bit_index(bits: Size) -> (usize, usize) { - // BLOCK_SIZE is the number of bits that can fit in a `Block`. - // Each bit in a `Block` represents the initialization state of one byte of an allocation, - // so we use `.bytes()` here. - let bits = bits.bytes(); - let a = bits / InitMask::BLOCK_SIZE; - let b = bits % InitMask::BLOCK_SIZE; - (usize::try_from(a).unwrap(), usize::try_from(b).unwrap()) +impl Ord for InitMask { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.set + .iter() + .cmp(other.set.iter()) + .then(self.set.domain_size().cmp(&other.set.domain_size())) } +} - #[inline] - fn size_from_bit_index(block: impl TryInto, bit: impl TryInto) -> Size { - let block = block.try_into().ok().unwrap(); - let bit = bit.try_into().ok().unwrap(); - Size::from_bytes(block * InitMask::BLOCK_SIZE + bit) +impl PartialOrd for InitMask { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } +} +impl InitMask { pub fn new(size: Size, state: bool) -> Self { - let mut m = InitMask { blocks: vec![], len: Size::ZERO }; - m.grow(size, state); - m + let mut set = IntervalSet::new(size.bytes_usize()); + if state { + set.insert_all(); + } + InitMask { set } } pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) { - let len = self.len; - if end > len { - self.grow(end - len, new_state); - } + self.set.ensure(end.bytes_usize() + 1); self.set_range_inbounds(start, end, new_state); } pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) { - let (blocka, bita) = Self::bit_index(start); - let (blockb, bitb) = Self::bit_index(end); - if blocka == blockb { - // First set all bits except the first `bita`, - // then unset the last `64 - bitb` bits. - let range = if bitb == 0 { - u64::MAX << bita - } else { - (u64::MAX << bita) & (u64::MAX >> (64 - bitb)) - }; - if new_state { - self.blocks[blocka] |= range; - } else { - self.blocks[blocka] &= !range; - } - return; - } - // across block boundaries + assert!(end.bytes_usize() <= self.set.domain_size()); if new_state { - // Set `bita..64` to `1`. - self.blocks[blocka] |= u64::MAX << bita; - // Set `0..bitb` to `1`. - if bitb != 0 { - self.blocks[blockb] |= u64::MAX >> (64 - bitb); - } - // Fill in all the other blocks (much faster than one bit at a time). - for block in (blocka + 1)..blockb { - self.blocks[block] = u64::MAX; - } + self.set.insert_range(start.bytes_usize()..end.bytes_usize()); } else { - // Set `bita..64` to `0`. - self.blocks[blocka] &= !(u64::MAX << bita); - // Set `0..bitb` to `0`. - if bitb != 0 { - self.blocks[blockb] &= !(u64::MAX >> (64 - bitb)); - } - // Fill in all the other blocks (much faster than one bit at a time). - for block in (blocka + 1)..blockb { - self.blocks[block] = 0; - } + self.set.remove_range(start.bytes_usize()..end.bytes_usize()); } } #[inline] pub fn get(&self, i: Size) -> bool { - let (block, bit) = Self::bit_index(i); - (self.blocks[block] & (1 << bit)) != 0 + self.set.contains(i.bytes_usize()) } #[inline] pub fn set(&mut self, i: Size, new_state: bool) { - let (block, bit) = Self::bit_index(i); - self.set_bit(block, bit, new_state); - } - - #[inline] - fn set_bit(&mut self, block: usize, bit: usize, new_state: bool) { if new_state { - self.blocks[block] |= 1 << bit; + self.set.insert(i.bytes_usize()); } else { - self.blocks[block] &= !(1 << bit); + self.set.remove(i.bytes_usize()); } } - pub fn grow(&mut self, amount: Size, new_state: bool) { - if amount.bytes() == 0 { - return; - } - let unused_trailing_bits = - u64::try_from(self.blocks.len()).unwrap() * Self::BLOCK_SIZE - self.len.bytes(); - if amount.bytes() > unused_trailing_bits { - let additional_blocks = amount.bytes() / Self::BLOCK_SIZE + 1; - self.blocks.extend( - // FIXME(oli-obk): optimize this by repeating `new_state as Block`. - iter::repeat(0).take(usize::try_from(additional_blocks).unwrap()), - ); - } - let start = self.len; - self.len += amount; - self.set_range_inbounds(start, start + amount, new_state); // `Size` operation - } - /// Returns the index of the first bit in `start..end` (end-exclusive) that is equal to is_init. fn find_bit(&self, start: Size, end: Size, is_init: bool) -> Option { - /// A fast implementation of `find_bit`, - /// which skips over an entire block at a time if it's all 0s (resp. 1s), - /// and finds the first 1 (resp. 0) bit inside a block using `trailing_zeros` instead of a loop. - /// - /// Note that all examples below are written with 8 (instead of 64) bit blocks for simplicity, - /// and with the least significant bit (and lowest block) first: - /// - /// 00000000|00000000 - /// ^ ^ ^ ^ - /// index: 0 7 8 15 - /// - /// Also, if not stated, assume that `is_init = true`, that is, we are searching for the first 1 bit. - fn find_bit_fast( - init_mask: &InitMask, - start: Size, - end: Size, - is_init: bool, - ) -> Option { - /// Search one block, returning the index of the first bit equal to `is_init`. - fn search_block( - bits: Block, - block: usize, - start_bit: usize, - is_init: bool, - ) -> Option { - // For the following examples, assume this function was called with: - // bits = 0b00111011 - // start_bit = 3 - // is_init = false - // Note that, for the examples in this function, the most significant bit is written first, - // which is backwards compared to the comments in `find_bit`/`find_bit_fast`. - - // Invert bits so we're always looking for the first set bit. - // ! 0b00111011 - // bits = 0b11000100 - let bits = if is_init { bits } else { !bits }; - // Mask off unused start bits. - // 0b11000100 - // & 0b11111000 - // bits = 0b11000000 - let bits = bits & (!0 << start_bit); - // Find set bit, if any. - // bit = trailing_zeros(0b11000000) - // bit = 6 - if bits == 0 { - None - } else { - let bit = bits.trailing_zeros(); - Some(InitMask::size_from_bit_index(block, bit)) - } - } - - if start >= end { - return None; - } - - // Convert `start` and `end` to block indexes and bit indexes within each block. - // We must convert `end` to an inclusive bound to handle block boundaries correctly. - // - // For example: - // - // (a) 00000000|00000000 (b) 00000000| - // ^~~~~~~~~~~^ ^~~~~~~~~^ - // start end start end - // - // In both cases, the block index of `end` is 1. - // But we do want to search block 1 in (a), and we don't in (b). - // - // We subtract 1 from both end positions to make them inclusive: - // - // (a) 00000000|00000000 (b) 00000000| - // ^~~~~~~~~~^ ^~~~~~~^ - // start end_inclusive start end_inclusive - // - // For (a), the block index of `end_inclusive` is 1, and for (b), it's 0. - // This provides the desired behavior of searching blocks 0 and 1 for (a), - // and searching only block 0 for (b). - // There is no concern of overflows since we checked for `start >= end` above. - let (start_block, start_bit) = InitMask::bit_index(start); - let end_inclusive = Size::from_bytes(end.bytes() - 1); - let (end_block_inclusive, _) = InitMask::bit_index(end_inclusive); - - // Handle first block: need to skip `start_bit` bits. - // - // We need to handle the first block separately, - // because there may be bits earlier in the block that should be ignored, - // such as the bit marked (1) in this example: - // - // (1) - // -|------ - // (c) 01000000|00000000|00000001 - // ^~~~~~~~~~~~~~~~~~^ - // start end - if let Some(i) = - search_block(init_mask.blocks[start_block], start_block, start_bit, is_init) - { - // If the range is less than a block, we may find a matching bit after `end`. - // - // For example, we shouldn't successfully find bit (2), because it's after `end`: - // - // (2) - // -------| - // (d) 00000001|00000000|00000001 - // ^~~~~^ - // start end - // - // An alternative would be to mask off end bits in the same way as we do for start bits, - // but performing this check afterwards is faster and simpler to implement. - if i < end { - return Some(i); - } else { - return None; - } - } - - // Handle remaining blocks. - // - // We can skip over an entire block at once if it's all 0s (resp. 1s). - // The block marked (3) in this example is the first block that will be handled by this loop, - // and it will be skipped for that reason: - // - // (3) - // -------- - // (e) 01000000|00000000|00000001 - // ^~~~~~~~~~~~~~~~~~^ - // start end - if start_block < end_block_inclusive { - // This loop is written in a specific way for performance. - // Notably: `..end_block_inclusive + 1` is used for an inclusive range instead of `..=end_block_inclusive`, - // and `.zip(start_block + 1..)` is used to track the index instead of `.enumerate().skip().take()`, - // because both alternatives result in significantly worse codegen. - // `end_block_inclusive + 1` is guaranteed not to wrap, because `end_block_inclusive <= end / BLOCK_SIZE`, - // and `BLOCK_SIZE` (the number of bits per block) will always be at least 8 (1 byte). - for (&bits, block) in init_mask.blocks[start_block + 1..end_block_inclusive + 1] - .iter() - .zip(start_block + 1..) - { - if let Some(i) = search_block(bits, block, 0, is_init) { - // If this is the last block, we may find a matching bit after `end`. - // - // For example, we shouldn't successfully find bit (4), because it's after `end`: - // - // (4) - // -------| - // (f) 00000001|00000000|00000001 - // ^~~~~~~~~~~~~~~~~~^ - // start end - // - // As above with example (d), we could handle the end block separately and mask off end bits, - // but unconditionally searching an entire block at once and performing this check afterwards - // is faster and much simpler to implement. - if i < end { - return Some(i); - } else { - return None; - } - } - } - } - - None - } - - #[cfg_attr(not(debug_assertions), allow(dead_code))] - fn find_bit_slow( - init_mask: &InitMask, - start: Size, - end: Size, - is_init: bool, - ) -> Option { - (start..end).find(|&i| init_mask.get(i) == is_init) + if is_init { + self.set.first_set_in(start.bytes_usize()..end.bytes_usize()).map(Size::from_bytes) + } else { + self.set.first_gap_in(start.bytes_usize()..end.bytes_usize()).map(Size::from_bytes) } - - let result = find_bit_fast(self, start, end, is_init); - - debug_assert_eq!( - result, - find_bit_slow(self, start, end, is_init), - "optimized implementation of find_bit is wrong for start={:?} end={:?} is_init={} init_mask={:#?}", - start, - end, - is_init, - self - ); - - result } } @@ -918,8 +667,8 @@ impl InitMask { /// indexes for the first contiguous span of the uninitialized access. #[inline] pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range> { - if end > self.len { - return Err(self.len..end); + if end.bytes_usize() > self.set.domain_size() { + return Err(Size::from_bytes(self.set.domain_size())..end); } let uninit_start = self.find_bit(start, end, false); @@ -943,7 +692,7 @@ impl InitMask { /// - Chunks alternate between [`InitChunk::Init`] and [`InitChunk::Uninit`]. #[inline] pub fn range_as_init_chunks(&self, start: Size, end: Size) -> InitChunkIter<'_> { - assert!(end <= self.len); + assert!(end.bytes_usize() <= self.set.domain_size()); let is_init = if start < end { self.get(start) From 7dee111b401e0d7c4cce8934f2c4c224da8f1e91 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 27 Feb 2022 13:55:18 -0500 Subject: [PATCH 3/5] Move IntervalSet to store I directly This avoids trouble with I = usize on 64-bit systems, where previously we would either assert or truncate when converting to u32. --- compiler/rustc_index/src/interval.rs | 52 +++++++++++++--------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 78655a491b8a6..f2b31f8980c7c 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -15,31 +15,31 @@ mod tests; #[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct IntervalSet { // Start, end - map: SmallVec<[(u32, u32); 4]>, + map: SmallVec<[(I, I); 4]>, domain: usize, _data: PhantomData, } #[inline] -fn inclusive_start(range: impl RangeBounds) -> u32 { +fn inclusive_start(range: impl RangeBounds) -> T { match range.start_bound() { - Bound::Included(start) => start.index() as u32, - Bound::Excluded(start) => start.index() as u32 + 1, - Bound::Unbounded => 0, + Bound::Included(start) => *start, + Bound::Excluded(start) => T::new(start.index() + 1), + Bound::Unbounded => T::new(0), } } #[inline] -fn inclusive_end(domain: usize, range: impl RangeBounds) -> Option { +fn inclusive_end(domain: usize, range: impl RangeBounds) -> Option { let end = match range.end_bound() { - Bound::Included(end) => end.index() as u32, - Bound::Excluded(end) => end.index().checked_sub(1)? as u32, - Bound::Unbounded => domain.checked_sub(1)? as u32, + Bound::Included(end) => *end, + Bound::Excluded(end) => T::new(end.index().checked_sub(1)?), + Bound::Unbounded => T::new(domain.checked_sub(1)?), }; Some(end) } -impl IntervalSet { +impl IntervalSet { pub fn new(domain: usize) -> IntervalSet { IntervalSet { map: SmallVec::new(), domain, _data: PhantomData } } @@ -71,7 +71,7 @@ impl IntervalSet { where I: Step, { - self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1)) + self.map.iter().map(|&(start, end)| start..I::new(end.index() + 1)) } /// Returns true if we increased the number of elements present. @@ -100,10 +100,10 @@ impl IntervalSet { // if r.0 == end + 1, then we're actually adjacent, so we want to // continue to the next range. We're looking here for the first // range which starts *non-adjacently* to our end. - let next = self.map.partition_point(|r| r.0 <= end + 1); + let next = self.map.partition_point(|r| r.0.index() <= end.index() + 1); if let Some(last) = next.checked_sub(1) { let (prev_start, prev_end) = &mut self.map[last]; - if *prev_end + 1 >= start { + if prev_end.index() + 1 >= start.index() { // If the start for the inserted range is adjacent to the // end of the previous, we can extend the previous range. if start < *prev_start { @@ -168,15 +168,11 @@ impl IntervalSet { let (prev_start, prev_end) = self.map.remove(idx); // The range we're looking at contains the range we're removing completely. assert!(prev_start <= start && end <= prev_end); - self.insert_range(I::new(prev_start as usize)..I::new(start as usize)); - self.insert_range(( - Bound::Excluded(I::new(end as usize)), - Bound::Included(I::new(prev_end as usize)), - )); + self.insert_range(prev_start..start); + self.insert_range((Bound::Excluded(end), Bound::Included(prev_end))); } pub fn contains(&self, needle: I) -> bool { - let needle = needle.index() as u32; let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else { // All ranges in the map start after the new range's end return false; @@ -209,7 +205,7 @@ impl IntervalSet { return None; } let range = self.map.get(self.map.partition_point(|r| r.1 < start))?; - if range.0 > end { None } else { Some(I::new(std::cmp::max(range.0, start) as usize)) } + if range.0 > end { None } else { Some(std::cmp::max(range.0, start)) } } /// Returns the minimum (first) element **not** present in the set from `range`. @@ -223,13 +219,13 @@ impl IntervalSet { return None; } let Some(range) = self.map.get(self.map.partition_point(|r| r.1 < start)) else { - return Some(I::new(start as usize)); + return Some(start); }; if start < range.0 { - return Some(I::new(start as usize)); - } else if range.1 as usize + 1 < self.domain { - if range.1 + 1 <= end { - return Some(I::new(range.1 as usize + 1)); + return Some(start); + } else if range.1.index() + 1 < self.domain { + if range.1.index() + 1 <= end.index() { + return Some(I::new(range.1.index() + 1)); } } @@ -251,12 +247,12 @@ impl IntervalSet { return None; }; let (_, prev_end) = &self.map[last]; - if start <= *prev_end { Some(I::new(std::cmp::min(*prev_end, end) as usize)) } else { None } + if start <= *prev_end { Some(std::cmp::min(*prev_end, end)) } else { None } } pub fn insert_all(&mut self) { self.clear(); - self.map.push((0, self.domain.try_into().unwrap())); + self.map.push((I::new(0), I::new(self.domain))); } pub fn union(&mut self, other: &IntervalSet) -> bool @@ -287,7 +283,7 @@ where column_size: usize, } -impl SparseIntervalMatrix { +impl SparseIntervalMatrix { pub fn new(column_size: usize) -> SparseIntervalMatrix { SparseIntervalMatrix { rows: IndexVec::new(), column_size } } From 60a95f1bf7cc1e1f7f4f59d47a886cf9faa6a7eb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 26 Feb 2022 17:40:22 -0500 Subject: [PATCH 4/5] Avoid compressing InitMasks for copy_repeatedly --- .../rustc_const_eval/src/interpret/memory.rs | 17 ++- .../src/mir/interpret/allocation.rs | 126 ++++++++---------- 2 files changed, 67 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 04a6209990ccf..65253ba740ad1 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1035,6 +1035,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // Zero-sized *destination*. return Ok(()); }; + let src_all_uninit = src_alloc.no_bytes_init(src_range); + // FIXME: This is potentially bad for performance as the init mask could + // be large, but is currently necessary to workaround needing to have + // both the init mask for the src_alloc (shared ref) and the dst_alloc + // (unique ref) available simultaneously. Those are access through + // `self.get_raw{,_mut}` and we can't currently explain to rustc that + // there's no invalidation of the two references. + let src_init_mask = src_alloc.init_mask().clone(); // This checks relocation edges on the src, which needs to happen before // `prepare_relocation_copy`. @@ -1047,8 +1055,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // since we don't want to keep any relocations at the target. let relocations = src_alloc.prepare_relocation_copy(self, src_range, dest_offset, num_copies); - // Prepare a copy of the initialization mask. - let compressed = src_alloc.compress_uninit_range(src_range); // Destination alloc preparations and access hooks. let (dest_alloc, extra) = self.get_raw_mut(dest_alloc_id)?; @@ -1059,7 +1065,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { .map_err(|e| e.to_interp_error(dest_alloc_id))? .as_mut_ptr(); - if compressed.no_bytes_init() { + if src_all_uninit { // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range // is marked as uninitialized but we otherwise omit changing the byte representation which may // be arbitrary for uninitialized bytes. @@ -1106,8 +1112,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } // now fill in all the "init" data - dest_alloc.mark_compressed_init_range( - &compressed, + dest_alloc.mark_init_range_repeated( + src_init_mask, + src_range, alloc_range(dest_offset, size), // just a single copy (i.e., not full `dest_range`) num_copies, ); diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index f95b7490e2bc4..32e43a63aac3d 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -773,89 +773,73 @@ impl Allocation { } } -/// Run-length encoding of the uninit mask. -/// Used to copy parts of a mask multiple times to another allocation. -pub struct InitMaskCompressed { - /// Whether the first range is initialized. - initial: bool, - /// The lengths of ranges that are run-length encoded. - /// The initialization state of the ranges alternate starting with `initial`. - ranges: smallvec::SmallVec<[u64; 1]>, -} - -impl InitMaskCompressed { - pub fn no_bytes_init(&self) -> bool { - // The `ranges` are run-length encoded and of alternating initialization state. - // So if `ranges.len() > 1` then the second block is an initialized range. - !self.initial && self.ranges.len() == 1 - } -} - /// Transferring the initialization mask to other allocations. impl Allocation { - /// Creates a run-length encoding of the initialization mask; panics if range is empty. - /// - /// This is essentially a more space-efficient version of - /// `InitMask::range_as_init_chunks(...).collect::>()`. - pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed { - // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), - // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from - // the source and write it to the destination. Even if we optimized the memory accesses, - // we'd be doing all of this `repeat` times. - // Therefore we precompute a compressed version of the initialization mask of the source value and - // then write it back `repeat` times without computing any more information from the source. - - // A precomputed cache for ranges of initialized / uninitialized bits - // 0000010010001110 will become - // `[5, 1, 2, 1, 3, 3, 1]`, - // where each element toggles the state. - - let mut ranges = smallvec::SmallVec::<[u64; 1]>::new(); - - let mut chunks = self.init_mask.range_as_init_chunks(range.start, range.end()).peekable(); - - let initial = chunks.peek().expect("range should be nonempty").is_init(); - - // Here we rely on `range_as_init_chunks` to yield alternating init/uninit chunks. - for chunk in chunks { - let len = chunk.range().end.bytes() - chunk.range().start.bytes(); - ranges.push(len); - } - - InitMaskCompressed { ranges, initial } + pub fn no_bytes_init(&self, range: AllocRange) -> bool { + // If no bits set in start..end + self.init_mask.find_bit(range.start, range.end(), true).is_none() } /// Applies multiple instances of the run-length encoding to the initialization mask. - pub fn mark_compressed_init_range( + pub fn mark_init_range_repeated( &mut self, - defined: &InitMaskCompressed, - range: AllocRange, + mut src_init: InitMask, + src_range: AllocRange, + dest_first_range: AllocRange, repeat: u64, ) { - // An optimization where we can just overwrite an entire range of initialization - // bits if they are going to be uniformly `1` or `0`. - if defined.ranges.len() <= 1 { - self.init_mask.set_range_inbounds( - range.start, - range.start + range.size * repeat, // `Size` operations - defined.initial, - ); - return; + // If the src_range and *each* destination range are of equal size, + // and the source range is either entirely initialized or entirely + // uninitialized, we can skip a bunch of inserts by just inserting for + // the full range once. + if src_range.size == dest_first_range.size { + let initialized = + if src_init.find_bit(src_range.start, src_range.end(), false).is_none() { + Some(true) + } else if src_init.find_bit(src_range.start, src_range.end(), true).is_none() { + Some(false) + } else { + None + }; + + if let Some(initialized) = initialized { + // De-initialize the destination range across all repetitions. + self.init_mask.set_range_inbounds( + dest_first_range.start, + dest_first_range.start + dest_first_range.size * repeat, + initialized, + ); + return; + } } - for mut j in 0..repeat { - j *= range.size.bytes(); - j += range.start.bytes(); - let mut cur = defined.initial; - for range in &defined.ranges { - let old_j = j; - j += range; + // Deinitialize the ranges outside the area we care about, so the loop below + // can do less work. + src_init.set_range_inbounds(Size::from_bytes(0), src_range.start, false); + src_init.set_range_inbounds( + src_range.end(), + Size::from_bytes(src_init.set.domain_size()), + false, + ); + + // De-initialize the destination range across all repetitions. + self.init_mask.set_range_inbounds( + dest_first_range.start, + dest_first_range.start + dest_first_range.size * repeat, + false, + ); + + // Then we initialize. + for count in 0..repeat { + let start = dest_first_range.start + count * dest_first_range.size; + for range in src_init.set.iter_intervals() { + // Offset the chunk start/end from src_range, and then + // offset from the start of this repetition. self.init_mask.set_range_inbounds( - Size::from_bytes(old_j), - Size::from_bytes(j), - cur, + start + (Size::from_bytes(range.start) - src_range.start), + start + (Size::from_bytes(range.end) - src_range.start), + true, ); - cur = !cur; } } } From 18c3cb275abe820ea2773c2e1b96015691e1649f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 28 Feb 2022 10:54:30 -0500 Subject: [PATCH 5/5] Bless mir-opt tests for new InitMask Debug impl --- compiler/rustc_index/src/interval.rs | 19 ++++++++++++++++++- .../src/mir/interpret/allocation.rs | 8 +++++++- .../const_debuginfo.main.ConstDebugInfo.diff | 2 +- ...l_flow_simplification.hello.ConstProp.diff | 2 +- .../inline/inline_diverging.g.Inline.diff | 2 +- ...line_into_box_place.main.Inline.32bit.diff | 2 +- ...line_into_box_place.main.Inline.64bit.diff | 2 +- ...76432.test.SimplifyComparisonIntegral.diff | 2 +- ...ue_59352.num_to_digit.PreCodegen.after.mir | 2 +- ...wrap.SimplifyCfg-elaborate-drops.after.mir | 2 +- ..._after_call.main.ElaborateDrops.before.mir | 2 +- ...age_live_dead_in_statics.XXX.mir_map.0.mir | 2 +- ...after-uninhabited-enum-branching.after.mir | 6 +++--- ...anching.main.UninhabitedEnumBranching.diff | 10 +++++----- ...after-uninhabited-enum-branching.after.mir | 8 ++++---- ...nching2.main.UninhabitedEnumBranching.diff | 16 ++++++++-------- 16 files changed, 55 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index f2b31f8980c7c..3b12549e6d041 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -12,7 +12,7 @@ use smallvec::SmallVec; mod tests; /// Stores a set of intervals on the indices. -#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] +#[derive(Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct IntervalSet { // Start, end map: SmallVec<[(I, I); 4]>, @@ -20,6 +20,23 @@ pub struct IntervalSet { _data: PhantomData, } +impl std::fmt::Debug for IntervalSet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + struct AsList<'a, I>(&'a IntervalSet); + + impl<'a, I: Idx + Ord + Step> std::fmt::Debug for AsList<'a, I> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_list().entries(self.0.iter_intervals()).finish() + } + } + + let mut s = f.debug_struct("IntervalSet"); + s.field("domain_size", &self.domain); + s.field("set", &AsList(&self)); + Ok(()) + } +} + #[inline] fn inclusive_start(range: impl RangeBounds) -> T { match range.start_bound() { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 32e43a63aac3d..6c2946d198213 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -568,12 +568,18 @@ impl Allocation { /// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte /// is initialized. If it is `false` the byte is uninitialized. -#[derive(Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] +#[derive(Clone, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct InitMask { set: IntervalSet, } +impl std::fmt::Debug for InitMask { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("InitMask").field(&self.set).finish() + } +} + impl Ord for InitMask { fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.set diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 7ed25c6c09e96..f2f2eb5fea959 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -77,7 +77,7 @@ _9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:14:13: 14:28 // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 13, set: [0..14]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) } StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:16:9: 16:10 (_10.0: bool) = const true; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 (_10.1: bool) = const false; // scope 5 at $DIR/const_debuginfo.rs:16:13: 16:34 diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index 49f6c10415763..faa34e66b8261 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -22,7 +22,7 @@ // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 14, set: [0..15]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } } bb2: { diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index 3b9d5e727b8a3..8497aecda2653 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -43,7 +43,7 @@ + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } + // mir::Constant + // + span: $SRC_DIR/std/src/panic.rs:LL:COL -+ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } ++ // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 14, set: [0..15]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } } } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 5903cdd9489e5..72b1544223d9e 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -44,7 +44,7 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) -+ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 9, set: [0..8]), align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 0f83b0c4a27ad..f0ba54fe08126 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -44,7 +44,7 @@ - bb2: { + // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // + user_ty: UserType(0) -+ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 17, set: [0..16]), align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) } + ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index c1a4fc301d7cd..fa4c08b38a282 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -73,7 +73,7 @@ // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1099511627775], len: Size { raw: 40 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 40, set: [0..41]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 }) } } bb2: { diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index e2051c85af215..22167550ae602 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -92,7 +92,7 @@ fn num_to_digit(_1: char) -> u32 { // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/option.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 43, set: [0..44]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) } } bb7: { diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir index d562f04560c34..d9d94271c67e1 100644 --- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir @@ -26,7 +26,7 @@ fn unwrap(_1: Option) -> T { // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 14, set: [0..15]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } } bb2: { diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 22bf1acc57d72..a4bec6e0fa1b5 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -15,7 +15,7 @@ fn main() -> () { _4 = const ""; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 0, set: [0..1]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) } _3 = &(*_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 _2 = ::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 // mir::Constant diff --git a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir index 62fbcaaa28938..c3f8fcf456707 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir +++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir @@ -192,7 +192,7 @@ static XXX: &Foo = { _2 = Foo { tup: const "hi", data: move _3 }; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:29: 23:2 // mir::Constant // + span: $DIR/storage_live_dead_in_statics.rs:6:10: 6:14 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 2, set: [0..3]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) } StorageDead(_3); // scope 0 at $DIR/storage_live_dead_in_statics.rs:23:1: 23:2 _1 = &_2; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2 _0 = &(*_1); // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:28: 23:2 diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 75cc100def580..f935949c2e1e7 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -21,7 +21,7 @@ fn main() -> () { _5 = const "C"; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _1 = &(*_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 StorageDead(_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:24:6: 24:7 @@ -38,7 +38,7 @@ fn main() -> () { _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _6 = &(*_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 StorageDead(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 goto -> bb3; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 @@ -48,7 +48,7 @@ fn main() -> () { _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } goto -> bb3; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 } diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff index f173d002e2d75..6e9df58c70d94 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff @@ -27,7 +27,7 @@ _5 = const "C"; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _1 = &(*_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 StorageDead(_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24 @@ -37,7 +37,7 @@ _1 = const "A(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:21:24: 21:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34 } @@ -46,7 +46,7 @@ _4 = const "B(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:22:24: 22:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } _1 = &(*_4); // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 StorageDead(_4); // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34 goto -> bb4; // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34 @@ -67,7 +67,7 @@ _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _6 = &(*_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 StorageDead(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 goto -> bb7; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24 @@ -77,7 +77,7 @@ _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } goto -> bb7; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 } diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 94fba142e001f..1fecf7472b21c 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -38,7 +38,7 @@ fn main() -> () { _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 @@ -49,7 +49,7 @@ fn main() -> () { _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 goto -> bb3; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 @@ -68,7 +68,7 @@ fn main() -> () { _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 @@ -79,7 +79,7 @@ fn main() -> () { _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 goto -> bb6; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff index 84ee885d1f5ee..ebbb599884ad5 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -40,7 +40,7 @@ _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _3 = &(*_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 StorageDead(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24 @@ -50,7 +50,7 @@ _3 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 } @@ -59,7 +59,7 @@ _6 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } _3 = &(*_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 StorageDead(_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34 @@ -70,7 +70,7 @@ _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _3 = &(*_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 StorageDead(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 goto -> bb5; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24 @@ -90,7 +90,7 @@ _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _9 = &(*_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 StorageDead(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24 @@ -100,7 +100,7 @@ _9 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 } @@ -109,7 +109,7 @@ _11 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 8, set: [0..9]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } _9 = &(*_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 StorageDead(_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34 @@ -120,7 +120,7 @@ _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask(IntervalSet { domain_size: 1, set: [0..2]), align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } _9 = &(*_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 StorageDead(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24 goto -> bb10; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24