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 #[cfg(test)]
113 pub(crate) fn of_pieces(pieces: &'a [Range]) -> Self {
114 Self { pieces, also: None }
115 }
116
117 #[must_use]
122 pub fn with(self, point: Point) -> Self {
123 Self { also: Some(point), ..self }
124 }
125
126 #[must_use]
129 pub fn hull(self) -> Range {
130 Range { start: self.piece(0).start, end: self.pieces[self.pieces.len() - 1].end }
131 }
132
133 #[must_use]
139 pub fn covers(self, point: Point) -> bool {
140 let first = self.pieces.partition_point(|piece| piece.end < point);
141 first < self.pieces.len() && self.piece(first).covers(point)
142 }
143
144 #[must_use]
149 pub fn overlaps(self, other: Self) -> bool {
150 let (mut mine, mut theirs) = (0, 0);
151 while mine < self.pieces.len() && theirs < other.pieces.len() {
152 let (one, two) = (self.piece(mine), other.piece(theirs));
153 if one.overlaps(two) {
154 return true;
155 }
156 if one.end < two.end {
158 mine += 1;
159 } else {
160 theirs += 1;
161 }
162 }
163 false
164 }
165
166 pub fn pieces(self) -> impl Iterator<Item = Range> + 'a {
168 (0..self.pieces.len()).map(move |piece| self.piece(piece))
169 }
170
171 pub(crate) fn count(self) -> usize {
173 self.pieces.len()
174 }
175
176 pub(crate) fn piece(self, index: usize) -> Range {
179 let piece = self.pieces[index];
180 match self.also {
181 Some(also) if also + 1 == piece.start => Range { start: also, end: piece.end },
182 _ => piece,
183 }
184 }
185}
186
187#[derive(Debug, Clone)]
189pub struct Live {
190 live_in: Rows,
191 live_out: Rows,
192 pieces: Vec<Range>,
194 spans: Vec<(usize, usize)>,
196}
197
198impl Live {
199 #[must_use]
201 pub fn of(func: &Func, order: &Order) -> Self {
202 let vregs = func.vregs();
203 let (used, defined) = exposed(func, order);
204 let (live_in, live_out) = flow(func, order, &used, &defined);
205 let (pieces, spans) = carve(func, order, &live_in, &live_out, vregs);
206 Self { live_in, live_out, pieces, spans }
207 }
208
209 #[must_use]
212 pub fn area(&self, reg: Reg) -> Option<Area<'_>> {
213 let pieces = self.pieces(reg);
214 if pieces.is_empty() {
215 return None;
216 }
217 Some(Area { pieces, also: None })
218 }
219
220 #[must_use]
222 pub fn range(&self, reg: Reg) -> Option<Range> {
223 self.area(reg).map(Area::hull)
224 }
225
226 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
231 self.live_in.iter(block.index())
232 }
233
234 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
237 self.live_out.iter(block.index())
238 }
239
240 fn pieces(&self, reg: Reg) -> &[Range] {
242 let number = reg.number().and_then(|number| usize::try_from(number).ok());
243 let Some(&(from, to)) = number.and_then(|number| self.spans.get(number)) else {
244 return &[];
245 };
246 &self.pieces[from..to]
247 }
248}
249
250fn carve(
260 func: &Func,
261 order: &Order,
262 live_in: &Rows,
263 live_out: &Rows,
264 vregs: usize,
265) -> (Vec<Range>, Vec<(usize, usize)>) {
266 let mut found: Vec<(u32, Range)> = Vec::new();
269 let mut last = vec![u32::MAX; vregs];
271 let mut here: Vec<Option<Range>> = vec![None; vregs];
272 let mut touched: Vec<usize> = Vec::new();
273
274 for &block in order.blocks() {
275 for reg in live_in.iter(block.index()) {
278 note(&mut here, &mut touched, reg, order.start(block));
279 }
280 for reg in live_out.iter(block.index()) {
281 note(&mut here, &mut touched, reg, order.end(block));
282 }
283 for param in &func[block].params {
284 note(&mut here, &mut touched, param.reg, order.start(block));
285 }
286 for inst in func.insts(block) {
287 for operand in &func[func[inst].operands] {
288 match operand.role {
289 Role::Use => note(&mut here, &mut touched, operand.reg, order.early(inst)),
290 Role::Def => note(&mut here, &mut touched, operand.reg, order.late(inst)),
291 Role::EarlyDef => {
298 note(&mut here, &mut touched, operand.reg, order.early(inst));
299 note(&mut here, &mut touched, operand.reg, order.late(inst));
300 }
301 }
302 }
303 }
304 for call in &func[block].succs {
305 for &arg in &call.args {
306 note(&mut here, &mut touched, arg, order.end(block));
307 }
308 }
309
310 for &number in &touched {
311 let Some(piece) = here[number].take() else { continue };
312 match found.get_mut(last[number] as usize) {
313 Some((_, previous)) if previous.end + 1 == piece.start => previous.end = piece.end,
317 _ => {
318 last[number] = u32::try_from(found.len()).expect("a piece number");
319 found.push((u32::try_from(number).expect("a register number"), piece));
320 }
321 }
322 }
323 touched.clear();
324 }
325
326 let mut starts = vec![0usize; vregs + 1];
328 for &(number, _) in &found {
329 starts[number as usize + 1] += 1;
330 }
331 for number in 0..vregs {
332 starts[number + 1] += starts[number];
333 }
334 let mut filled = starts.clone();
335 let mut pieces = vec![Range { start: 0, end: 0 }; found.len()];
336 for &(number, piece) in &found {
337 let at = &mut filled[number as usize];
338 pieces[*at] = piece;
339 *at += 1;
340 }
341 let spans = (0..vregs).map(|number| (starts[number], starts[number + 1])).collect();
342 (pieces, spans)
343}
344
345fn note(here: &mut [Option<Range>], touched: &mut Vec<usize>, reg: Reg, point: Point) {
347 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
348 return;
349 };
350 let Some(slot) = here.get_mut(number) else { return };
351 match slot {
352 Some(range) => *range = range.with(point),
353 None => {
354 *slot = Some(Range { start: point, end: point });
355 touched.push(number);
356 }
357 }
358}
359
360fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
365 let vregs = func.vregs();
366 let mut used = Vec::new();
367 let mut defined = Vec::new();
368 let mut reads = Building::new(vregs);
369 let mut writes = Building::new(vregs);
370 for &block in order.blocks() {
371 let row = block.index();
372 for call in &func[block].succs {
373 for &arg in &call.args {
374 reads.insert(arg);
375 }
376 }
377 let insts: Vec<_> = func.insts(block).collect();
378 for &inst in insts.iter().rev() {
379 let operands = &func[func[inst].operands];
380 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
381 reads.remove(operand.reg);
382 writes.insert(operand.reg);
383 }
384 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
385 reads.insert(operand.reg);
386 }
387 }
388 for param in &func[block].params {
389 reads.remove(param.reg);
390 writes.insert(param.reg);
391 }
392 used.extend(reads.take().into_iter().map(|number| (row_of(row), number)));
393 defined.extend(writes.take().into_iter().map(|number| (row_of(row), number)));
394 }
395 (Rows::gather(func.block_count(), &used), Rows::gather(func.block_count(), &defined))
396}
397
398fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
412 let count = func.block_count();
413 let vregs = func.vregs();
414 let mut preds: Vec<Vec<usize>> = vec![Vec::new(); count];
415 for &block in order.blocks() {
416 for call in &func[block].succs {
417 preds[call.block.index()].push(block.index());
418 }
419 }
420 let mut starts = vec![0usize; vregs + 1];
422 for &block in order.blocks() {
423 for &number in used.row(block.index()) {
424 starts[number as usize + 1] += 1;
425 }
426 }
427 for number in 0..vregs {
428 starts[number + 1] += starts[number];
429 }
430 let mut readers = vec![0usize; starts[vregs]];
431 let mut filled = starts.clone();
432 for &block in order.blocks() {
433 for &number in used.row(block.index()) {
434 readers[filled[number as usize]] = block.index();
435 filled[number as usize] += 1;
436 }
437 }
438 let mut ends = vec![0usize; vregs + 1];
441 for &block in order.blocks() {
442 for &number in defined.row(block.index()) {
443 ends[number as usize + 1] += 1;
444 }
445 }
446 for number in 0..vregs {
447 ends[number + 1] += ends[number];
448 }
449 let mut writers = vec![0usize; ends[vregs]];
450 let mut filled = ends.clone();
451 for &block in order.blocks() {
452 for &number in defined.row(block.index()) {
453 writers[filled[number as usize]] = block.index();
454 filled[number as usize] += 1;
455 }
456 }
457
458 let mut live_in = Vec::new();
459 let mut live_out = Vec::new();
460 let mut arrived = vec![u32::MAX; count];
463 let mut left = vec![u32::MAX; count];
464 let mut wrote = vec![u32::MAX; count];
465 let mut waiting = Vec::new();
466 for number in 0..vregs {
467 let value = u32::try_from(number).expect("a register number");
468 for &row in &writers[ends[number]..ends[number + 1]] {
469 wrote[row] = value;
470 }
471 for &row in &readers[starts[number]..starts[number + 1]] {
472 if arrived[row] != value {
473 arrived[row] = value;
474 live_in.push((row_of(row), value));
475 waiting.push(row);
476 }
477 }
478 while let Some(row) = waiting.pop() {
479 for &pred in &preds[row] {
480 if left[pred] != value {
481 left[pred] = value;
482 live_out.push((row_of(pred), value));
483 }
484 if arrived[pred] != value && wrote[pred] != value {
485 arrived[pred] = value;
486 live_in.push((row_of(pred), value));
487 waiting.push(pred);
488 }
489 }
490 }
491 }
492 (Rows::transpose(count, &live_in), Rows::transpose(count, &live_out))
493}
494
495#[derive(Debug, Clone)]
515struct Rows {
516 starts: Vec<usize>,
518 numbers: Vec<u32>,
519}
520
521impl Rows {
522 fn gather(rows: usize, pairs: &[(u32, u32)]) -> Self {
528 let (starts, mut filled) = Self::starts(rows, pairs);
529 let mut numbers = vec![0u32; pairs.len()];
530 for &(row, number) in pairs {
531 let at = &mut filled[row as usize];
532 numbers[*at] = number;
533 *at += 1;
534 }
535 Self { starts, numbers }
536 }
537
538 fn transpose(rows: usize, pairs: &[(u32, u32)]) -> Self {
547 let mut shift = 0;
548 while rows > Self::WAYS << shift {
549 shift += 1;
550 }
551 if shift == 0 {
552 return Self::gather(rows, pairs);
553 }
554 let (starts, mut filled) = Self::starts(rows, pairs);
555 let mut next: Vec<usize> =
557 (0..rows.div_ceil(1 << shift)).map(|run| starts[run << shift]).collect();
558 let mut runs = vec![(0u32, 0u32); pairs.len()];
559 for &pair in pairs {
560 let at = &mut next[(pair.0 >> shift) as usize];
561 runs[*at] = pair;
562 *at += 1;
563 }
564 let mut numbers = vec![0u32; pairs.len()];
565 for &(row, number) in &runs {
566 let at = &mut filled[row as usize];
567 numbers[*at] = number;
568 *at += 1;
569 }
570 Self { starts, numbers }
571 }
572
573 const WAYS: usize = 256;
575
576 fn starts(rows: usize, pairs: &[(u32, u32)]) -> (Vec<usize>, Vec<usize>) {
579 let mut starts = vec![0usize; rows + 1];
580 for &(row, _) in pairs {
581 starts[row as usize + 1] += 1;
582 }
583 for row in 0..rows {
584 starts[row + 1] += starts[row];
585 }
586 let filled = starts.clone();
587 (starts, filled)
588 }
589
590 fn row(&self, row: usize) -> &[u32] {
591 &self.numbers[self.starts[row]..self.starts[row + 1]]
592 }
593
594 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
595 self.row(row).iter().copied().map(Reg::virtual_reg)
596 }
597}
598
599fn row_of(index: usize) -> u32 {
601 u32::try_from(index).expect("a block number")
602}
603
604struct Building {
614 flags: Vec<bool>,
615 touched: Vec<u32>,
619}
620
621impl Building {
622 fn new(vregs: usize) -> Self {
623 Self { flags: vec![false; vregs], touched: Vec::new() }
624 }
625
626 fn number(&self, reg: Reg) -> Option<usize> {
630 let number = usize::try_from(reg.number()?).ok()?;
631 (number < self.flags.len()).then_some(number)
632 }
633
634 fn insert(&mut self, reg: Reg) {
635 let Some(number) = self.number(reg) else { return };
636 if !self.flags[number] {
637 self.flags[number] = true;
638 self.touched.push(u32::try_from(number).expect("a register number"));
639 }
640 }
641
642 fn remove(&mut self, reg: Reg) {
643 if let Some(number) = self.number(reg) {
644 self.flags[number] = false;
645 }
646 }
647
648 fn take(&mut self) -> Vec<u32> {
650 let flags = &mut self.flags;
651 let mut out: Vec<u32> = self
652 .touched
653 .drain(..)
654 .filter(|&number| std::mem::replace(&mut flags[number as usize], false))
655 .collect();
656 out.sort_unstable();
657 out
658 }
659}
660
661#[cfg(test)]
662mod tests {
663 use rucc_base::Interner;
664 use rucc_mir::{BlockCall, Constraint, Opcode, Operand};
665 use rucc_target::x86_64::GPR;
666
667 use super::*;
668
669 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
671 of.filter_map(Reg::number).collect()
672 }
673
674 #[test]
675 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
676 let mut names = Interner::new();
677 let mut func = Func::new(names.intern("f"));
678 let opcode = Opcode::new(names.intern("x64.nop"));
679 let block = func.create_block();
680 let value = func.new_vreg(GPR);
681 let other = func.new_vreg(GPR);
682 let write = func.build(block, opcode).def(value, GPR).finish();
683 let idle = func.build(block, opcode).def(other, GPR).finish();
684 let read = func.build(block, opcode).uses(value, GPR).finish();
685
686 let order = Order::of(&func);
687 let live = Live::of(&func, &order);
688 let range = live.range(value).expect("the value is live somewhere");
689 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
690 assert!(range.covers(order.early(idle)));
691 assert_eq!(
694 live.range(other),
695 Some(Range { start: order.late(idle), end: order.late(idle) })
696 );
697 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
698 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
699 }
700
701 #[test]
702 fn a_value_read_in_another_block_is_live_between_them() {
703 let mut names = Interner::new();
704 let mut func = Func::new(names.intern("f"));
705 let opcode = Opcode::new(names.intern("x64.nop"));
706 let head = func.create_block();
707 let middle = func.create_block();
708 let tail = func.create_block();
709 let value = func.new_vreg(GPR);
710 func.build(head, opcode).def(value, GPR).finish();
711 *func.succs_mut(head) = vec![BlockCall::to(middle)];
712 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
713 let read = func.build(tail, opcode).uses(value, GPR).finish();
714
715 let order = Order::of(&func);
716 let live = Live::of(&func, &order);
717 assert_eq!(regs(live.live_in(middle)), vec![0]);
720 assert_eq!(regs(live.live_out(middle)), vec![0]);
721 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
722 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
723 }
724
725 #[test]
726 fn a_block_the_value_never_reaches_is_a_hole_between_two_pieces() {
727 let mut names = Interner::new();
728 let mut func = Func::new(names.intern("f"));
729 let opcode = Opcode::new(names.intern("x64.nop"));
730 let entry = func.create_block();
731 let arm = func.create_block();
732 let tail = func.create_block();
733 let value = func.new_vreg(GPR);
734 let write = func.build(entry, opcode).def(value, GPR).finish();
735 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
736 let idle = func.build(arm, opcode).finish();
737 let read = func.build(tail, opcode).uses(value, GPR).finish();
738
739 let order = Order::of(&func);
740 let live = Live::of(&func, &order);
741 let area = live.area(value).expect("live somewhere");
742 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
746 assert!(!area.covers(order.early(idle)));
747 assert_eq!(
748 area.pieces().collect::<Vec<_>>(),
749 vec![
750 Range { start: order.late(write), end: order.end(entry) },
751 Range { start: order.start(tail), end: order.early(read) },
752 ]
753 );
754 }
755
756 #[test]
757 fn a_value_in_a_hole_of_another_may_have_its_register() {
758 let mut names = Interner::new();
759 let mut func = Func::new(names.intern("f"));
760 let opcode = Opcode::new(names.intern("x64.nop"));
761 let entry = func.create_block();
762 let arm = func.create_block();
763 let tail = func.create_block();
764 let value = func.new_vreg(GPR);
765 let inside = func.new_vreg(GPR);
766 func.build(entry, opcode).def(value, GPR).finish();
767 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
768 func.build(arm, opcode).def(inside, GPR).finish();
769 func.build(arm, opcode).uses(inside, GPR).finish();
770 func.build(tail, opcode).uses(value, GPR).finish();
771
772 let order = Order::of(&func);
773 let live = Live::of(&func, &order);
774 let value = live.area(value).expect("live somewhere");
775 let inside = live.area(inside).expect("live somewhere");
776 assert!(value.hull().overlaps(inside.hull()));
780 assert!(!value.overlaps(inside));
781 assert!(!inside.overlaps(value));
782 }
783
784 #[test]
785 fn one_point_added_in_front_of_a_piece_is_part_of_the_area() {
786 let mut names = Interner::new();
787 let mut func = Func::new(names.intern("f"));
788 let opcode = Opcode::new(names.intern("x64.nop"));
789 let block = func.create_block();
790 let first = func.new_vreg(GPR);
791 let second = func.new_vreg(GPR);
792 let write = func.build(block, opcode).def(first, GPR).finish();
793 let both = func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
794
795 let order = Order::of(&func);
796 let live = Live::of(&func, &order);
797 let first = live.area(first).expect("live somewhere");
798 let second = live.area(second).expect("live somewhere");
799 assert!(!first.overlaps(second));
804 assert!(first.overlaps(second.with(order.early(both))));
805 assert!(second.with(order.early(both)).covers(order.early(both)));
806 assert_eq!(second.with(order.early(both)).hull().start, order.early(both));
807 assert_eq!(first.hull().start, order.late(write));
808 }
809
810 #[test]
811 fn the_point_added_in_front_joins_the_piece_it_belongs_to_and_not_the_first_one() {
812 let mut names = Interner::new();
813 let mut func = Func::new(names.intern("f"));
814 let nop = Opcode::new(names.intern("x64.nop"));
815 let add = Opcode::new(names.intern("x64.add"));
816 let entry = func.create_block();
817 let head = func.create_block();
818 let arm = func.create_block();
819 let latch = func.create_block();
820 let out = func.create_block();
821 let seed = func.new_vreg(GPR);
822 let sum = func.new_vreg(GPR);
823 let inside = func.new_vreg(GPR);
824 let loaded = func.new_vreg(GPR);
825 func.build(entry, nop).def(seed, GPR).finish();
826 func.build(entry, nop).def(sum, GPR).finish();
827 *func.succs_mut(entry) = vec![BlockCall::to(head)];
828 func.build(head, nop).uses(sum, GPR).finish();
829 *func.succs_mut(head) = vec![BlockCall::to(arm), BlockCall::to(latch)];
830 func.build(arm, nop).def(inside, GPR).finish();
831 func.build(arm, nop).uses(inside, GPR).finish();
832 *func.succs_mut(arm) = vec![BlockCall::to(out)];
833 func.build(latch, nop).def(loaded, GPR).finish();
834 let carry = func
835 .build(latch, add)
836 .operand(Operand::write(sum, GPR).with(Constraint::Reuse(1)))
837 .uses(seed, GPR)
838 .uses(loaded, GPR)
839 .finish();
840 *func.succs_mut(latch) = vec![BlockCall::to(head), BlockCall::to(out)];
841
842 let order = Order::of(&func);
843 let live = Live::of(&func, &order);
844 let sum = live.area(sum).expect("live somewhere");
845 let loaded = live.area(loaded).expect("live somewhere");
846 assert_eq!(sum.pieces().count(), 2);
851 assert!(!sum.covers(order.early(carry)));
852 assert!(sum.with(order.early(carry)).covers(order.early(carry)));
853 assert!(!loaded.overlaps(sum));
854 assert!(loaded.overlaps(sum.with(order.early(carry))));
855 }
856
857 #[test]
858 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
859 let mut names = Interner::new();
860 let mut func = Func::new(names.intern("f"));
861 let opcode = Opcode::new(names.intern("x64.nop"));
862 let header = func.create_block();
863 let body = func.create_block();
864 let carried = func.append_param(header, GPR);
865 let next = func.new_vreg(GPR);
866 *func.succs_mut(header) = vec![BlockCall::to(body)];
867 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
868 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
869
870 let order = Order::of(&func);
871 let live = Live::of(&func, &order);
872 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
875 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
876 let range = live.range(next).expect("live somewhere");
877 assert_eq!(range.end, order.end(body));
878 }
879
880 #[test]
881 fn two_values_that_are_never_both_wanted_do_not_overlap() {
882 let mut names = Interner::new();
883 let mut func = Func::new(names.intern("f"));
884 let opcode = Opcode::new(names.intern("x64.nop"));
885 let block = func.create_block();
886 let first = func.new_vreg(GPR);
887 let second = func.new_vreg(GPR);
888 let write = func.build(block, opcode).def(first, GPR).finish();
889 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
890
891 let order = Order::of(&func);
892 let live = Live::of(&func, &order);
893 let first = live.range(first).expect("live somewhere");
894 let second = live.range(second).expect("live somewhere");
895 assert!(!first.overlaps(second));
899 assert!(first.start > order.start(block));
900 assert_eq!(first.start, order.late(write));
901 }
902
903 #[test]
904 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
905 let mut names = Interner::new();
906 let mut func = Func::new(names.intern("f"));
907 let opcode = Opcode::new(names.intern("x64.nop"));
908 let block = func.create_block();
909 let source = func.new_vreg(GPR);
910 let early = func.new_vreg(GPR);
911 func.build(block, opcode).def(source, GPR).finish();
912 func.build(block, opcode)
913 .operand(Operand::write_early(early, GPR))
914 .operand(Operand::read(source, GPR))
915 .finish();
916
917 let order = Order::of(&func);
918 let live = Live::of(&func, &order);
919 let source = live.range(source).expect("live somewhere");
920 let early = live.range(early).expect("live somewhere");
921 assert!(source.overlaps(early));
924 }
925
926 #[test]
927 fn a_register_a_memory_operand_names_is_read_like_any_other() {
928 use rucc_mir::Mem;
929
930 let mut names = Interner::new();
931 let mut func = Func::new(names.intern("f"));
932 let opcode = Opcode::new(names.intern("x64.nop"));
933 let block = func.create_block();
934 let address = func.new_vreg(GPR);
935 let write = func.build(block, opcode).def(address, GPR).finish();
936 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
937
938 let order = Order::of(&func);
939 let live = Live::of(&func, &order);
940 assert_eq!(
941 live.range(address),
942 Some(Range { start: order.late(write), end: order.early(load) })
943 );
944 }
945
946 #[test]
947 fn rows_from_a_list_a_value_at_a_time_over_many_blocks_keep_the_order_the_numbers_came_in() {
948 let rows = 3000;
951 let mut pairs = Vec::new();
952 let mut seed = 7u32;
953 for number in 0..400 {
954 for _ in 0..30 {
955 seed = seed.wrapping_mul(1_103_515_245).wrapping_add(12345);
956 pairs.push(((seed >> 8) % 3000, number));
957 }
958 }
959 let gathered = Rows::transpose(rows, &pairs);
960 for row in 0..rows {
961 let wanted: Vec<u32> = pairs
962 .iter()
963 .filter(|&&(at, _)| at as usize == row)
964 .map(|&(_, number)| number)
965 .collect();
966 assert_eq!(gathered.row(row), wanted, "row {row}");
967 }
968 }
969}