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