1use rucc_mir::{Block, Func, Reg, Role};
55
56use crate::order::{Order, Point};
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub struct Range {
67 pub start: Point,
69 pub end: Point,
71}
72
73impl Range {
74 #[must_use]
76 pub fn covers(self, point: Point) -> bool {
77 self.start <= point && point <= self.end
78 }
79
80 #[must_use]
82 pub fn overlaps(self, other: Self) -> bool {
83 self.start <= other.end && other.start <= self.end
84 }
85
86 fn with(self, point: Point) -> Self {
89 Self { start: self.start.min(point), end: self.end.max(point) }
90 }
91}
92
93#[derive(Debug, Clone, Copy)]
104pub struct Area<'a> {
105 pieces: &'a [Range],
106 also: Option<Point>,
107}
108
109impl<'a> Area<'a> {
110 #[must_use]
115 pub fn with(self, point: Point) -> Self {
116 Self { also: Some(point), ..self }
117 }
118
119 #[must_use]
122 pub fn hull(self) -> Range {
123 Range { start: self.piece(0).start, end: self.pieces[self.pieces.len() - 1].end }
124 }
125
126 #[must_use]
128 pub fn covers(self, point: Point) -> bool {
129 (0..self.pieces.len()).any(|piece| self.piece(piece).covers(point))
130 }
131
132 #[must_use]
137 pub fn overlaps(self, other: Self) -> bool {
138 let (mut mine, mut theirs) = (0, 0);
139 while mine < self.pieces.len() && theirs < other.pieces.len() {
140 let (one, two) = (self.piece(mine), other.piece(theirs));
141 if one.overlaps(two) {
142 return true;
143 }
144 if one.end < two.end {
146 mine += 1;
147 } else {
148 theirs += 1;
149 }
150 }
151 false
152 }
153
154 pub fn pieces(self) -> impl Iterator<Item = Range> + 'a {
156 (0..self.pieces.len()).map(move |piece| self.piece(piece))
157 }
158
159 fn piece(self, index: usize) -> Range {
162 let piece = self.pieces[index];
163 match self.also {
164 Some(also) if also + 1 == piece.start => Range { start: also, end: piece.end },
165 _ => piece,
166 }
167 }
168}
169
170#[derive(Debug, Clone)]
172pub struct Live {
173 live_in: Rows,
174 live_out: Rows,
175 pieces: Vec<Range>,
177 spans: Vec<(usize, usize)>,
179}
180
181impl Live {
182 #[must_use]
184 pub fn of(func: &Func, order: &Order) -> Self {
185 let vregs = func.vregs();
186 let (used, defined) = exposed(func, order);
187 let (live_in, live_out) = flow(func, order, &used, &defined);
188 let (pieces, spans) = carve(func, order, &live_in, &live_out, vregs);
189 Self { live_in, live_out, pieces, spans }
190 }
191
192 #[must_use]
195 pub fn area(&self, reg: Reg) -> Option<Area<'_>> {
196 let pieces = self.pieces(reg);
197 if pieces.is_empty() {
198 return None;
199 }
200 Some(Area { pieces, also: None })
201 }
202
203 #[must_use]
205 pub fn range(&self, reg: Reg) -> Option<Range> {
206 self.area(reg).map(Area::hull)
207 }
208
209 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
214 self.live_in.iter(block.index())
215 }
216
217 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
220 self.live_out.iter(block.index())
221 }
222
223 fn pieces(&self, reg: Reg) -> &[Range] {
225 let number = reg.number().and_then(|number| usize::try_from(number).ok());
226 let Some(&(from, to)) = number.and_then(|number| self.spans.get(number)) else {
227 return &[];
228 };
229 &self.pieces[from..to]
230 }
231}
232
233fn carve(
239 func: &Func,
240 order: &Order,
241 live_in: &Rows,
242 live_out: &Rows,
243 vregs: usize,
244) -> (Vec<Range>, Vec<(usize, usize)>) {
245 let mut lists: Vec<Vec<Range>> = vec![Vec::new(); vregs];
246 let mut here: Vec<Option<Range>> = vec![None; vregs];
247 let mut touched: Vec<usize> = Vec::new();
248
249 for &block in order.blocks() {
250 for reg in live_in.iter(block.index()) {
253 note(&mut here, &mut touched, reg, order.start(block));
254 }
255 for reg in live_out.iter(block.index()) {
256 note(&mut here, &mut touched, reg, order.end(block));
257 }
258 for param in &func[block].params {
259 note(&mut here, &mut touched, param.reg, order.start(block));
260 }
261 for inst in func.insts(block) {
262 for operand in &func[func[inst].operands] {
263 match operand.role {
264 Role::Use => note(&mut here, &mut touched, operand.reg, order.early(inst)),
265 Role::Def => note(&mut here, &mut touched, operand.reg, order.late(inst)),
266 Role::EarlyDef => {
273 note(&mut here, &mut touched, operand.reg, order.early(inst));
274 note(&mut here, &mut touched, operand.reg, order.late(inst));
275 }
276 }
277 }
278 }
279 for call in &func[block].succs {
280 for &arg in &call.args {
281 note(&mut here, &mut touched, arg, order.end(block));
282 }
283 }
284
285 for &number in &touched {
286 let Some(piece) = here[number].take() else { continue };
287 match lists[number].last_mut() {
288 Some(last) if last.end + 1 == piece.start => last.end = piece.end,
292 _ => lists[number].push(piece),
293 }
294 }
295 touched.clear();
296 }
297
298 let mut pieces = Vec::new();
299 let mut spans = Vec::with_capacity(vregs);
300 for list in &lists {
301 let from = pieces.len();
302 pieces.extend_from_slice(list);
303 spans.push((from, pieces.len()));
304 }
305 (pieces, spans)
306}
307
308fn note(here: &mut [Option<Range>], touched: &mut Vec<usize>, reg: Reg, point: Point) {
310 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
311 return;
312 };
313 let Some(slot) = here.get_mut(number) else { return };
314 match slot {
315 Some(range) => *range = range.with(point),
316 None => {
317 *slot = Some(Range { start: point, end: point });
318 touched.push(number);
319 }
320 }
321}
322
323fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
328 let vregs = func.vregs();
329 let mut used = Vec::new();
330 let mut defined = Vec::new();
331 let mut reads = Building::new(vregs);
332 let mut writes = Building::new(vregs);
333 for &block in order.blocks() {
334 let row = block.index();
335 for call in &func[block].succs {
336 for &arg in &call.args {
337 reads.insert(arg);
338 }
339 }
340 let insts: Vec<_> = func.insts(block).collect();
341 for &inst in insts.iter().rev() {
342 let operands = &func[func[inst].operands];
343 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
344 reads.remove(operand.reg);
345 writes.insert(operand.reg);
346 }
347 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
348 reads.insert(operand.reg);
349 }
350 }
351 for param in &func[block].params {
352 reads.remove(param.reg);
353 writes.insert(param.reg);
354 }
355 used.extend(reads.take().into_iter().map(|number| (row_of(row), number)));
356 defined.extend(writes.take().into_iter().map(|number| (row_of(row), number)));
357 }
358 (Rows::gather(func.block_count(), &used), Rows::gather(func.block_count(), &defined))
359}
360
361fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
375 let count = func.block_count();
376 let vregs = func.vregs();
377 let mut preds: Vec<Vec<usize>> = vec![Vec::new(); count];
378 for &block in order.blocks() {
379 for call in &func[block].succs {
380 preds[call.block.index()].push(block.index());
381 }
382 }
383 let mut starts = vec![0usize; vregs + 1];
385 for &block in order.blocks() {
386 for &number in used.row(block.index()) {
387 starts[number as usize + 1] += 1;
388 }
389 }
390 for number in 0..vregs {
391 starts[number + 1] += starts[number];
392 }
393 let mut readers = vec![0usize; starts[vregs]];
394 let mut filled = starts.clone();
395 for &block in order.blocks() {
396 for &number in used.row(block.index()) {
397 readers[filled[number as usize]] = block.index();
398 filled[number as usize] += 1;
399 }
400 }
401 let mut ends = vec![0usize; vregs + 1];
404 for &block in order.blocks() {
405 for &number in defined.row(block.index()) {
406 ends[number as usize + 1] += 1;
407 }
408 }
409 for number in 0..vregs {
410 ends[number + 1] += ends[number];
411 }
412 let mut writers = vec![0usize; ends[vregs]];
413 let mut filled = ends.clone();
414 for &block in order.blocks() {
415 for &number in defined.row(block.index()) {
416 writers[filled[number as usize]] = block.index();
417 filled[number as usize] += 1;
418 }
419 }
420
421 let mut live_in = Vec::new();
422 let mut live_out = Vec::new();
423 let mut arrived = vec![u32::MAX; count];
426 let mut left = vec![u32::MAX; count];
427 let mut wrote = vec![u32::MAX; count];
428 let mut waiting = Vec::new();
429 for number in 0..vregs {
430 let value = u32::try_from(number).expect("a register number");
431 for &row in &writers[ends[number]..ends[number + 1]] {
432 wrote[row] = value;
433 }
434 for &row in &readers[starts[number]..starts[number + 1]] {
435 if arrived[row] != value {
436 arrived[row] = value;
437 live_in.push((row_of(row), value));
438 waiting.push(row);
439 }
440 }
441 while let Some(row) = waiting.pop() {
442 for &pred in &preds[row] {
443 if left[pred] != value {
444 left[pred] = value;
445 live_out.push((row_of(pred), value));
446 }
447 if arrived[pred] != value && wrote[pred] != value {
448 arrived[pred] = value;
449 live_in.push((row_of(pred), value));
450 waiting.push(pred);
451 }
452 }
453 }
454 }
455 (Rows::gather(count, &live_in), Rows::gather(count, &live_out))
456}
457
458#[derive(Debug, Clone)]
478struct Rows {
479 starts: Vec<usize>,
481 numbers: Vec<u32>,
482}
483
484impl Rows {
485 fn gather(rows: usize, pairs: &[(u32, u32)]) -> Self {
488 let mut starts = vec![0usize; rows + 1];
489 for &(row, _) in pairs {
490 starts[row as usize + 1] += 1;
491 }
492 for row in 0..rows {
493 starts[row + 1] += starts[row];
494 }
495 let mut filled = starts.clone();
496 let mut numbers = vec![0u32; pairs.len()];
497 for &(row, number) in pairs {
498 let at = &mut filled[row as usize];
499 numbers[*at] = number;
500 *at += 1;
501 }
502 Self { starts, numbers }
503 }
504
505 fn row(&self, row: usize) -> &[u32] {
506 &self.numbers[self.starts[row]..self.starts[row + 1]]
507 }
508
509 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
510 self.row(row).iter().copied().map(Reg::virtual_reg)
511 }
512}
513
514fn row_of(index: usize) -> u32 {
516 u32::try_from(index).expect("a block number")
517}
518
519struct Building {
529 flags: Vec<bool>,
530 touched: Vec<u32>,
534}
535
536impl Building {
537 fn new(vregs: usize) -> Self {
538 Self { flags: vec![false; vregs], touched: Vec::new() }
539 }
540
541 fn number(&self, reg: Reg) -> Option<usize> {
545 let number = usize::try_from(reg.number()?).ok()?;
546 (number < self.flags.len()).then_some(number)
547 }
548
549 fn insert(&mut self, reg: Reg) {
550 let Some(number) = self.number(reg) else { return };
551 if !self.flags[number] {
552 self.flags[number] = true;
553 self.touched.push(u32::try_from(number).expect("a register number"));
554 }
555 }
556
557 fn remove(&mut self, reg: Reg) {
558 if let Some(number) = self.number(reg) {
559 self.flags[number] = false;
560 }
561 }
562
563 fn take(&mut self) -> Vec<u32> {
565 let flags = &mut self.flags;
566 let mut out: Vec<u32> = self
567 .touched
568 .drain(..)
569 .filter(|&number| std::mem::replace(&mut flags[number as usize], false))
570 .collect();
571 out.sort_unstable();
572 out
573 }
574}
575
576#[cfg(test)]
577mod tests {
578 use rucc_base::Interner;
579 use rucc_mir::{BlockCall, Constraint, Opcode, Operand};
580 use rucc_target::x86_64::GPR;
581
582 use super::*;
583
584 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
586 of.filter_map(Reg::number).collect()
587 }
588
589 #[test]
590 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
591 let mut names = Interner::new();
592 let mut func = Func::new(names.intern("f"));
593 let opcode = Opcode::new(names.intern("x64.nop"));
594 let block = func.create_block();
595 let value = func.new_vreg(GPR);
596 let other = func.new_vreg(GPR);
597 let write = func.build(block, opcode).def(value, GPR).finish();
598 let idle = func.build(block, opcode).def(other, GPR).finish();
599 let read = func.build(block, opcode).uses(value, GPR).finish();
600
601 let order = Order::of(&func);
602 let live = Live::of(&func, &order);
603 let range = live.range(value).expect("the value is live somewhere");
604 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
605 assert!(range.covers(order.early(idle)));
606 assert_eq!(
609 live.range(other),
610 Some(Range { start: order.late(idle), end: order.late(idle) })
611 );
612 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
613 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
614 }
615
616 #[test]
617 fn a_value_read_in_another_block_is_live_between_them() {
618 let mut names = Interner::new();
619 let mut func = Func::new(names.intern("f"));
620 let opcode = Opcode::new(names.intern("x64.nop"));
621 let head = func.create_block();
622 let middle = func.create_block();
623 let tail = func.create_block();
624 let value = func.new_vreg(GPR);
625 func.build(head, opcode).def(value, GPR).finish();
626 *func.succs_mut(head) = vec![BlockCall::to(middle)];
627 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
628 let read = func.build(tail, opcode).uses(value, GPR).finish();
629
630 let order = Order::of(&func);
631 let live = Live::of(&func, &order);
632 assert_eq!(regs(live.live_in(middle)), vec![0]);
635 assert_eq!(regs(live.live_out(middle)), vec![0]);
636 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
637 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
638 }
639
640 #[test]
641 fn a_block_the_value_never_reaches_is_a_hole_between_two_pieces() {
642 let mut names = Interner::new();
643 let mut func = Func::new(names.intern("f"));
644 let opcode = Opcode::new(names.intern("x64.nop"));
645 let entry = func.create_block();
646 let arm = func.create_block();
647 let tail = func.create_block();
648 let value = func.new_vreg(GPR);
649 let write = func.build(entry, opcode).def(value, GPR).finish();
650 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
651 let idle = func.build(arm, opcode).finish();
652 let read = func.build(tail, opcode).uses(value, GPR).finish();
653
654 let order = Order::of(&func);
655 let live = Live::of(&func, &order);
656 let area = live.area(value).expect("live somewhere");
657 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
661 assert!(!area.covers(order.early(idle)));
662 assert_eq!(
663 area.pieces().collect::<Vec<_>>(),
664 vec![
665 Range { start: order.late(write), end: order.end(entry) },
666 Range { start: order.start(tail), end: order.early(read) },
667 ]
668 );
669 }
670
671 #[test]
672 fn a_value_in_a_hole_of_another_may_have_its_register() {
673 let mut names = Interner::new();
674 let mut func = Func::new(names.intern("f"));
675 let opcode = Opcode::new(names.intern("x64.nop"));
676 let entry = func.create_block();
677 let arm = func.create_block();
678 let tail = func.create_block();
679 let value = func.new_vreg(GPR);
680 let inside = func.new_vreg(GPR);
681 func.build(entry, opcode).def(value, GPR).finish();
682 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
683 func.build(arm, opcode).def(inside, GPR).finish();
684 func.build(arm, opcode).uses(inside, GPR).finish();
685 func.build(tail, opcode).uses(value, GPR).finish();
686
687 let order = Order::of(&func);
688 let live = Live::of(&func, &order);
689 let value = live.area(value).expect("live somewhere");
690 let inside = live.area(inside).expect("live somewhere");
691 assert!(value.hull().overlaps(inside.hull()));
695 assert!(!value.overlaps(inside));
696 assert!(!inside.overlaps(value));
697 }
698
699 #[test]
700 fn one_point_added_in_front_of_a_piece_is_part_of_the_area() {
701 let mut names = Interner::new();
702 let mut func = Func::new(names.intern("f"));
703 let opcode = Opcode::new(names.intern("x64.nop"));
704 let block = func.create_block();
705 let first = func.new_vreg(GPR);
706 let second = func.new_vreg(GPR);
707 let write = func.build(block, opcode).def(first, GPR).finish();
708 let both = func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
709
710 let order = Order::of(&func);
711 let live = Live::of(&func, &order);
712 let first = live.area(first).expect("live somewhere");
713 let second = live.area(second).expect("live somewhere");
714 assert!(!first.overlaps(second));
719 assert!(first.overlaps(second.with(order.early(both))));
720 assert!(second.with(order.early(both)).covers(order.early(both)));
721 assert_eq!(second.with(order.early(both)).hull().start, order.early(both));
722 assert_eq!(first.hull().start, order.late(write));
723 }
724
725 #[test]
726 fn the_point_added_in_front_joins_the_piece_it_belongs_to_and_not_the_first_one() {
727 let mut names = Interner::new();
728 let mut func = Func::new(names.intern("f"));
729 let nop = Opcode::new(names.intern("x64.nop"));
730 let add = Opcode::new(names.intern("x64.add"));
731 let entry = func.create_block();
732 let head = func.create_block();
733 let arm = func.create_block();
734 let latch = func.create_block();
735 let out = func.create_block();
736 let seed = func.new_vreg(GPR);
737 let sum = func.new_vreg(GPR);
738 let inside = func.new_vreg(GPR);
739 let loaded = func.new_vreg(GPR);
740 func.build(entry, nop).def(seed, GPR).finish();
741 func.build(entry, nop).def(sum, GPR).finish();
742 *func.succs_mut(entry) = vec![BlockCall::to(head)];
743 func.build(head, nop).uses(sum, GPR).finish();
744 *func.succs_mut(head) = vec![BlockCall::to(arm), BlockCall::to(latch)];
745 func.build(arm, nop).def(inside, GPR).finish();
746 func.build(arm, nop).uses(inside, GPR).finish();
747 *func.succs_mut(arm) = vec![BlockCall::to(out)];
748 func.build(latch, nop).def(loaded, GPR).finish();
749 let carry = func
750 .build(latch, add)
751 .operand(Operand::write(sum, GPR).with(Constraint::Reuse(1)))
752 .uses(seed, GPR)
753 .uses(loaded, GPR)
754 .finish();
755 *func.succs_mut(latch) = vec![BlockCall::to(head), BlockCall::to(out)];
756
757 let order = Order::of(&func);
758 let live = Live::of(&func, &order);
759 let sum = live.area(sum).expect("live somewhere");
760 let loaded = live.area(loaded).expect("live somewhere");
761 assert_eq!(sum.pieces().count(), 2);
766 assert!(!sum.covers(order.early(carry)));
767 assert!(sum.with(order.early(carry)).covers(order.early(carry)));
768 assert!(!loaded.overlaps(sum));
769 assert!(loaded.overlaps(sum.with(order.early(carry))));
770 }
771
772 #[test]
773 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
774 let mut names = Interner::new();
775 let mut func = Func::new(names.intern("f"));
776 let opcode = Opcode::new(names.intern("x64.nop"));
777 let header = func.create_block();
778 let body = func.create_block();
779 let carried = func.append_param(header, GPR);
780 let next = func.new_vreg(GPR);
781 *func.succs_mut(header) = vec![BlockCall::to(body)];
782 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
783 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
784
785 let order = Order::of(&func);
786 let live = Live::of(&func, &order);
787 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
790 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
791 let range = live.range(next).expect("live somewhere");
792 assert_eq!(range.end, order.end(body));
793 }
794
795 #[test]
796 fn two_values_that_are_never_both_wanted_do_not_overlap() {
797 let mut names = Interner::new();
798 let mut func = Func::new(names.intern("f"));
799 let opcode = Opcode::new(names.intern("x64.nop"));
800 let block = func.create_block();
801 let first = func.new_vreg(GPR);
802 let second = func.new_vreg(GPR);
803 let write = func.build(block, opcode).def(first, GPR).finish();
804 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
805
806 let order = Order::of(&func);
807 let live = Live::of(&func, &order);
808 let first = live.range(first).expect("live somewhere");
809 let second = live.range(second).expect("live somewhere");
810 assert!(!first.overlaps(second));
814 assert!(first.start > order.start(block));
815 assert_eq!(first.start, order.late(write));
816 }
817
818 #[test]
819 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
820 let mut names = Interner::new();
821 let mut func = Func::new(names.intern("f"));
822 let opcode = Opcode::new(names.intern("x64.nop"));
823 let block = func.create_block();
824 let source = func.new_vreg(GPR);
825 let early = func.new_vreg(GPR);
826 func.build(block, opcode).def(source, GPR).finish();
827 func.build(block, opcode)
828 .operand(Operand::write_early(early, GPR))
829 .operand(Operand::read(source, GPR))
830 .finish();
831
832 let order = Order::of(&func);
833 let live = Live::of(&func, &order);
834 let source = live.range(source).expect("live somewhere");
835 let early = live.range(early).expect("live somewhere");
836 assert!(source.overlaps(early));
839 }
840
841 #[test]
842 fn a_register_a_memory_operand_names_is_read_like_any_other() {
843 use rucc_mir::Mem;
844
845 let mut names = Interner::new();
846 let mut func = Func::new(names.intern("f"));
847 let opcode = Opcode::new(names.intern("x64.nop"));
848 let block = func.create_block();
849 let address = func.new_vreg(GPR);
850 let write = func.build(block, opcode).def(address, GPR).finish();
851 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
852
853 let order = Order::of(&func);
854 let live = Live::of(&func, &order);
855 assert_eq!(
856 live.range(address),
857 Some(Range { start: order.late(write), end: order.early(load) })
858 );
859 }
860}