1use std::cmp::Ordering;
45
46use rucc_ir::{Block, Func, Inst, Value};
47
48use crate::cfg::Cfg;
49
50#[derive(Debug, Clone, Default, PartialEq, Eq)]
59struct Set {
60 words: Vec<(u32, u64)>,
63}
64
65impl Set {
66 fn find(&self, value: Value) -> (Result<usize, usize>, u64) {
68 let at = value.index();
69 let word = u32::try_from(at / 64).expect("a value number fits in 32 bits");
70 (self.words.binary_search_by_key(&word, |&(word, _)| word), 1 << (at % 64))
71 }
72
73 fn contains(&self, value: Value) -> bool {
74 match self.find(value) {
75 (Ok(at), bit) => self.words[at].1 & bit != 0,
76 (Err(_), _) => false,
77 }
78 }
79
80 fn insert(&mut self, value: Value) -> bool {
82 match self.find(value) {
83 (Ok(at), bit) => {
84 let word = &mut self.words[at].1;
85 let had = *word & bit != 0;
86 *word |= bit;
87 !had
88 }
89 (Err(at), bit) => {
90 let word = u32::try_from(value.index() / 64).expect("checked by find");
91 self.words.insert(at, (word, bit));
92 true
93 }
94 }
95 }
96
97 fn remove(&mut self, value: Value) -> bool {
99 let (Ok(at), bit) = self.find(value) else {
100 return false;
101 };
102 let word = &mut self.words[at].1;
103 let had = *word & bit != 0;
104 *word &= !bit;
105 if *word == 0 {
106 self.words.remove(at);
107 }
108 had
109 }
110
111 fn union_with(&mut self, other: &Self) {
113 if other.words.is_empty() {
114 return;
115 }
116 if self.words.is_empty() {
117 self.words.clone_from(&other.words);
118 return;
119 }
120 let (mine, theirs) = (&self.words, &other.words);
121 let mut both = Vec::with_capacity(mine.len() + theirs.len());
122 let (mut left, mut right) = (0, 0);
123 while left < mine.len() && right < theirs.len() {
124 let ((at, word), (other_at, other_word)) = (mine[left], theirs[right]);
125 match at.cmp(&other_at) {
126 Ordering::Less => {
127 both.push((at, word));
128 left += 1;
129 }
130 Ordering::Greater => {
131 both.push((other_at, other_word));
132 right += 1;
133 }
134 Ordering::Equal => {
135 both.push((at, word | other_word));
136 left += 1;
137 right += 1;
138 }
139 }
140 }
141 both.extend_from_slice(&mine[left..]);
142 both.extend_from_slice(&theirs[right..]);
143 self.words = both;
144 }
145
146 fn clear(&mut self) {
148 self.words.clear();
149 }
150
151 fn len(&self) -> usize {
152 self.words.iter().map(|&(_, word)| word.count_ones() as usize).sum()
153 }
154
155 fn iter(&self) -> impl Iterator<Item = Value> + use<'_> {
159 self.words
160 .iter()
161 .flat_map(|&(at, word)| Bits(word).map(move |bit| Value::new(at * 64 + bit)))
162 }
163}
164
165struct Bits(u64);
170
171impl Iterator for Bits {
172 type Item = u32;
173
174 fn next(&mut self) -> Option<u32> {
175 if self.0 == 0 {
176 return None;
177 }
178 let bit = self.0.trailing_zeros();
179 self.0 &= self.0 - 1;
180 Some(bit)
181 }
182}
183
184#[derive(Debug)]
191pub struct Groups<const N: usize> {
192 words: Vec<[u64; N]>,
193}
194
195impl<const N: usize> Groups<N> {
196 #[must_use]
202 pub fn of(func: &Func, group: impl Fn(Value) -> Option<usize>) -> Self {
203 let mut words = vec![[0; N]; func.values().count().div_ceil(64)];
204 for value in func.values() {
205 if let Some(group) = group(value) {
206 let at = value.index();
207 words[at / 64][group] |= 1 << (at % 64);
208 }
209 }
210 Self { words }
211 }
212
213 fn count(&self, set: &Set) -> [u32; N] {
215 let mut counts = [0; N];
216 for &(at, word) in &set.words {
217 let Some(masks) = self.words.get(at as usize) else { continue };
218 for (count, mask) in counts.iter_mut().zip(masks) {
219 *count += (word & mask).count_ones();
220 }
221 }
222 counts
223 }
224}
225
226#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct Liveness {
233 live_in: Vec<Set>,
234 live_out: Vec<Set>,
235}
236
237impl Liveness {
238 #[must_use]
240 pub fn of(func: &Func, cfg: &Cfg) -> Self {
241 let blocks = cfg.capacity();
242 let mut live_in = vec![Set::default(); blocks];
243 let mut live_out = vec![Set::default(); blocks];
244
245 let order: Vec<Block> = cfg.postorder().to_vec();
249 let mut reads: Vec<Vec<Value>> = vec![Vec::new(); blocks];
250 let mut writes: Vec<Vec<Value>> = vec![Vec::new(); blocks];
251 let mut defined = Set::default();
252 let mut read = Set::default();
253 for &block in &order {
254 let at = block.index();
255 for ¶m in &func[block].params {
256 defined.insert(param);
257 writes[at].push(param);
258 }
259 for inst in func.insts(block) {
260 let data = &func[inst];
261 let branches = func.successors(inst).flat_map(|call| &func[call.args]);
262 for &arg in func[data.args].iter().chain(branches) {
263 if !defined.contains(arg) && read.insert(arg) {
264 reads[at].push(arg);
265 }
266 }
267 for result in data.results() {
268 defined.insert(result);
269 writes[at].push(result);
270 }
271 }
272 for &value in &writes[at] {
273 defined.remove(value);
274 }
275 for &value in &reads[at] {
276 read.remove(value);
277 }
278 }
279
280 let mut stale = vec![true; blocks];
284 let mut set = Set::default();
285 let mut again = true;
286 while again {
287 again = false;
288 for &block in &order {
289 let at = block.index();
290 if !std::mem::take(&mut stale[at]) {
291 continue;
292 }
293 set.clear();
294 for &successor in cfg.successors(block) {
295 set.union_with(&live_in[successor.index()]);
296 }
297 live_out[at].clone_from(&set);
298 for &value in &writes[at] {
299 set.remove(value);
300 }
301 for &value in &reads[at] {
302 set.insert(value);
303 }
304 if live_in[at] != set {
305 live_in[at].clone_from(&set);
306 for &pred in cfg.predecessors(block) {
307 stale[pred.index()] = true;
308 again = true;
309 }
310 }
311 }
312 }
313
314 Self { live_in, live_out }
315 }
316
317 #[must_use]
319 pub fn grouped_in<const N: usize>(&self, block: Block, groups: &Groups<N>) -> [u32; N] {
320 groups.count(&self.live_in[block.index()])
321 }
322
323 #[must_use]
325 pub fn grouped_out<const N: usize>(&self, block: Block, groups: &Groups<N>) -> [u32; N] {
326 groups.count(&self.live_out[block.index()])
327 }
328
329 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Value> + use<'_> {
331 self.live_in[block.index()].iter()
332 }
333
334 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Value> + use<'_> {
336 self.live_out[block.index()].iter()
337 }
338
339 #[must_use]
341 pub fn is_live_in(&self, block: Block, value: Value) -> bool {
342 self.live_in[block.index()].contains(value)
343 }
344
345 #[must_use]
347 pub fn is_live_out(&self, block: Block, value: Value) -> bool {
348 self.live_out[block.index()].contains(value)
349 }
350
351 #[must_use]
353 pub fn count_in(&self, block: Block) -> usize {
354 self.live_in[block.index()].len()
355 }
356
357 #[must_use]
359 pub fn count_out(&self, block: Block) -> usize {
360 self.live_out[block.index()].len()
361 }
362
363 pub fn through(&self, func: &Func, block: Block, mut at: impl FnMut(Inst, &LiveHere<'_>)) {
370 let mut set = self.live_out[block.index()].clone();
371 walk(func, block, &mut set, |inst, set, _| at(inst, &LiveHere { set }));
372 }
373
374 pub fn changes(&self, func: &Func, block: Block, mut at: impl FnMut(Inst, &Change)) {
383 let mut set = self.live_out[block.index()].clone();
384 walk(func, block, &mut set, |inst, _, change| at(inst, change));
385 }
386}
387
388#[derive(Debug, Default)]
393pub struct Change {
394 pub gone: Vec<Value>,
396 pub arrived: Vec<Value>,
398}
399
400#[derive(Debug)]
405pub struct LiveHere<'a> {
406 set: &'a Set,
407}
408
409impl LiveHere<'_> {
410 #[must_use]
412 pub fn contains(&self, value: Value) -> bool {
413 self.set.contains(value)
414 }
415
416 #[must_use]
418 pub fn len(&self) -> usize {
419 self.set.len()
420 }
421
422 #[must_use]
424 pub fn is_empty(&self) -> bool {
425 self.len() == 0
426 }
427
428 pub fn iter(&self) -> impl Iterator<Item = Value> + use<'_> {
430 self.set.iter()
431 }
432}
433
434fn walk(func: &Func, block: Block, set: &mut Set, mut at: impl FnMut(Inst, &Set, &Change)) {
441 let mut change = Change::default();
442 for this in func.insts_backwards(block) {
443 change.gone.clear();
444 change.arrived.clear();
445 let data = &func[this];
446 for result in data.results() {
447 if set.remove(result) {
448 change.gone.push(result);
449 }
450 }
451 for &arg in &func[data.args] {
452 if set.insert(arg) {
453 change.arrived.push(arg);
454 }
455 }
456 for call in func.successors(this) {
459 for &arg in &func[call.args] {
460 if set.insert(arg) {
461 change.arrived.push(arg);
462 }
463 }
464 }
465 at(this, set, &change);
466 }
467}
468
469#[cfg(test)]
470mod tests {
471 use rucc_base::Interner;
472 use rucc_ir::{Block, Builder, Flags, Func, Opcode, Signature, Type, Value};
473
474 use super::{Groups, Liveness, Set};
475 use crate::cfg::Cfg;
476
477 const I32: Type = Type::int(32);
478
479 fn blank(count: usize) -> (Func, Vec<Block>) {
480 let mut names = Interner::new();
481 let mut func = Func::new(names.intern("f"), Signature::new());
482 let blocks: Vec<Block> = (0..count).map(|_| func.create_block()).collect();
483 (func, blocks)
484 }
485
486 fn liveness(func: &Func) -> (Cfg, Liveness) {
487 let cfg = Cfg::new(func);
488 let live = Liveness::of(func, &cfg);
489 (cfg, live)
490 }
491
492 #[test]
493 fn a_set_keeps_only_the_words_with_something_in_them() {
494 let value = Value::new;
495 let mut first = Set::default();
496 assert!(first.insert(value(3)));
497 assert!(first.insert(value(200)));
498 assert!(!first.insert(value(3)), "it was already there");
499 assert!(first.insert(value(70)));
500 assert!(first.remove(value(70)));
501 assert!(!first.remove(value(70)), "it went the first time");
502 assert!(!first.remove(value(5000)), "nothing was ever near it");
503 assert_eq!(first.words.len(), 2, "the word 70 was in went with it");
504
505 let mut second = Set::default();
506 second.insert(value(64));
507 second.insert(value(200));
508 second.insert(value(201));
509 second.insert(value(9000));
510 first.union_with(&second);
511 let all: Vec<u32> = first.iter().map(|value| value.raw()).collect();
512 assert_eq!(all, [3, 64, 200, 201, 9000]);
513 assert_eq!(first.len(), 5);
514 assert!(first.contains(value(201)) && !first.contains(value(202)));
515
516 let mut again = Set::default();
519 for number in [9000, 201, 5, 200, 64, 3] {
520 again.insert(value(number));
521 }
522 again.remove(value(5));
523 assert_eq!(again, first);
524 }
525
526 #[test]
527 fn a_value_made_and_read_in_one_block_never_crosses_an_edge() {
528 let (mut func, blocks) = blank(1);
529 let mut build = Builder::new(&mut func, blocks[0]);
530 let one = build.iconst(I32, 1);
531 let two = build.iconst(I32, 2);
532 let sum = build.binary(Opcode::Add, one, two, Flags::NONE);
533 build.ret(&[sum]);
534
535 let (_, live) = liveness(&func);
536 assert_eq!(live.count_in(blocks[0]), 0);
537 assert_eq!(live.count_out(blocks[0]), 0);
538 }
539
540 #[test]
541 fn a_value_read_in_a_later_block_is_live_on_the_edge_between_them() {
542 let (mut func, blocks) = blank(2);
543 let mut build = Builder::new(&mut func, blocks[0]);
544 let kept = build.iconst(I32, 7);
545 build.jump(blocks[1], &[]);
546 let mut build = Builder::new(&mut func, blocks[1]);
547 build.ret(&[kept]);
548
549 let (_, live) = liveness(&func);
550 assert!(live.is_live_out(blocks[0], kept), "it is read after the branch");
551 assert!(live.is_live_in(blocks[1], kept), "and it has to arrive there to be read");
552 assert!(!live.is_live_in(blocks[0], kept), "it does not exist before it is made");
553 }
554
555 #[test]
556 fn a_group_counts_what_counting_one_value_at_a_time_counts() {
557 let (mut func, blocks) = blank(2);
559 let mut build = Builder::new(&mut func, blocks[0]);
560 let kept: Vec<Value> = (0..150).map(|number| build.iconst(I32, number)).collect();
561 build.jump(blocks[1], &[]);
562 let mut build = Builder::new(&mut func, blocks[1]);
563 build.ret(&kept[..]);
564
565 let group = |value: Value| (value.index() % 3 != 0).then_some(value.index() % 2);
567 let groups = Groups::<2>::of(&func, group);
568 let (_, live) = liveness(&func);
569 for &block in &blocks {
570 for (grouped, values) in [
571 (live.grouped_in(block, &groups), live.live_in(block).collect::<Vec<_>>()),
572 (live.grouped_out(block, &groups), live.live_out(block).collect()),
573 ] {
574 let mut counted = [0; 2];
575 for value in values {
576 if let Some(group) = group(value) {
577 counted[group] += 1;
578 }
579 }
580 assert_eq!(grouped, counted);
581 }
582 }
583 assert_eq!(live.grouped_in(blocks[1], &groups), [50, 50]);
584 }
585
586 #[test]
587 fn a_value_passed_on_the_branch_is_used_by_the_branch_and_not_by_the_block_it_arrives_at() {
588 let (mut func, blocks) = blank(2);
592 let param = func.append_param(blocks[1], I32);
593 let mut build = Builder::new(&mut func, blocks[0]);
594 let sent = build.iconst(I32, 7);
595 build.jump(blocks[1], &[sent]);
596 let mut build = Builder::new(&mut func, blocks[1]);
597 build.ret(&[param]);
598
599 let (_, live) = liveness(&func);
600 let mut at_the_jump = false;
603 live.through(&func, blocks[0], |inst, here| {
604 if func[inst].opcode == Opcode::Jump {
605 at_the_jump = here.contains(sent);
606 }
607 });
608 assert!(at_the_jump, "the branch uses it");
609 assert!(!live.is_live_out(blocks[0], sent), "and it does not survive the edge");
610 assert!(!live.is_live_in(blocks[1], param), "a parameter is defined by arriving");
611 assert!(!live.is_live_in(blocks[1], sent), "nor does it arrive under its own name");
612 assert_eq!(live.count_in(blocks[1]), 0);
613 }
614
615 #[test]
616 fn a_value_read_on_one_arm_only_is_live_on_that_arm_and_not_the_other() {
617 let (mut func, blocks) = blank(4);
618 let mut build = Builder::new(&mut func, blocks[0]);
619 let kept = build.iconst(I32, 7);
620 let cond = build.iconst(Type::I1, 1);
621 build.br_if(cond, blocks[1], &[], blocks[2], &[]);
622 let mut build = Builder::new(&mut func, blocks[1]);
623 build.jump(blocks[3], &[]);
624 let mut build = Builder::new(&mut func, blocks[2]);
625 build.ret(&[kept]);
626 let mut build = Builder::new(&mut func, blocks[3]);
627 build.ret(&[]);
628
629 let (_, live) = liveness(&func);
630 assert!(live.is_live_out(blocks[0], kept), "one arm reads it, so it survives the branch");
631 assert!(live.is_live_in(blocks[2], kept));
632 assert!(!live.is_live_in(blocks[1], kept), "this arm never mentions it");
633 }
634
635 #[test]
636 fn a_value_read_after_the_loop_stays_live_all_the_way_round_it() {
637 let (mut func, blocks) = blank(3);
641 let mut build = Builder::new(&mut func, blocks[0]);
642 let kept = build.iconst(I32, 7);
643 let cond = build.iconst(Type::I1, 1);
644 build.jump(blocks[1], &[]);
645 let mut build = Builder::new(&mut func, blocks[1]);
646 build.br_if(cond, blocks[1], &[], blocks[2], &[]);
647 let mut build = Builder::new(&mut func, blocks[2]);
648 build.ret(&[kept]);
649
650 let (_, live) = liveness(&func);
651 assert!(live.is_live_in(blocks[1], kept), "it has to survive the loop to be read after it");
652 assert!(live.is_live_out(blocks[1], kept), "including round the back edge");
653 assert!(live.is_live_in(blocks[2], kept));
654 }
655
656 #[test]
657 fn nothing_is_live_in_a_block_control_never_reaches() {
658 let (mut func, blocks) = blank(2);
659 let mut build = Builder::new(&mut func, blocks[0]);
660 let kept = build.iconst(I32, 7);
661 build.ret(&[kept]);
662 let mut build = Builder::new(&mut func, blocks[1]);
663 build.ret(&[]);
664
665 let (cfg, live) = liveness(&func);
666 assert!(!cfg.reaches(blocks[1]));
667 assert_eq!(live.count_in(blocks[1]), 0);
668 assert_eq!(live.count_out(blocks[1]), 0);
669 }
670
671 #[test]
672 fn the_walk_through_a_block_says_what_is_live_before_each_instruction() {
673 let (mut func, blocks) = blank(2);
674 let mut build = Builder::new(&mut func, blocks[0]);
675 let one = build.iconst(I32, 1);
676 let two = build.iconst(I32, 2);
677 let sum = build.binary(Opcode::Add, one, two, Flags::NONE);
678 let jump = build.jump(blocks[1], &[sum]);
679 let param = func.append_param(blocks[1], I32);
680 let mut build = Builder::new(&mut func, blocks[1]);
681 build.ret(&[param]);
682
683 let (_, live) = liveness(&func);
684 let mut counts = Vec::new();
685 live.through(&func, blocks[0], |inst, here| counts.push((inst, here.len())));
686 assert_eq!(counts.len(), 4);
689 assert_eq!(counts[0], (jump, 1));
690 assert_eq!(counts[1].1, 2, "the add's two operands");
691 assert_eq!(counts[2].1, 1);
692 assert_eq!(counts[3].1, 0);
693 assert!(counts[0].1 <= counts[1].1, "the sum replaces the two it was made from");
694 }
695
696 #[test]
697 fn a_value_that_is_its_own_operand_stays_live_across_the_instruction_that_redefines_nothing() {
698 let (mut func, blocks) = blank(1);
701 let mut build = Builder::new(&mut func, blocks[0]);
702 let start = build.iconst(I32, 1);
703 let doubled = build.binary(Opcode::Add, start, start, Flags::NONE);
704 build.ret(&[doubled]);
705
706 let (_, live) = liveness(&func);
707 let mut most = 0;
708 live.through(&func, blocks[0], |_, here| most = most.max(here.len()));
709 assert_eq!(most, 1, "one value used twice is one value");
710 }
711}