Skip to main content

regalloc2/
lib.rs

1/*
2 * The following license applies to this file, which derives many
3 * details (register and constraint definitions, for example) from the
4 * files `BacktrackingAllocator.h`, `BacktrackingAllocator.cpp`,
5 * `LIR.h`, and possibly definitions in other related files in
6 * `js/src/jit/`:
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 */
12
13#![allow(dead_code)]
14#![allow(clippy::all)]
15#![no_std]
16
17#[cfg(feature = "fuzzing")]
18extern crate std;
19
20extern crate alloc;
21
22// Even when trace logging is disabled, the trace macro has a significant
23// performance cost so we disable it in release builds.
24macro_rules! trace {
25    ($($tt:tt)*) => {
26        if cfg!(feature = "trace-log") {
27            ::log::trace!($($tt)*);
28        }
29    };
30}
31
32macro_rules! trace_enabled {
33    () => {
34        cfg!(feature = "trace-log") && ::log::log_enabled!(::log::Level::Trace)
35    };
36}
37
38use alloc::rc::Rc;
39use allocator_api2::vec::Vec as Vec2;
40use core::ops::Deref as _;
41use core::{hash::BuildHasherDefault, iter::FromIterator};
42use rustc_hash::FxHasher;
43type FxHashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FxHasher>>;
44type FxHashSet<V> = hashbrown::HashSet<V, BuildHasherDefault<FxHasher>>;
45
46pub(crate) mod cfg;
47pub(crate) mod domtree;
48pub(crate) mod fastalloc;
49pub mod indexset;
50pub(crate) mod ion;
51pub(crate) mod moves;
52pub(crate) mod postorder;
53pub mod ssa;
54
55#[macro_use]
56mod index;
57
58pub use self::ion::data_structures::Ctx;
59use alloc::vec::Vec;
60pub use index::{Block, Inst, InstRange};
61
62pub mod checker;
63
64#[cfg(feature = "fuzzing")]
65pub mod fuzzing;
66
67#[cfg(feature = "enable-serde")]
68pub mod serialize;
69
70#[cfg(feature = "enable-serde")]
71use serde::{Deserialize, Serialize};
72
73/// Register classes.
74///
75/// Every value has a "register class", which is like a type at the
76/// register-allocator level. Every register must belong to only one
77/// class; i.e., they are disjoint.
78///
79/// For tight bit-packing throughout our data structures, we support
80/// only three classes, "int", "float" and "vector". Usually two will
81/// be enough on modern machines, as they have one class of general-purpose
82/// integer registers of machine width (e.g. 64 bits), and another
83/// class of float/vector registers used both for FP and for vector
84/// operations. Additionally for machines with totally separate vector
85/// registers a third class is provided.
86#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
87#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
88pub enum RegClass {
89    Int = 0,
90    Float = 1,
91    Vector = 2,
92}
93
94/// A physical register. Contains a physical register number and a class.
95///
96/// The `hw_enc` field contains the physical register number and is in
97/// a logically separate index space per class; in other words, Int
98/// register 0 is different than Float register 0.
99///
100/// Because of bit-packed encodings throughout the implementation,
101/// `hw_enc` must fit in 6 bits, i.e., at most 64 registers per class.
102///
103/// The value returned by `index()`, in contrast, is in a single index
104/// space shared by all classes, in order to enable uniform reasoning
105/// about physical registers. This is done by putting the class bit at
106/// the MSB, or equivalently, declaring that indices 0..=63 are the 64
107/// integer registers and indices 64..=127 are the 64 float registers.
108#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
109#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
110pub struct PReg {
111    bits: u8,
112}
113
114impl PReg {
115    pub const MAX_BITS: usize = 6;
116    pub const MAX: usize = (1 << Self::MAX_BITS) - 1;
117    pub const NUM_INDEX: usize = 1 << (Self::MAX_BITS + 2); // including RegClass bits
118    pub const INVALID: u8 = ((RegClass::Int as u8) << Self::MAX_BITS) | (Self::MAX as u8);
119
120    /// Create a new PReg. The `hw_enc` range is 6 bits.
121    #[inline(always)]
122    pub const fn new(hw_enc: usize, class: RegClass) -> Self {
123        debug_assert!(hw_enc <= PReg::MAX);
124        PReg {
125            bits: ((class as u8) << Self::MAX_BITS) | (hw_enc as u8),
126        }
127    }
128
129    /// The physical register number, as encoded by the ISA for the particular register class.
130    #[inline(always)]
131    pub const fn hw_enc(self) -> usize {
132        self.bits as usize & Self::MAX
133    }
134
135    /// The register class.
136    #[inline(always)]
137    pub const fn class(self) -> RegClass {
138        match (self.bits >> Self::MAX_BITS) & 0b11 {
139            0 => RegClass::Int,
140            1 => RegClass::Float,
141            2 => RegClass::Vector,
142            _ => unreachable!(),
143        }
144    }
145
146    /// Get an index into the (not necessarily contiguous) index space of
147    /// all physical registers. Allows one to maintain an array of data for
148    /// all PRegs and index it efficiently.
149    #[inline(always)]
150    pub const fn index(self) -> usize {
151        self.bits as usize
152    }
153
154    /// Construct a PReg from the value returned from `.index()`.
155    #[inline(always)]
156    pub const fn from_index(index: usize) -> Self {
157        PReg {
158            bits: (index & (Self::NUM_INDEX - 1)) as u8,
159        }
160    }
161
162    /// Return the "invalid PReg", which can be used to initialize
163    /// data structures.
164    #[inline(always)]
165    pub const fn invalid() -> Self {
166        PReg {
167            bits: Self::INVALID,
168        }
169    }
170
171    /// Return a valid [`PReg`] or [`None`] if it is invalid.
172    #[inline(always)]
173    pub const fn as_valid(self) -> Option<Self> {
174        if self.bits == Self::INVALID {
175            None
176        } else {
177            Some(self)
178        }
179    }
180}
181
182impl Default for PReg {
183    fn default() -> Self {
184        Self::invalid()
185    }
186}
187
188impl core::fmt::Debug for PReg {
189    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
190        write!(
191            f,
192            "PReg(hw = {}, class = {:?}, index = {})",
193            self.hw_enc(),
194            self.class(),
195            self.index()
196        )
197    }
198}
199
200impl core::fmt::Display for PReg {
201    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
202        let class = match self.class() {
203            RegClass::Int => "i",
204            RegClass::Float => "f",
205            RegClass::Vector => "v",
206        };
207        write!(f, "p{}{}", self.hw_enc(), class)
208    }
209}
210
211/// A type for internal bit arrays.
212type Bits = u64;
213
214/// A physical register set. Used to represent clobbers
215/// efficiently.
216///
217/// The set is `Copy` and is guaranteed to have constant, and small,
218/// size, as it is based on a bitset internally.
219#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
220#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
221pub struct PRegSet {
222    bits: [Bits; Self::LEN],
223}
224
225impl PRegSet {
226    /// The number of bits per element in the internal bit array.
227    const BITS: usize = core::mem::size_of::<Bits>() * 8;
228
229    /// Length of the internal bit array.
230    const LEN: usize = (PReg::NUM_INDEX + Self::BITS - 1) / Self::BITS;
231
232    /// Create an empty set.
233    pub const fn empty() -> Self {
234        Self {
235            bits: [0; Self::LEN],
236        }
237    }
238
239    /// Splits the given register index into parts to access the internal bit array.
240    const fn split_index(reg: PReg) -> (usize, usize) {
241        let index = reg.index();
242        (index >> Self::BITS.ilog2(), index & (Self::BITS - 1))
243    }
244
245    /// Returns whether the given register is part of the set.
246    pub fn contains(&self, reg: PReg) -> bool {
247        let (index, bit) = Self::split_index(reg);
248        self.bits[index] & (1 << bit) != 0
249    }
250
251    /// Add a physical register (PReg) to the set, returning the new value.
252    pub const fn with(self, reg: PReg) -> Self {
253        let (index, bit) = Self::split_index(reg);
254        let mut out = self;
255        out.bits[index] |= 1 << bit;
256        out
257    }
258
259    /// Add a physical register (PReg) to the set.
260    pub const fn add(&mut self, reg: PReg) {
261        let (index, bit) = Self::split_index(reg);
262        self.bits[index] |= 1 << bit;
263    }
264
265    /// Remove a physical register (PReg) from the set.
266    pub fn remove(&mut self, reg: PReg) {
267        let (index, bit) = Self::split_index(reg);
268        self.bits[index] &= !(1 << bit);
269    }
270
271    /// Add all of the registers in one set to this one, mutating in
272    /// place.
273    pub fn union_from(&mut self, other: PRegSet) {
274        for i in 0..self.bits.len() {
275            self.bits[i] |= other.bits[i];
276        }
277    }
278
279    pub fn intersect_from(&mut self, other: PRegSet) {
280        for i in 0..self.bits.len() {
281            self.bits[i] &= other.bits[i];
282        }
283    }
284
285    pub fn invert(&self) -> PRegSet {
286        let mut set = self.bits;
287        for i in 0..self.bits.len() {
288            set[i] = !self.bits[i];
289        }
290        PRegSet { bits: set }
291    }
292
293    pub fn is_empty(&self, regclass: RegClass) -> bool {
294        self.bits[regclass as usize] == 0
295    }
296
297    /// Returns the number of register in this set.
298    pub fn len(&self) -> u32 {
299        self.bits.iter().map(|s| s.count_ones()).sum()
300    }
301
302    /// Returns the maximum register in this set, with the highest hw_enc value.
303    pub fn max_preg(&self) -> Option<PReg> {
304        self.into_iter().last()
305    }
306
307    /// Add all registers from `0..reg` to this set, not including `reg` itself.
308    pub fn add_up_to(&mut self, reg: PReg) {
309        let (index, bit) = Self::split_index(reg);
310        for i in 0..index {
311            self.bits[i] = !0;
312        }
313        self.bits[index] = (1 << bit) - 1;
314    }
315}
316
317impl core::ops::BitAnd<PRegSet> for PRegSet {
318    type Output = PRegSet;
319
320    fn bitand(self, rhs: PRegSet) -> Self::Output {
321        let mut out = self;
322        out.intersect_from(rhs);
323        out
324    }
325}
326
327impl core::ops::BitOr<PRegSet> for PRegSet {
328    type Output = PRegSet;
329
330    fn bitor(self, rhs: PRegSet) -> Self::Output {
331        let mut out = self;
332        out.union_from(rhs);
333        out
334    }
335}
336
337impl IntoIterator for &PRegSet {
338    type Item = PReg;
339    type IntoIter = PRegSetIter;
340    fn into_iter(self) -> PRegSetIter {
341        (*self).into_iter()
342    }
343}
344
345impl IntoIterator for PRegSet {
346    type Item = PReg;
347    type IntoIter = PRegSetIter;
348    fn into_iter(self) -> PRegSetIter {
349        PRegSetIter {
350            bits: self.bits,
351            cur: 0,
352        }
353    }
354}
355
356pub struct PRegSetIter {
357    bits: [Bits; PRegSet::LEN],
358    cur: usize,
359}
360
361impl Iterator for PRegSetIter {
362    type Item = PReg;
363    fn next(&mut self) -> Option<PReg> {
364        loop {
365            let bits = self.bits.get_mut(self.cur)?;
366            if *bits != 0 {
367                let bit = bits.trailing_zeros();
368                *bits &= !(1 << bit);
369                let index = bit as usize + self.cur * PRegSet::BITS;
370                return Some(PReg::from_index(index));
371            }
372            self.cur += 1;
373        }
374    }
375}
376
377impl From<&MachineEnv> for PRegSet {
378    fn from(env: &MachineEnv) -> Self {
379        let mut res = Self::default();
380
381        for class in env.preferred_regs_by_class.iter() {
382            res.union_from(*class)
383        }
384
385        for class in env.non_preferred_regs_by_class.iter() {
386            res.union_from(*class)
387        }
388
389        res
390    }
391}
392
393impl FromIterator<PReg> for PRegSet {
394    fn from_iter<T: IntoIterator<Item = PReg>>(iter: T) -> Self {
395        let mut set = Self::default();
396        for preg in iter {
397            set.add(preg);
398        }
399        set
400    }
401}
402
403impl core::fmt::Display for PRegSet {
404    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
405        write!(f, "{{")?;
406        for preg in self.into_iter() {
407            write!(f, "{preg}, ")?;
408        }
409        write!(f, "}}")
410    }
411}
412
413/// A virtual register. Contains a virtual register number and a
414/// class.
415///
416/// A virtual register ("vreg") corresponds to an SSA value. All
417/// dataflow in the input program is specified via flow through a
418/// virtual register; even uses of specially-constrained locations,
419/// such as fixed physical registers, are done by using vregs, because
420/// we need the vreg's live range in order to track the use of that
421/// location.
422#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
423#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
424pub struct VReg {
425    bits: u32,
426}
427
428impl VReg {
429    pub const MAX_BITS: usize = 30;
430    pub const MAX: usize = (1 << Self::MAX_BITS) - 1;
431
432    #[inline(always)]
433    pub const fn new(virt_reg: usize, class: RegClass) -> Self {
434        debug_assert!(virt_reg <= VReg::MAX);
435        VReg {
436            bits: ((virt_reg as u32) << 2) | (class as u8 as u32),
437        }
438    }
439
440    #[inline(always)]
441    pub const fn vreg(self) -> usize {
442        let vreg = (self.bits >> 2) as usize;
443        vreg
444    }
445
446    #[inline(always)]
447    pub const fn class(self) -> RegClass {
448        match self.bits & 0b11 {
449            0 => RegClass::Int,
450            1 => RegClass::Float,
451            2 => RegClass::Vector,
452            _ => unreachable!(),
453        }
454    }
455
456    #[inline(always)]
457    pub const fn invalid() -> Self {
458        VReg::new(Self::MAX, RegClass::Int)
459    }
460
461    #[inline(always)]
462    pub const fn bits(self) -> usize {
463        self.bits as usize
464    }
465
466    #[inline(always)]
467    pub const fn from_bits(bits: u32) -> VReg {
468        Self { bits }
469    }
470}
471
472impl From<u32> for VReg {
473    fn from(value: u32) -> Self {
474        Self { bits: value }
475    }
476}
477
478impl core::fmt::Debug for VReg {
479    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
480        write!(
481            f,
482            "VReg(vreg = {}, class = {:?})",
483            self.vreg(),
484            self.class()
485        )
486    }
487}
488
489impl core::fmt::Display for VReg {
490    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
491        write!(f, "v{}", self.vreg())
492    }
493}
494
495/// A spillslot is a space in the stackframe used by the allocator to
496/// temporarily store a value.
497///
498/// The allocator is responsible for allocating indices in this space,
499/// and will specify how many spillslots have been used when the
500/// allocation is completed.
501#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
502#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
503pub struct SpillSlot {
504    bits: u32,
505}
506
507impl SpillSlot {
508    /// The maximum spillslot index.
509    pub const MAX: usize = (1 << 24) - 1;
510
511    /// Create a new SpillSlot.
512    #[inline(always)]
513    pub fn new(slot: usize) -> Self {
514        debug_assert!(slot <= Self::MAX);
515        SpillSlot { bits: slot as u32 }
516    }
517
518    /// Get the spillslot index for this spillslot.
519    #[inline(always)]
520    pub fn index(self) -> usize {
521        (self.bits & 0x00ffffff) as usize
522    }
523
524    /// Get the spillslot `offset` slots away.
525    #[inline(always)]
526    pub fn plus(self, offset: usize) -> Self {
527        SpillSlot::new(self.index() + offset)
528    }
529
530    /// Get the invalid spillslot, used for initializing data structures.
531    #[inline(always)]
532    pub fn invalid() -> Self {
533        SpillSlot { bits: 0xffff_ffff }
534    }
535
536    /// Is this the invalid spillslot?
537    #[inline(always)]
538    pub fn is_invalid(self) -> bool {
539        self == Self::invalid()
540    }
541
542    /// Is this a valid spillslot (not `SpillSlot::invalid()`)?
543    #[inline(always)]
544    pub fn is_valid(self) -> bool {
545        self != Self::invalid()
546    }
547}
548
549impl core::fmt::Display for SpillSlot {
550    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
551        write!(f, "stack{}", self.index())
552    }
553}
554
555/// An `OperandConstraint` specifies where a vreg's value must be
556/// placed at a particular reference to that vreg via an
557/// `Operand`. The constraint may be loose -- "any register of a given
558/// class", for example -- or very specific, such as "this particular
559/// physical register". The allocator's result will always satisfy all
560/// given constraints; however, if the input has a combination of
561/// constraints that are impossible to satisfy, then allocation may
562/// fail or the allocator may panic (providing impossible constraints
563/// is usually a programming error in the client, rather than a
564/// function of bad input).
565#[derive(Clone, Copy, Debug, PartialEq, Eq)]
566#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
567pub enum OperandConstraint {
568    /// Any location is fine (register or stack slot).
569    Any,
570    /// Operand must be in a register. Register is read-only for Uses.
571    Reg,
572    /// Operand must be on the stack.
573    Stack,
574    /// Operand must be in a fixed register.
575    FixedReg(PReg),
576    /// On defs only: reuse a use's register.
577    Reuse(usize),
578    /// Operand must be in a specific range of registers.
579    ///
580    /// The contained `usize` indicates the (exclusive) upper limit of a
581    /// register range, `n`. An operand with this constraint may allocate a
582    /// register between `0 ..= n-1`. Due to encoding constraints, `n` must be a
583    /// power of two and below 2^16.
584    Limit(usize),
585}
586
587impl core::fmt::Display for OperandConstraint {
588    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
589        match self {
590            Self::Any => write!(f, "any"),
591            Self::Reg => write!(f, "reg"),
592            Self::Stack => write!(f, "stack"),
593            Self::FixedReg(preg) => write!(f, "fixed({preg})"),
594            Self::Reuse(idx) => write!(f, "reuse({idx})"),
595            Self::Limit(max) => write!(f, "limit(0..={})", max - 1),
596        }
597    }
598}
599
600/// The "kind" of the operand: whether it reads a vreg (Use) or writes
601/// a vreg (Def).
602#[derive(Clone, Copy, Debug, PartialEq, Eq)]
603#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
604pub enum OperandKind {
605    Def = 0,
606    Use = 1,
607}
608
609/// The "position" of the operand: where it has its read/write
610/// effects. These are positions "in" the instruction, and "early" and
611/// "late" are relative to the instruction's main effect or
612/// computation. In other words, the allocator assumes that the
613/// instruction (i) performs all reads and writes of "early" operands,
614/// (ii) does its work, and (iii) performs all reads and writes of its
615/// "late" operands.
616///
617/// A "write" (def) at "early" or a "read" (use) at "late" may be
618/// slightly nonsensical, given the above, if the read is necessary
619/// for the computation or the write is a result of it. A way to think
620/// of it is that the value (even if a result of execution) *could*
621/// have been read or written at the given location without causing
622/// any register-usage conflicts. In other words, these write-early or
623/// use-late operands ensure that the particular allocations are valid
624/// for longer than usual and that a register is not reused between
625/// the use (normally complete at "Early") and the def (normally
626/// starting at "Late"). See `Operand` for more.
627#[derive(Clone, Copy, Debug, PartialEq, Eq)]
628#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
629pub enum OperandPos {
630    Early = 0,
631    Late = 1,
632}
633
634/// An `Operand` encodes everything about a mention of a register in
635/// an instruction: virtual register number, and any constraint that
636/// applies to the register at this program point.
637///
638/// An Operand may be a use or def (this corresponds to `LUse` and
639/// `LAllocation` in Ion).
640///
641/// Generally, regalloc2 considers operands to have their effects at
642/// one of two points that exist in an instruction: "Early" or
643/// "Late". All operands at a given program-point are assigned
644/// non-conflicting locations based on their constraints. Each operand
645/// has a "kind", one of use/def/mod, corresponding to
646/// read/write/read-write, respectively.
647///
648/// Usually, an instruction's inputs will be "early uses" and outputs
649/// will be "late defs", though there are valid use-cases for other
650/// combinations too. For example, a single "instruction" seen by the
651/// regalloc that lowers into multiple machine instructions and reads
652/// some of its inputs after it starts to write outputs must either
653/// make those input(s) "late uses" or those output(s) "early defs" so
654/// that the conflict (overlap) is properly accounted for. See
655/// comments on the constructors below for more.
656#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
657#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
658pub struct Operand {
659    /// Bit-pack into 64 bits.
660    ///
661    /// unused:21 constraint:7 kind:1 pos:1 class:2 vreg:32
662    ///
663    /// where `constraint` is an `OperandConstraint`, `kind` is an
664    /// `OperandKind`, `pos` is an `OperandPos`, `class` is a
665    /// `RegClass`, and `vreg` is a vreg index.
666    ///
667    /// The constraints are encoded as follows:
668    /// - 1xxxxxx => FixedReg(preg)
669    /// - 01xxxxx => Reuse(index)
670    /// - 001xxxx => Limit(max)
671    /// - 0000000 => Any
672    /// - 0000001 => Reg
673    /// - 0000010 => Stack
674    /// - _ => Unused for now
675    bits: u64,
676}
677
678impl Operand {
679    const VREG_BITS: usize = 32;
680    const VREG_SHIFT: usize = 0;
681    const VREG_MASK: u64 = (1 << Self::VREG_BITS) - 1;
682
683    const CLASS_BITS: usize = 2;
684    const CLASS_SHIFT: usize = Self::VREG_SHIFT + Self::VREG_BITS;
685    const CLASS_MASK: u64 = (1 << Self::CLASS_BITS) - 1;
686
687    const POS_BITS: usize = 1;
688    const POS_SHIFT: usize = Self::CLASS_SHIFT + Self::CLASS_BITS;
689    const POS_MASK: u64 = (1 << Self::POS_BITS) - 1;
690
691    const KIND_BITS: usize = 1;
692    const KIND_SHIFT: usize = Self::POS_SHIFT + Self::POS_BITS;
693    const KIND_MASK: u64 = (1 << Self::KIND_BITS) - 1;
694
695    const CONSTRAINT_BITS: usize = 7;
696    const CONSTRAINT_SHIFT: usize = Self::KIND_SHIFT + Self::KIND_BITS;
697    const CONSTRAINT_MASK: u64 = (1 << Self::CONSTRAINT_BITS) - 1;
698
699    const TOTAL_BITS: usize = Self::CONSTRAINT_SHIFT + Self::CONSTRAINT_BITS;
700
701    /// Construct a new operand.
702    #[inline(always)]
703    pub fn new(
704        vreg: VReg,
705        constraint: OperandConstraint,
706        kind: OperandKind,
707        pos: OperandPos,
708    ) -> Self {
709        let constraint_field = match constraint {
710            OperandConstraint::Any => 0,
711            OperandConstraint::Reg => 1,
712            OperandConstraint::Stack => 2,
713            OperandConstraint::FixedReg(preg) => {
714                debug_assert_eq!(preg.class(), vreg.class());
715                0b1000000 | preg.hw_enc() as u64
716            }
717            OperandConstraint::Reuse(which) => {
718                debug_assert!(which <= 0b11111);
719                0b0100000 | which as u64
720            }
721            OperandConstraint::Limit(max) => {
722                assert!(max.is_power_of_two());
723                assert!(
724                    max <= PReg::MAX + 1,
725                    "limit is larger than the allowed register encoding"
726                );
727                let log2 = max.ilog2();
728                debug_assert!(log2 <= 0b1111);
729                0b0010000 | log2 as u64
730            }
731        };
732        let class_field = vreg.class() as u8 as u64;
733        let pos_field = pos as u8 as u64;
734        let kind_field = kind as u8 as u64;
735        Operand {
736            bits: ((vreg.vreg() as u64) << Self::VREG_SHIFT)
737                | (class_field << Self::CLASS_SHIFT)
738                | (pos_field << Self::POS_SHIFT)
739                | (kind_field << Self::KIND_SHIFT)
740                | (constraint_field << Self::CONSTRAINT_SHIFT),
741        }
742    }
743
744    /// Create an `Operand` that designates a use of a VReg that must
745    /// be in a register, and that is used at the "before" point,
746    /// i.e., can be overwritten by a result.
747    #[inline(always)]
748    pub fn reg_use(vreg: VReg) -> Self {
749        Operand::new(
750            vreg,
751            OperandConstraint::Reg,
752            OperandKind::Use,
753            OperandPos::Early,
754        )
755    }
756
757    /// Create an `Operand` that designates a use of a VReg that must
758    /// be in a register, and that is used up until the "after" point,
759    /// i.e., must not conflict with any results.
760    #[inline(always)]
761    pub fn reg_use_at_end(vreg: VReg) -> Self {
762        Operand::new(
763            vreg,
764            OperandConstraint::Reg,
765            OperandKind::Use,
766            OperandPos::Late,
767        )
768    }
769
770    /// Create an `Operand` that designates a definition of a VReg
771    /// that must be in a register, and that occurs at the "after"
772    /// point, i.e. may reuse a register that carried a use into this
773    /// instruction.
774    #[inline(always)]
775    pub fn reg_def(vreg: VReg) -> Self {
776        Operand::new(
777            vreg,
778            OperandConstraint::Reg,
779            OperandKind::Def,
780            OperandPos::Late,
781        )
782    }
783
784    /// Create an `Operand` that designates a definition of a VReg
785    /// that must be in a register, and that occurs early at the
786    /// "before" point, i.e., must not conflict with any input to the
787    /// instruction.
788    ///
789    /// Note that the register allocator will ensure that such an
790    /// early-def operand is live throughout the instruction, i.e., also
791    /// at the after-point. Hence it will also avoid conflicts with all
792    /// outputs to the instruction. As such, early defs are appropriate
793    /// for use as "temporary registers" that an instruction can use
794    /// throughout its execution separately from the inputs and outputs.
795    #[inline(always)]
796    pub fn reg_def_at_start(vreg: VReg) -> Self {
797        Operand::new(
798            vreg,
799            OperandConstraint::Reg,
800            OperandKind::Def,
801            OperandPos::Early,
802        )
803    }
804
805    /// Create an `Operand` that designates a def (and use) of a
806    /// temporary *within* the instruction. This register is assumed
807    /// to be written by the instruction, and will not conflict with
808    /// any input or output, but should not be used after the
809    /// instruction completes.
810    ///
811    /// Note that within a single instruction, the dedicated scratch
812    /// register (as specified in the `MachineEnv`) is also always
813    /// available for use. The register allocator may use the register
814    /// *between* instructions in order to implement certain sequences
815    /// of moves, but will never hold a value live in the scratch
816    /// register across an instruction.
817    #[inline(always)]
818    pub fn reg_temp(vreg: VReg) -> Self {
819        // For now a temp is equivalent to a def-at-start operand,
820        // which gives the desired semantics but does not enforce the
821        // "not reused later" constraint.
822        Operand::new(
823            vreg,
824            OperandConstraint::Reg,
825            OperandKind::Def,
826            OperandPos::Early,
827        )
828    }
829
830    /// Create an `Operand` that designates a def of a vreg that must
831    /// reuse the register assigned to an input to the
832    /// instruction. The input is identified by `idx` (is the `idx`th
833    /// `Operand` for the instruction) and must be constraint to a
834    /// register, i.e., be the result of `Operand::reg_use(vreg)`.
835    #[inline(always)]
836    pub fn reg_reuse_def(vreg: VReg, idx: usize) -> Self {
837        Operand::new(
838            vreg,
839            OperandConstraint::Reuse(idx),
840            OperandKind::Def,
841            OperandPos::Late,
842        )
843    }
844
845    /// Create an `Operand` that designates a use of a vreg and
846    /// ensures that it is placed in the given, fixed PReg at the
847    /// use. It is guaranteed that the `Allocation` resulting for this
848    /// operand will be `preg`.
849    #[inline(always)]
850    pub fn reg_fixed_use(vreg: VReg, preg: PReg) -> Self {
851        Operand::new(
852            vreg,
853            OperandConstraint::FixedReg(preg),
854            OperandKind::Use,
855            OperandPos::Early,
856        )
857    }
858
859    /// Create an `Operand` that designates a def of a vreg and
860    /// ensures that it is placed in the given, fixed PReg at the
861    /// def. It is guaranteed that the `Allocation` resulting for this
862    /// operand will be `preg`.
863    #[inline(always)]
864    pub fn reg_fixed_def(vreg: VReg, preg: PReg) -> Self {
865        Operand::new(
866            vreg,
867            OperandConstraint::FixedReg(preg),
868            OperandKind::Def,
869            OperandPos::Late,
870        )
871    }
872
873    /// Same as `reg_fixed_use` but at `OperandPos::Late`.
874    #[inline(always)]
875    pub fn reg_fixed_use_at_end(vreg: VReg, preg: PReg) -> Self {
876        Operand::new(
877            vreg,
878            OperandConstraint::FixedReg(preg),
879            OperandKind::Use,
880            OperandPos::Late,
881        )
882    }
883
884    /// Same as `reg_fixed_def` but at `OperandPos::Early`.
885    #[inline(always)]
886    pub fn reg_fixed_def_at_start(vreg: VReg, preg: PReg) -> Self {
887        Operand::new(
888            vreg,
889            OperandConstraint::FixedReg(preg),
890            OperandKind::Def,
891            OperandPos::Early,
892        )
893    }
894
895    /// Create an `Operand` that designates a use of a vreg and places
896    /// no constraints on its location (i.e., it can be allocated into
897    /// either a register or on the stack).
898    #[inline(always)]
899    pub fn any_use(vreg: VReg) -> Self {
900        Operand::new(
901            vreg,
902            OperandConstraint::Any,
903            OperandKind::Use,
904            OperandPos::Early,
905        )
906    }
907
908    /// Create an `Operand` that designates a def of a vreg and places
909    /// no constraints on its location (i.e., it can be allocated into
910    /// either a register or on the stack).
911    #[inline(always)]
912    pub fn any_def(vreg: VReg) -> Self {
913        Operand::new(
914            vreg,
915            OperandConstraint::Any,
916            OperandKind::Def,
917            OperandPos::Late,
918        )
919    }
920
921    /// Create an `Operand` that always results in an assignment to the
922    /// given fixed `preg`, *without* tracking liveranges in that
923    /// `preg`. Must only be used for non-allocatable registers.
924    #[inline(always)]
925    pub fn fixed_nonallocatable(preg: PReg) -> Self {
926        Operand::new(
927            VReg::new(VReg::MAX, preg.class()),
928            OperandConstraint::FixedReg(preg),
929            OperandKind::Use,
930            OperandPos::Early,
931        )
932    }
933
934    /// Get the virtual register designated by an operand. Every
935    /// operand must name some virtual register, even if it constrains
936    /// the operand to a fixed physical register as well; the vregs
937    /// are used to track dataflow.
938    #[inline(always)]
939    pub fn vreg(self) -> VReg {
940        let vreg_idx = ((self.bits >> Self::VREG_SHIFT) & Self::VREG_MASK) as usize;
941        VReg::new(vreg_idx, self.class())
942    }
943
944    /// Get the register class used by this operand.
945    #[inline(always)]
946    pub fn class(self) -> RegClass {
947        let class_field = (self.bits >> Self::CLASS_SHIFT) & Self::CLASS_MASK;
948        match class_field {
949            0 => RegClass::Int,
950            1 => RegClass::Float,
951            2 => RegClass::Vector,
952            _ => unreachable!(),
953        }
954    }
955
956    /// Get the "kind" of this operand: a definition (write) or a use
957    /// (read).
958    #[inline(always)]
959    pub fn kind(self) -> OperandKind {
960        let kind_field = (self.bits >> Self::KIND_SHIFT) & Self::KIND_MASK;
961        match kind_field {
962            0 => OperandKind::Def,
963            1 => OperandKind::Use,
964            _ => unreachable!(),
965        }
966    }
967
968    /// Get the "position" of this operand, i.e., where its read
969    /// and/or write occurs: either before the instruction executes,
970    /// or after it does. Ordinarily, uses occur at "before" and defs
971    /// at "after", though there are cases where this is not true.
972    #[inline(always)]
973    pub fn pos(self) -> OperandPos {
974        let pos_field = (self.bits >> Self::POS_SHIFT) & Self::POS_MASK;
975        match pos_field {
976            0 => OperandPos::Early,
977            1 => OperandPos::Late,
978            _ => unreachable!(),
979        }
980    }
981
982    /// Get the "constraint" of this operand, i.e., what requirements
983    /// its allocation must fulfill.
984    #[inline(always)]
985    pub fn constraint(self) -> OperandConstraint {
986        let constraint_field =
987            ((self.bits >> Self::CONSTRAINT_SHIFT) & Self::CONSTRAINT_MASK) as usize;
988        if constraint_field & 0b1000000 != 0 {
989            OperandConstraint::FixedReg(PReg::new(constraint_field & 0b0111111, self.class()))
990        } else if constraint_field & 0b0100000 != 0 {
991            OperandConstraint::Reuse(constraint_field & 0b0011111)
992        } else if constraint_field & 0b0010000 != 0 {
993            OperandConstraint::Limit(1 << (constraint_field & 0b0001111))
994        } else {
995            match constraint_field {
996                0 => OperandConstraint::Any,
997                1 => OperandConstraint::Reg,
998                2 => OperandConstraint::Stack,
999                _ => unreachable!(),
1000            }
1001        }
1002    }
1003
1004    /// If this operand is for a fixed non-allocatable register (see
1005    /// [`Operand::fixed_nonallocatable`]), then returns the physical register that it will
1006    /// be assigned to.
1007    #[inline(always)]
1008    pub fn as_fixed_nonallocatable(self) -> Option<PReg> {
1009        match self.constraint() {
1010            OperandConstraint::FixedReg(preg) if self.vreg().vreg() == VReg::MAX => Some(preg),
1011            _ => None,
1012        }
1013    }
1014
1015    /// Get the raw 64-bit encoding of this operand's fields.
1016    #[inline(always)]
1017    pub fn bits(self) -> u64 {
1018        self.bits
1019    }
1020
1021    /// Construct an `Operand` from the raw 64-bit encoding returned
1022    /// from `bits()`.
1023    #[inline(always)]
1024    pub fn from_bits(bits: u64) -> Self {
1025        debug_assert_eq!(bits >> Self::TOTAL_BITS, 0);
1026        Operand { bits }
1027    }
1028}
1029
1030impl core::fmt::Debug for Operand {
1031    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1032        core::fmt::Display::fmt(self, f)
1033    }
1034}
1035
1036impl core::fmt::Display for Operand {
1037    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1038        if let Some(preg) = self.as_fixed_nonallocatable() {
1039            return write!(f, "Fixed: {preg}");
1040        }
1041        match (self.kind(), self.pos()) {
1042            (OperandKind::Def, OperandPos::Late) | (OperandKind::Use, OperandPos::Early) => {
1043                write!(f, "{:?}", self.kind())?;
1044            }
1045            _ => {
1046                write!(f, "{:?}@{:?}", self.kind(), self.pos())?;
1047            }
1048        }
1049        write!(
1050            f,
1051            ": {}{} {}",
1052            self.vreg(),
1053            match self.class() {
1054                RegClass::Int => "i",
1055                RegClass::Float => "f",
1056                RegClass::Vector => "v",
1057            },
1058            self.constraint()
1059        )
1060    }
1061}
1062
1063/// An Allocation represents the end result of regalloc for an
1064/// Operand.
1065#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1066#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1067pub struct Allocation {
1068    /// Bit-pack in 32 bits.
1069    ///
1070    /// kind:3 unused:1 index:28
1071    bits: u32,
1072}
1073
1074impl core::fmt::Debug for Allocation {
1075    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1076        core::fmt::Display::fmt(self, f)
1077    }
1078}
1079
1080impl core::fmt::Display for Allocation {
1081    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1082        match self.kind() {
1083            AllocationKind::None => write!(f, "none"),
1084            AllocationKind::Reg => write!(f, "{}", self.as_reg().unwrap()),
1085            AllocationKind::Stack => write!(f, "{}", self.as_stack().unwrap()),
1086        }
1087    }
1088}
1089
1090impl Allocation {
1091    /// Construct a new Allocation.
1092    #[inline(always)]
1093    pub(crate) fn new(kind: AllocationKind, index: usize) -> Self {
1094        debug_assert!(index < (1 << 28));
1095        Self {
1096            bits: ((kind as u8 as u32) << 29) | (index as u32),
1097        }
1098    }
1099
1100    /// Get the "none" allocation, which is distinct from the other
1101    /// possibilities and is used to initialize data structures.
1102    #[inline(always)]
1103    pub fn none() -> Allocation {
1104        Allocation::new(AllocationKind::None, 0)
1105    }
1106
1107    /// Create an allocation into a register.
1108    #[inline(always)]
1109    pub fn reg(preg: PReg) -> Allocation {
1110        Allocation::new(AllocationKind::Reg, preg.index())
1111    }
1112
1113    /// Create an allocation into a spillslot.
1114    #[inline(always)]
1115    pub fn stack(slot: SpillSlot) -> Allocation {
1116        Allocation::new(AllocationKind::Stack, slot.bits as usize)
1117    }
1118
1119    /// Get the allocation's "kind": none, register, or stack (spillslot).
1120    #[inline(always)]
1121    pub fn kind(self) -> AllocationKind {
1122        match (self.bits >> 29) & 7 {
1123            0 => AllocationKind::None,
1124            1 => AllocationKind::Reg,
1125            2 => AllocationKind::Stack,
1126            _ => unreachable!(),
1127        }
1128    }
1129
1130    /// Is the allocation "none"?
1131    #[inline(always)]
1132    pub fn is_none(self) -> bool {
1133        self.kind() == AllocationKind::None
1134    }
1135
1136    /// Is the allocation not "none"?
1137    #[inline(always)]
1138    pub fn is_some(self) -> bool {
1139        self.kind() != AllocationKind::None
1140    }
1141
1142    /// Is the allocation a register?
1143    #[inline(always)]
1144    pub fn is_reg(self) -> bool {
1145        self.kind() == AllocationKind::Reg
1146    }
1147
1148    /// Is the allocation on the stack (a spillslot)?
1149    #[inline(always)]
1150    pub fn is_stack(self) -> bool {
1151        self.kind() == AllocationKind::Stack
1152    }
1153
1154    /// Get the index of the spillslot or register. If register, this
1155    /// is an index that can be used by `PReg::from_index()`.
1156    #[inline(always)]
1157    pub fn index(self) -> usize {
1158        (self.bits & ((1 << 28) - 1)) as usize
1159    }
1160
1161    /// Get the allocation as a physical register, if any.
1162    #[inline(always)]
1163    pub fn as_reg(self) -> Option<PReg> {
1164        if self.kind() == AllocationKind::Reg {
1165            Some(PReg::from_index(self.index()))
1166        } else {
1167            None
1168        }
1169    }
1170
1171    /// Get the allocation as a spillslot, if any.
1172    #[inline(always)]
1173    pub fn as_stack(self) -> Option<SpillSlot> {
1174        if self.kind() == AllocationKind::Stack {
1175            Some(SpillSlot {
1176                bits: self.index() as u32,
1177            })
1178        } else {
1179            None
1180        }
1181    }
1182
1183    /// Get the raw bits for the packed encoding of this allocation.
1184    #[inline(always)]
1185    pub fn bits(self) -> u32 {
1186        self.bits
1187    }
1188
1189    /// Construct an allocation from its packed encoding.
1190    #[inline(always)]
1191    pub fn from_bits(bits: u32) -> Self {
1192        debug_assert!(bits >> 29 >= 5);
1193        Self { bits }
1194    }
1195}
1196
1197/// An allocation is one of two "kinds" (or "none"): register or
1198/// spillslot/stack.
1199#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1200#[repr(u8)]
1201#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1202pub enum AllocationKind {
1203    None = 0,
1204    Reg = 1,
1205    Stack = 2,
1206}
1207
1208/// A trait defined by the regalloc client to provide access to its
1209/// machine-instruction / CFG representation.
1210///
1211/// (This trait's design is inspired by, and derives heavily from, the
1212/// trait of the same name in regalloc.rs.)
1213///
1214/// The ids used in [`Block`] and [`VReg`] must start their numbering
1215/// at zero and be sequential.
1216pub trait Function {
1217    // -------------
1218    // CFG traversal
1219    // -------------
1220
1221    /// How many instructions are there?
1222    fn num_insts(&self) -> usize;
1223
1224    /// How many blocks are there?
1225    fn num_blocks(&self) -> usize;
1226
1227    /// Get the index of the entry block.
1228    fn entry_block(&self) -> Block;
1229
1230    /// Provide the range of instruction indices contained in each block.
1231    fn block_insns(&self, block: Block) -> InstRange;
1232
1233    /// Get CFG successors for a given block.
1234    fn block_succs(&self, block: Block) -> &[Block];
1235
1236    /// Get the CFG predecessors for a given block.
1237    fn block_preds(&self, block: Block) -> &[Block];
1238
1239    /// Get the block parameters for a given block.
1240    fn block_params(&self, block: Block) -> &[VReg];
1241
1242    /// Determine whether an instruction is a return instruction.
1243    fn is_ret(&self, insn: Inst) -> bool;
1244
1245    /// Determine whether an instruction is the end-of-block
1246    /// branch.
1247    fn is_branch(&self, insn: Inst) -> bool;
1248
1249    /// If `insn` is a branch at the end of `block`, returns the
1250    /// outgoing blockparam arguments for the given successor. The
1251    /// number of arguments must match the number incoming blockparams
1252    /// for each respective successor block.
1253    fn branch_blockparams(&self, block: Block, insn: Inst, succ_idx: usize) -> &[VReg];
1254
1255    // --------------------------
1256    // Instruction register slots
1257    // --------------------------
1258
1259    /// Get the Operands for an instruction.
1260    fn inst_operands(&self, insn: Inst) -> &[Operand];
1261
1262    /// Get the clobbers for an instruction; these are the registers
1263    /// that, after the instruction has executed, hold values that are
1264    /// arbitrary, separately from the usual outputs to the
1265    /// instruction. It is invalid to read a register that has been
1266    /// clobbered; the register allocator is free to assume that
1267    /// clobbered registers are filled with garbage and available for
1268    /// reuse. It will avoid storing any value in a clobbered register
1269    /// that must be live across the instruction.
1270    ///
1271    /// Another way of seeing this is that a clobber is equivalent to
1272    /// a "late def" of a fresh vreg that is not used anywhere else
1273    /// in the program, with a fixed-register constraint that places
1274    /// it in a given PReg chosen by the client prior to regalloc.
1275    ///
1276    /// Every register written by an instruction must either
1277    /// correspond to (be assigned to) an Operand of kind `Def`, or
1278    /// else must be a "clobber".
1279    ///
1280    /// This can be used to, for example, describe ABI-specified
1281    /// registers that are not preserved by a call instruction, or
1282    /// fixed physical registers written by an instruction but not
1283    /// used as a vreg output, or fixed physical registers used as
1284    /// temps within an instruction out of necessity.
1285    ///
1286    /// Note that clobbers and defs and late-uses must not collide: it
1287    /// is illegal to name the same physical register both as a clobber
1288    /// and in a fixed-register constraint on a def or late use.
1289    /// Internally, clobbers are modeled as defs (of throwaway vregs) at
1290    /// the instruction's late-point constrained to the named register.
1291    fn inst_clobbers(&self, insn: Inst) -> PRegSet;
1292
1293    /// Get the number of `VReg` in use in this function.
1294    fn num_vregs(&self) -> usize;
1295
1296    /// Get the VRegs for which we should generate value-location
1297    /// metadata for debugging purposes. This can be used to generate
1298    /// e.g. DWARF with valid prgram-point ranges for each value
1299    /// expression in a way that is more efficient than a post-hoc
1300    /// analysis of the allocator's output.
1301    ///
1302    /// Each tuple is (vreg, inclusive_start, exclusive_end,
1303    /// label). In the `Output` there will be (label, inclusive_start,
1304    /// exclusive_end, alloc)` tuples. The ranges may not exactly
1305    /// match -- specifically, the returned metadata may cover only a
1306    /// subset of the requested ranges -- if the value is not live for
1307    /// the entire requested ranges.
1308    ///
1309    /// The instruction indices imply a program point just *before*
1310    /// the instruction.
1311    ///
1312    /// Precondition: we require this slice to be sorted by vreg.
1313    fn debug_value_labels(&self) -> &[(VReg, Inst, Inst, u32)] {
1314        &[]
1315    }
1316
1317    // --------------
1318    // Spills/reloads
1319    // --------------
1320
1321    /// How many logical spill slots does the given regclass require?  E.g., on
1322    /// a 64-bit machine, spill slots may nominally be 64-bit words, but a
1323    /// 128-bit vector value will require two slots.  The regalloc will always
1324    /// align on this size.
1325    ///
1326    /// (This trait method's design and doc text derives from
1327    /// regalloc.rs' trait of the same name.)
1328    fn spillslot_size(&self, regclass: RegClass) -> usize;
1329
1330    /// When providing a spillslot number for a multi-slot spillslot,
1331    /// do we provide the first or the last? This is usually related
1332    /// to which direction the stack grows and different clients may
1333    /// have different preferences.
1334    fn multi_spillslot_named_by_last_slot(&self) -> bool {
1335        false
1336    }
1337
1338    // -----------
1339    // Misc config
1340    // -----------
1341
1342    /// Allow a single instruction to define a vreg multiple times. If
1343    /// allowed, the semantics are as if the definition occurs only
1344    /// once, and all defs will get the same alloc. This flexibility is
1345    /// meant to allow the embedder to more easily aggregate operands
1346    /// together in macro/pseudoinstructions, or e.g. add additional
1347    /// clobbered vregs without taking care to deduplicate. This may be
1348    /// particularly useful when referring to physical registers via
1349    /// pinned vregs. It is optional functionality because a strict mode
1350    /// (at most one def per vreg) is also useful for finding bugs in
1351    /// other applications.
1352    fn allow_multiple_vreg_defs(&self) -> bool {
1353        false
1354    }
1355}
1356
1357/// A position before or after an instruction at which we can make an
1358/// edit.
1359///
1360/// Note that this differs from `OperandPos` in that the former
1361/// describes specifically a constraint on an operand, while this
1362/// describes a program point. `OperandPos` could grow more options in
1363/// the future, for example if we decide that an "early write" or
1364/// "late read" phase makes sense, while `InstPosition` will always
1365/// describe these two insertion points.
1366#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1367#[repr(u8)]
1368#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1369pub enum InstPosition {
1370    Before = 0,
1371    After = 1,
1372}
1373
1374/// A program point: a single point before or after a given instruction.
1375#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1376#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1377pub struct ProgPoint {
1378    bits: u32,
1379}
1380
1381impl core::fmt::Debug for ProgPoint {
1382    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1383        write!(
1384            f,
1385            "progpoint{}{}",
1386            self.inst().index(),
1387            match self.pos() {
1388                InstPosition::Before => "-pre",
1389                InstPosition::After => "-post",
1390            }
1391        )
1392    }
1393}
1394
1395impl ProgPoint {
1396    /// Create a new ProgPoint before or after the given instruction.
1397    #[inline(always)]
1398    pub fn new(inst: Inst, pos: InstPosition) -> Self {
1399        let bits = ((inst.0 as u32) << 1) | (pos as u8 as u32);
1400        Self { bits }
1401    }
1402
1403    /// Create a new ProgPoint before the given instruction.
1404    #[inline(always)]
1405    pub fn before(inst: Inst) -> Self {
1406        Self::new(inst, InstPosition::Before)
1407    }
1408
1409    /// Create a new ProgPoint after the given instruction.
1410    #[inline(always)]
1411    pub fn after(inst: Inst) -> Self {
1412        Self::new(inst, InstPosition::After)
1413    }
1414
1415    /// Get the instruction that this ProgPoint is before or after.
1416    #[inline(always)]
1417    pub fn inst(self) -> Inst {
1418        // Cast to i32 to do an arithmetic right-shift, which will
1419        // preserve an `Inst::invalid()` (which is -1, or all-ones).
1420        Inst::new(((self.bits as i32) >> 1) as usize)
1421    }
1422
1423    /// Get the "position" (Before or After) relative to the
1424    /// instruction.
1425    #[inline(always)]
1426    pub fn pos(self) -> InstPosition {
1427        match self.bits & 1 {
1428            0 => InstPosition::Before,
1429            1 => InstPosition::After,
1430            _ => unreachable!(),
1431        }
1432    }
1433
1434    /// Get the "next" program point: for After, this is the Before of
1435    /// the next instruction, while for Before, this is After of the
1436    /// same instruction.
1437    #[inline(always)]
1438    pub fn next(self) -> ProgPoint {
1439        Self {
1440            bits: self.bits + 1,
1441        }
1442    }
1443
1444    /// Get the "previous" program point, the inverse of `.next()`
1445    /// above.
1446    #[inline(always)]
1447    pub fn prev(self) -> ProgPoint {
1448        Self {
1449            bits: self.bits - 1,
1450        }
1451    }
1452
1453    /// Convert to a raw encoding in 32 bits.
1454    #[inline(always)]
1455    pub fn to_index(self) -> u32 {
1456        self.bits
1457    }
1458
1459    /// Construct from the raw 32-bit encoding.
1460    #[inline(always)]
1461    pub fn from_index(index: u32) -> Self {
1462        Self { bits: index }
1463    }
1464
1465    #[inline(always)]
1466    pub fn invalid() -> Self {
1467        Self::before(Inst::new(usize::MAX))
1468    }
1469}
1470
1471/// An instruction to insert into the program to perform some data movement.
1472#[derive(Clone, Debug)]
1473#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1474pub enum Edit {
1475    /// Move one allocation to another. Each allocation may be a
1476    /// register or a stack slot (spillslot). However, stack-to-stack
1477    /// moves will never be generated.
1478    ///
1479    /// `Move` edits will be generated even if src and dst allocation
1480    /// are the same if the vreg changes; this allows proper metadata
1481    /// tracking even when moves are elided.
1482    Move { from: Allocation, to: Allocation },
1483}
1484
1485/// Wrapper around either an original instruction or an inserted edit.
1486#[derive(Clone, Debug)]
1487pub enum InstOrEdit<'a> {
1488    Inst(Inst),
1489    Edit(&'a Edit),
1490}
1491
1492/// Iterator over the instructions and edits in a block.
1493pub struct OutputIter<'a> {
1494    /// List of edits starting at the first for the current block.
1495    edits: &'a [(ProgPoint, Edit)],
1496
1497    /// Remaining instructions in the current block.
1498    inst_range: InstRange,
1499}
1500
1501impl<'a> Iterator for OutputIter<'a> {
1502    type Item = InstOrEdit<'a>;
1503
1504    fn next(&mut self) -> Option<InstOrEdit<'a>> {
1505        // There can't be any edits after the last instruction in a block, so
1506        // we don't need to worry about that case.
1507        if self.inst_range.len() == 0 {
1508            return None;
1509        }
1510
1511        // Return any edits that happen before the next instruction first.
1512        let next_inst = self.inst_range.first();
1513        if let Some((edit, remaining_edits)) = self.edits.split_first() {
1514            if edit.0 <= ProgPoint::before(next_inst) {
1515                self.edits = remaining_edits;
1516                return Some(InstOrEdit::Edit(&edit.1));
1517            }
1518        }
1519
1520        self.inst_range = self.inst_range.rest();
1521        Some(InstOrEdit::Inst(next_inst))
1522    }
1523}
1524
1525/// A machine environment tells the register allocator which registers
1526/// are available to allocate and what register may be used as a
1527/// scratch register for each class, and some other miscellaneous info
1528/// as well.
1529#[derive(Clone, Debug)]
1530#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1531pub struct MachineEnv {
1532    /// Preferred physical registers for each class. These are the
1533    /// registers that will be allocated first, if free.
1534    ///
1535    /// If an explicit scratch register is provided in `scratch_by_class` then
1536    /// it must not appear in this list.
1537    pub preferred_regs_by_class: [PRegSet; 3],
1538
1539    /// Non-preferred physical registers for each class. These are the
1540    /// registers that will be allocated if a preferred register is
1541    /// not available; using one of these is considered suboptimal,
1542    /// but still better than spilling.
1543    ///
1544    /// If an explicit scratch register is provided in `scratch_by_class` then
1545    /// it must not appear in this list.
1546    pub non_preferred_regs_by_class: [PRegSet; 3],
1547
1548    /// Optional dedicated scratch register per class. This is needed to perform
1549    /// moves between registers when cyclic move patterns occur. The
1550    /// register should not be placed in either the preferred or
1551    /// non-preferred list (i.e., it is not otherwise allocatable).
1552    ///
1553    /// Note that the register allocator will freely use this register
1554    /// between instructions, but *within* the machine code generated
1555    /// by a single (regalloc-level) instruction, the client is free
1556    /// to use the scratch register. E.g., if one "instruction" causes
1557    /// the emission of two machine-code instructions, this lowering
1558    /// can use the scratch register between them.
1559    ///
1560    /// If a scratch register is not provided then the register allocator will
1561    /// automatically allocate one as needed, spilling a value to the stack if
1562    /// necessary.
1563    pub scratch_by_class: [Option<PReg>; 3],
1564
1565    /// Some `PReg`s can be designated as locations on the stack rather than
1566    /// actual registers. These can be used to tell the register allocator about
1567    /// pre-defined stack slots used for function arguments and return values.
1568    ///
1569    /// `PReg`s in this list cannot be used as an allocatable or scratch
1570    /// register.
1571    pub fixed_stack_slots: Vec<PReg>,
1572}
1573
1574/// The output of the register allocator.
1575#[derive(Clone, Debug, Default)]
1576#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1577pub struct Output {
1578    /// How many spillslots are needed in the frame?
1579    pub num_spillslots: usize,
1580
1581    /// Edits (insertions or removals). Guaranteed to be sorted by
1582    /// program point.
1583    pub edits: Vec<(ProgPoint, Edit)>,
1584
1585    /// Allocations for each operand. Mapping from instruction to
1586    /// allocations provided by `inst_alloc_offsets` below.
1587    pub allocs: Vec<Allocation>,
1588
1589    /// Allocation offset in `allocs` for each instruction.
1590    pub inst_alloc_offsets: Vec<u32>,
1591
1592    /// Debug info: a labeled value (as applied to vregs by
1593    /// `Function::debug_value_labels()` on the input side) is located
1594    /// in the given allocation from the first program point
1595    /// (inclusive) to the second (exclusive). Guaranteed to be sorted
1596    /// by label and program point, and the ranges are guaranteed to
1597    /// be disjoint.
1598    pub debug_locations: Vec<(u32, ProgPoint, ProgPoint, Allocation)>,
1599
1600    /// Internal stats from the allocator.
1601    pub stats: ion::Stats,
1602}
1603
1604impl Output {
1605    /// Get the allocations assigned to a given instruction.
1606    pub fn inst_allocs(&self, inst: Inst) -> &[Allocation] {
1607        let start = self.inst_alloc_offsets[inst.index()] as usize;
1608        let end = if inst.index() + 1 == self.inst_alloc_offsets.len() {
1609            self.allocs.len()
1610        } else {
1611            self.inst_alloc_offsets[inst.index() + 1] as usize
1612        };
1613        &self.allocs[start..end]
1614    }
1615
1616    /// Returns an iterator over the instructions and edits in a block, in
1617    /// order.
1618    pub fn block_insts_and_edits(&self, func: &impl Function, block: Block) -> OutputIter<'_> {
1619        let inst_range = func.block_insns(block);
1620
1621        let edit_idx = self
1622            .edits
1623            .binary_search_by(|&(pos, _)| {
1624                // This predicate effectively searches for a point *just* before
1625                // the first ProgPoint. This never returns Ordering::Equal, but
1626                // binary_search_by returns the index of where it would have
1627                // been inserted in Err.
1628                if pos < ProgPoint::before(inst_range.first()) {
1629                    core::cmp::Ordering::Less
1630                } else {
1631                    core::cmp::Ordering::Greater
1632                }
1633            })
1634            .unwrap_err();
1635
1636        let edits = &self.edits[edit_idx..];
1637        OutputIter { inst_range, edits }
1638    }
1639}
1640
1641/// An error that prevents allocation.
1642#[derive(Clone, Debug)]
1643#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
1644pub enum RegAllocError {
1645    /// Critical edge is not split between given blocks.
1646    CritEdge(Block, Block),
1647    /// Invalid SSA for given vreg at given inst: multiple defs or
1648    /// illegal use. `inst` may be `Inst::invalid()` if this concerns
1649    /// a block param.
1650    SSA(VReg, Inst),
1651    /// Invalid basic block: does not end in branch/ret, or contains a
1652    /// branch/ret in the middle, or the VReg ids do not start at zero
1653    /// or aren't numbered sequentially.
1654    BB(Block),
1655    /// Invalid branch: operand count does not match sum of block
1656    /// params of successor blocks, or the block ids do not start at
1657    /// zero or aren't numbered sequentially.
1658    Branch(Inst),
1659    /// A VReg is live-in on entry; this is not allowed.
1660    EntryLivein,
1661    /// A branch has non-blockparam arg(s) and at least one of the
1662    /// successor blocks has more than one predecessor, forcing
1663    /// edge-moves before this branch. This is disallowed because it
1664    /// places a use after the edge moves occur; insert an edge block
1665    /// to avoid the situation.
1666    DisallowedBranchArg(Inst),
1667    /// Too many pinned VRegs + Reg-constrained Operands are live at
1668    /// once, making allocation impossible.
1669    TooManyLiveRegs,
1670    /// Too many operands on a single instruction (beyond limit of
1671    /// 2^16 - 1).
1672    TooManyOperands,
1673}
1674
1675impl core::fmt::Display for RegAllocError {
1676    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
1677        write!(f, "{:?}", self)
1678    }
1679}
1680
1681impl core::error::Error for RegAllocError {}
1682
1683/// Run the allocator.
1684pub fn run<F: Function>(
1685    func: &F,
1686    env: &MachineEnv,
1687    options: &RegallocOptions,
1688) -> Result<Output, RegAllocError> {
1689    match options.algorithm {
1690        Algorithm::Ion => {
1691            let mut ctx = Ctx::default();
1692            run_with_ctx(func, env, options, &mut ctx)?;
1693            Ok(ctx.output)
1694        }
1695        Algorithm::Fastalloc => {
1696            fastalloc::run(func, env, options.verbose_log, options.validate_ssa)
1697        }
1698    }
1699}
1700
1701/// Run the allocator with reusable context.
1702///
1703/// Return value points to `ctx.output` that can be alternatively `std::mem::take`n.
1704pub fn run_with_ctx<'a, F: Function>(
1705    func: &F,
1706    env: &MachineEnv,
1707    options: &RegallocOptions,
1708    ctx: &'a mut Ctx,
1709) -> Result<&'a Output, RegAllocError> {
1710    match options.algorithm {
1711        Algorithm::Ion => ion::run(func, env, ctx, options.verbose_log, options.validate_ssa)?,
1712        Algorithm::Fastalloc => {
1713            ctx.output = fastalloc::run(func, env, options.verbose_log, options.validate_ssa)?
1714        }
1715    }
1716    Ok(&ctx.output)
1717}
1718
1719#[derive(Clone, Copy, Debug, Default)]
1720pub enum Algorithm {
1721    #[default]
1722    Ion,
1723    Fastalloc,
1724}
1725
1726/// Options for allocation.
1727#[derive(Clone, Copy, Debug, Default)]
1728pub struct RegallocOptions {
1729    /// Add extra verbosity to debug logs.
1730    pub verbose_log: bool,
1731
1732    /// Run the SSA validator before allocating registers.
1733    pub validate_ssa: bool,
1734
1735    /// The register allocation algorithm to be used.
1736    pub algorithm: Algorithm,
1737}
1738
1739pub(crate) trait VecExt<T> {
1740    /// Fills `self` with `value` up to `len` and return the mutable slice to the values.
1741    fn repopulate(&mut self, len: usize, value: T) -> &mut [T]
1742    where
1743        T: Clone;
1744    /// Clears the `self` and returns a mutable reference to it.
1745    fn cleared(&mut self) -> &mut Self;
1746    /// Makes sure `self` is empty and has at least `cap` capacity.
1747    fn preallocate(&mut self, cap: usize) -> &mut Self;
1748}
1749
1750impl<T> VecExt<T> for Vec<T> {
1751    fn repopulate(&mut self, len: usize, value: T) -> &mut [T]
1752    where
1753        T: Clone,
1754    {
1755        self.clear();
1756        self.resize(len, value);
1757        self
1758    }
1759
1760    fn cleared(&mut self) -> &mut Self {
1761        self.clear();
1762        self
1763    }
1764
1765    fn preallocate(&mut self, cap: usize) -> &mut Self {
1766        self.clear();
1767        self.reserve(cap);
1768        self
1769    }
1770}
1771
1772#[derive(Debug, Clone, Default)]
1773pub(crate) struct Bump(Rc<bumpalo::Bump>);
1774
1775impl Bump {
1776    pub(crate) fn get_mut(&mut self) -> Option<&mut bumpalo::Bump> {
1777        Rc::get_mut(&mut self.0)
1778    }
1779}
1780
1781// Simply delegating because `Rc<bumpalo::Bump>` does not implement `Allocator`.
1782unsafe impl allocator_api2::alloc::Allocator for Bump {
1783    fn allocate(
1784        &self,
1785        layout: core::alloc::Layout,
1786    ) -> Result<core::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
1787        self.0.deref().allocate(layout)
1788    }
1789
1790    unsafe fn deallocate(&self, ptr: core::ptr::NonNull<u8>, layout: core::alloc::Layout) {
1791        self.0.deref().deallocate(ptr, layout);
1792    }
1793
1794    fn allocate_zeroed(
1795        &self,
1796        layout: core::alloc::Layout,
1797    ) -> Result<core::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
1798        self.0.deref().allocate_zeroed(layout)
1799    }
1800
1801    unsafe fn grow(
1802        &self,
1803        ptr: core::ptr::NonNull<u8>,
1804        old_layout: core::alloc::Layout,
1805        new_layout: core::alloc::Layout,
1806    ) -> Result<core::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
1807        self.0.deref().grow(ptr, old_layout, new_layout)
1808    }
1809
1810    unsafe fn grow_zeroed(
1811        &self,
1812        ptr: core::ptr::NonNull<u8>,
1813        old_layout: core::alloc::Layout,
1814        new_layout: core::alloc::Layout,
1815    ) -> Result<core::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
1816        self.0.deref().grow_zeroed(ptr, old_layout, new_layout)
1817    }
1818
1819    unsafe fn shrink(
1820        &self,
1821        ptr: core::ptr::NonNull<u8>,
1822        old_layout: core::alloc::Layout,
1823        new_layout: core::alloc::Layout,
1824    ) -> Result<core::ptr::NonNull<[u8]>, allocator_api2::alloc::AllocError> {
1825        self.0.deref().shrink(ptr, old_layout, new_layout)
1826    }
1827}
1828
1829#[cfg(test)]
1830mod tests {
1831    use super::{PReg, PRegSet, RegClass::*};
1832
1833    #[test]
1834    fn preg_set_len() {
1835        let mut set = PRegSet::empty();
1836        assert_eq!(set.len(), 0);
1837
1838        set.add(PReg::new(3, Int));
1839        assert_eq!(set.len(), 1);
1840        set.add(PReg::new(3, Int));
1841        assert_eq!(set.len(), 1);
1842
1843        set.add(PReg::new(4, Int));
1844        assert_eq!(set.len(), 2);
1845    }
1846
1847    #[test]
1848    fn preg_set_max_preg() {
1849        let mut set = PRegSet::empty();
1850        assert_eq!(set.max_preg(), None);
1851
1852        set.add(PReg::new(3, Int));
1853        assert_eq!(set.max_preg(), Some(PReg::new(3, Int)));
1854
1855        set.add(PReg::new(4, Int));
1856        assert_eq!(set.max_preg(), Some(PReg::new(4, Int)));
1857
1858        set.add(PReg::new(2, Int));
1859        assert_eq!(set.max_preg(), Some(PReg::new(4, Int)));
1860    }
1861
1862    #[test]
1863    fn preg_set_new_up_to() {
1864        for class in [Int, Float, Vector] {
1865            let p0 = PReg::new(0, class);
1866            let p1 = PReg::new(1, class);
1867            let p2 = PReg::new(2, class);
1868            let p3 = PReg::new(3, class);
1869            {
1870                let mut set = PRegSet::empty();
1871                set.add_up_to(p1);
1872                assert!(set.contains(p0));
1873                assert!(!set.contains(p1));
1874            }
1875            {
1876                let mut set = PRegSet::empty();
1877                set.add_up_to(p0);
1878                assert!(!set.contains(p0));
1879            }
1880            {
1881                let mut set = PRegSet::empty();
1882                set.add_up_to(p3);
1883                assert!(set.contains(p0));
1884                assert!(set.contains(p1));
1885                assert!(set.contains(p2));
1886                assert!(!set.contains(p3));
1887            }
1888            for i in 1..64 {
1889                let mut set = PRegSet::empty();
1890                set.add_up_to(PReg::new(i, class));
1891                assert!(set.contains(p0));
1892                assert!(set.contains(PReg::new(i - 1, class)));
1893                assert!(!set.contains(PReg::new(i, class)));
1894            }
1895        }
1896    }
1897}