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, Clone, PartialEq, Eq)]
190pub struct Liveness {
191 live_in: Vec<Set>,
192 live_out: Vec<Set>,
193}
194
195impl Liveness {
196 #[must_use]
198 pub fn of(func: &Func, cfg: &Cfg) -> Self {
199 let blocks = cfg.capacity();
200 let mut live_in = vec![Set::default(); blocks];
201 let mut live_out = vec![Set::default(); blocks];
202
203 let order: Vec<Block> = cfg.postorder().to_vec();
207 let mut reads: Vec<Vec<Value>> = vec![Vec::new(); blocks];
208 let mut writes: Vec<Vec<Value>> = vec![Vec::new(); blocks];
209 let mut defined = Set::default();
210 let mut read = Set::default();
211 for &block in &order {
212 let at = block.index();
213 for ¶m in &func[block].params {
214 defined.insert(param);
215 writes[at].push(param);
216 }
217 for inst in func.insts(block) {
218 let data = &func[inst];
219 let branches = func.successors(inst).flat_map(|call| &func[call.args]);
220 for &arg in func[data.args].iter().chain(branches) {
221 if !defined.contains(arg) && read.insert(arg) {
222 reads[at].push(arg);
223 }
224 }
225 for result in data.results() {
226 defined.insert(result);
227 writes[at].push(result);
228 }
229 }
230 for &value in &writes[at] {
231 defined.remove(value);
232 }
233 for &value in &reads[at] {
234 read.remove(value);
235 }
236 }
237
238 let mut stale = vec![true; blocks];
242 let mut set = Set::default();
243 let mut again = true;
244 while again {
245 again = false;
246 for &block in &order {
247 let at = block.index();
248 if !std::mem::take(&mut stale[at]) {
249 continue;
250 }
251 set.clear();
252 for &successor in cfg.successors(block) {
253 set.union_with(&live_in[successor.index()]);
254 }
255 live_out[at].clone_from(&set);
256 for &value in &writes[at] {
257 set.remove(value);
258 }
259 for &value in &reads[at] {
260 set.insert(value);
261 }
262 if live_in[at] != set {
263 live_in[at].clone_from(&set);
264 for &pred in cfg.predecessors(block) {
265 stale[pred.index()] = true;
266 again = true;
267 }
268 }
269 }
270 }
271
272 Self { live_in, live_out }
273 }
274
275 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Value> + use<'_> {
277 self.live_in[block.index()].iter()
278 }
279
280 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Value> + use<'_> {
282 self.live_out[block.index()].iter()
283 }
284
285 #[must_use]
287 pub fn is_live_in(&self, block: Block, value: Value) -> bool {
288 self.live_in[block.index()].contains(value)
289 }
290
291 #[must_use]
293 pub fn is_live_out(&self, block: Block, value: Value) -> bool {
294 self.live_out[block.index()].contains(value)
295 }
296
297 #[must_use]
299 pub fn count_in(&self, block: Block) -> usize {
300 self.live_in[block.index()].len()
301 }
302
303 #[must_use]
305 pub fn count_out(&self, block: Block) -> usize {
306 self.live_out[block.index()].len()
307 }
308
309 pub fn through(&self, func: &Func, block: Block, mut at: impl FnMut(Inst, &LiveHere<'_>)) {
316 let mut set = self.live_out[block.index()].clone();
317 walk(func, block, &mut set, |inst, set, _| at(inst, &LiveHere { set }));
318 }
319
320 pub fn changes(&self, func: &Func, block: Block, mut at: impl FnMut(Inst, &Change)) {
329 let mut set = self.live_out[block.index()].clone();
330 walk(func, block, &mut set, |inst, _, change| at(inst, change));
331 }
332}
333
334#[derive(Debug, Default)]
339pub struct Change {
340 pub gone: Vec<Value>,
342 pub arrived: Vec<Value>,
344}
345
346#[derive(Debug)]
351pub struct LiveHere<'a> {
352 set: &'a Set,
353}
354
355impl LiveHere<'_> {
356 #[must_use]
358 pub fn contains(&self, value: Value) -> bool {
359 self.set.contains(value)
360 }
361
362 #[must_use]
364 pub fn len(&self) -> usize {
365 self.set.len()
366 }
367
368 #[must_use]
370 pub fn is_empty(&self) -> bool {
371 self.len() == 0
372 }
373
374 pub fn iter(&self) -> impl Iterator<Item = Value> + use<'_> {
376 self.set.iter()
377 }
378}
379
380fn walk(func: &Func, block: Block, set: &mut Set, mut at: impl FnMut(Inst, &Set, &Change)) {
387 let mut change = Change::default();
388 for this in func.insts_backwards(block) {
389 change.gone.clear();
390 change.arrived.clear();
391 let data = &func[this];
392 for result in data.results() {
393 if set.remove(result) {
394 change.gone.push(result);
395 }
396 }
397 for &arg in &func[data.args] {
398 if set.insert(arg) {
399 change.arrived.push(arg);
400 }
401 }
402 for call in func.successors(this) {
405 for &arg in &func[call.args] {
406 if set.insert(arg) {
407 change.arrived.push(arg);
408 }
409 }
410 }
411 at(this, set, &change);
412 }
413}
414
415#[cfg(test)]
416mod tests {
417 use rucc_base::Interner;
418 use rucc_ir::{Block, Builder, Flags, Func, Opcode, Signature, Type, Value};
419
420 use super::{Liveness, Set};
421 use crate::cfg::Cfg;
422
423 const I32: Type = Type::int(32);
424
425 fn blank(count: usize) -> (Func, Vec<Block>) {
426 let mut names = Interner::new();
427 let mut func = Func::new(names.intern("f"), Signature::new());
428 let blocks: Vec<Block> = (0..count).map(|_| func.create_block()).collect();
429 (func, blocks)
430 }
431
432 fn liveness(func: &Func) -> (Cfg, Liveness) {
433 let cfg = Cfg::new(func);
434 let live = Liveness::of(func, &cfg);
435 (cfg, live)
436 }
437
438 #[test]
439 fn a_set_keeps_only_the_words_with_something_in_them() {
440 let value = Value::new;
441 let mut first = Set::default();
442 assert!(first.insert(value(3)));
443 assert!(first.insert(value(200)));
444 assert!(!first.insert(value(3)), "it was already there");
445 assert!(first.insert(value(70)));
446 assert!(first.remove(value(70)));
447 assert!(!first.remove(value(70)), "it went the first time");
448 assert!(!first.remove(value(5000)), "nothing was ever near it");
449 assert_eq!(first.words.len(), 2, "the word 70 was in went with it");
450
451 let mut second = Set::default();
452 second.insert(value(64));
453 second.insert(value(200));
454 second.insert(value(201));
455 second.insert(value(9000));
456 first.union_with(&second);
457 let all: Vec<u32> = first.iter().map(|value| value.raw()).collect();
458 assert_eq!(all, [3, 64, 200, 201, 9000]);
459 assert_eq!(first.len(), 5);
460 assert!(first.contains(value(201)) && !first.contains(value(202)));
461
462 let mut again = Set::default();
465 for number in [9000, 201, 5, 200, 64, 3] {
466 again.insert(value(number));
467 }
468 again.remove(value(5));
469 assert_eq!(again, first);
470 }
471
472 #[test]
473 fn a_value_made_and_read_in_one_block_never_crosses_an_edge() {
474 let (mut func, blocks) = blank(1);
475 let mut build = Builder::new(&mut func, blocks[0]);
476 let one = build.iconst(I32, 1);
477 let two = build.iconst(I32, 2);
478 let sum = build.binary(Opcode::Add, one, two, Flags::NONE);
479 build.ret(&[sum]);
480
481 let (_, live) = liveness(&func);
482 assert_eq!(live.count_in(blocks[0]), 0);
483 assert_eq!(live.count_out(blocks[0]), 0);
484 }
485
486 #[test]
487 fn a_value_read_in_a_later_block_is_live_on_the_edge_between_them() {
488 let (mut func, blocks) = blank(2);
489 let mut build = Builder::new(&mut func, blocks[0]);
490 let kept = build.iconst(I32, 7);
491 build.jump(blocks[1], &[]);
492 let mut build = Builder::new(&mut func, blocks[1]);
493 build.ret(&[kept]);
494
495 let (_, live) = liveness(&func);
496 assert!(live.is_live_out(blocks[0], kept), "it is read after the branch");
497 assert!(live.is_live_in(blocks[1], kept), "and it has to arrive there to be read");
498 assert!(!live.is_live_in(blocks[0], kept), "it does not exist before it is made");
499 }
500
501 #[test]
502 fn a_value_passed_on_the_branch_is_used_by_the_branch_and_not_by_the_block_it_arrives_at() {
503 let (mut func, blocks) = blank(2);
507 let param = func.append_param(blocks[1], I32);
508 let mut build = Builder::new(&mut func, blocks[0]);
509 let sent = build.iconst(I32, 7);
510 build.jump(blocks[1], &[sent]);
511 let mut build = Builder::new(&mut func, blocks[1]);
512 build.ret(&[param]);
513
514 let (_, live) = liveness(&func);
515 let mut at_the_jump = false;
518 live.through(&func, blocks[0], |inst, here| {
519 if func[inst].opcode == Opcode::Jump {
520 at_the_jump = here.contains(sent);
521 }
522 });
523 assert!(at_the_jump, "the branch uses it");
524 assert!(!live.is_live_out(blocks[0], sent), "and it does not survive the edge");
525 assert!(!live.is_live_in(blocks[1], param), "a parameter is defined by arriving");
526 assert!(!live.is_live_in(blocks[1], sent), "nor does it arrive under its own name");
527 assert_eq!(live.count_in(blocks[1]), 0);
528 }
529
530 #[test]
531 fn a_value_read_on_one_arm_only_is_live_on_that_arm_and_not_the_other() {
532 let (mut func, blocks) = blank(4);
533 let mut build = Builder::new(&mut func, blocks[0]);
534 let kept = build.iconst(I32, 7);
535 let cond = build.iconst(Type::I1, 1);
536 build.br_if(cond, blocks[1], &[], blocks[2], &[]);
537 let mut build = Builder::new(&mut func, blocks[1]);
538 build.jump(blocks[3], &[]);
539 let mut build = Builder::new(&mut func, blocks[2]);
540 build.ret(&[kept]);
541 let mut build = Builder::new(&mut func, blocks[3]);
542 build.ret(&[]);
543
544 let (_, live) = liveness(&func);
545 assert!(live.is_live_out(blocks[0], kept), "one arm reads it, so it survives the branch");
546 assert!(live.is_live_in(blocks[2], kept));
547 assert!(!live.is_live_in(blocks[1], kept), "this arm never mentions it");
548 }
549
550 #[test]
551 fn a_value_read_after_the_loop_stays_live_all_the_way_round_it() {
552 let (mut func, blocks) = blank(3);
556 let mut build = Builder::new(&mut func, blocks[0]);
557 let kept = build.iconst(I32, 7);
558 let cond = build.iconst(Type::I1, 1);
559 build.jump(blocks[1], &[]);
560 let mut build = Builder::new(&mut func, blocks[1]);
561 build.br_if(cond, blocks[1], &[], blocks[2], &[]);
562 let mut build = Builder::new(&mut func, blocks[2]);
563 build.ret(&[kept]);
564
565 let (_, live) = liveness(&func);
566 assert!(live.is_live_in(blocks[1], kept), "it has to survive the loop to be read after it");
567 assert!(live.is_live_out(blocks[1], kept), "including round the back edge");
568 assert!(live.is_live_in(blocks[2], kept));
569 }
570
571 #[test]
572 fn nothing_is_live_in_a_block_control_never_reaches() {
573 let (mut func, blocks) = blank(2);
574 let mut build = Builder::new(&mut func, blocks[0]);
575 let kept = build.iconst(I32, 7);
576 build.ret(&[kept]);
577 let mut build = Builder::new(&mut func, blocks[1]);
578 build.ret(&[]);
579
580 let (cfg, live) = liveness(&func);
581 assert!(!cfg.reaches(blocks[1]));
582 assert_eq!(live.count_in(blocks[1]), 0);
583 assert_eq!(live.count_out(blocks[1]), 0);
584 }
585
586 #[test]
587 fn the_walk_through_a_block_says_what_is_live_before_each_instruction() {
588 let (mut func, blocks) = blank(2);
589 let mut build = Builder::new(&mut func, blocks[0]);
590 let one = build.iconst(I32, 1);
591 let two = build.iconst(I32, 2);
592 let sum = build.binary(Opcode::Add, one, two, Flags::NONE);
593 let jump = build.jump(blocks[1], &[sum]);
594 let param = func.append_param(blocks[1], I32);
595 let mut build = Builder::new(&mut func, blocks[1]);
596 build.ret(&[param]);
597
598 let (_, live) = liveness(&func);
599 let mut counts = Vec::new();
600 live.through(&func, blocks[0], |inst, here| counts.push((inst, here.len())));
601 assert_eq!(counts.len(), 4);
604 assert_eq!(counts[0], (jump, 1));
605 assert_eq!(counts[1].1, 2, "the add's two operands");
606 assert_eq!(counts[2].1, 1);
607 assert_eq!(counts[3].1, 0);
608 assert!(counts[0].1 <= counts[1].1, "the sum replaces the two it was made from");
609 }
610
611 #[test]
612 fn a_value_that_is_its_own_operand_stays_live_across_the_instruction_that_redefines_nothing() {
613 let (mut func, blocks) = blank(1);
616 let mut build = Builder::new(&mut func, blocks[0]);
617 let start = build.iconst(I32, 1);
618 let doubled = build.binary(Opcode::Add, start, start, Flags::NONE);
619 build.ret(&[doubled]);
620
621 let (_, live) = liveness(&func);
622 let mut most = 0;
623 live.through(&func, blocks[0], |_, here| most = most.max(here.len()));
624 assert_eq!(most, 1, "one value used twice is one value");
625 }
626}