1use rucc_mir::{Block, Func, Reg, Role};
34
35use crate::order::{Order, Point};
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub struct Range {
44 pub start: Point,
46 pub end: Point,
48}
49
50impl Range {
51 #[must_use]
53 pub fn covers(self, point: Point) -> bool {
54 self.start <= point && point <= self.end
55 }
56
57 #[must_use]
59 pub fn overlaps(self, other: Self) -> bool {
60 self.start <= other.end && other.start <= self.end
61 }
62
63 fn with(self, point: Point) -> Self {
66 Self { start: self.start.min(point), end: self.end.max(point) }
67 }
68}
69
70#[derive(Debug, Clone)]
72pub struct Live {
73 live_in: Rows,
74 live_out: Rows,
75 ranges: Vec<Option<Range>>,
76}
77
78impl Live {
79 #[must_use]
81 pub fn of(func: &Func, order: &Order) -> Self {
82 let vregs = func.vregs();
83 let (used, defined) = exposed(func, order);
84 let (live_in, live_out) = flow(func, order, &used, &defined);
85 let ranges = measure(func, order, &live_in, &live_out, vregs);
86 Self { live_in, live_out, ranges }
87 }
88
89 #[must_use]
92 pub fn range(&self, reg: Reg) -> Option<Range> {
93 self.ranges.get(usize::try_from(reg.number()?).ok()?).copied().flatten()
94 }
95
96 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
101 self.live_in.iter(block.index())
102 }
103
104 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
107 self.live_out.iter(block.index())
108 }
109}
110
111fn measure(
113 func: &Func,
114 order: &Order,
115 live_in: &Rows,
116 live_out: &Rows,
117 vregs: usize,
118) -> Vec<Option<Range>> {
119 let mut ranges: Vec<Option<Range>> = vec![None; vregs];
120 let mut extend = |reg: Reg, point: Point| {
121 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
122 return;
123 };
124 let Some(slot) = ranges.get_mut(number) else { return };
125 *slot = Some(match *slot {
126 Some(range) => range.with(point),
127 None => Range { start: point, end: point },
128 });
129 };
130
131 for &block in order.blocks() {
132 for reg in live_in.iter(block.index()) {
135 extend(reg, order.start(block));
136 }
137 for reg in live_out.iter(block.index()) {
138 extend(reg, order.end(block));
139 }
140 for param in &func[block].params {
141 extend(param.reg, order.start(block));
142 }
143 for inst in func.insts(block) {
144 for operand in &func[func[inst].operands] {
145 let point = match operand.role {
146 Role::Use | Role::EarlyDef => order.early(inst),
147 Role::Def => order.late(inst),
148 };
149 extend(operand.reg, point);
150 }
151 }
152 for call in &func[block].succs {
153 for &arg in &call.args {
154 extend(arg, order.end(block));
155 }
156 }
157 }
158 ranges
159}
160
161fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
166 let mut used = Rows::new(func.block_count(), func.vregs());
167 let mut defined = Rows::new(func.block_count(), func.vregs());
168 for &block in order.blocks() {
169 let row = block.index();
170 for call in &func[block].succs {
171 for &arg in &call.args {
172 used.insert(row, arg);
173 }
174 }
175 let insts: Vec<_> = func.insts(block).collect();
176 for &inst in insts.iter().rev() {
177 let operands = &func[func[inst].operands];
178 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
179 used.remove(row, operand.reg);
180 defined.insert(row, operand.reg);
181 }
182 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
183 used.insert(row, operand.reg);
184 }
185 }
186 for param in &func[block].params {
187 used.remove(row, param.reg);
188 defined.insert(row, param.reg);
189 }
190 }
191 (used, defined)
192}
193
194fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
196 let mut live_in = Rows::new(func.block_count(), func.vregs());
197 let mut live_out = Rows::new(func.block_count(), func.vregs());
198 let width = live_in.width;
199 let mut next = vec![0u64; width];
200 let mut changed = true;
201 while changed {
202 changed = false;
203 for &block in order.blocks().iter().rev() {
204 let row = block.index();
205 for call in &func[block].succs {
206 let successor = call.block.index();
207 for (word, &incoming) in
208 live_out.row_mut(row).iter_mut().zip(live_in.row(successor))
209 {
210 *word |= incoming;
211 }
212 }
213 for (index, word) in next.iter_mut().enumerate() {
214 *word =
215 used.row(row)[index] | (live_out.row(row)[index] & !defined.row(row)[index]);
216 }
217 if live_in.row(row) != next.as_slice() {
218 live_in.row_mut(row).copy_from_slice(&next);
219 changed = true;
220 }
221 }
222 }
223 (live_in, live_out)
224}
225
226#[derive(Debug, Clone)]
228struct Rows {
229 words: Vec<u64>,
230 width: usize,
233}
234
235impl Rows {
236 fn new(rows: usize, columns: usize) -> Self {
237 let width = columns.div_ceil(64).max(1);
238 Self { words: vec![0; rows * width], width }
239 }
240
241 fn row(&self, row: usize) -> &[u64] {
242 &self.words[row * self.width..(row + 1) * self.width]
243 }
244
245 fn row_mut(&mut self, row: usize) -> &mut [u64] {
246 &mut self.words[row * self.width..(row + 1) * self.width]
247 }
248
249 fn column(&self, reg: Reg) -> Option<usize> {
251 let number = usize::try_from(reg.number()?).ok()?;
252 (number < self.width * 64).then_some(number)
253 }
254
255 fn insert(&mut self, row: usize, reg: Reg) {
256 if let Some(column) = self.column(reg) {
257 self.row_mut(row)[column / 64] |= 1 << (column % 64);
258 }
259 }
260
261 fn remove(&mut self, row: usize, reg: Reg) {
262 if let Some(column) = self.column(reg) {
263 self.row_mut(row)[column / 64] &= !(1 << (column % 64));
264 }
265 }
266
267 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
268 self.row(row).iter().enumerate().flat_map(|(word, &bits)| {
269 (0..64).filter(move |bit| bits & (1 << bit) != 0).map(move |bit| {
270 Reg::virtual_reg(u32::try_from(word * 64 + bit).expect("a register number"))
271 })
272 })
273 }
274}
275
276#[cfg(test)]
277mod tests {
278 use rucc_base::Interner;
279 use rucc_mir::{BlockCall, Opcode, Operand};
280 use rucc_target::x86_64::GPR;
281
282 use super::*;
283
284 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
286 of.filter_map(Reg::number).collect()
287 }
288
289 #[test]
290 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
291 let mut names = Interner::new();
292 let mut func = Func::new(names.intern("f"));
293 let opcode = Opcode::new(names.intern("x64.nop"));
294 let block = func.create_block();
295 let value = func.new_vreg(GPR);
296 let other = func.new_vreg(GPR);
297 let write = func.build(block, opcode).def(value, GPR).finish();
298 let idle = func.build(block, opcode).def(other, GPR).finish();
299 let read = func.build(block, opcode).uses(value, GPR).finish();
300
301 let order = Order::of(&func);
302 let live = Live::of(&func, &order);
303 let range = live.range(value).expect("the value is live somewhere");
304 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
305 assert!(range.covers(order.early(idle)));
306 assert_eq!(
309 live.range(other),
310 Some(Range { start: order.late(idle), end: order.late(idle) })
311 );
312 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
313 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
314 }
315
316 #[test]
317 fn a_value_read_in_another_block_is_live_between_them() {
318 let mut names = Interner::new();
319 let mut func = Func::new(names.intern("f"));
320 let opcode = Opcode::new(names.intern("x64.nop"));
321 let head = func.create_block();
322 let middle = func.create_block();
323 let tail = func.create_block();
324 let value = func.new_vreg(GPR);
325 func.build(head, opcode).def(value, GPR).finish();
326 *func.succs_mut(head) = vec![BlockCall::to(middle)];
327 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
328 let read = func.build(tail, opcode).uses(value, GPR).finish();
329
330 let order = Order::of(&func);
331 let live = Live::of(&func, &order);
332 assert_eq!(regs(live.live_in(middle)), vec![0]);
335 assert_eq!(regs(live.live_out(middle)), vec![0]);
336 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
337 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
338 }
339
340 #[test]
341 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
342 let mut names = Interner::new();
343 let mut func = Func::new(names.intern("f"));
344 let opcode = Opcode::new(names.intern("x64.nop"));
345 let header = func.create_block();
346 let body = func.create_block();
347 let carried = func.append_param(header, GPR);
348 let next = func.new_vreg(GPR);
349 *func.succs_mut(header) = vec![BlockCall::to(body)];
350 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
351 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
352
353 let order = Order::of(&func);
354 let live = Live::of(&func, &order);
355 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
358 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
359 let range = live.range(next).expect("live somewhere");
360 assert_eq!(range.end, order.end(body));
361 }
362
363 #[test]
364 fn two_values_that_are_never_both_wanted_do_not_overlap() {
365 let mut names = Interner::new();
366 let mut func = Func::new(names.intern("f"));
367 let opcode = Opcode::new(names.intern("x64.nop"));
368 let block = func.create_block();
369 let first = func.new_vreg(GPR);
370 let second = func.new_vreg(GPR);
371 let write = func.build(block, opcode).def(first, GPR).finish();
372 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
373
374 let order = Order::of(&func);
375 let live = Live::of(&func, &order);
376 let first = live.range(first).expect("live somewhere");
377 let second = live.range(second).expect("live somewhere");
378 assert!(!first.overlaps(second));
382 assert!(first.start > order.start(block));
383 assert_eq!(first.start, order.late(write));
384 }
385
386 #[test]
387 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
388 let mut names = Interner::new();
389 let mut func = Func::new(names.intern("f"));
390 let opcode = Opcode::new(names.intern("x64.nop"));
391 let block = func.create_block();
392 let source = func.new_vreg(GPR);
393 let early = func.new_vreg(GPR);
394 func.build(block, opcode).def(source, GPR).finish();
395 func.build(block, opcode)
396 .operand(Operand::write_early(early, GPR))
397 .operand(Operand::read(source, GPR))
398 .finish();
399
400 let order = Order::of(&func);
401 let live = Live::of(&func, &order);
402 let source = live.range(source).expect("live somewhere");
403 let early = live.range(early).expect("live somewhere");
404 assert!(source.overlaps(early));
407 }
408
409 #[test]
410 fn a_register_a_memory_operand_names_is_read_like_any_other() {
411 use rucc_mir::Mem;
412
413 let mut names = Interner::new();
414 let mut func = Func::new(names.intern("f"));
415 let opcode = Opcode::new(names.intern("x64.nop"));
416 let block = func.create_block();
417 let address = func.new_vreg(GPR);
418 let write = func.build(block, opcode).def(address, GPR).finish();
419 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
420
421 let order = Order::of(&func);
422 let live = Live::of(&func, &order);
423 assert_eq!(
424 live.range(address),
425 Some(Range { start: order.late(write), end: order.early(load) })
426 );
427 }
428}