1 //! Data structures for the whole crate.
2
3 use rustc_hash::FxHashMap;
4 use rustc_hash::FxHashSet;
5 use smallvec::SmallVec;
6
7 use std::cmp::Ordering;
8 use std::collections::VecDeque;
9 use std::fmt;
10 use std::hash::Hash;
11 use std::marker::PhantomData;
12 use std::ops::Index;
13 use std::ops::IndexMut;
14 use std::slice::{Iter, IterMut};
15
16 use crate::{Function, RegUsageMapper};
17
18 #[cfg(feature = "enable-serde")]
19 use serde::{Deserialize, Serialize};
20
21 //=============================================================================
22 // Queues
23
24 pub type Queue<T> = VecDeque<T>;
25
26 //=============================================================================
27 // Maps
28
29 // NOTE: plain HashMap is nondeterministic, even in a single-threaded
30 // scenario, which can make debugging code that uses it really confusing. So
31 // we use FxHashMap instead, as it *is* deterministic, and, allegedly, faster
32 // too.
33 pub type Map<K, V> = FxHashMap<K, V>;
34
35 //=============================================================================
36 // Sets of things
37
38 // Same comment as above for FxHashMap.
39 #[derive(Clone)]
40 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
41 pub struct Set<T: Eq + Hash> {
42 set: FxHashSet<T>,
43 }
44
45 impl<T: Eq + Ord + Hash + Copy + fmt::Debug> Set<T> {
46 #[inline(never)]
empty() -> Self47 pub fn empty() -> Self {
48 Self {
49 set: FxHashSet::<T>::default(),
50 }
51 }
52
53 #[inline(never)]
unit(item: T) -> Self54 pub fn unit(item: T) -> Self {
55 let mut s = Self::empty();
56 s.insert(item);
57 s
58 }
59
60 #[inline(never)]
two(item1: T, item2: T) -> Self61 pub fn two(item1: T, item2: T) -> Self {
62 let mut s = Self::empty();
63 s.insert(item1);
64 s.insert(item2);
65 s
66 }
67
68 #[inline(never)]
card(&self) -> usize69 pub fn card(&self) -> usize {
70 self.set.len()
71 }
72
73 #[inline(never)]
insert(&mut self, item: T)74 pub fn insert(&mut self, item: T) {
75 self.set.insert(item);
76 }
77
78 #[inline(never)]
delete(&mut self, item: T)79 pub fn delete(&mut self, item: T) {
80 self.set.remove(&item);
81 }
82
83 #[inline(never)]
is_empty(&self) -> bool84 pub fn is_empty(&self) -> bool {
85 self.set.is_empty()
86 }
87
88 #[inline(never)]
contains(&self, item: T) -> bool89 pub fn contains(&self, item: T) -> bool {
90 self.set.contains(&item)
91 }
92
93 #[inline(never)]
intersect(&mut self, other: &Self)94 pub fn intersect(&mut self, other: &Self) {
95 let mut res = FxHashSet::<T>::default();
96 for item in self.set.iter() {
97 if other.set.contains(item) {
98 res.insert(*item);
99 }
100 }
101 self.set = res;
102 }
103
104 #[inline(never)]
union(&mut self, other: &Self)105 pub fn union(&mut self, other: &Self) {
106 for item in other.set.iter() {
107 self.set.insert(*item);
108 }
109 }
110
111 #[inline(never)]
remove(&mut self, other: &Self)112 pub fn remove(&mut self, other: &Self) {
113 for item in other.set.iter() {
114 self.set.remove(item);
115 }
116 }
117
118 #[inline(never)]
intersects(&self, other: &Self) -> bool119 pub fn intersects(&self, other: &Self) -> bool {
120 !self.set.is_disjoint(&other.set)
121 }
122
123 #[inline(never)]
is_subset_of(&self, other: &Self) -> bool124 pub fn is_subset_of(&self, other: &Self) -> bool {
125 self.set.is_subset(&other.set)
126 }
127
128 #[inline(never)]
to_vec(&self) -> Vec<T>129 pub fn to_vec(&self) -> Vec<T> {
130 let mut res = Vec::<T>::new();
131 for item in self.set.iter() {
132 res.push(*item)
133 }
134 // Don't delete this. It is important.
135 res.sort_unstable();
136 res
137 }
138
139 #[inline(never)]
from_vec(vec: Vec<T>) -> Self140 pub fn from_vec(vec: Vec<T>) -> Self {
141 let mut res = Set::<T>::empty();
142 for x in vec {
143 res.insert(x);
144 }
145 res
146 }
147
148 #[inline(never)]
equals(&self, other: &Self) -> bool149 pub fn equals(&self, other: &Self) -> bool {
150 self.set == other.set
151 }
152
153 #[inline(never)]
retain<F>(&mut self, f: F) where F: FnMut(&T) -> bool,154 pub fn retain<F>(&mut self, f: F)
155 where
156 F: FnMut(&T) -> bool,
157 {
158 self.set.retain(f)
159 }
160
161 #[inline(never)]
map<F, U>(&self, f: F) -> Set<U> where F: Fn(&T) -> U, U: Eq + Ord + Hash + Copy + fmt::Debug,162 pub fn map<F, U>(&self, f: F) -> Set<U>
163 where
164 F: Fn(&T) -> U,
165 U: Eq + Ord + Hash + Copy + fmt::Debug,
166 {
167 Set {
168 set: self.set.iter().map(f).collect(),
169 }
170 }
171
172 #[inline(never)]
filter_map<F, U>(&self, f: F) -> Set<U> where F: Fn(&T) -> Option<U>, U: Eq + Ord + Hash + Copy + fmt::Debug,173 pub fn filter_map<F, U>(&self, f: F) -> Set<U>
174 where
175 F: Fn(&T) -> Option<U>,
176 U: Eq + Ord + Hash + Copy + fmt::Debug,
177 {
178 Set {
179 set: self.set.iter().filter_map(f).collect(),
180 }
181 }
182
clear(&mut self)183 pub fn clear(&mut self) {
184 self.set.clear();
185 }
186 }
187
188 impl<T: Eq + Ord + Hash + Copy + fmt::Debug> fmt::Debug for Set<T> {
189 #[inline(never)]
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result190 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
191 // Print the elements in some way which depends only on what is
192 // present in the set, and not on any other factor. In particular,
193 // <Debug for FxHashSet> has been observed to to print the elements
194 // of a two element set in both orders on different occasions.
195 let sorted_vec = self.to_vec();
196 let mut s = "{".to_string();
197 for i in 0..sorted_vec.len() {
198 if i > 0 {
199 s = s + &", ".to_string();
200 }
201 s = s + &format!("{:?}", &sorted_vec[i]);
202 }
203 s = s + &"}".to_string();
204 write!(fmt, "{}", s)
205 }
206 }
207
208 pub struct SetIter<'a, T> {
209 set_iter: std::collections::hash_set::Iter<'a, T>,
210 }
211 impl<T: Eq + Hash> Set<T> {
iter(&self) -> SetIter<T>212 pub fn iter(&self) -> SetIter<T> {
213 SetIter {
214 set_iter: self.set.iter(),
215 }
216 }
217 }
218 impl<'a, T> Iterator for SetIter<'a, T> {
219 type Item = &'a T;
next(&mut self) -> Option<Self::Item>220 fn next(&mut self) -> Option<Self::Item> {
221 self.set_iter.next()
222 }
223 }
224
225 //=============================================================================
226 // Iteration boilerplate for entities. The only purpose of this is to support
227 // constructions of the form
228 //
229 // for ent in startEnt .dotdot( endPlus1Ent ) {
230 // }
231 //
232 // until such time as `trait Step` is available in stable Rust. At that point
233 // `fn dotdot` and all of the following can be removed, and the loops
234 // rewritten using the standard syntax:
235 //
236 // for ent in startEnt .. endPlus1Ent {
237 // }
238
239 pub trait Zero {
zero() -> Self240 fn zero() -> Self;
241 }
242
243 pub trait PlusN {
plus_n(&self, n: usize) -> Self244 fn plus_n(&self, n: usize) -> Self;
245 }
246
247 #[derive(Clone, Copy)]
248 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
249 pub struct Range<T> {
250 first: T,
251 len: usize,
252 }
253
254 impl<T: Copy + PartialOrd + PlusN> IntoIterator for Range<T> {
255 type Item = T;
256 type IntoIter = MyIterator<T>;
into_iter(self) -> Self::IntoIter257 fn into_iter(self) -> Self::IntoIter {
258 MyIterator {
259 range: self,
260 next: self.first,
261 }
262 }
263 }
264
265 impl<T: Copy + Eq + Ord + PlusN> Range<T> {
266 /// Create a new range object.
new(from: T, len: usize) -> Range<T>267 pub fn new(from: T, len: usize) -> Range<T> {
268 Range { first: from, len }
269 }
270
start(&self) -> T271 pub fn start(&self) -> T {
272 self.first
273 }
274
first(&self) -> T275 pub fn first(&self) -> T {
276 assert!(self.len() > 0);
277 self.start()
278 }
279
last(&self) -> T280 pub fn last(&self) -> T {
281 assert!(self.len() > 0);
282 self.start().plus_n(self.len() - 1)
283 }
284
last_plus1(&self) -> T285 pub fn last_plus1(&self) -> T {
286 self.start().plus_n(self.len())
287 }
288
len(&self) -> usize289 pub fn len(&self) -> usize {
290 self.len
291 }
292
contains(&self, t: T) -> bool293 pub fn contains(&self, t: T) -> bool {
294 t >= self.first && t < self.first.plus_n(self.len)
295 }
296 }
297
298 pub struct MyIterator<T> {
299 range: Range<T>,
300 next: T,
301 }
302 impl<T: Copy + PartialOrd + PlusN> Iterator for MyIterator<T> {
303 type Item = T;
next(&mut self) -> Option<Self::Item>304 fn next(&mut self) -> Option<Self::Item> {
305 if self.next >= self.range.first.plus_n(self.range.len) {
306 None
307 } else {
308 let res = Some(self.next);
309 self.next = self.next.plus_n(1);
310 res
311 }
312 }
313 }
314
315 //=============================================================================
316 // Vectors where both the index and element types can be specified (and at
317 // most 2^32-1 elems can be stored. What if this overflows?)
318
319 pub struct TypedIxVec<TyIx, Ty> {
320 vek: Vec<Ty>,
321 ty_ix: PhantomData<TyIx>,
322 }
323
324 impl<TyIx, Ty> TypedIxVec<TyIx, Ty>
325 where
326 Ty: Clone,
327 TyIx: Copy + Eq + Ord + Zero + PlusN + Into<u32>,
328 {
new() -> Self329 pub fn new() -> Self {
330 Self {
331 vek: Vec::new(),
332 ty_ix: PhantomData::<TyIx>,
333 }
334 }
from_vec(vek: Vec<Ty>) -> Self335 pub fn from_vec(vek: Vec<Ty>) -> Self {
336 Self {
337 vek,
338 ty_ix: PhantomData::<TyIx>,
339 }
340 }
append(&mut self, other: &mut TypedIxVec<TyIx, Ty>)341 pub fn append(&mut self, other: &mut TypedIxVec<TyIx, Ty>) {
342 // FIXME what if this overflows?
343 self.vek.append(&mut other.vek);
344 }
iter(&self) -> Iter<Ty>345 pub fn iter(&self) -> Iter<Ty> {
346 self.vek.iter()
347 }
iter_mut(&mut self) -> IterMut<Ty>348 pub fn iter_mut(&mut self) -> IterMut<Ty> {
349 self.vek.iter_mut()
350 }
len(&self) -> u32351 pub fn len(&self) -> u32 {
352 // FIXME what if this overflows?
353 self.vek.len() as u32
354 }
push(&mut self, item: Ty)355 pub fn push(&mut self, item: Ty) {
356 // FIXME what if this overflows?
357 self.vek.push(item);
358 }
resize(&mut self, new_len: u32, value: Ty)359 pub fn resize(&mut self, new_len: u32, value: Ty) {
360 self.vek.resize(new_len as usize, value);
361 }
reserve(&mut self, additional: usize)362 pub fn reserve(&mut self, additional: usize) {
363 self.vek.reserve(additional);
364 }
elems(&self) -> &[Ty]365 pub fn elems(&self) -> &[Ty] {
366 &self.vek[..]
367 }
elems_mut(&mut self) -> &mut [Ty]368 pub fn elems_mut(&mut self) -> &mut [Ty] {
369 &mut self.vek[..]
370 }
range(&self) -> Range<TyIx>371 pub fn range(&self) -> Range<TyIx> {
372 Range::new(TyIx::zero(), self.len() as usize)
373 }
remove(&mut self, idx: TyIx) -> Ty374 pub fn remove(&mut self, idx: TyIx) -> Ty {
375 self.vek.remove(idx.into() as usize)
376 }
sort_by<F: FnMut(&Ty, &Ty) -> Ordering>(&mut self, compare: F)377 pub fn sort_by<F: FnMut(&Ty, &Ty) -> Ordering>(&mut self, compare: F) {
378 self.vek.sort_by(compare)
379 }
sort_unstable_by<F: FnMut(&Ty, &Ty) -> Ordering>(&mut self, compare: F)380 pub fn sort_unstable_by<F: FnMut(&Ty, &Ty) -> Ordering>(&mut self, compare: F) {
381 self.vek.sort_unstable_by(compare)
382 }
clear(&mut self)383 pub fn clear(&mut self) {
384 self.vek.clear();
385 }
386 }
387
388 impl<TyIx, Ty> Index<TyIx> for TypedIxVec<TyIx, Ty>
389 where
390 TyIx: Into<u32>,
391 {
392 type Output = Ty;
index(&self, ix: TyIx) -> &Ty393 fn index(&self, ix: TyIx) -> &Ty {
394 &self.vek[ix.into() as usize]
395 }
396 }
397
398 impl<TyIx, Ty> IndexMut<TyIx> for TypedIxVec<TyIx, Ty>
399 where
400 TyIx: Into<u32>,
401 {
index_mut(&mut self, ix: TyIx) -> &mut Ty402 fn index_mut(&mut self, ix: TyIx) -> &mut Ty {
403 &mut self.vek[ix.into() as usize]
404 }
405 }
406
407 impl<TyIx, Ty> Clone for TypedIxVec<TyIx, Ty>
408 where
409 Ty: Clone,
410 {
411 // This is only needed for debug printing.
clone(&self) -> Self412 fn clone(&self) -> Self {
413 Self {
414 vek: self.vek.clone(),
415 ty_ix: PhantomData::<TyIx>,
416 }
417 }
418 }
419
420 //=============================================================================
421
422 macro_rules! generate_boilerplate {
423 ($TypeIx:ident, $Type:ident, $PrintingPrefix:expr) => {
424 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
425 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
426 // Firstly, the indexing type (TypeIx)
427 pub enum $TypeIx {
428 $TypeIx(u32),
429 }
430 impl $TypeIx {
431 #[allow(dead_code)]
432 #[inline(always)]
433 pub fn new(n: u32) -> Self {
434 debug_assert!(n != u32::max_value());
435 Self::$TypeIx(n)
436 }
437 #[allow(dead_code)]
438 #[inline(always)]
439 pub const fn max_value() -> Self {
440 Self::$TypeIx(u32::max_value() - 1)
441 }
442 #[allow(dead_code)]
443 #[inline(always)]
444 pub const fn min_value() -> Self {
445 Self::$TypeIx(u32::min_value())
446 }
447 #[allow(dead_code)]
448 #[inline(always)]
449 pub const fn invalid_value() -> Self {
450 Self::$TypeIx(u32::max_value())
451 }
452 #[allow(dead_code)]
453 #[inline(always)]
454 pub fn is_valid(self) -> bool {
455 self != Self::invalid_value()
456 }
457 #[allow(dead_code)]
458 #[inline(always)]
459 pub fn is_invalid(self) -> bool {
460 self == Self::invalid_value()
461 }
462 #[allow(dead_code)]
463 #[inline(always)]
464 pub fn get(self) -> u32 {
465 debug_assert!(self.is_valid());
466 match self {
467 $TypeIx::$TypeIx(n) => n,
468 }
469 }
470 #[allow(dead_code)]
471 #[inline(always)]
472 pub fn plus(self, delta: u32) -> $TypeIx {
473 debug_assert!(self.is_valid());
474 $TypeIx::$TypeIx(self.get() + delta)
475 }
476 #[allow(dead_code)]
477 #[inline(always)]
478 pub fn minus(self, delta: u32) -> $TypeIx {
479 debug_assert!(self.is_valid());
480 $TypeIx::$TypeIx(self.get() - delta)
481 }
482 #[allow(dead_code)]
483 pub fn dotdot(&self, last_plus1: $TypeIx) -> Range<$TypeIx> {
484 debug_assert!(self.is_valid());
485 let len = (last_plus1.get() - self.get()) as usize;
486 Range::new(*self, len)
487 }
488 }
489 impl fmt::Debug for $TypeIx {
490 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
491 if self.is_invalid() {
492 write!(fmt, "{}<NONE>", $PrintingPrefix)
493 } else {
494 write!(fmt, "{}{}", $PrintingPrefix, &self.get())
495 }
496 }
497 }
498 impl PlusN for $TypeIx {
499 #[inline(always)]
500 fn plus_n(&self, n: usize) -> Self {
501 debug_assert!(self.is_valid());
502 self.plus(n as u32)
503 }
504 }
505 impl Into<u32> for $TypeIx {
506 #[inline(always)]
507 fn into(self) -> u32 {
508 debug_assert!(self.is_valid());
509 self.get()
510 }
511 }
512 impl Zero for $TypeIx {
513 #[inline(always)]
514 fn zero() -> Self {
515 $TypeIx::new(0)
516 }
517 }
518 };
519 }
520
521 generate_boilerplate!(InstIx, Inst, "i");
522
523 generate_boilerplate!(BlockIx, Block, "b");
524
525 generate_boilerplate!(RangeFragIx, RangeFrag, "f");
526
527 generate_boilerplate!(VirtualRangeIx, VirtualRange, "vr");
528
529 generate_boilerplate!(RealRangeIx, RealRange, "rr");
530
531 impl<TyIx, Ty: fmt::Debug> fmt::Debug for TypedIxVec<TyIx, Ty> {
532 // This is something of a hack in the sense that it doesn't show the
533 // indices, but oh well ..
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result534 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
535 write!(fmt, "{:?}", self.vek)
536 }
537 }
538
539 //=============================================================================
540 // Definitions of register classes, registers and stack slots, and printing
541 // thereof. Note that this register class definition is meant to be
542 // architecture-independent: it simply captures common integer/float/vector
543 // types that machines are likely to use. TODO: investigate whether we need a
544 // more flexible register-class definition mechanism.
545
546 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
547 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
548 pub enum RegClass {
549 I32 = 0,
550 F32 = 1,
551 I64 = 2,
552 F64 = 3,
553 V128 = 4,
554 INVALID = 5,
555 }
556
557 /// The number of register classes that exist.
558 /// N.B.: must be <= 7 (fit into 3 bits) for 32-bit VReg/RReg packed format!
559 pub const NUM_REG_CLASSES: usize = 5;
560
561 impl RegClass {
562 /// Convert a register class to a u32 index.
563 #[inline(always)]
rc_to_u32(self) -> u32564 pub fn rc_to_u32(self) -> u32 {
565 self as u32
566 }
567 /// Convert a register class to a usize index.
568 #[inline(always)]
rc_to_usize(self) -> usize569 pub fn rc_to_usize(self) -> usize {
570 self as usize
571 }
572 /// Construct a register class from a u32.
573 #[inline(always)]
rc_from_u32(rc: u32) -> RegClass574 pub fn rc_from_u32(rc: u32) -> RegClass {
575 match rc {
576 0 => RegClass::I32,
577 1 => RegClass::F32,
578 2 => RegClass::I64,
579 3 => RegClass::F64,
580 4 => RegClass::V128,
581 _ => panic!("RegClass::rc_from_u32"),
582 }
583 }
584
short_name(self) -> &'static str585 pub fn short_name(self) -> &'static str {
586 match self {
587 RegClass::I32 => "I",
588 RegClass::I64 => "J",
589 RegClass::F32 => "F",
590 RegClass::F64 => "D",
591 RegClass::V128 => "V",
592 RegClass::INVALID => panic!("RegClass::short_name"),
593 }
594 }
595
long_name(self) -> &'static str596 pub fn long_name(self) -> &'static str {
597 match self {
598 RegClass::I32 => "I32",
599 RegClass::I64 => "I32",
600 RegClass::F32 => "F32",
601 RegClass::F64 => "F32",
602 RegClass::V128 => "V128",
603 RegClass::INVALID => panic!("RegClass::long_name"),
604 }
605 }
606 }
607
608 // Reg represents both real and virtual registers. For compactness and speed,
609 // these fields are packed into a single u32. The format is:
610 //
611 // Virtual Reg: 1 rc:3 index:28
612 // Real Reg: 0 rc:3 uu:12 enc:8 index:8
613 //
614 // `rc` is the register class. `uu` means "unused". `enc` is the hardware
615 // encoding for the reg. `index` is a zero based index which has the
616 // following meanings:
617 //
618 // * for a Virtual Reg, `index` is just the virtual register number.
619 // * for a Real Reg, `index` is the entry number in the associated
620 // `RealRegUniverse`.
621 //
622 // This scheme gives us:
623 //
624 // * a compact (32-bit) representation for registers
625 // * fast equality tests for registers
626 // * ability to handle up to 2^28 (268.4 million) virtual regs per function
627 // * ability to handle up to 8 register classes
628 // * ability to handle targets with up to 256 real registers
629 // * ability to emit instructions containing real regs without having to
630 // look up encodings in any side tables, since a real reg carries its
631 // encoding
632 // * efficient bitsets and arrays of virtual registers, since each has a
633 // zero-based index baked in
634 // * efficient bitsets and arrays of real registers, for the same reason
635 //
636 // This scheme makes it impossible to represent overlapping register classes,
637 // but that doesn't seem important. AFAIK only ARM32 VFP/Neon has that.
638
639 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
640 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
641 pub struct Reg {
642 bits: u32,
643 }
644
645 static INVALID_REG: u32 = 0xffffffff;
646
647 impl Reg {
648 #[inline(always)]
is_virtual(self) -> bool649 pub fn is_virtual(self) -> bool {
650 self.is_valid() && (self.bits & 0x8000_0000) != 0
651 }
652 #[inline(always)]
is_real(self) -> bool653 pub fn is_real(self) -> bool {
654 self.is_valid() && (self.bits & 0x8000_0000) == 0
655 }
new_real(rc: RegClass, enc: u8, index: u8) -> Self656 pub fn new_real(rc: RegClass, enc: u8, index: u8) -> Self {
657 let n = (0 << 31) | (rc.rc_to_u32() << 28) | ((enc as u32) << 8) | ((index as u32) << 0);
658 Reg { bits: n }
659 }
new_virtual(rc: RegClass, index: u32) -> Self660 pub fn new_virtual(rc: RegClass, index: u32) -> Self {
661 if index >= (1 << 28) {
662 panic!("new_virtual(): index too large");
663 }
664 let n = (1 << 31) | (rc.rc_to_u32() << 28) | (index << 0);
665 Reg { bits: n }
666 }
invalid() -> Reg667 pub fn invalid() -> Reg {
668 Reg { bits: INVALID_REG }
669 }
670 #[inline(always)]
is_invalid(self) -> bool671 pub fn is_invalid(self) -> bool {
672 self.bits == INVALID_REG
673 }
674 #[inline(always)]
is_valid(self) -> bool675 pub fn is_valid(self) -> bool {
676 !self.is_invalid()
677 }
is_virtual_or_invalid(self) -> bool678 pub fn is_virtual_or_invalid(self) -> bool {
679 self.is_virtual() || self.is_invalid()
680 }
is_real_or_invalid(self) -> bool681 pub fn is_real_or_invalid(self) -> bool {
682 self.is_real() || self.is_invalid()
683 }
684 #[inline(always)]
get_class(self) -> RegClass685 pub fn get_class(self) -> RegClass {
686 debug_assert!(self.is_valid());
687 RegClass::rc_from_u32((self.bits >> 28) & 0x7)
688 }
689 #[inline(always)]
get_index(self) -> usize690 pub fn get_index(self) -> usize {
691 debug_assert!(self.is_valid());
692 // Return type is usize because typically we will want to use the
693 // result for indexing into a Vec
694 if self.is_virtual() {
695 (self.bits & ((1 << 28) - 1)) as usize
696 } else {
697 (self.bits & ((1 << 8) - 1)) as usize
698 }
699 }
700 #[inline(always)]
get_index_u32(self) -> u32701 pub fn get_index_u32(self) -> u32 {
702 debug_assert!(self.is_valid());
703 if self.is_virtual() {
704 self.bits & ((1 << 28) - 1)
705 } else {
706 self.bits & ((1 << 8) - 1)
707 }
708 }
get_hw_encoding(self) -> u8709 pub fn get_hw_encoding(self) -> u8 {
710 debug_assert!(self.is_valid());
711 if self.is_virtual() {
712 panic!("Virtual register does not have a hardware encoding")
713 } else {
714 ((self.bits >> 8) & ((1 << 8) - 1)) as u8
715 }
716 }
as_virtual_reg(self) -> Option<VirtualReg>717 pub fn as_virtual_reg(self) -> Option<VirtualReg> {
718 // Allow invalid virtual regs as well.
719 if self.is_virtual_or_invalid() {
720 Some(VirtualReg { reg: self })
721 } else {
722 None
723 }
724 }
as_real_reg(self) -> Option<RealReg>725 pub fn as_real_reg(self) -> Option<RealReg> {
726 // Allow invalid real regs as well.
727 if self.is_real_or_invalid() {
728 Some(RealReg { reg: self })
729 } else {
730 None
731 }
732 }
show_with_rru(self, univ: &RealRegUniverse) -> String733 pub fn show_with_rru(self, univ: &RealRegUniverse) -> String {
734 if self.is_real() && self.get_index() < univ.regs.len() {
735 univ.regs[self.get_index()].1.clone()
736 } else if self.is_valid() {
737 format!("{:?}", self)
738 } else {
739 "rINVALID".to_string()
740 }
741 }
742 }
743
744 impl fmt::Debug for Reg {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result745 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
746 if self.is_valid() {
747 write!(
748 fmt,
749 "{}{}{}",
750 if self.is_virtual() { "v" } else { "r" },
751 self.get_index(),
752 self.get_class().short_name(),
753 )
754 } else {
755 write!(fmt, "rINVALID")
756 }
757 }
758 }
759
760 // RealReg and VirtualReg are merely wrappers around Reg, which try to
761 // dynamically ensure that they are really wrapping the correct flavour of
762 // register.
763
764 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
765 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
766 pub struct RealReg {
767 reg: Reg,
768 }
769 impl Reg /* !!not RealReg!! */ {
to_real_reg(self) -> RealReg770 pub fn to_real_reg(self) -> RealReg {
771 if self.is_virtual() {
772 panic!("Reg::to_real_reg: this is a virtual register")
773 } else {
774 RealReg { reg: self }
775 }
776 }
777 }
778 impl RealReg {
get_class(self) -> RegClass779 pub fn get_class(self) -> RegClass {
780 self.reg.get_class()
781 }
782 #[inline(always)]
get_index(self) -> usize783 pub fn get_index(self) -> usize {
784 self.reg.get_index()
785 }
get_hw_encoding(self) -> usize786 pub fn get_hw_encoding(self) -> usize {
787 self.reg.get_hw_encoding() as usize
788 }
789 #[inline(always)]
to_reg(self) -> Reg790 pub fn to_reg(self) -> Reg {
791 self.reg
792 }
invalid() -> RealReg793 pub fn invalid() -> RealReg {
794 RealReg {
795 reg: Reg::invalid(),
796 }
797 }
is_valid(self) -> bool798 pub fn is_valid(self) -> bool {
799 self.reg.is_valid()
800 }
is_invalid(self) -> bool801 pub fn is_invalid(self) -> bool {
802 self.reg.is_invalid()
803 }
maybe_valid(self) -> Option<RealReg>804 pub fn maybe_valid(self) -> Option<RealReg> {
805 if self == RealReg::invalid() {
806 None
807 } else {
808 Some(self)
809 }
810 }
811 }
812 impl fmt::Debug for RealReg {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result813 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
814 write!(fmt, "{:?}", self.reg)
815 }
816 }
817
818 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
819 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
820 pub struct VirtualReg {
821 reg: Reg,
822 }
823 impl Reg /* !!not VirtualReg!! */ {
824 #[inline(always)]
to_virtual_reg(self) -> VirtualReg825 pub fn to_virtual_reg(self) -> VirtualReg {
826 if self.is_virtual() {
827 VirtualReg { reg: self }
828 } else {
829 panic!("Reg::to_virtual_reg: this is a real register")
830 }
831 }
832 }
833 impl VirtualReg {
get_class(self) -> RegClass834 pub fn get_class(self) -> RegClass {
835 self.reg.get_class()
836 }
837 #[inline(always)]
get_index(self) -> usize838 pub fn get_index(self) -> usize {
839 self.reg.get_index()
840 }
841 #[inline(always)]
to_reg(self) -> Reg842 pub fn to_reg(self) -> Reg {
843 self.reg
844 }
invalid() -> VirtualReg845 pub fn invalid() -> VirtualReg {
846 VirtualReg {
847 reg: Reg::invalid(),
848 }
849 }
is_valid(self) -> bool850 pub fn is_valid(self) -> bool {
851 self.reg.is_valid()
852 }
is_invalid(self) -> bool853 pub fn is_invalid(self) -> bool {
854 self.reg.is_invalid()
855 }
maybe_valid(self) -> Option<VirtualReg>856 pub fn maybe_valid(self) -> Option<VirtualReg> {
857 if self == VirtualReg::invalid() {
858 None
859 } else {
860 Some(self)
861 }
862 }
863 }
864 impl fmt::Debug for VirtualReg {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result865 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
866 write!(fmt, "{:?}", self.reg)
867 }
868 }
869
870 impl Reg {
871 /// Apply a vreg-rreg mapping to a Reg. This is used for registers used in
872 /// a read-role.
apply_uses<RUM: RegUsageMapper>(&mut self, mapper: &RUM)873 pub fn apply_uses<RUM: RegUsageMapper>(&mut self, mapper: &RUM) {
874 self.apply(|vreg| mapper.get_use(vreg));
875 }
876
877 /// Apply a vreg-rreg mapping to a Reg. This is used for registers used in
878 /// a write-role.
apply_defs<RUM: RegUsageMapper>(&mut self, mapper: &RUM)879 pub fn apply_defs<RUM: RegUsageMapper>(&mut self, mapper: &RUM) {
880 self.apply(|vreg| mapper.get_def(vreg));
881 }
882
883 /// Apply a vreg-rreg mapping to a Reg. This is used for registers used in
884 /// a modify-role.
apply_mods<RUM: RegUsageMapper>(&mut self, mapper: &RUM)885 pub fn apply_mods<RUM: RegUsageMapper>(&mut self, mapper: &RUM) {
886 self.apply(|vreg| mapper.get_mod(vreg));
887 }
888
apply<F: Fn(VirtualReg) -> Option<RealReg>>(&mut self, f: F)889 fn apply<F: Fn(VirtualReg) -> Option<RealReg>>(&mut self, f: F) {
890 if let Some(vreg) = self.as_virtual_reg() {
891 if let Some(rreg) = f(vreg) {
892 debug_assert!(rreg.get_class() == vreg.get_class());
893 *self = rreg.to_reg();
894 } else {
895 panic!("Reg::apply: no mapping for {:?}", self);
896 }
897 }
898 }
899 }
900
901 /// A "writable register". This is a zero-cost wrapper that can be used to
902 /// create a distinction, at the Rust type level, between a plain "register"
903 /// and a "writable register".
904 ///
905 /// Only structs that implement the `WritableBase` trait can be wrapped with
906 /// `Writable`. These are the Reg, RealReg and VirtualReg data structures only,
907 /// since `WritableBase` is not exposed to end users.
908 ///
909 /// Writable<..> can be used by the client to ensure that, internally, it only
910 /// generates instructions that write to registers that should be written. The
911 /// `InstRegUses` below, which must be implemented for every instruction,
912 /// requires a `Writable<Reg>` (not just `Reg`) in its `defined` and
913 /// `modified` sets. While we cannot hide the constructor for `Writable<..>`
914 /// from certain parts of the client while exposing it to others, the client
915 /// *can* adopt conventions to e.g. only ever call the Writable<..>
916 /// constructor from its central vreg-management logic, and decide that any
917 /// invocation of this constructor in a machine backend (for example) is an
918 /// error.
919 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
920 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
921 pub struct Writable<R: WritableBase> {
922 reg: R,
923 }
924
925 /// Set of requirements for types that can be wrapped in Writable.
926 pub trait WritableBase:
927 Copy + Clone + PartialEq + Eq + Hash + PartialOrd + Ord + fmt::Debug
928 {
929 }
930
931 impl WritableBase for Reg {}
932 impl WritableBase for RealReg {}
933 impl WritableBase for VirtualReg {}
934
935 impl<R: WritableBase> Writable<R> {
936 /// Create a Writable<R> from an R. The client should carefully audit where
937 /// it calls this constructor to ensure correctness (see `Writable<..>`
938 /// struct documentation).
939 #[inline(always)]
from_reg(reg: R) -> Writable<R>940 pub fn from_reg(reg: R) -> Writable<R> {
941 Writable { reg }
942 }
943
944 /// Get the inner Reg.
to_reg(&self) -> R945 pub fn to_reg(&self) -> R {
946 self.reg
947 }
948
map<F, U>(&self, f: F) -> Writable<U> where F: Fn(R) -> U, U: WritableBase,949 pub fn map<F, U>(&self, f: F) -> Writable<U>
950 where
951 F: Fn(R) -> U,
952 U: WritableBase,
953 {
954 Writable { reg: f(self.reg) }
955 }
956 }
957
958 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
959 pub struct SpillSlot(u32);
960
961 impl SpillSlot {
962 #[inline(always)]
new(n: u32) -> Self963 pub fn new(n: u32) -> Self {
964 Self(n)
965 }
966 #[inline(always)]
get(self) -> u32967 pub fn get(self) -> u32 {
968 self.0
969 }
970 #[inline(always)]
get_usize(self) -> usize971 pub fn get_usize(self) -> usize {
972 self.get() as usize
973 }
round_up(self, num_slots: u32) -> SpillSlot974 pub fn round_up(self, num_slots: u32) -> SpillSlot {
975 assert!(num_slots > 0);
976 SpillSlot::new((self.get() + num_slots - 1) / num_slots * num_slots)
977 }
inc(self, num_slots: u32) -> SpillSlot978 pub fn inc(self, num_slots: u32) -> SpillSlot {
979 SpillSlot::new(self.get() + num_slots)
980 }
981 }
982
983 impl fmt::Debug for SpillSlot {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result984 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
985 write!(fmt, "S{}", self.get())
986 }
987 }
988
989 //=============================================================================
990 // Register uses: low level interface
991
992 // This minimal struct is visible from outside the regalloc.rs interface. It
993 // is intended to be a safe wrapper around `RegVecs`, which isn't externally
994 // visible. It is used to collect unsanitized reg use info from client
995 // instructions.
996 pub struct RegUsageCollector<'a> {
997 pub reg_vecs: &'a mut RegVecs,
998 }
999
1000 impl<'a> RegUsageCollector<'a> {
new(reg_vecs: &'a mut RegVecs) -> Self1001 pub fn new(reg_vecs: &'a mut RegVecs) -> Self {
1002 Self { reg_vecs }
1003 }
add_use(&mut self, r: Reg)1004 pub fn add_use(&mut self, r: Reg) {
1005 self.reg_vecs.uses.push(r);
1006 }
add_uses(&mut self, regs: &[Reg])1007 pub fn add_uses(&mut self, regs: &[Reg]) {
1008 self.reg_vecs.uses.extend(regs.iter());
1009 }
add_def(&mut self, r: Writable<Reg>)1010 pub fn add_def(&mut self, r: Writable<Reg>) {
1011 self.reg_vecs.defs.push(r.to_reg());
1012 }
add_defs(&mut self, regs: &[Writable<Reg>])1013 pub fn add_defs(&mut self, regs: &[Writable<Reg>]) {
1014 self.reg_vecs.defs.reserve(regs.len());
1015 for r in regs {
1016 self.reg_vecs.defs.push(r.to_reg());
1017 }
1018 }
add_mod(&mut self, r: Writable<Reg>)1019 pub fn add_mod(&mut self, r: Writable<Reg>) {
1020 self.reg_vecs.mods.push(r.to_reg());
1021 }
add_mods(&mut self, regs: &[Writable<Reg>])1022 pub fn add_mods(&mut self, regs: &[Writable<Reg>]) {
1023 self.reg_vecs.mods.reserve(regs.len());
1024 for r in regs {
1025 self.reg_vecs.mods.push(r.to_reg());
1026 }
1027 }
1028
1029 // The presence of the following two is a hack, needed to support fuzzing
1030 // in the test framework. Real clients should not call them.
get_use_def_mod_vecs_test_framework_only(&self) -> (Vec<Reg>, Vec<Reg>, Vec<Reg>)1031 pub fn get_use_def_mod_vecs_test_framework_only(&self) -> (Vec<Reg>, Vec<Reg>, Vec<Reg>) {
1032 (
1033 self.reg_vecs.uses.clone(),
1034 self.reg_vecs.defs.clone(),
1035 self.reg_vecs.mods.clone(),
1036 )
1037 }
1038
get_empty_reg_vecs_test_framework_only(sanitized: bool) -> RegVecs1039 pub fn get_empty_reg_vecs_test_framework_only(sanitized: bool) -> RegVecs {
1040 RegVecs::new(sanitized)
1041 }
1042 }
1043
1044 // Everything else is not visible outside the regalloc.rs interface.
1045
1046 // There is one of these per function. Note that `defs` and `mods` lose the
1047 // `Writable` constraint at this point. This is for convenience of having all
1048 // three vectors be the same type, but comes at the cost of the loss of being
1049 // able to differentiate readonly vs read/write registers in the Rust type
1050 // system.
1051 #[derive(Debug)]
1052 pub struct RegVecs {
1053 pub uses: Vec<Reg>,
1054 pub defs: Vec<Reg>,
1055 pub mods: Vec<Reg>,
1056 sanitized: bool,
1057 }
1058
1059 impl RegVecs {
new(sanitized: bool) -> Self1060 pub fn new(sanitized: bool) -> Self {
1061 Self {
1062 uses: vec![],
1063 defs: vec![],
1064 mods: vec![],
1065 sanitized,
1066 }
1067 }
is_sanitized(&self) -> bool1068 pub fn is_sanitized(&self) -> bool {
1069 self.sanitized
1070 }
set_sanitized(&mut self, sanitized: bool)1071 pub fn set_sanitized(&mut self, sanitized: bool) {
1072 self.sanitized = sanitized;
1073 }
clear(&mut self)1074 pub fn clear(&mut self) {
1075 self.uses.clear();
1076 self.defs.clear();
1077 self.mods.clear();
1078 }
1079 }
1080
1081 // There is one of these per insn, so try and keep it as compact as possible.
1082 // I think this should fit in 16 bytes.
1083 #[derive(Clone, Debug)]
1084 pub struct RegVecBounds {
1085 // These are the group start indices in RegVecs.{uses, defs, mods}.
1086 pub uses_start: u32,
1087 pub defs_start: u32,
1088 pub mods_start: u32,
1089 // And these are the group lengths. This does limit each instruction to
1090 // mentioning only 256 registers in any group, but that does not seem like a
1091 // problem.
1092 pub uses_len: u8,
1093 pub defs_len: u8,
1094 pub mods_len: u8,
1095 }
1096
1097 impl RegVecBounds {
new() -> Self1098 pub fn new() -> Self {
1099 Self {
1100 uses_start: 0,
1101 defs_start: 0,
1102 mods_start: 0,
1103 uses_len: 0,
1104 defs_len: 0,
1105 mods_len: 0,
1106 }
1107 }
1108 }
1109
1110 // This is the primary structure. We compute just one of these for an entire
1111 // function.
1112 pub struct RegVecsAndBounds {
1113 // The three vectors of registers. These can be arbitrarily long.
1114 pub vecs: RegVecs,
1115 // Admin info which tells us the location, for each insn, of its register
1116 // groups in `vecs`.
1117 pub bounds: TypedIxVec<InstIx, RegVecBounds>,
1118 }
1119
1120 impl RegVecsAndBounds {
new(vecs: RegVecs, bounds: TypedIxVec<InstIx, RegVecBounds>) -> Self1121 pub fn new(vecs: RegVecs, bounds: TypedIxVec<InstIx, RegVecBounds>) -> Self {
1122 Self { vecs, bounds }
1123 }
is_sanitized(&self) -> bool1124 pub fn is_sanitized(&self) -> bool {
1125 self.vecs.sanitized
1126 }
1127 #[allow(dead_code)] // XXX for some reason, Rustc 1.43.1 thinks this is currently unused.
num_insns(&self) -> u321128 pub fn num_insns(&self) -> u32 {
1129 self.bounds.len()
1130 }
1131 }
1132
1133 //=============================================================================
1134 // Register uses: convenience interface
1135
1136 // Some call sites want to get reg use information as three Sets. This is a
1137 // "convenience facility" which is easier to use but much slower than working
1138 // with a whole-function `RegVecsAndBounds`. It shouldn't be used on critical
1139 // paths.
1140 #[derive(Debug)]
1141 pub struct RegSets {
1142 pub uses: Set<Reg>, // registers that are read.
1143 pub defs: Set<Reg>, // registers that are written.
1144 pub mods: Set<Reg>, // registers that are modified.
1145 sanitized: bool,
1146 }
1147
1148 impl RegSets {
new(sanitized: bool) -> Self1149 pub fn new(sanitized: bool) -> Self {
1150 Self {
1151 uses: Set::<Reg>::empty(),
1152 defs: Set::<Reg>::empty(),
1153 mods: Set::<Reg>::empty(),
1154 sanitized,
1155 }
1156 }
1157
is_sanitized(&self) -> bool1158 pub fn is_sanitized(&self) -> bool {
1159 self.sanitized
1160 }
1161 }
1162
1163 impl RegVecsAndBounds {
1164 /* !!not RegSets!! */
1165 #[inline(never)]
1166 // Convenience function. Try to avoid using this.
get_reg_sets_for_iix(&self, iix: InstIx) -> RegSets1167 pub fn get_reg_sets_for_iix(&self, iix: InstIx) -> RegSets {
1168 let bounds = &self.bounds[iix];
1169 let mut regsets = RegSets::new(self.vecs.sanitized);
1170 for i in bounds.uses_start as usize..bounds.uses_start as usize + bounds.uses_len as usize {
1171 regsets.uses.insert(self.vecs.uses[i]);
1172 }
1173 for i in bounds.defs_start as usize..bounds.defs_start as usize + bounds.defs_len as usize {
1174 regsets.defs.insert(self.vecs.defs[i]);
1175 }
1176 for i in bounds.mods_start as usize..bounds.mods_start as usize + bounds.mods_len as usize {
1177 regsets.mods.insert(self.vecs.mods[i]);
1178 }
1179 regsets
1180 }
1181 }
1182
1183 //=============================================================================
1184 // Definitions of the "real register universe".
1185
1186 // A "Real Register Universe" is a read-only structure that contains all
1187 // information about real registers on a given host. It serves several
1188 // purposes:
1189 //
1190 // * defines the mapping from real register indices to the registers
1191 // themselves
1192 //
1193 // * defines the size of the initial section of that mapping that is available
1194 // to the register allocator for use, so that it can treat the registers
1195 // under its control as a zero based, contiguous array. This is important
1196 // for its efficiency.
1197 //
1198 // * gives meaning to Set<RealReg>, which otherwise would merely be a bunch of
1199 // bits.
1200
1201 #[derive(Clone, Debug)]
1202 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1203 pub struct RealRegUniverse {
1204 // The registers themselves. All must be real registers, and all must
1205 // have their index number (.get_index()) equal to the array index here,
1206 // since this is the only place where we map index numbers to actual
1207 // registers.
1208 pub regs: Vec<(RealReg, String)>,
1209
1210 // This is the size of the initial section of `regs` that is available to
1211 // the allocator. It must be <= `regs`.len().
1212 pub allocable: usize,
1213
1214 // Information about groups of allocable registers. Used to quickly address
1215 // only a group of allocable registers belonging to the same register class.
1216 // Indexes into `allocable_by_class` are RegClass values, such as
1217 // RegClass::F32. If the resulting entry is `None` then there are no
1218 // registers in that class. Otherwise the value is a `RegClassInfo`, which
1219 // provides a register range and possibly information about fixed uses.
1220 pub allocable_by_class: [Option<RegClassInfo>; NUM_REG_CLASSES],
1221 }
1222
1223 /// Information about a single register class in the `RealRegUniverse`.
1224 #[derive(Clone, Copy, Debug)]
1225 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1226 pub struct RegClassInfo {
1227 // Range of allocatable registers in this register class, in terms of
1228 // register indices.
1229 //
1230 // A range (first, last) specifies the range of entries in
1231 // `RealRegUniverse.regs` corresponding to that class. The range includes
1232 // both `first` and `last`.
1233 //
1234 // In all cases, `last` must be < `RealRegUniverse.allocable`. In other
1235 // words, all ranges together in `allocable_by_class` must describe only the
1236 // allocable prefix of `regs`.
1237 //
1238 // For example, let's say
1239 // allocable_by_class[RegClass::F32] ==
1240 // Some(RegClassInfo { first: 10, last: 14, .. })
1241 // Then regs[10], regs[11], regs[12], regs[13], and regs[14] give all
1242 // registers of register class RegClass::F32.
1243 //
1244 // The effect of the above is that registers in `regs` must form
1245 // contiguous groups. This is checked by RealRegUniverse::check_is_sane().
1246 pub first: usize,
1247 pub last: usize,
1248
1249 // A register, if any, that is *guaranteed* not to be used as a fixed use
1250 // in any code, and so that the register allocator can statically reserve
1251 // for its own use as a temporary. Some register allocators may need such
1252 // a register for various maneuvers, for example a spillslot-to-spillslot
1253 // move when no (other) registers are free.
1254 pub suggested_scratch: Option<usize>,
1255 }
1256
1257 impl RealRegUniverse {
1258 /// Show it in a pretty way.
show(&self) -> Vec<String>1259 pub fn show(&self) -> Vec<String> {
1260 let mut res = vec![];
1261 // Show the allocables
1262 for class_num in 0..NUM_REG_CLASSES {
1263 let class_info = match &self.allocable_by_class[class_num] {
1264 None => continue,
1265 Some(info) => info,
1266 };
1267 let class = RegClass::rc_from_u32(class_num as u32);
1268 let mut class_str = "class ".to_string()
1269 + &class.long_name().to_string()
1270 + &"(".to_string()
1271 + &class.short_name().to_string()
1272 + &") at ".to_string();
1273 class_str = class_str + &format!("[{} .. {}]: ", class_info.first, class_info.last);
1274 for ix in class_info.first..=class_info.last {
1275 class_str = class_str + &self.regs[ix].1;
1276 if let Some(suggested_ix) = class_info.suggested_scratch {
1277 if ix == suggested_ix {
1278 class_str = class_str + "*";
1279 }
1280 }
1281 class_str = class_str + " ";
1282 }
1283 res.push(class_str);
1284 }
1285 // And the non-allocables
1286 if self.allocable < self.regs.len() {
1287 let mut stragglers = format!(
1288 "not allocable at [{} .. {}]: ",
1289 self.allocable,
1290 self.regs.len() - 1
1291 );
1292 for ix in self.allocable..self.regs.len() {
1293 stragglers = stragglers + &self.regs[ix].1 + &" ".to_string();
1294 }
1295 res.push(stragglers);
1296 }
1297 res
1298 }
1299
1300 /// Check that the given universe satisfies various invariants, and panic
1301 /// if not. All the invariants are important.
check_is_sane(&self)1302 pub fn check_is_sane(&self) {
1303 let regs_len = self.regs.len();
1304 let regs_allocable = self.allocable;
1305 // The universe must contain at most 256 registers. That's because
1306 // `Reg` only has an 8-bit index value field, so if the universe
1307 // contained more than 256 registers, we'd never be able to index into
1308 // entries 256 and above. This is no limitation in practice since all
1309 // targets we're interested in contain (many) fewer than 256 regs in
1310 // total.
1311 let mut ok = regs_len <= 256;
1312 // The number of allocable registers must not exceed the number of
1313 // `regs` presented. In general it will be less, since the universe
1314 // will list some registers (stack pointer, etc) which are not
1315 // available for allocation.
1316 if ok {
1317 ok = regs_allocable <= regs_len;
1318 }
1319 // All registers must have an index value which points back at the
1320 // `regs` slot they are in. Also they really must be real regs.
1321 if ok {
1322 for i in 0..regs_len {
1323 let (reg, _name) = &self.regs[i];
1324 if ok && (reg.to_reg().is_virtual() || reg.get_index() != i) {
1325 ok = false;
1326 }
1327 }
1328 }
1329 // The allocatable regclass groupings defined by `allocable_first` and
1330 // `allocable_last` must be contiguous.
1331 if ok {
1332 let mut regclass_used = [false; NUM_REG_CLASSES];
1333 for rc in 0..NUM_REG_CLASSES {
1334 regclass_used[rc] = false;
1335 }
1336 for i in 0..regs_allocable {
1337 let (reg, _name) = &self.regs[i];
1338 let rc = reg.get_class().rc_to_u32() as usize;
1339 regclass_used[rc] = true;
1340 }
1341 // Scan forward through each grouping, checking that the listed
1342 // registers really are of the claimed class. Also count the
1343 // total number visited. This seems a fairly reliable way to
1344 // ensure that the groupings cover all allocated registers exactly
1345 // once, and that all classes are contiguous groups.
1346 let mut regs_visited = 0;
1347 for rc in 0..NUM_REG_CLASSES {
1348 match &self.allocable_by_class[rc] {
1349 &None => {
1350 if regclass_used[rc] {
1351 ok = false;
1352 }
1353 }
1354 &Some(RegClassInfo {
1355 first,
1356 last,
1357 suggested_scratch,
1358 }) => {
1359 if !regclass_used[rc] {
1360 ok = false;
1361 }
1362 if ok {
1363 for i in first..last + 1 {
1364 let (reg, _name) = &self.regs[i];
1365 if ok && RegClass::rc_from_u32(rc as u32) != reg.get_class() {
1366 ok = false;
1367 }
1368 regs_visited += 1;
1369 }
1370 }
1371 if ok {
1372 if let Some(s) = suggested_scratch {
1373 if s < first || s > last {
1374 ok = false;
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381 if ok && regs_visited != regs_allocable {
1382 ok = false;
1383 }
1384 }
1385 // So finally ..
1386 if !ok {
1387 panic!("RealRegUniverse::check_is_sane: invalid RealRegUniverse");
1388 }
1389 }
1390 }
1391
1392 //=============================================================================
1393 // Representing and printing of live range fragments.
1394
1395 #[derive(Copy, Clone, Hash, PartialEq, Eq, Ord)]
1396 // There are four "points" within an instruction that are of interest, and
1397 // these have a total ordering: R < U < D < S. They are:
1398 //
1399 // * R(eload): this is where any reload insns for the insn itself are
1400 // considered to live.
1401 //
1402 // * U(se): this is where the insn is considered to use values from those of
1403 // its register operands that appear in a Read or Modify role.
1404 //
1405 // * D(ef): this is where the insn is considered to define new values for
1406 // those of its register operands that appear in a Write or Modify role.
1407 //
1408 // * S(pill): this is where any spill insns for the insn itself are considered
1409 // to live.
1410 //
1411 // Instructions in the incoming Func may only exist at the U and D points,
1412 // and so their associated live range fragments will only mention the U and D
1413 // points. However, when adding spill code, we need a way to represent live
1414 // ranges involving the added spill and reload insns, in which case R and S
1415 // come into play:
1416 //
1417 // * A reload for instruction i is considered to be live from i.R to i.U.
1418 //
1419 // * A spill for instruction i is considered to be live from i.D to i.S.
1420
1421 pub enum Point {
1422 // The values here are important. Don't change them.
1423 Reload = 0,
1424 Use = 1,
1425 Def = 2,
1426 Spill = 3,
1427 }
1428
1429 impl Point {
1430 #[inline(always)]
is_reload(self) -> bool1431 pub fn is_reload(self) -> bool {
1432 match self {
1433 Point::Reload => true,
1434 _ => false,
1435 }
1436 }
1437 #[inline(always)]
is_use(self) -> bool1438 pub fn is_use(self) -> bool {
1439 match self {
1440 Point::Use => true,
1441 _ => false,
1442 }
1443 }
1444 #[inline(always)]
is_def(self) -> bool1445 pub fn is_def(self) -> bool {
1446 match self {
1447 Point::Def => true,
1448 _ => false,
1449 }
1450 }
1451 #[inline(always)]
is_spill(self) -> bool1452 pub fn is_spill(self) -> bool {
1453 match self {
1454 Point::Spill => true,
1455 _ => false,
1456 }
1457 }
1458 #[inline(always)]
is_use_or_def(self) -> bool1459 pub fn is_use_or_def(self) -> bool {
1460 self.is_use() || self.is_def()
1461 }
1462 }
1463
1464 impl PartialOrd for Point {
1465 // In short .. R < U < D < S. This is probably what would be #derive'd
1466 // anyway, but we need to be sure.
partial_cmp(&self, other: &Self) -> Option<Ordering>1467 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1468 (*self as u32).partial_cmp(&(*other as u32))
1469 }
1470 }
1471
1472 // See comments below on `RangeFrag` for the meaning of `InstPoint`.
1473 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1474 pub struct InstPoint {
1475 /// This is conceptually:
1476 /// pub iix: InstIx,
1477 /// pub pt: Point,
1478 ///
1479 /// but packed into a single 32 bit word, so as
1480 /// (1) to ensure it is only 32 bits (and hence to guarantee that `RangeFrag`
1481 /// is 64 bits), and
1482 /// (2) to make it possible to implement `PartialOrd` using `PartialOrd`
1483 /// directly on 32 bit words (and hence we let it be derived).
1484 ///
1485 /// This has the format:
1486 /// InstIx as bits 31:2, Point as bits 1:0.
1487 ///
1488 /// It does give the slight limitation that all InstIxs must be < 2^30, but
1489 /// that's hardly a big deal: the analysis module rejects any input with 2^24
1490 /// or more Insns.
1491 ///
1492 /// Do not access this directly:
1493 bits: u32,
1494 }
1495
1496 impl InstPoint {
1497 #[inline(always)]
new(iix: InstIx, pt: Point) -> Self1498 pub fn new(iix: InstIx, pt: Point) -> Self {
1499 let iix_n = iix.get();
1500 assert!(iix_n < 0x4000_0000u32);
1501 let pt_n = pt as u32;
1502 InstPoint {
1503 bits: (iix_n << 2) | pt_n,
1504 }
1505 }
1506 #[inline(always)]
iix(self) -> InstIx1507 pub fn iix(self) -> InstIx {
1508 InstIx::new(self.bits >> 2)
1509 }
1510 #[inline(always)]
pt(self) -> Point1511 pub fn pt(self) -> Point {
1512 match self.bits & 3 {
1513 0 => Point::Reload,
1514 1 => Point::Use,
1515 2 => Point::Def,
1516 3 => Point::Spill,
1517 // This can never happen, but rustc doesn't seem to know that.
1518 _ => panic!("InstPt::pt: unreachable case"),
1519 }
1520 }
1521 #[inline(always)]
set_iix(&mut self, iix: InstIx)1522 pub fn set_iix(&mut self, iix: InstIx) {
1523 let iix_n = iix.get();
1524 assert!(iix_n < 0x4000_0000u32);
1525 self.bits = (iix_n << 2) | (self.bits & 3);
1526 }
1527 #[inline(always)]
set_pt(&mut self, pt: Point)1528 pub fn set_pt(&mut self, pt: Point) {
1529 self.bits = (self.bits & 0xFFFF_FFFCu32) | pt as u32;
1530 }
1531 #[inline(always)]
new_reload(iix: InstIx) -> Self1532 pub fn new_reload(iix: InstIx) -> Self {
1533 InstPoint::new(iix, Point::Reload)
1534 }
1535 #[inline(always)]
new_use(iix: InstIx) -> Self1536 pub fn new_use(iix: InstIx) -> Self {
1537 InstPoint::new(iix, Point::Use)
1538 }
1539 #[inline(always)]
new_def(iix: InstIx) -> Self1540 pub fn new_def(iix: InstIx) -> Self {
1541 InstPoint::new(iix, Point::Def)
1542 }
1543 #[inline(always)]
new_spill(iix: InstIx) -> Self1544 pub fn new_spill(iix: InstIx) -> Self {
1545 InstPoint::new(iix, Point::Spill)
1546 }
1547 #[inline(always)]
invalid_value() -> Self1548 pub fn invalid_value() -> Self {
1549 Self {
1550 bits: 0xFFFF_FFFFu32,
1551 }
1552 }
1553 #[inline(always)]
max_value() -> Self1554 pub fn max_value() -> Self {
1555 Self {
1556 bits: 0xFFFF_FFFFu32,
1557 }
1558 }
1559 #[inline(always)]
min_value() -> Self1560 pub fn min_value() -> Self {
1561 Self { bits: 0u32 }
1562 }
1563 }
1564
1565 impl fmt::Debug for InstPoint {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1566 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1567 write!(
1568 fmt,
1569 "{:?}{}",
1570 self.iix(),
1571 match self.pt() {
1572 Point::Reload => ".r",
1573 Point::Use => ".u",
1574 Point::Def => ".d",
1575 Point::Spill => ".s",
1576 }
1577 )
1578 }
1579 }
1580
1581 //=============================================================================
1582 // Live Range Fragments, and their metrics
1583
1584 // A Live Range Fragment (RangeFrag) describes a consecutive sequence of one or
1585 // more instructions, in which a Reg is "live". The sequence must exist
1586 // entirely inside only one basic block.
1587 //
1588 // However, merely indicating the start and end instruction numbers isn't
1589 // enough: we must also include a "Use or Def" indication. These indicate two
1590 // different "points" within each instruction: the Use position, where
1591 // incoming registers are read, and the Def position, where outgoing registers
1592 // are written. The Use position is considered to come before the Def
1593 // position, as described for `Point` above.
1594 //
1595 // When we come to generate spill/restore live ranges, Point::S and Point::R
1596 // also come into play. Live ranges (and hence, RangeFrags) that do not perform
1597 // spills or restores should not use either of Point::S or Point::R.
1598 //
1599 // The set of positions denoted by
1600 //
1601 // {0 .. #insns-1} x {Reload point, Use point, Def point, Spill point}
1602 //
1603 // is exactly the set of positions that we need to keep track of when mapping
1604 // live ranges to registers. This the reason for the type InstPoint. Note
1605 // that InstPoint values have a total ordering, at least within a single basic
1606 // block: the insn number is used as the primary key, and the Point part is
1607 // the secondary key, with Reload < Use < Def < Spill.
1608 #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1609 pub struct RangeFrag {
1610 pub first: InstPoint,
1611 pub last: InstPoint,
1612 }
1613
1614 impl fmt::Debug for RangeFrag {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1615 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1616 write!(fmt, "(RF: {:?}-{:?})", self.first, self.last)
1617 }
1618 }
1619
1620 impl RangeFrag {
1621 #[allow(dead_code)] // XXX for some reason, Rustc 1.43.1 thinks this is unused.
new(first: InstPoint, last: InstPoint) -> Self1622 pub fn new(first: InstPoint, last: InstPoint) -> Self {
1623 debug_assert!(first <= last);
1624 RangeFrag { first, last }
1625 }
1626
invalid_value() -> Self1627 pub fn invalid_value() -> Self {
1628 Self {
1629 first: InstPoint::invalid_value(),
1630 last: InstPoint::invalid_value(),
1631 }
1632 }
1633
new_with_metrics<F: Function>( f: &F, bix: BlockIx, first: InstPoint, last: InstPoint, count: u16, ) -> (Self, RangeFragMetrics)1634 pub fn new_with_metrics<F: Function>(
1635 f: &F,
1636 bix: BlockIx,
1637 first: InstPoint,
1638 last: InstPoint,
1639 count: u16,
1640 ) -> (Self, RangeFragMetrics) {
1641 debug_assert!(f.block_insns(bix).len() >= 1);
1642 debug_assert!(f.block_insns(bix).contains(first.iix()));
1643 debug_assert!(f.block_insns(bix).contains(last.iix()));
1644 debug_assert!(first <= last);
1645 if first == last {
1646 debug_assert!(count == 1);
1647 }
1648 let first_iix_in_block = f.block_insns(bix).first();
1649 let last_iix_in_block = f.block_insns(bix).last();
1650 let first_pt_in_block = InstPoint::new_use(first_iix_in_block);
1651 let last_pt_in_block = InstPoint::new_def(last_iix_in_block);
1652 let kind = match (first == first_pt_in_block, last == last_pt_in_block) {
1653 (false, false) => RangeFragKind::Local,
1654 (false, true) => RangeFragKind::LiveOut,
1655 (true, false) => RangeFragKind::LiveIn,
1656 (true, true) => RangeFragKind::Thru,
1657 };
1658 (
1659 RangeFrag { first, last },
1660 RangeFragMetrics { bix, kind, count },
1661 )
1662 }
1663 }
1664
1665 // Comparison of RangeFrags. They form a partial order.
1666
cmp_range_frags(f1: &RangeFrag, f2: &RangeFrag) -> Option<Ordering>1667 pub fn cmp_range_frags(f1: &RangeFrag, f2: &RangeFrag) -> Option<Ordering> {
1668 if f1.last < f2.first {
1669 return Some(Ordering::Less);
1670 }
1671 if f1.first > f2.last {
1672 return Some(Ordering::Greater);
1673 }
1674 if f1.first == f2.first && f1.last == f2.last {
1675 return Some(Ordering::Equal);
1676 }
1677 None
1678 }
1679
1680 impl RangeFrag {
contains(&self, ipt: &InstPoint) -> bool1681 pub fn contains(&self, ipt: &InstPoint) -> bool {
1682 self.first <= *ipt && *ipt <= self.last
1683 }
1684 }
1685
1686 // A handy summary hint for a RangeFrag. Note that none of these are correct
1687 // if the RangeFrag has been extended so as to cover multiple basic blocks.
1688 // But that ("RangeFrag compression") is something done locally within each
1689 // algorithm (BT and LSRA). The analysis-phase output will not include any
1690 // such compressed RangeFrags.
1691 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1692 pub enum RangeFragKind {
1693 Local, // Fragment exists entirely inside one block
1694 LiveIn, // Fragment is live in to a block, but ends inside it
1695 LiveOut, // Fragment is live out of a block, but starts inside it
1696 Thru, // Fragment is live through the block (starts and ends outside it)
1697 }
1698
1699 impl fmt::Debug for RangeFragKind {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1700 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1701 match self {
1702 RangeFragKind::Local => write!(fmt, "Local"),
1703 RangeFragKind::LiveIn => write!(fmt, "LiveIn"),
1704 RangeFragKind::LiveOut => write!(fmt, "LiveOut"),
1705 RangeFragKind::Thru => write!(fmt, "Thru"),
1706 }
1707 }
1708 }
1709
1710 // `RangeFrags` resulting from the initial analysis phase (analysis_data_flow.rs)
1711 // exist only within single basic blocks, and therefore have some associated
1712 // metrics, held by `RangeFragMetrics`:
1713 //
1714 // * a `count` field, which is a u16 indicating how often the associated storage
1715 // unit (Reg) is mentioned inside the RangeFrag. It is assumed that the RangeFrag
1716 // is associated with some Reg. If not, the `count` field is meaningless. This
1717 // field has no effect on the correctness of the resulting allocation. It is used
1718 // however in the estimation of `VirtualRange` spill costs, which are important
1719 // for prioritising which `VirtualRange`s get assigned a register vs which have
1720 // to be spilled.
1721 //
1722 // * `bix` field, which indicates which `Block` the fragment exists in. This
1723 // field is actually redundant, since the containing `Block` can be inferred,
1724 // laboriously, from the associated `RangeFrag`s `first` and `last` fields,
1725 // providing you have an `InstIxToBlockIx` mapping table to hand. It is included
1726 // here for convenience.
1727 //
1728 // * `kind` is another convenience field, indicating how the range is included
1729 // within its owning block.
1730 //
1731 // The analysis phase (fn `deref_and_compress_sorted_range_frag_ixs`)
1732 // compresses ranges and as a result breaks the invariant that a `RangeFrag`
1733 // exists only within a single `Block`. For a `RangeFrag` spanning multiple
1734 // `Block`s, all three `RangeFragMetric` fields are meaningless. This is the
1735 // reason for separating `RangeFrag` and `RangeFragMetrics` -- so that it is
1736 // possible to merge `RangeFrag`s without being forced to create fake values
1737 // for the metrics fields.
1738 #[derive(Clone, PartialEq)]
1739 pub struct RangeFragMetrics {
1740 pub bix: BlockIx,
1741 pub kind: RangeFragKind,
1742 pub count: u16,
1743 }
1744
1745 impl fmt::Debug for RangeFragMetrics {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1746 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1747 write!(
1748 fmt,
1749 "(RFM: {:?}, count={}, {:?})",
1750 self.kind, self.count, self.bix
1751 )
1752 }
1753 }
1754
1755 //=============================================================================
1756 // Vectors of RangeFragIxs, sorted so that the associated RangeFrags are in
1757 // ascending order, per their InstPoint fields. The associated RangeFrags may
1758 // not overlap.
1759 //
1760 // The "fragment environment" (usually called "frag_env"), to which the
1761 // RangeFragIxs refer, is not stored here.
1762
1763 #[derive(Clone)]
1764 pub struct SortedRangeFragIxs {
1765 pub frag_ixs: SmallVec<[RangeFragIx; 4]>,
1766 }
1767
1768 impl fmt::Debug for SortedRangeFragIxs {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1769 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1770 self.frag_ixs.fmt(fmt)
1771 }
1772 }
1773
1774 impl SortedRangeFragIxs {
check(&self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>)1775 pub(crate) fn check(&self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>) {
1776 for i in 1..self.frag_ixs.len() {
1777 let prev_frag = &fenv[self.frag_ixs[i - 1]];
1778 let this_frag = &fenv[self.frag_ixs[i]];
1779 if cmp_range_frags(prev_frag, this_frag) != Some(Ordering::Less) {
1780 panic!("SortedRangeFragIxs::check: vector not ok");
1781 }
1782 }
1783 }
1784
sort(&mut self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>)1785 pub fn sort(&mut self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>) {
1786 self.frag_ixs.sort_unstable_by(|fix_a, fix_b| {
1787 match cmp_range_frags(&fenv[*fix_a], &fenv[*fix_b]) {
1788 Some(Ordering::Less) => Ordering::Less,
1789 Some(Ordering::Greater) => Ordering::Greater,
1790 Some(Ordering::Equal) | None => {
1791 panic!("SortedRangeFragIxs::sort: overlapping Frags!")
1792 }
1793 }
1794 });
1795 }
1796
new( frag_ixs: SmallVec<[RangeFragIx; 4]>, fenv: &TypedIxVec<RangeFragIx, RangeFrag>, ) -> Self1797 pub fn new(
1798 frag_ixs: SmallVec<[RangeFragIx; 4]>,
1799 fenv: &TypedIxVec<RangeFragIx, RangeFrag>,
1800 ) -> Self {
1801 let mut res = SortedRangeFragIxs { frag_ixs };
1802 // check the source is ordered, and clone (or sort it)
1803 res.sort(fenv);
1804 res.check(fenv);
1805 res
1806 }
1807
unit(fix: RangeFragIx, fenv: &TypedIxVec<RangeFragIx, RangeFrag>) -> Self1808 pub fn unit(fix: RangeFragIx, fenv: &TypedIxVec<RangeFragIx, RangeFrag>) -> Self {
1809 let mut res = SortedRangeFragIxs {
1810 frag_ixs: SmallVec::<[RangeFragIx; 4]>::new(),
1811 };
1812 res.frag_ixs.push(fix);
1813 res.check(fenv);
1814 res
1815 }
1816
1817 /// Does this sorted list of range fragments contain the given instruction point?
contains_pt(&self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>, pt: InstPoint) -> bool1818 pub fn contains_pt(&self, fenv: &TypedIxVec<RangeFragIx, RangeFrag>, pt: InstPoint) -> bool {
1819 self.frag_ixs
1820 .binary_search_by(|&ix| {
1821 let frag = &fenv[ix];
1822 if pt < frag.first {
1823 Ordering::Greater
1824 } else if pt >= frag.first && pt <= frag.last {
1825 Ordering::Equal
1826 } else {
1827 Ordering::Less
1828 }
1829 })
1830 .is_ok()
1831 }
1832 }
1833
1834 //=============================================================================
1835 // Vectors of RangeFrags, sorted so that they are in ascending order, per
1836 // their InstPoint fields. The RangeFrags may not overlap.
1837
1838 #[derive(Clone)]
1839 pub struct SortedRangeFrags {
1840 pub frags: SmallVec<[RangeFrag; 4]>,
1841 }
1842
1843 impl fmt::Debug for SortedRangeFrags {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1844 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1845 self.frags.fmt(fmt)
1846 }
1847 }
1848
1849 impl SortedRangeFrags {
unit(frag: RangeFrag) -> Self1850 pub fn unit(frag: RangeFrag) -> Self {
1851 let mut res = SortedRangeFrags {
1852 frags: SmallVec::<[RangeFrag; 4]>::new(),
1853 };
1854 res.frags.push(frag);
1855 res
1856 }
1857
empty() -> Self1858 pub fn empty() -> Self {
1859 Self {
1860 frags: SmallVec::<[RangeFrag; 4]>::new(),
1861 }
1862 }
1863
overlaps(&self, other: &Self) -> bool1864 pub fn overlaps(&self, other: &Self) -> bool {
1865 // Since both vectors are sorted and individually non-overlapping, we
1866 // can establish that they are mutually non-overlapping by walking
1867 // them simultaneously and checking, at each step, that there is a
1868 // unique "next lowest" frag available.
1869 let frags1 = &self.frags;
1870 let frags2 = &other.frags;
1871 let n1 = frags1.len();
1872 let n2 = frags2.len();
1873 let mut c1 = 0;
1874 let mut c2 = 0;
1875 loop {
1876 if c1 >= n1 || c2 >= n2 {
1877 // We made it to the end of one (or both) vectors without
1878 // finding any conflicts.
1879 return false; // "no overlaps"
1880 }
1881 let f1 = &frags1[c1];
1882 let f2 = &frags2[c2];
1883 match cmp_range_frags(f1, f2) {
1884 Some(Ordering::Less) => c1 += 1,
1885 Some(Ordering::Greater) => c2 += 1,
1886 _ => {
1887 // There's no unique "next frag" -- either they are
1888 // identical, or they overlap. So we're done.
1889 return true; // "there's an overlap"
1890 }
1891 }
1892 }
1893 }
1894
1895 /// Does this sorted list of range fragments contain the given instruction point?
contains_pt(&self, pt: InstPoint) -> bool1896 pub fn contains_pt(&self, pt: InstPoint) -> bool {
1897 self.frags
1898 .binary_search_by(|frag| {
1899 if pt < frag.first {
1900 Ordering::Greater
1901 } else if pt >= frag.first && pt <= frag.last {
1902 Ordering::Equal
1903 } else {
1904 Ordering::Less
1905 }
1906 })
1907 .is_ok()
1908 }
1909 }
1910
1911 //=============================================================================
1912 // Representing spill costs. A spill cost can either be infinite, in which
1913 // case the associated VirtualRange may not be spilled, because it's already a
1914 // spill/reload range. Or it can be finite, in which case it must be a 32-bit
1915 // floating point number, which is (in the IEEE754 meaning of the terms)
1916 // non-infinite, non-NaN and it must be non negative. In fact it's
1917 // meaningless for a VLR to have a zero spill cost (how could that really be
1918 // the case?) but we allow it here for convenience.
1919
1920 #[derive(Copy, Clone)]
1921 pub enum SpillCost {
1922 Infinite, // Infinite, positive
1923 Finite(f32), // Finite, non-negative
1924 }
1925
1926 impl fmt::Debug for SpillCost {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result1927 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
1928 match self {
1929 SpillCost::Infinite => write!(fmt, "INFINITY"),
1930 SpillCost::Finite(c) => write!(fmt, "{:<.3}", c),
1931 }
1932 }
1933 }
1934
1935 impl SpillCost {
1936 #[inline(always)]
zero() -> Self1937 pub fn zero() -> Self {
1938 SpillCost::Finite(0.0)
1939 }
1940 #[inline(always)]
infinite() -> Self1941 pub fn infinite() -> Self {
1942 SpillCost::Infinite
1943 }
1944 #[inline(always)]
finite(cost: f32) -> Self1945 pub fn finite(cost: f32) -> Self {
1946 // "`is_normal` returns true if the number is neither zero, infinite,
1947 // subnormal, or NaN."
1948 assert!(cost.is_normal() || cost == 0.0);
1949 // And also it can't be negative.
1950 assert!(cost >= 0.0);
1951 // Somewhat arbitrarily ..
1952 assert!(cost < 1e18);
1953 SpillCost::Finite(cost)
1954 }
1955 #[inline(always)]
is_zero(&self) -> bool1956 pub fn is_zero(&self) -> bool {
1957 match self {
1958 SpillCost::Infinite => false,
1959 SpillCost::Finite(c) => *c == 0.0,
1960 }
1961 }
1962 #[inline(always)]
is_infinite(&self) -> bool1963 pub fn is_infinite(&self) -> bool {
1964 match self {
1965 SpillCost::Infinite => true,
1966 SpillCost::Finite(_) => false,
1967 }
1968 }
1969 #[inline(always)]
is_finite(&self) -> bool1970 pub fn is_finite(&self) -> bool {
1971 !self.is_infinite()
1972 }
1973 #[inline(always)]
is_less_than(&self, other: &Self) -> bool1974 pub fn is_less_than(&self, other: &Self) -> bool {
1975 match (self, other) {
1976 // Dubious .. both are infinity
1977 (SpillCost::Infinite, SpillCost::Infinite) => false,
1978 // finite < inf
1979 (SpillCost::Finite(_), SpillCost::Infinite) => true,
1980 // inf is not < finite
1981 (SpillCost::Infinite, SpillCost::Finite(_)) => false,
1982 // straightforward
1983 (SpillCost::Finite(c1), SpillCost::Finite(c2)) => c1 < c2,
1984 }
1985 }
1986 #[inline(always)]
add(&mut self, other: &Self)1987 pub fn add(&mut self, other: &Self) {
1988 match (*self, other) {
1989 (SpillCost::Finite(c1), SpillCost::Finite(c2)) => {
1990 // The 10^18 limit above gives us a lot of headroom here, since max
1991 // f32 is around 10^37.
1992 *self = SpillCost::Finite(c1 + c2);
1993 }
1994 (_, _) => {
1995 // All other cases produce an infinity.
1996 *self = SpillCost::Infinite;
1997 }
1998 }
1999 }
2000 }
2001
2002 //=============================================================================
2003 // Representing and printing live ranges. These are represented by two
2004 // different but closely related types, RealRange and VirtualRange.
2005
2006 // RealRanges are live ranges for real regs (RealRegs). VirtualRanges are
2007 // live ranges for virtual regs (VirtualRegs). VirtualRanges are the
2008 // fundamental unit of allocation.
2009 //
2010 // A RealRange pairs a RealReg with a vector of RangeFragIxs in which it is
2011 // live. The RangeFragIxs are indices into some vector of RangeFrags (a
2012 // "fragment environment", 'fenv'), which is not specified here. They are
2013 // sorted so as to give ascending order to the RangeFrags which they refer to.
2014 //
2015 // A VirtualRange pairs a VirtualReg with a vector of RangeFrags in which it
2016 // is live. Same scheme as for a RealRange, except it avoids the overhead of
2017 // having to indirect into the fragment environment.
2018 //
2019 // VirtualRanges also contain metrics:
2020 //
2021 // * `size` is the number of instructions in total spanned by the LR. It must
2022 // not be zero.
2023 //
2024 // * `total cost` is an abstractified measure of the cost of the LR. Each
2025 // basic block in which the range exists gives a contribution to the `total
2026 // cost`, which is the number of times the register is mentioned in this
2027 // block, multiplied by the estimated execution frequency for the block.
2028 //
2029 // * `spill_cost` is an abstractified measure of the cost of spilling the LR,
2030 // and is the `total cost` divided by the `size`. The only constraint
2031 // (w.r.t. correctness) is that normal LRs have a `Some` value, whilst
2032 // `None` is reserved for live ranges created for spills and reloads and
2033 // interpreted to mean "infinity". This is needed to guarantee that
2034 // allocation can always succeed in the worst case, in which all of the
2035 // original live ranges of the program are spilled.
2036 //
2037 // RealRanges don't carry any metrics info since we are not trying to allocate
2038 // them. We merely need to work around them.
2039 //
2040 // I find it helpful to think of a live range, both RealRange and
2041 // VirtualRange, as a "renaming equivalence class". That is, if you rename
2042 // `reg` at some point inside `sorted_frags`, then you must rename *all*
2043 // occurrences of `reg` inside `sorted_frags`, since otherwise the program will
2044 // no longer work.
2045
2046 #[derive(Clone)]
2047 pub struct RealRange {
2048 pub rreg: RealReg,
2049 pub sorted_frags: SortedRangeFragIxs,
2050 pub is_ref: bool,
2051 }
2052
2053 impl fmt::Debug for RealRange {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2054 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2055 write!(
2056 fmt,
2057 "(RR: {:?}{}, {:?})",
2058 self.rreg,
2059 if self.is_ref { " REF" } else { "" },
2060 self.sorted_frags
2061 )
2062 }
2063 }
2064
2065 impl RealRange {
show_with_rru(&self, univ: &RealRegUniverse) -> String2066 pub fn show_with_rru(&self, univ: &RealRegUniverse) -> String {
2067 format!(
2068 "(RR: {}{}, {:?})",
2069 self.rreg.to_reg().show_with_rru(univ),
2070 if self.is_ref { " REF" } else { "" },
2071 self.sorted_frags
2072 )
2073 }
2074 }
2075
2076 // VirtualRanges are live ranges for virtual regs (VirtualRegs). This does
2077 // carry metrics info and also the identity of the RealReg to which it
2078 // eventually got allocated. (Or in the backtracking allocator, the identity
2079 // of the RealReg to which it is *currently* assigned; that may be undone at
2080 // some later point.)
2081
2082 #[derive(Clone)]
2083 pub struct VirtualRange {
2084 pub vreg: VirtualReg,
2085 pub rreg: Option<RealReg>,
2086 pub sorted_frags: SortedRangeFrags,
2087 pub is_ref: bool,
2088 pub size: u16,
2089 pub total_cost: u32,
2090 pub spill_cost: SpillCost, // == total_cost / size
2091 }
2092
2093 impl VirtualRange {
overlaps(&self, other: &Self) -> bool2094 pub fn overlaps(&self, other: &Self) -> bool {
2095 self.sorted_frags.overlaps(&other.sorted_frags)
2096 }
2097 }
2098
2099 impl fmt::Debug for VirtualRange {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2100 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2101 write!(
2102 fmt,
2103 "(VR: {:?}{},",
2104 self.vreg,
2105 if self.is_ref { " REF" } else { "" }
2106 )?;
2107 if self.rreg.is_some() {
2108 write!(fmt, " -> {:?}", self.rreg.unwrap())?;
2109 }
2110 write!(
2111 fmt,
2112 " sz={}, tc={}, sc={:?}, {:?})",
2113 self.size, self.total_cost, self.spill_cost, self.sorted_frags
2114 )
2115 }
2116 }
2117
2118 //=============================================================================
2119 // Some auxiliary/miscellaneous data structures that are useful: RegToRangesMaps
2120
2121 // Mappings from RealRegs and VirtualRegs to the sets of RealRanges and VirtualRanges that
2122 // belong to them. These are needed for BT's coalescing analysis and for the dataflow analysis
2123 // that supports reftype handling.
2124
2125 pub struct RegToRangesMaps {
2126 // This maps RealReg indices to the set of RealRangeIxs for that RealReg. Valid indices are
2127 // real register indices for all non-sanitised real regs; that is,
2128 // 0 .. RealRegUniverse::allocable, for ".." having the Rust meaning. The Vecs of
2129 // RealRangeIxs are duplicate-free. The SmallVec capacity of 6 was chosen after quite
2130 // some profiling, of CL/x64/newBE compiling ZenGarden.wasm -- a huge input, with many
2131 // relatively small functions. Profiling was performed in August 2020, using Valgrind/DHAT.
2132 pub rreg_to_rlrs_map: Vec</*real reg ix, */ SmallVec<[RealRangeIx; 6]>>,
2133
2134 // This maps VirtualReg indices to the set of VirtualRangeIxs for that VirtualReg. Valid
2135 // indices are 0 .. Function::get_num_vregs(). For functions mostly translated from SSA,
2136 // most VirtualRegs will have just one VirtualRange, and there are a lot of VirtualRegs in
2137 // general. So SmallVec is a definite benefit here.
2138 pub vreg_to_vlrs_map: Vec</*virtual reg ix, */ SmallVec<[VirtualRangeIx; 3]>>,
2139
2140 // As an optimisation heuristic for BT's coalescing analysis, these indicate which
2141 // real/virtual registers have "many" `RangeFrag`s in their live ranges. For some
2142 // definition of "many", perhaps "200 or more". This is not important for overall
2143 // allocation result or correctness: it merely allows the coalescing analysis to switch
2144 // between two search strategies, one of which is fast for regs with few `RangeFrag`s (the
2145 // vast majority) and the other of which has better asymptotic behaviour for regs with many
2146 // `RangeFrag`s (in order to keep out of trouble on some pathological inputs). These
2147 // vectors are duplicate-free but the elements may be in an arbitrary order.
2148 pub rregs_with_many_frags: Vec<u32 /*RealReg index*/>,
2149 pub vregs_with_many_frags: Vec<u32 /*VirtualReg index*/>,
2150
2151 // And this indicates what the thresh is actually set to. A frag will be in
2152 // `r/vregs_with_many_frags` if it has `many_frags_thresh` or more RangeFrags.
2153 pub many_frags_thresh: usize,
2154 }
2155
2156 //=============================================================================
2157 // Some auxiliary/miscellaneous data structures that are useful: MoveInfo
2158
2159 // `MoveInfoElem` holds info about the two registers connected a move: the source and destination
2160 // of the move, the insn performing the move, and the estimated execution frequency of the
2161 // containing block. In `MoveInfo`, the moves are not presented in any particular order, but
2162 // they are duplicate-free in that each such instruction will be listed only once.
2163
2164 pub struct MoveInfoElem {
2165 pub dst: Reg,
2166 pub src: Reg,
2167 pub iix: InstIx,
2168 pub est_freq: u32,
2169 }
2170
2171 pub struct MoveInfo {
2172 pub moves: Vec<MoveInfoElem>,
2173 }
2174
2175 // Something that can be either a VirtualRangeIx or a RealRangeIx, whilst still being 32 bits
2176 // (by stealing one bit from those spaces). Note that the resulting thing no longer denotes a
2177 // contiguous index space, and so it has a name that indicates it is an identifier rather than
2178 // an index.
2179
2180 #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
2181 pub struct RangeId {
2182 // 1 X--(31)--X is a RealRangeIx with value X--(31)--X
2183 // 0 X--(31)--X is a VirtualRangeIx with value X--(31)--X
2184 bits: u32,
2185 }
2186
2187 impl RangeId {
2188 #[inline(always)]
new_real(rlrix: RealRangeIx) -> Self2189 pub fn new_real(rlrix: RealRangeIx) -> Self {
2190 let n = rlrix.get();
2191 assert!(n <= 0x7FFF_FFFF);
2192 Self {
2193 bits: n | 0x8000_0000,
2194 }
2195 }
2196 #[inline(always)]
new_virtual(vlrix: VirtualRangeIx) -> Self2197 pub fn new_virtual(vlrix: VirtualRangeIx) -> Self {
2198 let n = vlrix.get();
2199 assert!(n <= 0x7FFF_FFFF);
2200 Self { bits: n }
2201 }
2202 #[inline(always)]
is_real(self) -> bool2203 pub fn is_real(self) -> bool {
2204 self.bits & 0x8000_0000 != 0
2205 }
2206 #[allow(dead_code)]
2207 #[inline(always)]
is_virtual(self) -> bool2208 pub fn is_virtual(self) -> bool {
2209 self.bits & 0x8000_0000 == 0
2210 }
2211 #[inline(always)]
to_real(self) -> RealRangeIx2212 pub fn to_real(self) -> RealRangeIx {
2213 assert!(self.bits & 0x8000_0000 != 0);
2214 RealRangeIx::new(self.bits & 0x7FFF_FFFF)
2215 }
2216 #[inline(always)]
to_virtual(self) -> VirtualRangeIx2217 pub fn to_virtual(self) -> VirtualRangeIx {
2218 assert!(self.bits & 0x8000_0000 == 0);
2219 VirtualRangeIx::new(self.bits)
2220 }
2221 #[inline(always)]
invalid_value() -> Self2222 pub fn invalid_value() -> Self {
2223 // Real, and inplausibly huge
2224 Self { bits: 0xFFFF_FFFF }
2225 }
2226 }
2227
2228 impl fmt::Debug for RangeId {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result2229 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2230 if self.is_real() {
2231 self.to_real().fmt(fmt)
2232 } else {
2233 self.to_virtual().fmt(fmt)
2234 }
2235 }
2236 }
2237
2238 //=============================================================================
2239 // Test cases
2240
2241 // sewardj 2020Mar04: these are commented out for now, as they no longer
2242 // compile. They may be useful later though, once BT acquires an interval
2243 // tree implementation for its CommitmentMap.
2244
2245 /*
2246 #[test]
2247 fn test_sorted_frag_ranges() {
2248 // Create a RangeFrag and RangeFragIx from two InstPoints.
2249 fn gen_fix(
2250 fenv: &mut TypedIxVec<RangeFragIx, RangeFrag>, first: InstPoint,
2251 last: InstPoint,
2252 ) -> RangeFragIx {
2253 assert!(first <= last);
2254 let res = RangeFragIx::new(fenv.len() as u32);
2255 let frag = RangeFrag {
2256 bix: BlockIx::new(123),
2257 kind: RangeFragKind::Local,
2258 first,
2259 last,
2260 count: 0,
2261 };
2262 fenv.push(frag);
2263 res
2264 }
2265
2266 fn get_range_frag(
2267 fenv: &TypedIxVec<RangeFragIx, RangeFrag>, fix: RangeFragIx,
2268 ) -> &RangeFrag {
2269 &fenv[fix]
2270 }
2271
2272 // Structural equality, at least. Not equality in the sense of
2273 // deferencing the contained RangeFragIxes.
2274 fn sorted_range_eq(
2275 fixs1: &SortedRangeFragIxs, fixs2: &SortedRangeFragIxs,
2276 ) -> bool {
2277 if fixs1.frag_ixs.len() != fixs2.frag_ixs.len() {
2278 return false;
2279 }
2280 for (mf1, mf2) in fixs1.frag_ixs.iter().zip(&fixs2.frag_ixs) {
2281 if mf1 != mf2 {
2282 return false;
2283 }
2284 }
2285 true
2286 }
2287
2288 let iix3 = InstIx::new(3);
2289 let iix4 = InstIx::new(4);
2290 let iix5 = InstIx::new(5);
2291 let iix6 = InstIx::new(6);
2292 let iix7 = InstIx::new(7);
2293 let iix10 = InstIx::new(10);
2294 let iix12 = InstIx::new(12);
2295
2296 let fp_3u = InstPoint::new_use(iix3);
2297 let fp_3d = InstPoint::new_def(iix3);
2298
2299 let fp_4u = InstPoint::new_use(iix4);
2300
2301 let fp_5u = InstPoint::new_use(iix5);
2302 let fp_5d = InstPoint::new_def(iix5);
2303
2304 let fp_6u = InstPoint::new_use(iix6);
2305 let fp_6d = InstPoint::new_def(iix6);
2306
2307 let fp_7u = InstPoint::new_use(iix7);
2308 let fp_7d = InstPoint::new_def(iix7);
2309
2310 let fp_10u = InstPoint::new_use(iix10);
2311 let fp_12u = InstPoint::new_use(iix12);
2312
2313 let mut fenv = TypedIxVec::<RangeFragIx, RangeFrag>::new();
2314
2315 let fix_3u = gen_fix(&mut fenv, fp_3u, fp_3u);
2316 let fix_3d = gen_fix(&mut fenv, fp_3d, fp_3d);
2317 let fix_4u = gen_fix(&mut fenv, fp_4u, fp_4u);
2318 let fix_3u_5u = gen_fix(&mut fenv, fp_3u, fp_5u);
2319 let fix_3d_5d = gen_fix(&mut fenv, fp_3d, fp_5d);
2320 let fix_3d_5u = gen_fix(&mut fenv, fp_3d, fp_5u);
2321 let fix_3u_5d = gen_fix(&mut fenv, fp_3u, fp_5d);
2322 let fix_6u_6d = gen_fix(&mut fenv, fp_6u, fp_6d);
2323 let fix_7u_7d = gen_fix(&mut fenv, fp_7u, fp_7d);
2324 let fix_10u = gen_fix(&mut fenv, fp_10u, fp_10u);
2325 let fix_12u = gen_fix(&mut fenv, fp_12u, fp_12u);
2326
2327 // Boundary checks for point ranges, 3u vs 3d
2328 assert!(
2329 cmp_range_frags(
2330 get_range_frag(&fenv, fix_3u),
2331 get_range_frag(&fenv, fix_3u)
2332 ) == Some(Ordering::Equal)
2333 );
2334 assert!(
2335 cmp_range_frags(
2336 get_range_frag(&fenv, fix_3u),
2337 get_range_frag(&fenv, fix_3d)
2338 ) == Some(Ordering::Less)
2339 );
2340 assert!(
2341 cmp_range_frags(
2342 get_range_frag(&fenv, fix_3d),
2343 get_range_frag(&fenv, fix_3u)
2344 ) == Some(Ordering::Greater)
2345 );
2346
2347 // Boundary checks for point ranges, 3d vs 4u
2348 assert!(
2349 cmp_range_frags(
2350 get_range_frag(&fenv, fix_3d),
2351 get_range_frag(&fenv, fix_3d)
2352 ) == Some(Ordering::Equal)
2353 );
2354 assert!(
2355 cmp_range_frags(
2356 get_range_frag(&fenv, fix_3d),
2357 get_range_frag(&fenv, fix_4u)
2358 ) == Some(Ordering::Less)
2359 );
2360 assert!(
2361 cmp_range_frags(
2362 get_range_frag(&fenv, fix_4u),
2363 get_range_frag(&fenv, fix_3d)
2364 ) == Some(Ordering::Greater)
2365 );
2366
2367 // Partially overlapping
2368 assert!(
2369 cmp_range_frags(
2370 get_range_frag(&fenv, fix_3d_5d),
2371 get_range_frag(&fenv, fix_3u_5u)
2372 ) == None
2373 );
2374 assert!(
2375 cmp_range_frags(
2376 get_range_frag(&fenv, fix_3u_5u),
2377 get_range_frag(&fenv, fix_3d_5d)
2378 ) == None
2379 );
2380
2381 // Completely overlapping: one contained within the other
2382 assert!(
2383 cmp_range_frags(
2384 get_range_frag(&fenv, fix_3d_5u),
2385 get_range_frag(&fenv, fix_3u_5d)
2386 ) == None
2387 );
2388 assert!(
2389 cmp_range_frags(
2390 get_range_frag(&fenv, fix_3u_5d),
2391 get_range_frag(&fenv, fix_3d_5u)
2392 ) == None
2393 );
2394
2395 // Create a SortedRangeFragIxs from a bunch of RangeFrag indices
2396 fn new_sorted_frag_ranges(
2397 fenv: &TypedIxVec<RangeFragIx, RangeFrag>, frags: &Vec<RangeFragIx>,
2398 ) -> SortedRangeFragIxs {
2399 SortedRangeFragIxs::new(&frags, fenv)
2400 }
2401
2402 // Construction tests
2403 // These fail due to overlap
2404 //let _ = new_sorted_frag_ranges(&fenv, &vec![fix_3u_3u, fix_3u_3u]);
2405 //let _ = new_sorted_frag_ranges(&fenv, &vec![fix_3u_5u, fix_3d_5d]);
2406
2407 // These fail due to not being in order
2408 //let _ = new_sorted_frag_ranges(&fenv, &vec![fix_4u_4u, fix_3u_3u]);
2409
2410 // Simple non-overlap tests for add()
2411
2412 let smf_empty = new_sorted_frag_ranges(&fenv, &vec![]);
2413 let smf_6_7_10 =
2414 new_sorted_frag_ranges(&fenv, &vec![fix_6u_6d, fix_7u_7d, fix_10u]);
2415 let smf_3_12 = new_sorted_frag_ranges(&fenv, &vec![fix_3u, fix_12u]);
2416 let smf_3_6_7_10_12 = new_sorted_frag_ranges(
2417 &fenv,
2418 &vec![fix_3u, fix_6u_6d, fix_7u_7d, fix_10u, fix_12u],
2419 );
2420 let mut tmp;
2421
2422 tmp = smf_empty.clone();
2423 tmp.add(&smf_empty, &fenv);
2424 assert!(sorted_range_eq(&tmp, &smf_empty));
2425
2426 tmp = smf_3_12.clone();
2427 tmp.add(&smf_empty, &fenv);
2428 assert!(sorted_range_eq(&tmp, &smf_3_12));
2429
2430 tmp = smf_empty.clone();
2431 tmp.add(&smf_3_12, &fenv);
2432 assert!(sorted_range_eq(&tmp, &smf_3_12));
2433
2434 tmp = smf_6_7_10.clone();
2435 tmp.add(&smf_3_12, &fenv);
2436 assert!(sorted_range_eq(&tmp, &smf_3_6_7_10_12));
2437
2438 tmp = smf_3_12.clone();
2439 tmp.add(&smf_6_7_10, &fenv);
2440 assert!(sorted_range_eq(&tmp, &smf_3_6_7_10_12));
2441
2442 // Tests for can_add()
2443 assert!(true == smf_empty.can_add(&smf_empty, &fenv));
2444 assert!(true == smf_empty.can_add(&smf_3_12, &fenv));
2445 assert!(true == smf_3_12.can_add(&smf_empty, &fenv));
2446 assert!(false == smf_3_12.can_add(&smf_3_12, &fenv));
2447
2448 assert!(true == smf_6_7_10.can_add(&smf_3_12, &fenv));
2449
2450 assert!(true == smf_3_12.can_add(&smf_6_7_10, &fenv));
2451
2452 // Tests for del()
2453 let smf_6_7 = new_sorted_frag_ranges(&fenv, &vec![fix_6u_6d, fix_7u_7d]);
2454 let smf_6_10 = new_sorted_frag_ranges(&fenv, &vec![fix_6u_6d, fix_10u]);
2455 let smf_7 = new_sorted_frag_ranges(&fenv, &vec![fix_7u_7d]);
2456 let smf_10 = new_sorted_frag_ranges(&fenv, &vec![fix_10u]);
2457
2458 tmp = smf_empty.clone();
2459 tmp.del(&smf_empty, &fenv);
2460 assert!(sorted_range_eq(&tmp, &smf_empty));
2461
2462 tmp = smf_3_12.clone();
2463 tmp.del(&smf_empty, &fenv);
2464 assert!(sorted_range_eq(&tmp, &smf_3_12));
2465
2466 tmp = smf_empty.clone();
2467 tmp.del(&smf_3_12, &fenv);
2468 assert!(sorted_range_eq(&tmp, &smf_empty));
2469
2470 tmp = smf_6_7_10.clone();
2471 tmp.del(&smf_3_12, &fenv);
2472 assert!(sorted_range_eq(&tmp, &smf_6_7_10));
2473
2474 tmp = smf_3_12.clone();
2475 tmp.del(&smf_6_7_10, &fenv);
2476 assert!(sorted_range_eq(&tmp, &smf_3_12));
2477
2478 tmp = smf_6_7_10.clone();
2479 tmp.del(&smf_6_7, &fenv);
2480 assert!(sorted_range_eq(&tmp, &smf_10));
2481
2482 tmp = smf_6_7_10.clone();
2483 tmp.del(&smf_10, &fenv);
2484 assert!(sorted_range_eq(&tmp, &smf_6_7));
2485
2486 tmp = smf_6_7_10.clone();
2487 tmp.del(&smf_7, &fenv);
2488 assert!(sorted_range_eq(&tmp, &smf_6_10));
2489
2490 // Tests for can_add_if_we_first_del()
2491 let smf_10_12 = new_sorted_frag_ranges(&fenv, &vec![fix_10u, fix_12u]);
2492
2493 assert!(
2494 true
2495 == smf_6_7_10
2496 .can_add_if_we_first_del(/*d=*/ &smf_10_12, /*a=*/ &smf_3_12, &fenv)
2497 );
2498
2499 assert!(
2500 false
2501 == smf_6_7_10
2502 .can_add_if_we_first_del(/*d=*/ &smf_10_12, /*a=*/ &smf_7, &fenv)
2503 );
2504 }
2505 */
2506