Coverage Report

Created: 2025-01-06 07:43

/src/regalloc2/src/ion/mod.rs
Line
Count
Source (jump to first uncovered line)
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
11.1k
    pub(crate) fn new(func: &'a F, env: &'a MachineEnv, ctx: &'a mut Ctx) -> Self {
40
11.1k
        let ninstrs = func.num_insts();
41
11.1k
        let nblocks = func.num_blocks();
42
11.1k
43
11.1k
        ctx.liveins.preallocate(nblocks);
44
11.1k
        ctx.liveouts.preallocate(nblocks);
45
11.1k
        ctx.blockparam_ins.clear();
46
11.1k
        ctx.blockparam_outs.clear();
47
11.1k
        ctx.ranges.preallocate(4 * ninstrs);
48
11.1k
        ctx.bundles.preallocate(ninstrs);
49
11.1k
        ctx.spillsets.preallocate(ninstrs);
50
11.1k
        ctx.vregs.preallocate(ninstrs);
51
2.85M
        for preg in ctx.pregs.iter_mut() {
52
2.85M
            preg.is_stack = false;
53
2.85M
            preg.allocations.btree.clear();
54
2.85M
        }
55
11.1k
        ctx.allocation_queue.heap.clear();
56
11.1k
        ctx.spilled_bundles.clear();
57
11.1k
        ctx.scratch_spillset_pool
58
101k
            .extend(ctx.spillslots.drain(..).map(|mut s| {
59
101k
                s.ranges.btree.clear();
60
101k
                s.ranges
61
101k
            }));
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::new::{closure#0}
Line
Count
Source
58
101k
            .extend(ctx.spillslots.drain(..).map(|mut s| {
59
101k
                s.ranges.btree.clear();
60
101k
                s.ranges
61
101k
            }));
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::new::{closure#0}
62
33.4k
        ctx.slots_by_class = core::array::from_fn(|_| SpillSlotList::default());
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::new::{closure#1}
Line
Count
Source
62
33.4k
        ctx.slots_by_class = core::array::from_fn(|_| SpillSlotList::default());
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::new::{closure#1}
63
33.4k
        ctx.extra_spillslots_by_class = core::array::from_fn(|_| smallvec![]);
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::new::{closure#2}
Line
Count
Source
63
33.4k
        ctx.extra_spillslots_by_class = core::array::from_fn(|_| smallvec![]);
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::new::{closure#2}
64
11.1k
        ctx.preferred_victim_by_class = [PReg::invalid(); 3];
65
11.1k
        ctx.multi_fixed_reg_fixups.clear();
66
11.1k
        ctx.allocated_bundle_count = 0;
67
11.1k
        ctx.debug_annotations.clear();
68
11.1k
        ctx.scratch_bump
69
11.1k
            .get_mut()
70
11.1k
            .expect("we dropped all refs to this")
71
11.1k
            .reset();
72
11.1k
73
11.1k
        ctx.output.allocs.preallocate(4 * ninstrs);
74
11.1k
        ctx.output.inst_alloc_offsets.clear();
75
11.1k
        ctx.output.num_spillslots = 0;
76
11.1k
        ctx.output.debug_locations.clear();
77
11.1k
        ctx.output.edits.clear();
78
11.1k
        ctx.output.stats = Stats::default();
79
11.1k
80
11.1k
        Self { func, env, ctx }
81
11.1k
    }
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::new
Line
Count
Source
39
11.1k
    pub(crate) fn new(func: &'a F, env: &'a MachineEnv, ctx: &'a mut Ctx) -> Self {
40
11.1k
        let ninstrs = func.num_insts();
41
11.1k
        let nblocks = func.num_blocks();
42
11.1k
43
11.1k
        ctx.liveins.preallocate(nblocks);
44
11.1k
        ctx.liveouts.preallocate(nblocks);
45
11.1k
        ctx.blockparam_ins.clear();
46
11.1k
        ctx.blockparam_outs.clear();
47
11.1k
        ctx.ranges.preallocate(4 * ninstrs);
48
11.1k
        ctx.bundles.preallocate(ninstrs);
49
11.1k
        ctx.spillsets.preallocate(ninstrs);
50
11.1k
        ctx.vregs.preallocate(ninstrs);
51
2.85M
        for preg in ctx.pregs.iter_mut() {
52
2.85M
            preg.is_stack = false;
53
2.85M
            preg.allocations.btree.clear();
54
2.85M
        }
55
11.1k
        ctx.allocation_queue.heap.clear();
56
11.1k
        ctx.spilled_bundles.clear();
57
11.1k
        ctx.scratch_spillset_pool
58
11.1k
            .extend(ctx.spillslots.drain(..).map(|mut s| {
59
                s.ranges.btree.clear();
60
                s.ranges
61
11.1k
            }));
62
11.1k
        ctx.slots_by_class = core::array::from_fn(|_| SpillSlotList::default());
63
11.1k
        ctx.extra_spillslots_by_class = core::array::from_fn(|_| smallvec![]);
64
11.1k
        ctx.preferred_victim_by_class = [PReg::invalid(); 3];
65
11.1k
        ctx.multi_fixed_reg_fixups.clear();
66
11.1k
        ctx.allocated_bundle_count = 0;
67
11.1k
        ctx.debug_annotations.clear();
68
11.1k
        ctx.scratch_bump
69
11.1k
            .get_mut()
70
11.1k
            .expect("we dropped all refs to this")
71
11.1k
            .reset();
72
11.1k
73
11.1k
        ctx.output.allocs.preallocate(4 * ninstrs);
74
11.1k
        ctx.output.inst_alloc_offsets.clear();
75
11.1k
        ctx.output.num_spillslots = 0;
76
11.1k
        ctx.output.debug_locations.clear();
77
11.1k
        ctx.output.edits.clear();
78
11.1k
        ctx.output.stats = Stats::default();
79
11.1k
80
11.1k
        Self { func, env, ctx }
81
11.1k
    }
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::new
82
83
11.1k
    pub(crate) fn init(&mut self) -> Result<(), RegAllocError> {
84
11.1k
        self.create_pregs_and_vregs();
85
11.1k
        self.compute_liveness()?;
86
11.1k
        self.build_liveranges();
87
11.1k
        self.fixup_multi_fixed_vregs();
88
11.1k
        self.merge_vreg_bundles();
89
11.1k
        self.queue_bundles();
90
11.1k
        if trace_enabled!() {
91
0
            self.dump_state();
92
11.1k
        }
93
11.1k
        Ok(())
94
11.1k
    }
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::init
Line
Count
Source
83
11.1k
    pub(crate) fn init(&mut self) -> Result<(), RegAllocError> {
84
11.1k
        self.create_pregs_and_vregs();
85
11.1k
        self.compute_liveness()?;
86
11.1k
        self.build_liveranges();
87
11.1k
        self.fixup_multi_fixed_vregs();
88
11.1k
        self.merge_vreg_bundles();
89
11.1k
        self.queue_bundles();
90
11.1k
        if trace_enabled!() {
91
0
            self.dump_state();
92
11.1k
        }
93
11.1k
        Ok(())
94
11.1k
    }
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::init
95
96
11.1k
    pub(crate) fn run(&mut self) -> Result<Edits, RegAllocError> {
97
11.1k
        self.process_bundles()?;
98
11.1k
        self.try_allocating_regs_for_spilled_bundles();
99
11.1k
        self.allocate_spillslots();
100
11.1k
        let moves = self.apply_allocations_and_insert_moves();
101
11.1k
        Ok(self.resolve_inserted_moves(moves))
102
11.1k
    }
<regalloc2::ion::data_structures::Env<regalloc2::fuzzing::func::Func>>::run
Line
Count
Source
96
11.1k
    pub(crate) fn run(&mut self) -> Result<Edits, RegAllocError> {
97
11.1k
        self.process_bundles()?;
98
11.1k
        self.try_allocating_regs_for_spilled_bundles();
99
11.1k
        self.allocate_spillslots();
100
11.1k
        let moves = self.apply_allocations_and_insert_moves();
101
11.1k
        Ok(self.resolve_inserted_moves(moves))
102
11.1k
    }
Unexecuted instantiation: <regalloc2::ion::data_structures::Env<_>>::run
103
}
104
105
11.1k
pub fn run<F: Function>(
106
11.1k
    func: &F,
107
11.1k
    mach_env: &MachineEnv,
108
11.1k
    ctx: &mut Ctx,
109
11.1k
    enable_annotations: bool,
110
11.1k
    enable_ssa_checker: bool,
111
11.1k
) -> Result<(), RegAllocError> {
112
11.1k
    ctx.cfginfo.init(func, &mut ctx.cfginfo_ctx)?;
113
114
11.1k
    if enable_ssa_checker {
115
0
        validate_ssa(func, &ctx.cfginfo)?;
116
11.1k
    }
117
118
11.1k
    ctx.annotations_enabled = enable_annotations;
119
11.1k
    let mut env = Env::new(func, mach_env, ctx);
120
11.1k
    env.init()?;
121
122
11.1k
    let mut edits = env.run()?;
123
124
11.1k
    if enable_annotations {
125
11.1k
        env.dump_results();
126
11.1k
    }
127
128
11.1k
    ctx.output.edits.extend(edits.drain_edits());
129
11.1k
130
11.1k
    Ok(())
131
11.1k
}
regalloc2::ion::run::<regalloc2::fuzzing::func::Func>
Line
Count
Source
105
11.1k
pub fn run<F: Function>(
106
11.1k
    func: &F,
107
11.1k
    mach_env: &MachineEnv,
108
11.1k
    ctx: &mut Ctx,
109
11.1k
    enable_annotations: bool,
110
11.1k
    enable_ssa_checker: bool,
111
11.1k
) -> Result<(), RegAllocError> {
112
11.1k
    ctx.cfginfo.init(func, &mut ctx.cfginfo_ctx)?;
113
114
11.1k
    if enable_ssa_checker {
115
0
        validate_ssa(func, &ctx.cfginfo)?;
116
11.1k
    }
117
118
11.1k
    ctx.annotations_enabled = enable_annotations;
119
11.1k
    let mut env = Env::new(func, mach_env, ctx);
120
11.1k
    env.init()?;
121
122
11.1k
    let mut edits = env.run()?;
123
124
11.1k
    if enable_annotations {
125
11.1k
        env.dump_results();
126
11.1k
    }
127
128
11.1k
    ctx.output.edits.extend(edits.drain_edits());
129
11.1k
130
11.1k
    Ok(())
131
11.1k
}
Unexecuted instantiation: regalloc2::ion::run::<_>