1use rucc_mir::{Block, Func, Reg, Role};
41
42use crate::order::{Order, Point};
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct Range {
53 pub start: Point,
55 pub end: Point,
57}
58
59impl Range {
60 #[must_use]
62 pub fn covers(self, point: Point) -> bool {
63 self.start <= point && point <= self.end
64 }
65
66 #[must_use]
68 pub fn overlaps(self, other: Self) -> bool {
69 self.start <= other.end && other.start <= self.end
70 }
71
72 fn with(self, point: Point) -> Self {
75 Self { start: self.start.min(point), end: self.end.max(point) }
76 }
77}
78
79#[derive(Debug, Clone)]
81pub struct Live {
82 live_in: Rows,
83 live_out: Rows,
84 defined: Rows,
85 ranges: Vec<Option<Range>>,
86}
87
88impl Live {
89 #[must_use]
91 pub fn of(func: &Func, order: &Order) -> Self {
92 let vregs = func.vregs();
93 let (used, defined) = exposed(func, order);
94 let (live_in, live_out) = flow(func, order, &used, &defined);
95 let ranges = measure(func, order, &live_in, &live_out, vregs);
96 Self { live_in, live_out, defined, ranges }
97 }
98
99 #[must_use]
102 pub fn range(&self, reg: Reg) -> Option<Range> {
103 self.ranges.get(usize::try_from(reg.number()?).ok()?).copied().flatten()
104 }
105
106 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
111 self.live_in.iter(block.index())
112 }
113
114 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
117 self.live_out.iter(block.index())
118 }
119
120 #[must_use]
134 pub fn anywhere_in(&self, reg: Reg, block: Block) -> bool {
135 let row = block.index();
136 self.live_in.contains(row, reg)
137 || self.live_out.contains(row, reg)
138 || self.defined.contains(row, reg)
139 }
140}
141
142fn measure(
144 func: &Func,
145 order: &Order,
146 live_in: &Rows,
147 live_out: &Rows,
148 vregs: usize,
149) -> Vec<Option<Range>> {
150 let mut ranges: Vec<Option<Range>> = vec![None; vregs];
151 let mut extend = |reg: Reg, point: Point| {
152 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
153 return;
154 };
155 let Some(slot) = ranges.get_mut(number) else { return };
156 *slot = Some(match *slot {
157 Some(range) => range.with(point),
158 None => Range { start: point, end: point },
159 });
160 };
161
162 for &block in order.blocks() {
163 for reg in live_in.iter(block.index()) {
166 extend(reg, order.start(block));
167 }
168 for reg in live_out.iter(block.index()) {
169 extend(reg, order.end(block));
170 }
171 for param in &func[block].params {
172 extend(param.reg, order.start(block));
173 }
174 for inst in func.insts(block) {
175 for operand in &func[func[inst].operands] {
176 match operand.role {
177 Role::Use => extend(operand.reg, order.early(inst)),
178 Role::Def => extend(operand.reg, order.late(inst)),
179 Role::EarlyDef => {
186 extend(operand.reg, order.early(inst));
187 extend(operand.reg, order.late(inst));
188 }
189 }
190 }
191 }
192 for call in &func[block].succs {
193 for &arg in &call.args {
194 extend(arg, order.end(block));
195 }
196 }
197 }
198 ranges
199}
200
201fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
206 let mut used = Rows::new(func.block_count(), func.vregs());
207 let mut defined = Rows::new(func.block_count(), func.vregs());
208 for &block in order.blocks() {
209 let row = block.index();
210 for call in &func[block].succs {
211 for &arg in &call.args {
212 used.insert(row, arg);
213 }
214 }
215 let insts: Vec<_> = func.insts(block).collect();
216 for &inst in insts.iter().rev() {
217 let operands = &func[func[inst].operands];
218 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
219 used.remove(row, operand.reg);
220 defined.insert(row, operand.reg);
221 }
222 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
223 used.insert(row, operand.reg);
224 }
225 }
226 for param in &func[block].params {
227 used.remove(row, param.reg);
228 defined.insert(row, param.reg);
229 }
230 }
231 (used, defined)
232}
233
234fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
236 let mut live_in = Rows::new(func.block_count(), func.vregs());
237 let mut live_out = Rows::new(func.block_count(), func.vregs());
238 let width = live_in.width;
239 let mut next = vec![0u64; width];
240 let mut changed = true;
241 while changed {
242 changed = false;
243 for &block in order.blocks().iter().rev() {
244 let row = block.index();
245 for call in &func[block].succs {
246 let successor = call.block.index();
247 for (word, &incoming) in
248 live_out.row_mut(row).iter_mut().zip(live_in.row(successor))
249 {
250 *word |= incoming;
251 }
252 }
253 for (index, word) in next.iter_mut().enumerate() {
254 *word =
255 used.row(row)[index] | (live_out.row(row)[index] & !defined.row(row)[index]);
256 }
257 if live_in.row(row) != next.as_slice() {
258 live_in.row_mut(row).copy_from_slice(&next);
259 changed = true;
260 }
261 }
262 }
263 (live_in, live_out)
264}
265
266#[derive(Debug, Clone)]
268struct Rows {
269 words: Vec<u64>,
270 width: usize,
273}
274
275impl Rows {
276 fn new(rows: usize, columns: usize) -> Self {
277 let width = columns.div_ceil(64).max(1);
278 Self { words: vec![0; rows * width], width }
279 }
280
281 fn row(&self, row: usize) -> &[u64] {
282 &self.words[row * self.width..(row + 1) * self.width]
283 }
284
285 fn row_mut(&mut self, row: usize) -> &mut [u64] {
286 &mut self.words[row * self.width..(row + 1) * self.width]
287 }
288
289 fn column(&self, reg: Reg) -> Option<usize> {
291 let number = usize::try_from(reg.number()?).ok()?;
292 (number < self.width * 64).then_some(number)
293 }
294
295 fn insert(&mut self, row: usize, reg: Reg) {
296 if let Some(column) = self.column(reg) {
297 self.row_mut(row)[column / 64] |= 1 << (column % 64);
298 }
299 }
300
301 fn contains(&self, row: usize, reg: Reg) -> bool {
302 self.column(reg)
303 .is_some_and(|column| self.row(row)[column / 64] & (1 << (column % 64)) != 0)
304 }
305
306 fn remove(&mut self, row: usize, reg: Reg) {
307 if let Some(column) = self.column(reg) {
308 self.row_mut(row)[column / 64] &= !(1 << (column % 64));
309 }
310 }
311
312 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
313 self.row(row).iter().enumerate().flat_map(|(word, &bits)| {
314 (0..64).filter(move |bit| bits & (1 << bit) != 0).map(move |bit| {
315 Reg::virtual_reg(u32::try_from(word * 64 + bit).expect("a register number"))
316 })
317 })
318 }
319}
320
321#[cfg(test)]
322mod tests {
323 use rucc_base::Interner;
324 use rucc_mir::{BlockCall, Opcode, Operand};
325 use rucc_target::x86_64::GPR;
326
327 use super::*;
328
329 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
331 of.filter_map(Reg::number).collect()
332 }
333
334 #[test]
335 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
336 let mut names = Interner::new();
337 let mut func = Func::new(names.intern("f"));
338 let opcode = Opcode::new(names.intern("x64.nop"));
339 let block = func.create_block();
340 let value = func.new_vreg(GPR);
341 let other = func.new_vreg(GPR);
342 let write = func.build(block, opcode).def(value, GPR).finish();
343 let idle = func.build(block, opcode).def(other, GPR).finish();
344 let read = func.build(block, opcode).uses(value, GPR).finish();
345
346 let order = Order::of(&func);
347 let live = Live::of(&func, &order);
348 let range = live.range(value).expect("the value is live somewhere");
349 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
350 assert!(range.covers(order.early(idle)));
351 assert_eq!(
354 live.range(other),
355 Some(Range { start: order.late(idle), end: order.late(idle) })
356 );
357 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
358 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
359 }
360
361 #[test]
362 fn a_value_read_in_another_block_is_live_between_them() {
363 let mut names = Interner::new();
364 let mut func = Func::new(names.intern("f"));
365 let opcode = Opcode::new(names.intern("x64.nop"));
366 let head = func.create_block();
367 let middle = func.create_block();
368 let tail = func.create_block();
369 let value = func.new_vreg(GPR);
370 func.build(head, opcode).def(value, GPR).finish();
371 *func.succs_mut(head) = vec![BlockCall::to(middle)];
372 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
373 let read = func.build(tail, opcode).uses(value, GPR).finish();
374
375 let order = Order::of(&func);
376 let live = Live::of(&func, &order);
377 assert_eq!(regs(live.live_in(middle)), vec![0]);
380 assert_eq!(regs(live.live_out(middle)), vec![0]);
381 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
382 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
383 }
384
385 #[test]
386 fn a_range_covers_a_block_the_value_never_reaches_and_being_live_there_does_not() {
387 let mut names = Interner::new();
388 let mut func = Func::new(names.intern("f"));
389 let opcode = Opcode::new(names.intern("x64.nop"));
390 let entry = func.create_block();
391 let arm = func.create_block();
392 let tail = func.create_block();
393 let value = func.new_vreg(GPR);
394 func.build(entry, opcode).def(value, GPR).finish();
395 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
396 let idle = func.build(arm, opcode).finish();
397 func.build(tail, opcode).uses(value, GPR).finish();
398
399 let order = Order::of(&func);
400 let live = Live::of(&func, &order);
401 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
404 assert!(live.anywhere_in(value, entry));
405 assert!(live.anywhere_in(value, tail));
406 assert!(!live.anywhere_in(value, arm));
407 }
408
409 #[test]
410 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
411 let mut names = Interner::new();
412 let mut func = Func::new(names.intern("f"));
413 let opcode = Opcode::new(names.intern("x64.nop"));
414 let header = func.create_block();
415 let body = func.create_block();
416 let carried = func.append_param(header, GPR);
417 let next = func.new_vreg(GPR);
418 *func.succs_mut(header) = vec![BlockCall::to(body)];
419 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
420 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
421
422 let order = Order::of(&func);
423 let live = Live::of(&func, &order);
424 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
427 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
428 let range = live.range(next).expect("live somewhere");
429 assert_eq!(range.end, order.end(body));
430 }
431
432 #[test]
433 fn two_values_that_are_never_both_wanted_do_not_overlap() {
434 let mut names = Interner::new();
435 let mut func = Func::new(names.intern("f"));
436 let opcode = Opcode::new(names.intern("x64.nop"));
437 let block = func.create_block();
438 let first = func.new_vreg(GPR);
439 let second = func.new_vreg(GPR);
440 let write = func.build(block, opcode).def(first, GPR).finish();
441 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
442
443 let order = Order::of(&func);
444 let live = Live::of(&func, &order);
445 let first = live.range(first).expect("live somewhere");
446 let second = live.range(second).expect("live somewhere");
447 assert!(!first.overlaps(second));
451 assert!(first.start > order.start(block));
452 assert_eq!(first.start, order.late(write));
453 }
454
455 #[test]
456 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
457 let mut names = Interner::new();
458 let mut func = Func::new(names.intern("f"));
459 let opcode = Opcode::new(names.intern("x64.nop"));
460 let block = func.create_block();
461 let source = func.new_vreg(GPR);
462 let early = func.new_vreg(GPR);
463 func.build(block, opcode).def(source, GPR).finish();
464 func.build(block, opcode)
465 .operand(Operand::write_early(early, GPR))
466 .operand(Operand::read(source, GPR))
467 .finish();
468
469 let order = Order::of(&func);
470 let live = Live::of(&func, &order);
471 let source = live.range(source).expect("live somewhere");
472 let early = live.range(early).expect("live somewhere");
473 assert!(source.overlaps(early));
476 }
477
478 #[test]
479 fn a_register_a_memory_operand_names_is_read_like_any_other() {
480 use rucc_mir::Mem;
481
482 let mut names = Interner::new();
483 let mut func = Func::new(names.intern("f"));
484 let opcode = Opcode::new(names.intern("x64.nop"));
485 let block = func.create_block();
486 let address = func.new_vreg(GPR);
487 let write = func.build(block, opcode).def(address, GPR).finish();
488 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
489
490 let order = Order::of(&func);
491 let live = Live::of(&func, &order);
492 assert_eq!(
493 live.range(address),
494 Some(Range { start: order.late(write), end: order.early(load) })
495 );
496 }
497}