1use rucc_mir::{Block, Func, Reg, Role};
49
50use crate::order::{Order, Point};
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub struct Range {
61 pub start: Point,
63 pub end: Point,
65}
66
67impl Range {
68 #[must_use]
70 pub fn covers(self, point: Point) -> bool {
71 self.start <= point && point <= self.end
72 }
73
74 #[must_use]
76 pub fn overlaps(self, other: Self) -> bool {
77 self.start <= other.end && other.start <= self.end
78 }
79
80 fn with(self, point: Point) -> Self {
83 Self { start: self.start.min(point), end: self.end.max(point) }
84 }
85}
86
87#[derive(Debug, Clone, Copy)]
98pub struct Area<'a> {
99 pieces: &'a [Range],
100 also: Option<Point>,
101}
102
103impl<'a> Area<'a> {
104 #[must_use]
109 pub fn with(self, point: Point) -> Self {
110 Self { also: Some(point), ..self }
111 }
112
113 #[must_use]
116 pub fn hull(self) -> Range {
117 Range { start: self.piece(0).start, end: self.pieces[self.pieces.len() - 1].end }
118 }
119
120 #[must_use]
122 pub fn covers(self, point: Point) -> bool {
123 (0..self.pieces.len()).any(|piece| self.piece(piece).covers(point))
124 }
125
126 #[must_use]
131 pub fn overlaps(self, other: Self) -> bool {
132 let (mut mine, mut theirs) = (0, 0);
133 while mine < self.pieces.len() && theirs < other.pieces.len() {
134 let (one, two) = (self.piece(mine), other.piece(theirs));
135 if one.overlaps(two) {
136 return true;
137 }
138 if one.end < two.end {
140 mine += 1;
141 } else {
142 theirs += 1;
143 }
144 }
145 false
146 }
147
148 pub fn pieces(self) -> impl Iterator<Item = Range> + 'a {
150 (0..self.pieces.len()).map(move |piece| self.piece(piece))
151 }
152
153 fn piece(self, index: usize) -> Range {
156 let piece = self.pieces[index];
157 match self.also {
158 Some(also) if also + 1 == piece.start => Range { start: also, end: piece.end },
159 _ => piece,
160 }
161 }
162}
163
164#[derive(Debug, Clone)]
166pub struct Live {
167 live_in: Rows,
168 live_out: Rows,
169 pieces: Vec<Range>,
171 spans: Vec<(usize, usize)>,
173}
174
175impl Live {
176 #[must_use]
178 pub fn of(func: &Func, order: &Order) -> Self {
179 let vregs = func.vregs();
180 let (used, defined) = exposed(func, order);
181 let (live_in, live_out) = flow(func, order, &used, &defined);
182 let (pieces, spans) = carve(func, order, &live_in, &live_out, vregs);
183 Self { live_in, live_out, pieces, spans }
184 }
185
186 #[must_use]
189 pub fn area(&self, reg: Reg) -> Option<Area<'_>> {
190 let pieces = self.pieces(reg);
191 if pieces.is_empty() {
192 return None;
193 }
194 Some(Area { pieces, also: None })
195 }
196
197 #[must_use]
199 pub fn range(&self, reg: Reg) -> Option<Range> {
200 self.area(reg).map(Area::hull)
201 }
202
203 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
208 self.live_in.iter(block.index())
209 }
210
211 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
214 self.live_out.iter(block.index())
215 }
216
217 fn pieces(&self, reg: Reg) -> &[Range] {
219 let number = reg.number().and_then(|number| usize::try_from(number).ok());
220 let Some(&(from, to)) = number.and_then(|number| self.spans.get(number)) else {
221 return &[];
222 };
223 &self.pieces[from..to]
224 }
225}
226
227fn carve(
233 func: &Func,
234 order: &Order,
235 live_in: &Rows,
236 live_out: &Rows,
237 vregs: usize,
238) -> (Vec<Range>, Vec<(usize, usize)>) {
239 let mut lists: Vec<Vec<Range>> = vec![Vec::new(); vregs];
240 let mut here: Vec<Option<Range>> = vec![None; vregs];
241 let mut touched: Vec<usize> = Vec::new();
242
243 for &block in order.blocks() {
244 for reg in live_in.iter(block.index()) {
247 note(&mut here, &mut touched, reg, order.start(block));
248 }
249 for reg in live_out.iter(block.index()) {
250 note(&mut here, &mut touched, reg, order.end(block));
251 }
252 for param in &func[block].params {
253 note(&mut here, &mut touched, param.reg, order.start(block));
254 }
255 for inst in func.insts(block) {
256 for operand in &func[func[inst].operands] {
257 match operand.role {
258 Role::Use => note(&mut here, &mut touched, operand.reg, order.early(inst)),
259 Role::Def => note(&mut here, &mut touched, operand.reg, order.late(inst)),
260 Role::EarlyDef => {
267 note(&mut here, &mut touched, operand.reg, order.early(inst));
268 note(&mut here, &mut touched, operand.reg, order.late(inst));
269 }
270 }
271 }
272 }
273 for call in &func[block].succs {
274 for &arg in &call.args {
275 note(&mut here, &mut touched, arg, order.end(block));
276 }
277 }
278
279 for &number in &touched {
280 let Some(piece) = here[number].take() else { continue };
281 match lists[number].last_mut() {
282 Some(last) if last.end + 1 == piece.start => last.end = piece.end,
286 _ => lists[number].push(piece),
287 }
288 }
289 touched.clear();
290 }
291
292 let mut pieces = Vec::new();
293 let mut spans = Vec::with_capacity(vregs);
294 for list in &lists {
295 let from = pieces.len();
296 pieces.extend_from_slice(list);
297 spans.push((from, pieces.len()));
298 }
299 (pieces, spans)
300}
301
302fn note(here: &mut [Option<Range>], touched: &mut Vec<usize>, reg: Reg, point: Point) {
304 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
305 return;
306 };
307 let Some(slot) = here.get_mut(number) else { return };
308 match slot {
309 Some(range) => *range = range.with(point),
310 None => {
311 *slot = Some(Range { start: point, end: point });
312 touched.push(number);
313 }
314 }
315}
316
317fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
322 let mut used = Rows::new(func.block_count(), func.vregs());
323 let mut defined = Rows::new(func.block_count(), func.vregs());
324 for &block in order.blocks() {
325 let row = block.index();
326 for call in &func[block].succs {
327 for &arg in &call.args {
328 used.insert(row, arg);
329 }
330 }
331 let insts: Vec<_> = func.insts(block).collect();
332 for &inst in insts.iter().rev() {
333 let operands = &func[func[inst].operands];
334 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
335 used.remove(row, operand.reg);
336 defined.insert(row, operand.reg);
337 }
338 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
339 used.insert(row, operand.reg);
340 }
341 }
342 for param in &func[block].params {
343 used.remove(row, param.reg);
344 defined.insert(row, param.reg);
345 }
346 }
347 (used, defined)
348}
349
350fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
352 let mut live_in = Rows::new(func.block_count(), func.vregs());
353 let mut live_out = Rows::new(func.block_count(), func.vregs());
354 let width = live_in.width;
355 let mut next = vec![0u64; width];
356 let mut changed = true;
357 while changed {
358 changed = false;
359 for &block in order.blocks().iter().rev() {
360 let row = block.index();
361 for call in &func[block].succs {
362 let successor = call.block.index();
363 for (word, &incoming) in
364 live_out.row_mut(row).iter_mut().zip(live_in.row(successor))
365 {
366 *word |= incoming;
367 }
368 }
369 for (index, word) in next.iter_mut().enumerate() {
370 *word =
371 used.row(row)[index] | (live_out.row(row)[index] & !defined.row(row)[index]);
372 }
373 if live_in.row(row) != next.as_slice() {
374 live_in.row_mut(row).copy_from_slice(&next);
375 changed = true;
376 }
377 }
378 }
379 (live_in, live_out)
380}
381
382#[derive(Debug, Clone)]
384struct Rows {
385 words: Vec<u64>,
386 width: usize,
389}
390
391impl Rows {
392 fn new(rows: usize, columns: usize) -> Self {
393 let width = columns.div_ceil(64).max(1);
394 Self { words: vec![0; rows * width], width }
395 }
396
397 fn row(&self, row: usize) -> &[u64] {
398 &self.words[row * self.width..(row + 1) * self.width]
399 }
400
401 fn row_mut(&mut self, row: usize) -> &mut [u64] {
402 &mut self.words[row * self.width..(row + 1) * self.width]
403 }
404
405 fn column(&self, reg: Reg) -> Option<usize> {
407 let number = usize::try_from(reg.number()?).ok()?;
408 (number < self.width * 64).then_some(number)
409 }
410
411 fn insert(&mut self, row: usize, reg: Reg) {
412 if let Some(column) = self.column(reg) {
413 self.row_mut(row)[column / 64] |= 1 << (column % 64);
414 }
415 }
416
417 fn remove(&mut self, row: usize, reg: Reg) {
418 if let Some(column) = self.column(reg) {
419 self.row_mut(row)[column / 64] &= !(1 << (column % 64));
420 }
421 }
422
423 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
424 self.row(row).iter().enumerate().flat_map(|(word, &bits)| {
425 (0..64).filter(move |bit| bits & (1 << bit) != 0).map(move |bit| {
426 Reg::virtual_reg(u32::try_from(word * 64 + bit).expect("a register number"))
427 })
428 })
429 }
430}
431
432#[cfg(test)]
433mod tests {
434 use rucc_base::Interner;
435 use rucc_mir::{BlockCall, Constraint, Opcode, Operand};
436 use rucc_target::x86_64::GPR;
437
438 use super::*;
439
440 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
442 of.filter_map(Reg::number).collect()
443 }
444
445 #[test]
446 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
447 let mut names = Interner::new();
448 let mut func = Func::new(names.intern("f"));
449 let opcode = Opcode::new(names.intern("x64.nop"));
450 let block = func.create_block();
451 let value = func.new_vreg(GPR);
452 let other = func.new_vreg(GPR);
453 let write = func.build(block, opcode).def(value, GPR).finish();
454 let idle = func.build(block, opcode).def(other, GPR).finish();
455 let read = func.build(block, opcode).uses(value, GPR).finish();
456
457 let order = Order::of(&func);
458 let live = Live::of(&func, &order);
459 let range = live.range(value).expect("the value is live somewhere");
460 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
461 assert!(range.covers(order.early(idle)));
462 assert_eq!(
465 live.range(other),
466 Some(Range { start: order.late(idle), end: order.late(idle) })
467 );
468 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
469 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
470 }
471
472 #[test]
473 fn a_value_read_in_another_block_is_live_between_them() {
474 let mut names = Interner::new();
475 let mut func = Func::new(names.intern("f"));
476 let opcode = Opcode::new(names.intern("x64.nop"));
477 let head = func.create_block();
478 let middle = func.create_block();
479 let tail = func.create_block();
480 let value = func.new_vreg(GPR);
481 func.build(head, opcode).def(value, GPR).finish();
482 *func.succs_mut(head) = vec![BlockCall::to(middle)];
483 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
484 let read = func.build(tail, opcode).uses(value, GPR).finish();
485
486 let order = Order::of(&func);
487 let live = Live::of(&func, &order);
488 assert_eq!(regs(live.live_in(middle)), vec![0]);
491 assert_eq!(regs(live.live_out(middle)), vec![0]);
492 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
493 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
494 }
495
496 #[test]
497 fn a_block_the_value_never_reaches_is_a_hole_between_two_pieces() {
498 let mut names = Interner::new();
499 let mut func = Func::new(names.intern("f"));
500 let opcode = Opcode::new(names.intern("x64.nop"));
501 let entry = func.create_block();
502 let arm = func.create_block();
503 let tail = func.create_block();
504 let value = func.new_vreg(GPR);
505 let write = func.build(entry, opcode).def(value, GPR).finish();
506 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
507 let idle = func.build(arm, opcode).finish();
508 let read = func.build(tail, opcode).uses(value, GPR).finish();
509
510 let order = Order::of(&func);
511 let live = Live::of(&func, &order);
512 let area = live.area(value).expect("live somewhere");
513 assert!(live.range(value).expect("live somewhere").covers(order.early(idle)));
517 assert!(!area.covers(order.early(idle)));
518 assert_eq!(
519 area.pieces().collect::<Vec<_>>(),
520 vec![
521 Range { start: order.late(write), end: order.end(entry) },
522 Range { start: order.start(tail), end: order.early(read) },
523 ]
524 );
525 }
526
527 #[test]
528 fn a_value_in_a_hole_of_another_may_have_its_register() {
529 let mut names = Interner::new();
530 let mut func = Func::new(names.intern("f"));
531 let opcode = Opcode::new(names.intern("x64.nop"));
532 let entry = func.create_block();
533 let arm = func.create_block();
534 let tail = func.create_block();
535 let value = func.new_vreg(GPR);
536 let inside = func.new_vreg(GPR);
537 func.build(entry, opcode).def(value, GPR).finish();
538 *func.succs_mut(entry) = vec![BlockCall::to(arm), BlockCall::to(tail)];
539 func.build(arm, opcode).def(inside, GPR).finish();
540 func.build(arm, opcode).uses(inside, GPR).finish();
541 func.build(tail, opcode).uses(value, GPR).finish();
542
543 let order = Order::of(&func);
544 let live = Live::of(&func, &order);
545 let value = live.area(value).expect("live somewhere");
546 let inside = live.area(inside).expect("live somewhere");
547 assert!(value.hull().overlaps(inside.hull()));
551 assert!(!value.overlaps(inside));
552 assert!(!inside.overlaps(value));
553 }
554
555 #[test]
556 fn one_point_added_in_front_of_a_piece_is_part_of_the_area() {
557 let mut names = Interner::new();
558 let mut func = Func::new(names.intern("f"));
559 let opcode = Opcode::new(names.intern("x64.nop"));
560 let block = func.create_block();
561 let first = func.new_vreg(GPR);
562 let second = func.new_vreg(GPR);
563 let write = func.build(block, opcode).def(first, GPR).finish();
564 let both = func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
565
566 let order = Order::of(&func);
567 let live = Live::of(&func, &order);
568 let first = live.area(first).expect("live somewhere");
569 let second = live.area(second).expect("live somewhere");
570 assert!(!first.overlaps(second));
575 assert!(first.overlaps(second.with(order.early(both))));
576 assert!(second.with(order.early(both)).covers(order.early(both)));
577 assert_eq!(second.with(order.early(both)).hull().start, order.early(both));
578 assert_eq!(first.hull().start, order.late(write));
579 }
580
581 #[test]
582 fn the_point_added_in_front_joins_the_piece_it_belongs_to_and_not_the_first_one() {
583 let mut names = Interner::new();
584 let mut func = Func::new(names.intern("f"));
585 let nop = Opcode::new(names.intern("x64.nop"));
586 let add = Opcode::new(names.intern("x64.add"));
587 let entry = func.create_block();
588 let head = func.create_block();
589 let arm = func.create_block();
590 let latch = func.create_block();
591 let out = func.create_block();
592 let seed = func.new_vreg(GPR);
593 let sum = func.new_vreg(GPR);
594 let inside = func.new_vreg(GPR);
595 let loaded = func.new_vreg(GPR);
596 func.build(entry, nop).def(seed, GPR).finish();
597 func.build(entry, nop).def(sum, GPR).finish();
598 *func.succs_mut(entry) = vec![BlockCall::to(head)];
599 func.build(head, nop).uses(sum, GPR).finish();
600 *func.succs_mut(head) = vec![BlockCall::to(arm), BlockCall::to(latch)];
601 func.build(arm, nop).def(inside, GPR).finish();
602 func.build(arm, nop).uses(inside, GPR).finish();
603 *func.succs_mut(arm) = vec![BlockCall::to(out)];
604 func.build(latch, nop).def(loaded, GPR).finish();
605 let carry = func
606 .build(latch, add)
607 .operand(Operand::write(sum, GPR).with(Constraint::Reuse(1)))
608 .uses(seed, GPR)
609 .uses(loaded, GPR)
610 .finish();
611 *func.succs_mut(latch) = vec![BlockCall::to(head), BlockCall::to(out)];
612
613 let order = Order::of(&func);
614 let live = Live::of(&func, &order);
615 let sum = live.area(sum).expect("live somewhere");
616 let loaded = live.area(loaded).expect("live somewhere");
617 assert_eq!(sum.pieces().count(), 2);
622 assert!(!sum.covers(order.early(carry)));
623 assert!(sum.with(order.early(carry)).covers(order.early(carry)));
624 assert!(!loaded.overlaps(sum));
625 assert!(loaded.overlaps(sum.with(order.early(carry))));
626 }
627
628 #[test]
629 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
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 header = func.create_block();
634 let body = func.create_block();
635 let carried = func.append_param(header, GPR);
636 let next = func.new_vreg(GPR);
637 *func.succs_mut(header) = vec![BlockCall::to(body)];
638 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
639 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
640
641 let order = Order::of(&func);
642 let live = Live::of(&func, &order);
643 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
646 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
647 let range = live.range(next).expect("live somewhere");
648 assert_eq!(range.end, order.end(body));
649 }
650
651 #[test]
652 fn two_values_that_are_never_both_wanted_do_not_overlap() {
653 let mut names = Interner::new();
654 let mut func = Func::new(names.intern("f"));
655 let opcode = Opcode::new(names.intern("x64.nop"));
656 let block = func.create_block();
657 let first = func.new_vreg(GPR);
658 let second = func.new_vreg(GPR);
659 let write = func.build(block, opcode).def(first, GPR).finish();
660 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
661
662 let order = Order::of(&func);
663 let live = Live::of(&func, &order);
664 let first = live.range(first).expect("live somewhere");
665 let second = live.range(second).expect("live somewhere");
666 assert!(!first.overlaps(second));
670 assert!(first.start > order.start(block));
671 assert_eq!(first.start, order.late(write));
672 }
673
674 #[test]
675 fn an_operand_written_early_is_wanted_where_the_operands_are_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 source = func.new_vreg(GPR);
681 let early = func.new_vreg(GPR);
682 func.build(block, opcode).def(source, GPR).finish();
683 func.build(block, opcode)
684 .operand(Operand::write_early(early, GPR))
685 .operand(Operand::read(source, GPR))
686 .finish();
687
688 let order = Order::of(&func);
689 let live = Live::of(&func, &order);
690 let source = live.range(source).expect("live somewhere");
691 let early = live.range(early).expect("live somewhere");
692 assert!(source.overlaps(early));
695 }
696
697 #[test]
698 fn a_register_a_memory_operand_names_is_read_like_any_other() {
699 use rucc_mir::Mem;
700
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 address = func.new_vreg(GPR);
706 let write = func.build(block, opcode).def(address, GPR).finish();
707 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
708
709 let order = Order::of(&func);
710 let live = Live::of(&func, &order);
711 assert_eq!(
712 live.range(address),
713 Some(Range { start: order.late(write), end: order.early(load) })
714 );
715 }
716}