1use rucc_mir::{Block, Func, Reg, Role};
34
35use crate::order::{Order, Point};
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub struct Range {
46 pub start: Point,
48 pub end: Point,
50}
51
52impl Range {
53 #[must_use]
55 pub fn covers(self, point: Point) -> bool {
56 self.start <= point && point <= self.end
57 }
58
59 #[must_use]
61 pub fn overlaps(self, other: Self) -> bool {
62 self.start <= other.end && other.start <= self.end
63 }
64
65 fn with(self, point: Point) -> Self {
68 Self { start: self.start.min(point), end: self.end.max(point) }
69 }
70}
71
72#[derive(Debug, Clone)]
74pub struct Live {
75 live_in: Rows,
76 live_out: Rows,
77 ranges: Vec<Option<Range>>,
78}
79
80impl Live {
81 #[must_use]
83 pub fn of(func: &Func, order: &Order) -> Self {
84 let vregs = func.vregs();
85 let (used, defined) = exposed(func, order);
86 let (live_in, live_out) = flow(func, order, &used, &defined);
87 let ranges = measure(func, order, &live_in, &live_out, vregs);
88 Self { live_in, live_out, ranges }
89 }
90
91 #[must_use]
94 pub fn range(&self, reg: Reg) -> Option<Range> {
95 self.ranges.get(usize::try_from(reg.number()?).ok()?).copied().flatten()
96 }
97
98 pub fn live_in(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
103 self.live_in.iter(block.index())
104 }
105
106 pub fn live_out(&self, block: Block) -> impl Iterator<Item = Reg> + '_ {
109 self.live_out.iter(block.index())
110 }
111}
112
113fn measure(
115 func: &Func,
116 order: &Order,
117 live_in: &Rows,
118 live_out: &Rows,
119 vregs: usize,
120) -> Vec<Option<Range>> {
121 let mut ranges: Vec<Option<Range>> = vec![None; vregs];
122 let mut extend = |reg: Reg, point: Point| {
123 let Some(number) = reg.number().and_then(|number| usize::try_from(number).ok()) else {
124 return;
125 };
126 let Some(slot) = ranges.get_mut(number) else { return };
127 *slot = Some(match *slot {
128 Some(range) => range.with(point),
129 None => Range { start: point, end: point },
130 });
131 };
132
133 for &block in order.blocks() {
134 for reg in live_in.iter(block.index()) {
137 extend(reg, order.start(block));
138 }
139 for reg in live_out.iter(block.index()) {
140 extend(reg, order.end(block));
141 }
142 for param in &func[block].params {
143 extend(param.reg, order.start(block));
144 }
145 for inst in func.insts(block) {
146 for operand in &func[func[inst].operands] {
147 match operand.role {
148 Role::Use => extend(operand.reg, order.early(inst)),
149 Role::Def => extend(operand.reg, order.late(inst)),
150 Role::EarlyDef => {
157 extend(operand.reg, order.early(inst));
158 extend(operand.reg, order.late(inst));
159 }
160 }
161 }
162 }
163 for call in &func[block].succs {
164 for &arg in &call.args {
165 extend(arg, order.end(block));
166 }
167 }
168 }
169 ranges
170}
171
172fn exposed(func: &Func, order: &Order) -> (Rows, Rows) {
177 let mut used = Rows::new(func.block_count(), func.vregs());
178 let mut defined = Rows::new(func.block_count(), func.vregs());
179 for &block in order.blocks() {
180 let row = block.index();
181 for call in &func[block].succs {
182 for &arg in &call.args {
183 used.insert(row, arg);
184 }
185 }
186 let insts: Vec<_> = func.insts(block).collect();
187 for &inst in insts.iter().rev() {
188 let operands = &func[func[inst].operands];
189 for operand in operands.iter().filter(|operand| operand.role.is_def()) {
190 used.remove(row, operand.reg);
191 defined.insert(row, operand.reg);
192 }
193 for operand in operands.iter().filter(|operand| !operand.role.is_def()) {
194 used.insert(row, operand.reg);
195 }
196 }
197 for param in &func[block].params {
198 used.remove(row, param.reg);
199 defined.insert(row, param.reg);
200 }
201 }
202 (used, defined)
203}
204
205fn flow(func: &Func, order: &Order, used: &Rows, defined: &Rows) -> (Rows, Rows) {
207 let mut live_in = Rows::new(func.block_count(), func.vregs());
208 let mut live_out = Rows::new(func.block_count(), func.vregs());
209 let width = live_in.width;
210 let mut next = vec![0u64; width];
211 let mut changed = true;
212 while changed {
213 changed = false;
214 for &block in order.blocks().iter().rev() {
215 let row = block.index();
216 for call in &func[block].succs {
217 let successor = call.block.index();
218 for (word, &incoming) in
219 live_out.row_mut(row).iter_mut().zip(live_in.row(successor))
220 {
221 *word |= incoming;
222 }
223 }
224 for (index, word) in next.iter_mut().enumerate() {
225 *word =
226 used.row(row)[index] | (live_out.row(row)[index] & !defined.row(row)[index]);
227 }
228 if live_in.row(row) != next.as_slice() {
229 live_in.row_mut(row).copy_from_slice(&next);
230 changed = true;
231 }
232 }
233 }
234 (live_in, live_out)
235}
236
237#[derive(Debug, Clone)]
239struct Rows {
240 words: Vec<u64>,
241 width: usize,
244}
245
246impl Rows {
247 fn new(rows: usize, columns: usize) -> Self {
248 let width = columns.div_ceil(64).max(1);
249 Self { words: vec![0; rows * width], width }
250 }
251
252 fn row(&self, row: usize) -> &[u64] {
253 &self.words[row * self.width..(row + 1) * self.width]
254 }
255
256 fn row_mut(&mut self, row: usize) -> &mut [u64] {
257 &mut self.words[row * self.width..(row + 1) * self.width]
258 }
259
260 fn column(&self, reg: Reg) -> Option<usize> {
262 let number = usize::try_from(reg.number()?).ok()?;
263 (number < self.width * 64).then_some(number)
264 }
265
266 fn insert(&mut self, row: usize, reg: Reg) {
267 if let Some(column) = self.column(reg) {
268 self.row_mut(row)[column / 64] |= 1 << (column % 64);
269 }
270 }
271
272 fn remove(&mut self, row: usize, reg: Reg) {
273 if let Some(column) = self.column(reg) {
274 self.row_mut(row)[column / 64] &= !(1 << (column % 64));
275 }
276 }
277
278 fn iter(&self, row: usize) -> impl Iterator<Item = Reg> + '_ {
279 self.row(row).iter().enumerate().flat_map(|(word, &bits)| {
280 (0..64).filter(move |bit| bits & (1 << bit) != 0).map(move |bit| {
281 Reg::virtual_reg(u32::try_from(word * 64 + bit).expect("a register number"))
282 })
283 })
284 }
285}
286
287#[cfg(test)]
288mod tests {
289 use rucc_base::Interner;
290 use rucc_mir::{BlockCall, Opcode, Operand};
291 use rucc_target::x86_64::GPR;
292
293 use super::*;
294
295 fn regs(of: impl Iterator<Item = Reg>) -> Vec<u32> {
297 of.filter_map(Reg::number).collect()
298 }
299
300 #[test]
301 fn a_value_is_live_from_where_it_is_written_to_where_it_is_last_read() {
302 let mut names = Interner::new();
303 let mut func = Func::new(names.intern("f"));
304 let opcode = Opcode::new(names.intern("x64.nop"));
305 let block = func.create_block();
306 let value = func.new_vreg(GPR);
307 let other = func.new_vreg(GPR);
308 let write = func.build(block, opcode).def(value, GPR).finish();
309 let idle = func.build(block, opcode).def(other, GPR).finish();
310 let read = func.build(block, opcode).uses(value, GPR).finish();
311
312 let order = Order::of(&func);
313 let live = Live::of(&func, &order);
314 let range = live.range(value).expect("the value is live somewhere");
315 assert_eq!(range, Range { start: order.late(write), end: order.early(read) });
316 assert!(range.covers(order.early(idle)));
317 assert_eq!(
320 live.range(other),
321 Some(Range { start: order.late(idle), end: order.late(idle) })
322 );
323 assert!(!range.overlaps(Range { start: order.late(read), end: order.late(read) }));
324 assert_eq!(regs(live.live_in(block)), Vec::<u32>::new());
325 }
326
327 #[test]
328 fn a_value_read_in_another_block_is_live_between_them() {
329 let mut names = Interner::new();
330 let mut func = Func::new(names.intern("f"));
331 let opcode = Opcode::new(names.intern("x64.nop"));
332 let head = func.create_block();
333 let middle = func.create_block();
334 let tail = func.create_block();
335 let value = func.new_vreg(GPR);
336 func.build(head, opcode).def(value, GPR).finish();
337 *func.succs_mut(head) = vec![BlockCall::to(middle)];
338 *func.succs_mut(middle) = vec![BlockCall::to(tail)];
339 let read = func.build(tail, opcode).uses(value, GPR).finish();
340
341 let order = Order::of(&func);
342 let live = Live::of(&func, &order);
343 assert_eq!(regs(live.live_in(middle)), vec![0]);
346 assert_eq!(regs(live.live_out(middle)), vec![0]);
347 assert!(live.range(value).expect("live somewhere").covers(order.start(middle)));
348 assert_eq!(live.range(value).expect("live somewhere").end, order.early(read));
349 }
350
351 #[test]
352 fn a_value_carried_round_a_loop_is_live_round_all_of_it() {
353 let mut names = Interner::new();
354 let mut func = Func::new(names.intern("f"));
355 let opcode = Opcode::new(names.intern("x64.nop"));
356 let header = func.create_block();
357 let body = func.create_block();
358 let carried = func.append_param(header, GPR);
359 let next = func.new_vreg(GPR);
360 *func.succs_mut(header) = vec![BlockCall::to(body)];
361 func.build(body, opcode).def(next, GPR).uses(carried, GPR).finish();
362 *func.succs_mut(body) = vec![BlockCall::with(header, vec![next])];
363
364 let order = Order::of(&func);
365 let live = Live::of(&func, &order);
366 assert_eq!(regs(live.live_in(header)), Vec::<u32>::new());
369 assert_eq!(regs(live.live_in(body)), vec![carried.number().expect("virtual")]);
370 let range = live.range(next).expect("live somewhere");
371 assert_eq!(range.end, order.end(body));
372 }
373
374 #[test]
375 fn two_values_that_are_never_both_wanted_do_not_overlap() {
376 let mut names = Interner::new();
377 let mut func = Func::new(names.intern("f"));
378 let opcode = Opcode::new(names.intern("x64.nop"));
379 let block = func.create_block();
380 let first = func.new_vreg(GPR);
381 let second = func.new_vreg(GPR);
382 let write = func.build(block, opcode).def(first, GPR).finish();
383 func.build(block, opcode).def(second, GPR).uses(first, GPR).finish();
384
385 let order = Order::of(&func);
386 let live = Live::of(&func, &order);
387 let first = live.range(first).expect("live somewhere");
388 let second = live.range(second).expect("live somewhere");
389 assert!(!first.overlaps(second));
393 assert!(first.start > order.start(block));
394 assert_eq!(first.start, order.late(write));
395 }
396
397 #[test]
398 fn an_operand_written_early_is_wanted_where_the_operands_are_read() {
399 let mut names = Interner::new();
400 let mut func = Func::new(names.intern("f"));
401 let opcode = Opcode::new(names.intern("x64.nop"));
402 let block = func.create_block();
403 let source = func.new_vreg(GPR);
404 let early = func.new_vreg(GPR);
405 func.build(block, opcode).def(source, GPR).finish();
406 func.build(block, opcode)
407 .operand(Operand::write_early(early, GPR))
408 .operand(Operand::read(source, GPR))
409 .finish();
410
411 let order = Order::of(&func);
412 let live = Live::of(&func, &order);
413 let source = live.range(source).expect("live somewhere");
414 let early = live.range(early).expect("live somewhere");
415 assert!(source.overlaps(early));
418 }
419
420 #[test]
421 fn a_register_a_memory_operand_names_is_read_like_any_other() {
422 use rucc_mir::Mem;
423
424 let mut names = Interner::new();
425 let mut func = Func::new(names.intern("f"));
426 let opcode = Opcode::new(names.intern("x64.nop"));
427 let block = func.create_block();
428 let address = func.new_vreg(GPR);
429 let write = func.build(block, opcode).def(address, GPR).finish();
430 let load = func.build(block, opcode).mem(Mem::at(Operand::read(address, GPR))).finish();
431
432 let order = Order::of(&func);
433 let live = Live::of(&func, &order);
434 assert_eq!(
435 live.range(address),
436 Some(Range { start: order.late(write), end: order.early(load) })
437 );
438 }
439}