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