1use crate::ssa::validate_ssa;
17use crate::{Function, MachineEnv, PReg, RegAllocError, RegClass, VecExt};
18pub(crate) mod data_structures;
19pub use data_structures::Ctx;
20pub use data_structures::Stats;
21use data_structures::*;
22pub(crate) mod reg_traversal;
23use reg_traversal::*;
24pub(crate) mod requirement;
25use requirement::*;
26pub(crate) mod redundant_moves;
27use redundant_moves::*;
28pub(crate) mod liveranges;
29use liveranges::*;
30pub(crate) mod merge;
31pub(crate) mod process;
32use process::*;
33use smallvec::smallvec;
34pub(crate) mod dump;
35pub(crate) mod moves;
36pub(crate) mod spill;
37
38impl<'a, F: Function> Env<'a, F> {
39 pub(crate) fn new(func: &'a F, env: &'a MachineEnv, ctx: &'a mut Ctx) -> Self {
40 let ninstrs = func.num_insts();
41 let nblocks = func.num_blocks();
42
43 ctx.liveins.preallocate(nblocks);
44 ctx.liveouts.preallocate(nblocks);
45 ctx.blockparam_ins.clear();
46 ctx.blockparam_outs.clear();
47 ctx.ranges.preallocate(4 * ninstrs);
48 ctx.bundles.preallocate(ninstrs);
49 ctx.spillsets.preallocate(ninstrs);
50 ctx.vregs.preallocate(ninstrs);
51 for preg in ctx.pregs.iter_mut() {
52 preg.is_stack = false;
53 preg.allocations.btree.clear();
54 }
55 ctx.allocation_queue.heap.clear();
56 ctx.spilled_bundles.clear();
57 ctx.scratch_spillset_pool
58 .extend(ctx.spillslots.drain(..).map(|mut s| {
59 s.ranges.btree.clear();
60 s.ranges
61 }));
62 ctx.slots_by_class = core::array::from_fn(|_| SpillSlotList::default());
63 ctx.extra_spillslots_by_class = core::array::from_fn(|_| smallvec![]);
64 ctx.preferred_victim_by_class = [PReg::invalid(); 3];
65 ctx.multi_fixed_reg_fixups.clear();
66 ctx.allocated_bundle_count = 0;
67 ctx.debug_annotations.clear();
68 ctx.scratch_bump
69 .get_mut()
70 .expect("we dropped all refs to this")
71 .reset();
72
73 ctx.output.allocs.preallocate(4 * ninstrs);
74 ctx.output.inst_alloc_offsets.clear();
75 ctx.output.num_spillslots = 0;
76 ctx.output.debug_locations.clear();
77 ctx.output.edits.clear();
78 ctx.output.stats = Stats::default();
79
80 Self { func, env, ctx }
81 }
82
83 pub(crate) fn init(&mut self) -> Result<(), RegAllocError> {
84 self.create_pregs_and_vregs();
85 self.compute_liveness()?;
86 self.build_liveranges()?;
87 self.fixup_multi_fixed_vregs();
88 self.merge_vreg_bundles();
89 self.queue_bundles();
90 if trace_enabled!() {
91 self.dump_state();
92 }
93 Ok(())
94 }
95
96 pub(crate) fn run(&mut self) -> Result<Edits, RegAllocError> {
97 self.process_bundles()?;
98 self.try_allocating_regs_for_spilled_bundles();
99 self.allocate_spillslots();
100 if trace_enabled!() {
101 self.dump_state();
102 }
103 let moves = self.apply_allocations_and_insert_moves();
104 Ok(self.resolve_inserted_moves(moves))
105 }
106}
107
108pub fn run<F: Function>(
109 func: &F,
110 mach_env: &MachineEnv,
111 ctx: &mut Ctx,
112 enable_annotations: bool,
113 enable_ssa_checker: bool,
114) -> Result<(), RegAllocError> {
115 ctx.cfginfo.init(func, &mut ctx.cfginfo_ctx)?;
116
117 if enable_ssa_checker {
118 validate_ssa(func, &ctx.cfginfo)?;
119 }
120
121 ctx.annotations_enabled = enable_annotations;
122 let mut env = Env::new(func, mach_env, ctx);
123 env.init()?;
124
125 let mut edits = env.run()?;
126
127 if enable_annotations {
128 env.dump_results();
129 }
130
131 ctx.output.edits.extend(edits.drain_edits());
132
133 Ok(())
134}