1use rucc_mir::{Func, Reg};
35use rucc_target::RegClass;
36
37use crate::assign::{self, Env};
38use crate::live::{Area, Live};
39use crate::order::{Order, Point};
40
41#[derive(Debug, Clone, Default)]
43pub struct Pressure {
44 wanted: Vec<Vec<u32>>,
46 room: Vec<Vec<u32>>,
48}
49
50impl Pressure {
51 #[must_use]
58 pub fn of(func: &Func, order: &Order, live: &Live, env: &Env) -> Self {
59 let points = usize::try_from(order.points()).expect("a point count");
60 let mut forced = vec![false; func.vregs()];
61 for reg in assign::forced(func) {
62 forced[index(reg)] = true;
63 }
64 let mut steps: Vec<Vec<i64>> = Vec::new();
67 for (number, &forced) in forced.iter().enumerate() {
68 let reg = Reg::virtual_reg(u32::try_from(number).expect("a register number"));
69 let (Some(area), Some(class)) = (live.area(reg), func.class_of(reg)) else {
70 continue;
71 };
72 if forced {
73 continue;
74 }
75 let class = usize::from(class.number());
76 if steps.len() <= class {
77 steps.resize_with(class + 1, Vec::new);
78 }
79 let row = &mut steps[class];
80 if row.is_empty() {
81 *row = vec![0; points + 1];
82 }
83 for piece in area.pieces() {
84 row[at(piece.start)] += 1;
85 row[at(piece.end) + 1] -= 1;
86 }
87 }
88 let wanted = steps
89 .into_iter()
90 .map(|row| {
91 let mut count = 0i64;
92 let mut wanted: Vec<u32> = row
93 .iter()
94 .map(|step| {
95 count += step;
96 u32::try_from(count).expect("a count of values")
97 })
98 .collect();
99 wanted.truncate(points);
100 wanted
101 })
102 .collect();
103
104 let mut room: Vec<Vec<u32>> = env
105 .offered()
106 .map(|offered| {
107 let count = u32::try_from(offered.len()).expect("a count of registers");
108 if count == 0 { Vec::new() } else { vec![count; points] }
109 })
110 .collect();
111 let mut taken: Vec<_> = assign::blocked(func, order).taken().collect();
114 taken.dedup();
115 for (class, reg, point) in taken {
116 let Some(row) = room.get_mut(usize::from(class.number())) else { continue };
117 if row.is_empty() || !env.order(class).contains(®) {
118 continue;
119 }
120 row[at(point)] = row[at(point)].saturating_sub(1);
121 }
122 Self { wanted, room }
123 }
124
125 #[must_use]
127 pub fn wanted(&self, class: RegClass, point: Point) -> u32 {
128 read(&self.wanted, class, point)
129 }
130
131 #[must_use]
133 pub fn room(&self, class: RegClass, point: Point) -> u32 {
134 read(&self.room, class, point)
135 }
136
137 #[must_use]
139 pub fn excess(&self, class: RegClass, point: Point) -> u32 {
140 self.wanted(class, point).saturating_sub(self.room(class, point))
141 }
142
143 #[must_use]
145 pub fn peak(&self, class: RegClass) -> u32 {
146 row(&self.wanted, class).iter().copied().max().unwrap_or(0)
147 }
148
149 pub fn over(&self, class: RegClass) -> impl Iterator<Item = Point> + '_ {
151 let wanted = row(&self.wanted, class);
152 (0..wanted.len())
153 .filter_map(|point| u32::try_from(point).ok())
154 .filter(move |&point| self.excess(class, point) > 0)
155 }
156
157 pub(crate) fn lift(&mut self, class: RegClass, area: Area<'_>) {
159 let Some(row) = self.wanted.get_mut(usize::from(class.number())) else { return };
160 for piece in area.pieces() {
161 for point in piece.start..=piece.end {
162 if let Some(count) = row.get_mut(at(point)) {
163 *count = count.saturating_sub(1);
164 }
165 }
166 }
167 }
168}
169
170fn row(table: &[Vec<u32>], class: RegClass) -> &[u32] {
171 table.get(usize::from(class.number())).map_or(&[], Vec::as_slice)
172}
173
174fn read(table: &[Vec<u32>], class: RegClass, point: Point) -> u32 {
175 row(table, class).get(at(point)).copied().unwrap_or(0)
176}
177
178fn at(point: Point) -> usize {
179 usize::try_from(point).expect("a point")
180}
181
182fn index(reg: Reg) -> usize {
183 usize::try_from(reg.number().expect("a virtual register")).expect("a register number")
184}
185
186#[cfg(test)]
187mod tests {
188 use rucc_base::Interner;
189 use rucc_mir::{Opcode, Operand};
190 use rucc_target::x86_64::{GPR, RAX, SYSV};
191
192 use super::*;
193
194 fn narrow(count: usize) -> Env {
195 Env::new().with(GPR, &SYSV.int_order[..count], &SYSV.int_order[count..count + 1])
196 }
197
198 fn of(func: &Func, env: &Env) -> (Order, Pressure) {
199 let order = Order::of(func);
200 let live = Live::of(func, &order);
201 let pressure = Pressure::of(func, &order, &live, env);
202 (order, pressure)
203 }
204
205 #[test]
206 fn every_value_live_at_a_point_is_counted_there() {
207 let mut names = Interner::new();
208 let mut func = Func::new(names.intern("f"));
209 let opcode = Opcode::new(names.intern("x64.nop"));
210 let block = func.create_block();
211 let values: Vec<Reg> = (0..3).map(|_| func.new_vreg(GPR)).collect();
212 let defs: Vec<_> = values
213 .iter()
214 .map(|&value| func.build(block, opcode).def(value, GPR).finish())
215 .collect();
216 let reads = func.build(block, opcode);
217 let reads = values.iter().fold(reads, |build, &value| build.uses(value, GPR));
218 let last = reads.finish();
219
220 let (order, pressure) = of(&func, &narrow(2));
221 assert_eq!(pressure.wanted(GPR, order.early(last)), 3);
222 assert_eq!(pressure.room(GPR, order.early(last)), 2);
223 assert_eq!(pressure.excess(GPR, order.early(last)), 1);
224 assert_eq!(pressure.peak(GPR), 3);
225 let over = [order.late(defs[2]), order.early(last)];
227 assert_eq!(pressure.over(GPR).collect::<Vec<_>>(), over);
228 }
229
230 #[test]
231 fn a_register_an_instruction_writes_outright_is_not_room_where_it_writes_it() {
232 let mut names = Interner::new();
233 let mut func = Func::new(names.intern("f"));
234 let opcode = Opcode::new(names.intern("x64.nop"));
235 let block = func.create_block();
236 let value = func.new_vreg(GPR);
237 func.build(block, opcode).def(value, GPR).finish();
238 let call =
239 func.build(block, opcode).operand(Operand::write(Reg::physical(RAX), GPR)).finish();
240 func.build(block, opcode).uses(value, GPR).finish();
241
242 let (order, pressure) = of(&func, &narrow(2));
243 assert_eq!(pressure.room(GPR, order.early(call)), 2);
244 assert_eq!(pressure.room(GPR, order.late(call)), 1);
245 assert_eq!(pressure.wanted(GPR, order.late(call)), 1);
246 assert_eq!(pressure.over(GPR).count(), 0);
247 }
248
249 #[test]
250 fn a_value_sent_to_memory_is_taken_off_every_point_it_was_live_at() {
251 let mut names = Interner::new();
252 let mut func = Func::new(names.intern("f"));
253 let opcode = Opcode::new(names.intern("x64.nop"));
254 let block = func.create_block();
255 let first = func.new_vreg(GPR);
256 let second = func.new_vreg(GPR);
257 func.build(block, opcode).def(first, GPR).finish();
258 func.build(block, opcode).def(second, GPR).finish();
259 let last = func.build(block, opcode).uses(first, GPR).uses(second, GPR).finish();
260
261 let order = Order::of(&func);
262 let live = Live::of(&func, &order);
263 let mut pressure = Pressure::of(&func, &order, &live, &narrow(1));
264 assert_eq!(pressure.excess(GPR, order.early(last)), 1);
265 pressure.lift(GPR, live.area(first).expect("live"));
266 assert_eq!(pressure.over(GPR).count(), 0);
267 assert_eq!(pressure.wanted(GPR, order.early(last)), 1);
268 }
269}