1use std::cmp::Ordering;
54
55use rucc_mir::{Block, Func, Reg, Role};
56
57use crate::order::{Order, Point};
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67pub struct Range {
68 pub start: Point,
70 pub end: Point,
72}
73
74impl Range {
75 #[must_use]
77 pub fn covers(self, point: Point) -> bool {
78 self.start <= point && point <= self.end
79 }
80
81 #[must_use]
83 pub fn overlaps(self, other: Self) -> bool {
84 self.start <= other.end && other.start <= self.end
85 }
86
87 fn with(self, point: Point) -> Self {
90 Self { start: self.start.min(point), end: self.end.max(point) }
91 }
92}
93
94#[derive(Debug, Clone, Copy)]
105pub struct Area<'a> {
106 pieces: &'a [Range],
107 also: Option<Point>,
108}
109
110impl<'a> Area<'a> {
111 #[must_use]
116 pub fn with(self, point: Point) -> Self {
117 Self { also: Some(point), ..self }
118 }
119
120 #[must_use]
123 pub fn hull(self) -> Range {
124 Range { start: self.piece(0).start, end: self.pieces[self.pieces.len() - 1].end }
125 }
126
127 #[must_use]
129 pub fn covers(self, point: Point) -> bool {
130 (0..self.pieces.len()).any(|piece| self.piece(piece).covers(point))
131 }
132
133 #[must_use]
138 pub fn overlaps(self, other: Self) -> bool {
139 let (mut mine, mut theirs) = (0, 0);
140 while mine < self.pieces.len() && theirs < other.pieces.len() {
141 let (one, two) = (self.piece(mine), other.piece(theirs));
142 if one.overlaps(two) {
143 return true;
144 }
145 if one.end < two.end {
147 mine += 1;
148 } else {
149 theirs += 1;
150 }
151 }
152 false
153 }
154
155 pub fn pieces(self) -> impl Iterator<Item = Range> + 'a {
157 (0..self.pieces.len()).map(move |piece| self.piece(piece))
158 }
159
160 fn piece(self, index: usize) -> Range {
163 let piece = self.pieces[index];
164 match self.also {
165 Some(also) if also + 1 == piece.start => Range { start: also, end: piece.end },
166 _ => piece,
167 }
168 }
169}
170
171#[derive(Debug, Clone)]
173pub struct Live {
174 live_in: Rows,
175 live_out: Rows,
176 pieces: Vec<Range>,
178 spans: Vec<(usize, usize)>,
180}
181
182impl Live {
183 #[must_use]
185 pub fn of(func: &Func, order: &Order) -> Self {
186 let vregs = func.vregs();
187 let (used, defined) = exposed(func, order);
188 let (live_in, live_out) = flow(func, order, &used, &defined);
189 let (pieces, spans) = carve(func, order, &live_in, &live_out, vregs);
190 Self { live_in, live_out, pieces, spans }
191 }
192
193 #[must_use]
196 pub fn area(&self, reg: Reg) -> Option<Area<'_>> {
197 let pieces = self.pieces(reg);
198 if pieces.is_empty() {
199 return None;
200 }
201 Some(Area { pieces, also: None })
202 }
203
204 #[must_use]
206 pub fn range(&self, reg: Reg) -> Option<Range> {
207 self.area(reg).map(Area::hull)
208 }
209
210 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
215 self.live_in.iter(block.index())
216 }
217
218 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
221 self.live_out.iter(block.index())
222 }
223
224 fn pieces(&self, reg: Reg) -> &[Range] {
226 let number = reg.number().and_then(|number| usize::try_from(number).ok());
227 let Some(&(from, to)) = number.and_then(|number| self.spans.get(number)) else {
228 return &[];
229 };
230 &self.pieces[from..to]
231 }
232}
233
234fn carve(
240 func: &Func,
241 order: &Order,
242 live_in: &Rows,
243 live_out: &Rows,
244 vregs: usize,
245) -> (Vec<Range>, Vec<(usize, usize)>) {
246 let mut lists: Vec<Vec<Range>> = vec![Vec::new(); vregs];
247 let mut here: Vec<Option<Range>> = vec![None; vregs];
248 let mut touched: Vec<usize> = Vec::new();
249
250 for &block in order.blocks() {
251 for reg in live_in.iter(block.index()) {
254 note(&mut here, &mut touched, reg, order.start(block));
255 }
256 for reg in live_out.iter(block.index()) {
257 note(&mut here, &mut touched, reg, order.end(block));
258 }
259 for param in &func[block].params {
260 note(&mut here, &mut touched, param.reg, order.start(block));
261 }
262 for inst in func.insts(block) {
263 for operand in &func[func[inst].operands] {
264 match operand.role {
265 Role::Use => note(&mut here, &mut touched, operand.reg, order.early(inst)),
266 Role::Def => note(&mut here, &mut touched, operand.reg, order.late(inst)),
267 Role::EarlyDef => {
274 note(&mut here, &mut touched, operand.reg, order.early(inst));
275 note(&mut here, &mut touched, operand.reg, order.late(inst));
276 }
277 }
278 }
279 }
280 for call in &func[block].succs {
281 for &arg in &call.args {
282 note(&mut here, &mut touched, arg, order.end(block));
283 }
284 }
285
286 for &number in &touched {
287 let Some(piece) = here[number].take() else { continue };
288 match lists[number].last_mut() {
289 Some(last) if last.end + 1 == piece.start => last.end = piece.end,
293 _ => lists[number].push(piece),
294 }
295 }
296 touched.clear();
297 }
298
299 let mut pieces = Vec::new();
300 let mut spans = Vec::with_capacity(vregs);
301 for list in &lists {
302 let from = pieces.len();
303 pieces.extend_from_slice(list);
304 spans.push((from, pieces.len()));
305 }
306 (pieces, spans)
307}
308
309fn note(here: &mut [Option<Range>], touched: &mut Vec<usize>, reg: Reg, point: Point) {
311 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
312 return;
313 };
314 let Some(slot) = here.get_mut(number) else { return };
315 match slot {
316 Some(range) => *range = range.with(point),
317 None => {
318 *slot = Some(Range { start: point, end: point });
319 touched.push(number);
320 }
321 }
322}
323
324fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
329 let vregs = func.vregs();
330 let mut used = Rows::new(func.block_count());
331 let mut defined = Rows::new(func.block_count());
332 let mut reads = Building::new(vregs);
333 let mut writes = Building::new(vregs);
334 for &block in order.blocks() {
335 let row = block.index();
336 for call in &func[block].succs {
337 for &arg in &call.args {
338 reads.insert(arg);
339 }
340 }
341 let insts: Vec<_> = func.insts(block).collect();
342 for &inst in insts.iter().rev() {
343 let operands = &func[func[inst].operands];
344 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
345 reads.remove(operand.reg);
346 writes.insert(operand.reg);
347 }
348 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
349 reads.insert(operand.reg);
350 }
351 }
352 for param in &func[block].params {
353 reads.remove(param.reg);
354 writes.insert(param.reg);
355 }
356 used.set(row, &reads.take());
357 defined.set(row, &writes.take());
358 }
359 (used, defined)
360}
361
362fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
364 let mut live_in = Rows::new(func.block_count());
365 let mut live_out = Rows::new(func.block_count());
366 let (mut out, mut scratch, mut rest, mut next) =
367 (Vec::new(), Vec::new(), Vec::new(), Vec::new());
368 let mut changed = true;
369 while changed {
370 changed = false;
371 for &block in order.blocks().iter().rev() {
372 let row = block.index();
373 out.clear();
374 for call in &func[block].succs {
375 union(&out, live_in.row(call.block.index()), &mut scratch);
376 std::mem::swap(&mut out, &mut scratch);
377 }
378 without(&out, defined.row(row), &mut rest);
379 union(used.row(row), &rest, &mut next);
380 if live_in.row(row) != next.as_slice() {
381 live_in.set(row, &next);
382 changed = true;
383 }
384 live_out.set(row, &out);
385 }
386 }
387 (live_in, live_out)
388}
389
390fn union(one: &[u32], two: &[u32], out: &mut Vec<u32>) {
395 out.clear();
396 let (mut here, mut there) = (0, 0);
397 while here < one.len() && there < two.len() {
398 match one[here].cmp(&two[there]) {
399 Ordering::Less => {
400 out.push(one[here]);
401 here += 1;
402 }
403 Ordering::Greater => {
404 out.push(two[there]);
405 there += 1;
406 }
407 Ordering::Equal => {
408 out.push(one[here]);
409 here += 1;
410 there += 1;
411 }
412 }
413 }
414 out.extend_from_slice(&one[here..]);
415 out.extend_from_slice(&two[there..]);
416}
417
418fn without(one: &[u32], two: &[u32], out: &mut Vec<u32>) {
420 out.clear();
421 let mut there = 0;
422 for &number in one {
423 while there < two.len() && two[there] < number {
424 there += 1;
425 }
426 if there < two.len() && two[there] == number {
427 continue;
428 }
429 out.push(number);
430 }
431}
432
433#[derive(Debug, Clone)]
449struct Rows {
450 rows: Vec<Vec<u32>>,
451}
452
453impl Rows {
454 fn new(rows: usize) -> Self {
455 Self { rows: vec![Vec::new(); rows] }
456 }
457
458 fn row(&self, row: usize) -> &[u32] {
459 &self.rows[row]
460 }
461
462 fn set(&mut self, row: usize, numbers: &[u32]) {
466 let row = &mut self.rows[row];
467 row.clear();
468 row.extend_from_slice(numbers);
469 }
470
471 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
472 self.rows[row].iter().copied().map(Reg::virtual_reg)
473 }
474}
475
476struct Building {
486 flags: Vec<bool>,
487 touched: Vec<u32>,
491}
492
493impl Building {
494 fn new(vregs: usize) -> Self {
495 Self { flags: vec![false; vregs], touched: Vec::new() }
496 }
497
498 fn number(&self, reg: Reg) -> Option<usize> {
502 let number = usize::try_from(reg.number()?).ok()?;
503 (number < self.flags.len()).then_some(number)
504 }
505
506 fn insert(&mut self, reg: Reg) {
507 let Some(number) = self.number(reg) else { return };
508 if !self.flags[number] {
509 self.flags[number] = true;
510 self.touched.push(u32::try_from(number).expect("a register number"));
511 }
512 }
513
514 fn remove(&mut self, reg: Reg) {
515 if let Some(number) = self.number(reg) {
516 self.flags[number] = false;
517 }
518 }
519
520 fn take(&mut self) -> Vec<u32> {
522 let flags = &mut self.flags;
523 let mut out: Vec<u32> = self
524 .touched
525 .drain(..)
526 .filter(|&number| std::mem::replace(&mut flags[number as usize], false))
527 .collect();
528 out.sort_unstable();
529 out
530 }
531}
532
533#[cfg(test)]
534mod tests {
535 use rucc_base::Interner;
536 use rucc_mir::{BlockCall, Constraint, Opcode, Operand};
537 use rucc_target::x86_64::GPR;
538
539 use super::*;
540
541 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
543 of.filter_map(Reg::number).collect()
544 }
545
546 #[test]
547 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
548 let mut names = Interner::new();
549 let mut func = Func::new(names.intern("f"));
550 let opcode = Opcode::new(names.intern("x64.nop"));
551 let block = func.create_block();
552 let value = func.new_vreg(GPR);
553 let other = func.new_vreg(GPR);
554 let write = func.build(block, opcode).def(value, GPR).finish();
555 let idle = func.build(block, opcode).def(other, GPR).finish();
556 let read = func.build(block, opcode).uses(value, GPR).finish();
557
558 let order = Order::of(&func);
559 let live = Live::of(&func, &order);
560 let range = live.range(value).expect("the value is live somewhere");
561 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
562 assert!(range.covers(order.early(idle)));
563 assert_eq!(
566 live.range(other),
567 Some(Range { start: order.late(idle), end: order.late(idle) })
568 );
569 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
570 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
571 }
572
573 #[test]
574 fn a_value_read_in_another_block_is_live_between_them() {
575 let mut names = Interner::new();
576 let mut func = Func::new(names.intern("f"));
577 let opcode = Opcode::new(names.intern("x64.nop"));
578 let head = func.create_block();
579 let middle = func.create_block();
580 let tail = func.create_block();
581 let value = func.new_vreg(GPR);
582 func.build(head, opcode).def(value, GPR).finish();
583 *func.succs_mut(head) = vec![BlockCall::to(middle)];
584 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
585 let read = func.build(tail, opcode).uses(value, GPR).finish();
586
587 let order = Order::of(&func);
588 let live = Live::of(&func, &order);
589 assert_eq!(regs(live.live_in(middle)), vec![0]);
592 assert_eq!(regs(live.live_out(middle)), vec![0]);
593 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
594 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
595 }
596
597 #[test]
598 fn a_block_the_value_never_reaches_is_a_hole_between_two_pieces() {
599 let mut names = Interner::new();
600 let mut func = Func::new(names.intern("f"));
601 let opcode = Opcode::new(names.intern("x64.nop"));
602 let entry = func.create_block();
603 let arm = func.create_block();
604 let tail = func.create_block();
605 let value = func.new_vreg(GPR);
606 let write = func.build(entry, opcode).def(value, GPR).finish();
607 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
608 let idle = func.build(arm, opcode).finish();
609 let read = func.build(tail, opcode).uses(value, GPR).finish();
610
611 let order = Order::of(&func);
612 let live = Live::of(&func, &order);
613 let area = live.area(value).expect("live somewhere");
614 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
618 assert!(!area.covers(order.early(idle)));
619 assert_eq!(
620 area.pieces().collect::<Vec<_>>(),
621 vec![
622 Range { start: order.late(write), end: order.end(entry) },
623 Range { start: order.start(tail), end: order.early(read) },
624 ]
625 );
626 }
627
628 #[test]
629 fn a_value_in_a_hole_of_another_may_have_its_register() {
630 let mut names = Interner::new();
631 let mut func = Func::new(names.intern("f"));
632 let opcode = Opcode::new(names.intern("x64.nop"));
633 let entry = func.create_block();
634 let arm = func.create_block();
635 let tail = func.create_block();
636 let value = func.new_vreg(GPR);
637 let inside = func.new_vreg(GPR);
638 func.build(entry, opcode).def(value, GPR).finish();
639 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
640 func.build(arm, opcode).def(inside, GPR).finish();
641 func.build(arm, opcode).uses(inside, GPR).finish();
642 func.build(tail, opcode).uses(value, GPR).finish();
643
644 let order = Order::of(&func);
645 let live = Live::of(&func, &order);
646 let value = live.area(value).expect("live somewhere");
647 let inside = live.area(inside).expect("live somewhere");
648 assert!(value.hull().overlaps(inside.hull()));
652 assert!(!value.overlaps(inside));
653 assert!(!inside.overlaps(value));
654 }
655
656 #[test]
657 fn one_point_added_in_front_of_a_piece_is_part_of_the_area() {
658 let mut names = Interner::new();
659 let mut func = Func::new(names.intern("f"));
660 let opcode = Opcode::new(names.intern("x64.nop"));
661 let block = func.create_block();
662 let first = func.new_vreg(GPR);
663 let second = func.new_vreg(GPR);
664 let write = func.build(block, opcode).def(first, GPR).finish();
665 let both = func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
666
667 let order = Order::of(&func);
668 let live = Live::of(&func, &order);
669 let first = live.area(first).expect("live somewhere");
670 let second = live.area(second).expect("live somewhere");
671 assert!(!first.overlaps(second));
676 assert!(first.overlaps(second.with(order.early(both))));
677 assert!(second.with(order.early(both)).covers(order.early(both)));
678 assert_eq!(second.with(order.early(both)).hull().start, order.early(both));
679 assert_eq!(first.hull().start, order.late(write));
680 }
681
682 #[test]
683 fn the_point_added_in_front_joins_the_piece_it_belongs_to_and_not_the_first_one() {
684 let mut names = Interner::new();
685 let mut func = Func::new(names.intern("f"));
686 let nop = Opcode::new(names.intern("x64.nop"));
687 let add = Opcode::new(names.intern("x64.add"));
688 let entry = func.create_block();
689 let head = func.create_block();
690 let arm = func.create_block();
691 let latch = func.create_block();
692 let out = func.create_block();
693 let seed = func.new_vreg(GPR);
694 let sum = func.new_vreg(GPR);
695 let inside = func.new_vreg(GPR);
696 let loaded = func.new_vreg(GPR);
697 func.build(entry, nop).def(seed, GPR).finish();
698 func.build(entry, nop).def(sum, GPR).finish();
699 *func.succs_mut(entry) = vec![BlockCall::to(head)];
700 func.build(head, nop).uses(sum, GPR).finish();
701 *func.succs_mut(head) = vec![BlockCall::to(arm), BlockCall::to(latch)];
702 func.build(arm, nop).def(inside, GPR).finish();
703 func.build(arm, nop).uses(inside, GPR).finish();
704 *func.succs_mut(arm) = vec![BlockCall::to(out)];
705 func.build(latch, nop).def(loaded, GPR).finish();
706 let carry = func
707 .build(latch, add)
708 .operand(Operand::write(sum, GPR).with(Constraint::Reuse(1)))
709 .uses(seed, GPR)
710 .uses(loaded, GPR)
711 .finish();
712 *func.succs_mut(latch) = vec![BlockCall::to(head), BlockCall::to(out)];
713
714 let order = Order::of(&func);
715 let live = Live::of(&func, &order);
716 let sum = live.area(sum).expect("live somewhere");
717 let loaded = live.area(loaded).expect("live somewhere");
718 assert_eq!(sum.pieces().count(), 2);
723 assert!(!sum.covers(order.early(carry)));
724 assert!(sum.with(order.early(carry)).covers(order.early(carry)));
725 assert!(!loaded.overlaps(sum));
726 assert!(loaded.overlaps(sum.with(order.early(carry))));
727 }
728
729 #[test]
730 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
731 let mut names = Interner::new();
732 let mut func = Func::new(names.intern("f"));
733 let opcode = Opcode::new(names.intern("x64.nop"));
734 let header = func.create_block();
735 let body = func.create_block();
736 let carried = func.append_param(header, GPR);
737 let next = func.new_vreg(GPR);
738 *func.succs_mut(header) = vec![BlockCall::to(body)];
739 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
740 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
741
742 let order = Order::of(&func);
743 let live = Live::of(&func, &order);
744 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
747 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
748 let range = live.range(next).expect("live somewhere");
749 assert_eq!(range.end, order.end(body));
750 }
751
752 #[test]
753 fn two_values_that_are_never_both_wanted_do_not_overlap() {
754 let mut names = Interner::new();
755 let mut func = Func::new(names.intern("f"));
756 let opcode = Opcode::new(names.intern("x64.nop"));
757 let block = func.create_block();
758 let first = func.new_vreg(GPR);
759 let second = func.new_vreg(GPR);
760 let write = func.build(block, opcode).def(first, GPR).finish();
761 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
762
763 let order = Order::of(&func);
764 let live = Live::of(&func, &order);
765 let first = live.range(first).expect("live somewhere");
766 let second = live.range(second).expect("live somewhere");
767 assert!(!first.overlaps(second));
771 assert!(first.start > order.start(block));
772 assert_eq!(first.start, order.late(write));
773 }
774
775 #[test]
776 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
777 let mut names = Interner::new();
778 let mut func = Func::new(names.intern("f"));
779 let opcode = Opcode::new(names.intern("x64.nop"));
780 let block = func.create_block();
781 let source = func.new_vreg(GPR);
782 let early = func.new_vreg(GPR);
783 func.build(block, opcode).def(source, GPR).finish();
784 func.build(block, opcode)
785 .operand(Operand::write_early(early, GPR))
786 .operand(Operand::read(source, GPR))
787 .finish();
788
789 let order = Order::of(&func);
790 let live = Live::of(&func, &order);
791 let source = live.range(source).expect("live somewhere");
792 let early = live.range(early).expect("live somewhere");
793 assert!(source.overlaps(early));
796 }
797
798 #[test]
799 fn a_register_a_memory_operand_names_is_read_like_any_other() {
800 use rucc_mir::Mem;
801
802 let mut names = Interner::new();
803 let mut func = Func::new(names.intern("f"));
804 let opcode = Opcode::new(names.intern("x64.nop"));
805 let block = func.create_block();
806 let address = func.new_vreg(GPR);
807 let write = func.build(block, opcode).def(address, GPR).finish();
808 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
809
810 let order = Order::of(&func);
811 let live = Live::of(&func, &order);
812 assert_eq!(
813 live.range(address),
814 Some(Range { start: order.late(write), end: order.early(load) })
815 );
816 }
817}