/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::<_> |