Coverage Report

Created: 2026-10-12 08:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/regalloc2/src/ion/mod.rs
Line
Count
Source
1
/*
2
 * This file was initially derived from the files
3
 * `js/src/jit/BacktrackingAllocator.h` and
4
 * `js/src/jit/BacktrackingAllocator.cpp` in Mozilla Firefox, and was
5
 * originally licensed under the Mozilla Public License 2.0. We
6
 * subsequently relicensed it to Apache-2.0 WITH LLVM-exception (see
7
 * https://github.com/bytecodealliance/regalloc2/issues/7).
8
 *
9
 * Since the initial port, the design has been substantially evolved
10
 * and optimized.
11
 */
12
13
//! Backtracking register allocator. See doc/DESIGN.md for details of
14
//! its design.
15
16
use crate::ssa::validate_ssa;
17
use crate::{Function, MachineEnv, PReg, RegAllocError, RegClass, VecExt};
18
pub(crate) mod data_structures;
19
pub use data_structures::Ctx;
20
pub use data_structures::Stats;
21
use data_structures::*;
22
pub(crate) mod reg_traversal;
23
use reg_traversal::*;
24
pub(crate) mod requirement;
25
use requirement::*;
26
pub(crate) mod redundant_moves;
27
use redundant_moves::*;
28
pub(crate) mod liveranges;
29
use liveranges::*;
30
pub(crate) mod merge;
31
pub(crate) mod process;
32
use process::*;
33
use smallvec::smallvec;
34
pub(crate) mod dump;
35
pub(crate) mod moves;
36
pub(crate) mod spill;
37
38
impl<'a, F: Function> Env<'a, F> {
39
10.3k
    pub(crate) fn new(func: &'a F, env: &'a MachineEnv, ctx: &'a mut Ctx) -> Self {
40
10.3k
        let ninstrs = func.num_insts();
41
10.3k
        let nblocks = func.num_blocks();
42
43
10.3k
        ctx.liveins.preallocate(nblocks);
44
10.3k
        ctx.liveouts.preallocate(nblocks);
45
10.3k
        ctx.blockparam_ins.clear();
46
10.3k
        ctx.blockparam_outs.clear();
47
10.3k
        ctx.ranges.preallocate(4 * ninstrs);
48
10.3k
        ctx.bundles.preallocate(ninstrs);
49
10.3k
        ctx.spillsets.preallocate(ninstrs);
50
10.3k
        ctx.vregs.preallocate(ninstrs);
51
2.65M
        for preg in ctx.pregs.iter_mut() {
52
2.65M
            preg.is_stack = false;
53
2.65M
            preg.allocations.btree.clear();
54
2.65M
        }
55
10.3k
        ctx.allocation_queue.heap.clear();
56
10.3k
        ctx.spilled_bundles.clear();
57
10.3k
        ctx.scratch_spillset_pool
58
134k
            .extend(ctx.spillslots.drain(..).map(|mut s| {
59
134k
                s.ranges.btree.clear();
60
134k
                s.ranges
61
134k
            }));
62
31.1k
        ctx.slots_by_class = core::array::from_fn(|_| SpillSlotList::default());
63
31.1k
        ctx.extra_spillslots_by_class = core::array::from_fn(|_| smallvec![]);
64
10.3k
        ctx.preferred_victim_by_class = [PReg::invalid(); 3];
65
10.3k
        ctx.multi_fixed_reg_fixups.clear();
66
10.3k
        ctx.allocated_bundle_count = 0;
67
10.3k
        ctx.debug_annotations.clear();
68
10.3k
        ctx.scratch_bump
69
10.3k
            .get_mut()
70
10.3k
            .expect("we dropped all refs to this")
71
10.3k
            .reset();
72
73
10.3k
        ctx.output.allocs.preallocate(4 * ninstrs);
74
10.3k
        ctx.output.inst_alloc_offsets.clear();
75
10.3k
        ctx.output.num_spillslots = 0;
76
10.3k
        ctx.output.debug_locations.clear();
77
10.3k
        ctx.output.edits.clear();
78
10.3k
        ctx.output.stats = Stats::default();
79
80
10.3k
        Self { func, env, ctx }
81
10.3k
    }
82
83
10.3k
    pub(crate) fn init(&mut self) -> Result<(), RegAllocError> {
84
10.3k
        self.create_pregs_and_vregs();
85
10.3k
        self.compute_liveness()?;
86
10.3k
        self.build_liveranges()?;
87
10.3k
        self.fixup_multi_fixed_vregs();
88
10.3k
        self.merge_vreg_bundles();
89
10.3k
        self.queue_bundles();
90
10.3k
        if trace_enabled!() {
91
0
            self.dump_state();
92
10.3k
        }
93
10.3k
        Ok(())
94
10.3k
    }
95
96
10.3k
    pub(crate) fn run(&mut self) -> Result<Edits, RegAllocError> {
97
10.3k
        self.process_bundles()?;
98
8.60k
        self.try_allocating_regs_for_spilled_bundles();
99
8.60k
        self.allocate_spillslots();
100
8.60k
        if trace_enabled!() {
101
0
            self.dump_state();
102
8.60k
        }
103
8.60k
        let moves = self.apply_allocations_and_insert_moves();
104
8.60k
        Ok(self.resolve_inserted_moves(moves))
105
10.3k
    }
106
}
107
108
10.3k
pub fn run<F: Function>(
109
10.3k
    func: &F,
110
10.3k
    mach_env: &MachineEnv,
111
10.3k
    ctx: &mut Ctx,
112
10.3k
    enable_annotations: bool,
113
10.3k
    enable_ssa_checker: bool,
114
10.3k
) -> Result<(), RegAllocError> {
115
10.3k
    ctx.cfginfo.init(func, &mut ctx.cfginfo_ctx)?;
116
117
10.3k
    if enable_ssa_checker {
118
725
        validate_ssa(func, &ctx.cfginfo)?;
119
9.65k
    }
120
121
10.3k
    ctx.annotations_enabled = enable_annotations;
122
10.3k
    let mut env = Env::new(func, mach_env, ctx);
123
10.3k
    env.init()?;
124
125
10.3k
    let mut edits = env.run()?;
126
127
8.60k
    if enable_annotations {
128
751
        env.dump_results();
129
7.84k
    }
130
131
8.60k
    ctx.output.edits.extend(edits.drain_edits());
132
133
8.60k
    Ok(())
134
10.3k
}