1use std::cmp::Ordering;
54use std::collections::VecDeque;
55
56use rucc_mir::{Block, Func, Reg, Role};
57
58use crate::order::{Order, Point};
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub struct Range {
69 pub start: Point,
71 pub end: Point,
73}
74
75impl Range {
76 #[must_use]
78 pub fn covers(self, point: Point) -> bool {
79 self.start <= point && point <= self.end
80 }
81
82 #[must_use]
84 pub fn overlaps(self, other: Self) -> bool {
85 self.start <= other.end && other.start <= self.end
86 }
87
88 fn with(self, point: Point) -> Self {
91 Self { start: self.start.min(point), end: self.end.max(point) }
92 }
93}
94
95#[derive(Debug, Clone, Copy)]
106pub struct Area<'a> {
107 pieces: &'a [Range],
108 also: Option<Point>,
109}
110
111impl<'a> Area<'a> {
112 #[must_use]
117 pub fn with(self, point: Point) -> Self {
118 Self { also: Some(point), ..self }
119 }
120
121 #[must_use]
124 pub fn hull(self) -> Range {
125 Range { start: self.piece(0).start, end: self.pieces[self.pieces.len() - 1].end }
126 }
127
128 #[must_use]
130 pub fn covers(self, point: Point) -> bool {
131 (0..self.pieces.len()).any(|piece| self.piece(piece).covers(point))
132 }
133
134 #[must_use]
139 pub fn overlaps(self, other: Self) -> bool {
140 let (mut mine, mut theirs) = (0, 0);
141 while mine < self.pieces.len() && theirs < other.pieces.len() {
142 let (one, two) = (self.piece(mine), other.piece(theirs));
143 if one.overlaps(two) {
144 return true;
145 }
146 if one.end < two.end {
148 mine += 1;
149 } else {
150 theirs += 1;
151 }
152 }
153 false
154 }
155
156 pub fn pieces(self) -> impl Iterator<Item = Range> + 'a {
158 (0..self.pieces.len()).map(move |piece| self.piece(piece))
159 }
160
161 fn piece(self, index: usize) -> Range {
164 let piece = self.pieces[index];
165 match self.also {
166 Some(also) if also + 1 == piece.start => Range { start: also, end: piece.end },
167 _ => piece,
168 }
169 }
170}
171
172#[derive(Debug, Clone)]
174pub struct Live {
175 live_in: Rows,
176 live_out: Rows,
177 pieces: Vec<Range>,
179 spans: Vec<(usize, usize)>,
181}
182
183impl Live {
184 #[must_use]
186 pub fn of(func: &Func, order: &Order) -> Self {
187 let vregs = func.vregs();
188 let (used, defined) = exposed(func, order);
189 let (live_in, live_out) = flow(func, order, &used, &defined);
190 let (pieces, spans) = carve(func, order, &live_in, &live_out, vregs);
191 Self { live_in, live_out, pieces, spans }
192 }
193
194 #[must_use]
197 pub fn area(&self, reg: Reg) -> Option<Area<'_>> {
198 let pieces = self.pieces(reg);
199 if pieces.is_empty() {
200 return None;
201 }
202 Some(Area { pieces, also: None })
203 }
204
205 #[must_use]
207 pub fn range(&self, reg: Reg) -> Option<Range> {
208 self.area(reg).map(Area::hull)
209 }
210
211 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
216 self.live_in.iter(block.index())
217 }
218
219 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
222 self.live_out.iter(block.index())
223 }
224
225 fn pieces(&self, reg: Reg) -> &[Range] {
227 let number = reg.number().and_then(|number| usize::try_from(number).ok());
228 let Some(&(from, to)) = number.and_then(|number| self.spans.get(number)) else {
229 return &[];
230 };
231 &self.pieces[from..to]
232 }
233}
234
235fn carve(
241 func: &Func,
242 order: &Order,
243 live_in: &Rows,
244 live_out: &Rows,
245 vregs: usize,
246) -> (Vec<Range>, Vec<(usize, usize)>) {
247 let mut lists: Vec<Vec<Range>> = vec![Vec::new(); vregs];
248 let mut here: Vec<Option<Range>> = vec![None; vregs];
249 let mut touched: Vec<usize> = Vec::new();
250
251 for &block in order.blocks() {
252 for reg in live_in.iter(block.index()) {
255 note(&mut here, &mut touched, reg, order.start(block));
256 }
257 for reg in live_out.iter(block.index()) {
258 note(&mut here, &mut touched, reg, order.end(block));
259 }
260 for param in &func[block].params {
261 note(&mut here, &mut touched, param.reg, order.start(block));
262 }
263 for inst in func.insts(block) {
264 for operand in &func[func[inst].operands] {
265 match operand.role {
266 Role::Use => note(&mut here, &mut touched, operand.reg, order.early(inst)),
267 Role::Def => note(&mut here, &mut touched, operand.reg, order.late(inst)),
268 Role::EarlyDef => {
275 note(&mut here, &mut touched, operand.reg, order.early(inst));
276 note(&mut here, &mut touched, operand.reg, order.late(inst));
277 }
278 }
279 }
280 }
281 for call in &func[block].succs {
282 for &arg in &call.args {
283 note(&mut here, &mut touched, arg, order.end(block));
284 }
285 }
286
287 for &number in &touched {
288 let Some(piece) = here[number].take() else { continue };
289 match lists[number].last_mut() {
290 Some(last) if last.end + 1 == piece.start => last.end = piece.end,
294 _ => lists[number].push(piece),
295 }
296 }
297 touched.clear();
298 }
299
300 let mut pieces = Vec::new();
301 let mut spans = Vec::with_capacity(vregs);
302 for list in &lists {
303 let from = pieces.len();
304 pieces.extend_from_slice(list);
305 spans.push((from, pieces.len()));
306 }
307 (pieces, spans)
308}
309
310fn note(here: &mut [Option<Range>], touched: &mut Vec<usize>, reg: Reg, point: Point) {
312 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
313 return;
314 };
315 let Some(slot) = here.get_mut(number) else { return };
316 match slot {
317 Some(range) => *range = range.with(point),
318 None => {
319 *slot = Some(Range { start: point, end: point });
320 touched.push(number);
321 }
322 }
323}
324
325fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
330 let vregs = func.vregs();
331 let mut used = Rows::new(func.block_count());
332 let mut defined = Rows::new(func.block_count());
333 let mut reads = Building::new(vregs);
334 let mut writes = Building::new(vregs);
335 for &block in order.blocks() {
336 let row = block.index();
337 for call in &func[block].succs {
338 for &arg in &call.args {
339 reads.insert(arg);
340 }
341 }
342 let insts: Vec<_> = func.insts(block).collect();
343 for &inst in insts.iter().rev() {
344 let operands = &func[func[inst].operands];
345 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
346 reads.remove(operand.reg);
347 writes.insert(operand.reg);
348 }
349 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
350 reads.insert(operand.reg);
351 }
352 }
353 for param in &func[block].params {
354 reads.remove(param.reg);
355 writes.insert(param.reg);
356 }
357 used.set(row, &reads.take());
358 defined.set(row, &writes.take());
359 }
360 (used, defined)
361}
362
363fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
371 let count = func.block_count();
372 let mut live_in = Rows::new(count);
373 let mut live_out = Rows::new(count);
374 let mut placed = vec![false; count];
375 for &block in order.blocks() {
376 placed[block.index()] = true;
377 }
378 let mut preds: Vec<Vec<Block>> = vec![Vec::new(); count];
379 for &block in order.blocks() {
380 for call in &func[block].succs {
381 preds[call.block.index()].push(block);
382 }
383 }
384 let mut waiting: VecDeque<Block> = order.blocks().iter().rev().copied().collect();
385 let mut queued = placed.clone();
386 let (mut out, mut scratch, mut rest, mut next) =
387 (Vec::new(), Vec::new(), Vec::new(), Vec::new());
388 while let Some(block) = waiting.pop_front() {
389 let row = block.index();
390 queued[row] = false;
391 leaving(func, block, &live_in, &mut out, &mut scratch);
392 without(&out, defined.row(row), &mut rest);
393 union(used.row(row), &rest, &mut next);
394 if live_in.row(row) != next.as_slice() {
395 live_in.set(row, &next);
396 for &pred in &preds[row] {
397 if placed[pred.index()] && !queued[pred.index()] {
398 queued[pred.index()] = true;
399 waiting.push_back(pred);
400 }
401 }
402 }
403 }
404 for &block in order.blocks() {
405 leaving(func, block, &live_in, &mut out, &mut scratch);
406 live_out.set(block.index(), &out);
407 }
408 (live_in, live_out)
409}
410
411fn leaving(func: &Func, block: Block, live_in: &Rows, out: &mut Vec<u32>, scratch: &mut Vec<u32>) {
413 out.clear();
414 for call in &func[block].succs {
415 union(out, live_in.row(call.block.index()), scratch);
416 std::mem::swap(out, scratch);
417 }
418}
419
420fn union(one: &[u32], two: &[u32], out: &mut Vec<u32>) {
425 out.clear();
426 let (mut here, mut there) = (0, 0);
427 while here < one.len() && there < two.len() {
428 match one[here].cmp(&two[there]) {
429 Ordering::Less => {
430 out.push(one[here]);
431 here += 1;
432 }
433 Ordering::Greater => {
434 out.push(two[there]);
435 there += 1;
436 }
437 Ordering::Equal => {
438 out.push(one[here]);
439 here += 1;
440 there += 1;
441 }
442 }
443 }
444 out.extend_from_slice(&one[here..]);
445 out.extend_from_slice(&two[there..]);
446}
447
448fn without(one: &[u32], two: &[u32], out: &mut Vec<u32>) {
450 out.clear();
451 let mut there = 0;
452 for &number in one {
453 while there < two.len() && two[there] < number {
454 there += 1;
455 }
456 if there < two.len() && two[there] == number {
457 continue;
458 }
459 out.push(number);
460 }
461}
462
463#[derive(Debug, Clone)]
479struct Rows {
480 rows: Vec<Vec<u32>>,
481}
482
483impl Rows {
484 fn new(rows: usize) -> Self {
485 Self { rows: vec![Vec::new(); rows] }
486 }
487
488 fn row(&self, row: usize) -> &[u32] {
489 &self.rows[row]
490 }
491
492 fn set(&mut self, row: usize, numbers: &[u32]) {
496 let row = &mut self.rows[row];
497 row.clear();
498 row.extend_from_slice(numbers);
499 }
500
501 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
502 self.rows[row].iter().copied().map(Reg::virtual_reg)
503 }
504}
505
506struct Building {
516 flags: Vec<bool>,
517 touched: Vec<u32>,
521}
522
523impl Building {
524 fn new(vregs: usize) -> Self {
525 Self { flags: vec![false; vregs], touched: Vec::new() }
526 }
527
528 fn number(&self, reg: Reg) -> Option<usize> {
532 let number = usize::try_from(reg.number()?).ok()?;
533 (number < self.flags.len()).then_some(number)
534 }
535
536 fn insert(&mut self, reg: Reg) {
537 let Some(number) = self.number(reg) else { return };
538 if !self.flags[number] {
539 self.flags[number] = true;
540 self.touched.push(u32::try_from(number).expect("a register number"));
541 }
542 }
543
544 fn remove(&mut self, reg: Reg) {
545 if let Some(number) = self.number(reg) {
546 self.flags[number] = false;
547 }
548 }
549
550 fn take(&mut self) -> Vec<u32> {
552 let flags = &mut self.flags;
553 let mut out: Vec<u32> = self
554 .touched
555 .drain(..)
556 .filter(|&number| std::mem::replace(&mut flags[number as usize], false))
557 .collect();
558 out.sort_unstable();
559 out
560 }
561}
562
563#[cfg(test)]
564mod tests {
565 use rucc_base::Interner;
566 use rucc_mir::{BlockCall, Constraint, Opcode, Operand};
567 use rucc_target::x86_64::GPR;
568
569 use super::*;
570
571 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
573 of.filter_map(Reg::number).collect()
574 }
575
576 #[test]
577 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
578 let mut names = Interner::new();
579 let mut func = Func::new(names.intern("f"));
580 let opcode = Opcode::new(names.intern("x64.nop"));
581 let block = func.create_block();
582 let value = func.new_vreg(GPR);
583 let other = func.new_vreg(GPR);
584 let write = func.build(block, opcode).def(value, GPR).finish();
585 let idle = func.build(block, opcode).def(other, GPR).finish();
586 let read = func.build(block, opcode).uses(value, GPR).finish();
587
588 let order = Order::of(&func);
589 let live = Live::of(&func, &order);
590 let range = live.range(value).expect("the value is live somewhere");
591 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
592 assert!(range.covers(order.early(idle)));
593 assert_eq!(
596 live.range(other),
597 Some(Range { start: order.late(idle), end: order.late(idle) })
598 );
599 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
600 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
601 }
602
603 #[test]
604 fn a_value_read_in_another_block_is_live_between_them() {
605 let mut names = Interner::new();
606 let mut func = Func::new(names.intern("f"));
607 let opcode = Opcode::new(names.intern("x64.nop"));
608 let head = func.create_block();
609 let middle = func.create_block();
610 let tail = func.create_block();
611 let value = func.new_vreg(GPR);
612 func.build(head, opcode).def(value, GPR).finish();
613 *func.succs_mut(head) = vec![BlockCall::to(middle)];
614 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
615 let read = func.build(tail, opcode).uses(value, GPR).finish();
616
617 let order = Order::of(&func);
618 let live = Live::of(&func, &order);
619 assert_eq!(regs(live.live_in(middle)), vec![0]);
622 assert_eq!(regs(live.live_out(middle)), vec![0]);
623 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
624 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
625 }
626
627 #[test]
628 fn a_block_the_value_never_reaches_is_a_hole_between_two_pieces() {
629 let mut names = Interner::new();
630 let mut func = Func::new(names.intern("f"));
631 let opcode = Opcode::new(names.intern("x64.nop"));
632 let entry = func.create_block();
633 let arm = func.create_block();
634 let tail = func.create_block();
635 let value = func.new_vreg(GPR);
636 let write = func.build(entry, opcode).def(value, GPR).finish();
637 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
638 let idle = func.build(arm, opcode).finish();
639 let read = func.build(tail, opcode).uses(value, GPR).finish();
640
641 let order = Order::of(&func);
642 let live = Live::of(&func, &order);
643 let area = live.area(value).expect("live somewhere");
644 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
648 assert!(!area.covers(order.early(idle)));
649 assert_eq!(
650 area.pieces().collect::<Vec<_>>(),
651 vec![
652 Range { start: order.late(write), end: order.end(entry) },
653 Range { start: order.start(tail), end: order.early(read) },
654 ]
655 );
656 }
657
658 #[test]
659 fn a_value_in_a_hole_of_another_may_have_its_register() {
660 let mut names = Interner::new();
661 let mut func = Func::new(names.intern("f"));
662 let opcode = Opcode::new(names.intern("x64.nop"));
663 let entry = func.create_block();
664 let arm = func.create_block();
665 let tail = func.create_block();
666 let value = func.new_vreg(GPR);
667 let inside = func.new_vreg(GPR);
668 func.build(entry, opcode).def(value, GPR).finish();
669 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
670 func.build(arm, opcode).def(inside, GPR).finish();
671 func.build(arm, opcode).uses(inside, GPR).finish();
672 func.build(tail, opcode).uses(value, GPR).finish();
673
674 let order = Order::of(&func);
675 let live = Live::of(&func, &order);
676 let value = live.area(value).expect("live somewhere");
677 let inside = live.area(inside).expect("live somewhere");
678 assert!(value.hull().overlaps(inside.hull()));
682 assert!(!value.overlaps(inside));
683 assert!(!inside.overlaps(value));
684 }
685
686 #[test]
687 fn one_point_added_in_front_of_a_piece_is_part_of_the_area() {
688 let mut names = Interner::new();
689 let mut func = Func::new(names.intern("f"));
690 let opcode = Opcode::new(names.intern("x64.nop"));
691 let block = func.create_block();
692 let first = func.new_vreg(GPR);
693 let second = func.new_vreg(GPR);
694 let write = func.build(block, opcode).def(first, GPR).finish();
695 let both = func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
696
697 let order = Order::of(&func);
698 let live = Live::of(&func, &order);
699 let first = live.area(first).expect("live somewhere");
700 let second = live.area(second).expect("live somewhere");
701 assert!(!first.overlaps(second));
706 assert!(first.overlaps(second.with(order.early(both))));
707 assert!(second.with(order.early(both)).covers(order.early(both)));
708 assert_eq!(second.with(order.early(both)).hull().start, order.early(both));
709 assert_eq!(first.hull().start, order.late(write));
710 }
711
712 #[test]
713 fn the_point_added_in_front_joins_the_piece_it_belongs_to_and_not_the_first_one() {
714 let mut names = Interner::new();
715 let mut func = Func::new(names.intern("f"));
716 let nop = Opcode::new(names.intern("x64.nop"));
717 let add = Opcode::new(names.intern("x64.add"));
718 let entry = func.create_block();
719 let head = func.create_block();
720 let arm = func.create_block();
721 let latch = func.create_block();
722 let out = func.create_block();
723 let seed = func.new_vreg(GPR);
724 let sum = func.new_vreg(GPR);
725 let inside = func.new_vreg(GPR);
726 let loaded = func.new_vreg(GPR);
727 func.build(entry, nop).def(seed, GPR).finish();
728 func.build(entry, nop).def(sum, GPR).finish();
729 *func.succs_mut(entry) = vec![BlockCall::to(head)];
730 func.build(head, nop).uses(sum, GPR).finish();
731 *func.succs_mut(head) = vec![BlockCall::to(arm), BlockCall::to(latch)];
732 func.build(arm, nop).def(inside, GPR).finish();
733 func.build(arm, nop).uses(inside, GPR).finish();
734 *func.succs_mut(arm) = vec![BlockCall::to(out)];
735 func.build(latch, nop).def(loaded, GPR).finish();
736 let carry = func
737 .build(latch, add)
738 .operand(Operand::write(sum, GPR).with(Constraint::Reuse(1)))
739 .uses(seed, GPR)
740 .uses(loaded, GPR)
741 .finish();
742 *func.succs_mut(latch) = vec![BlockCall::to(head), BlockCall::to(out)];
743
744 let order = Order::of(&func);
745 let live = Live::of(&func, &order);
746 let sum = live.area(sum).expect("live somewhere");
747 let loaded = live.area(loaded).expect("live somewhere");
748 assert_eq!(sum.pieces().count(), 2);
753 assert!(!sum.covers(order.early(carry)));
754 assert!(sum.with(order.early(carry)).covers(order.early(carry)));
755 assert!(!loaded.overlaps(sum));
756 assert!(loaded.overlaps(sum.with(order.early(carry))));
757 }
758
759 #[test]
760 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
761 let mut names = Interner::new();
762 let mut func = Func::new(names.intern("f"));
763 let opcode = Opcode::new(names.intern("x64.nop"));
764 let header = func.create_block();
765 let body = func.create_block();
766 let carried = func.append_param(header, GPR);
767 let next = func.new_vreg(GPR);
768 *func.succs_mut(header) = vec![BlockCall::to(body)];
769 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
770 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
771
772 let order = Order::of(&func);
773 let live = Live::of(&func, &order);
774 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
777 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
778 let range = live.range(next).expect("live somewhere");
779 assert_eq!(range.end, order.end(body));
780 }
781
782 #[test]
783 fn two_values_that_are_never_both_wanted_do_not_overlap() {
784 let mut names = Interner::new();
785 let mut func = Func::new(names.intern("f"));
786 let opcode = Opcode::new(names.intern("x64.nop"));
787 let block = func.create_block();
788 let first = func.new_vreg(GPR);
789 let second = func.new_vreg(GPR);
790 let write = func.build(block, opcode).def(first, GPR).finish();
791 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
792
793 let order = Order::of(&func);
794 let live = Live::of(&func, &order);
795 let first = live.range(first).expect("live somewhere");
796 let second = live.range(second).expect("live somewhere");
797 assert!(!first.overlaps(second));
801 assert!(first.start > order.start(block));
802 assert_eq!(first.start, order.late(write));
803 }
804
805 #[test]
806 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
807 let mut names = Interner::new();
808 let mut func = Func::new(names.intern("f"));
809 let opcode = Opcode::new(names.intern("x64.nop"));
810 let block = func.create_block();
811 let source = func.new_vreg(GPR);
812 let early = func.new_vreg(GPR);
813 func.build(block, opcode).def(source, GPR).finish();
814 func.build(block, opcode)
815 .operand(Operand::write_early(early, GPR))
816 .operand(Operand::read(source, GPR))
817 .finish();
818
819 let order = Order::of(&func);
820 let live = Live::of(&func, &order);
821 let source = live.range(source).expect("live somewhere");
822 let early = live.range(early).expect("live somewhere");
823 assert!(source.overlaps(early));
826 }
827
828 #[test]
829 fn a_register_a_memory_operand_names_is_read_like_any_other() {
830 use rucc_mir::Mem;
831
832 let mut names = Interner::new();
833 let mut func = Func::new(names.intern("f"));
834 let opcode = Opcode::new(names.intern("x64.nop"));
835 let block = func.create_block();
836 let address = func.new_vreg(GPR);
837 let write = func.build(block, opcode).def(address, GPR).finish();
838 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
839
840 let order = Order::of(&func);
841 let live = Live::of(&func, &order);
842 assert_eq!(
843 live.range(address),
844 Some(Range { start: order.late(write), end: order.early(load) })
845 );
846 }
847}