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