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() {
163 let end = at(piece.end).saturating_add(1).min(row.len());
164 let start = at(piece.start).min(end);
165 for count in &mut row[start..end] {
166 *count = count.saturating_sub(1);
167 }
168 }
169 }
170}
171
172fn row(table: &[Vec<u32>], class: RegClass) -> &[u32] {
173 table.get(usize::from(class.number())).map_or(&[], Vec::as_slice)
174}
175
176fn read(table: &[Vec<u32>], class: RegClass, point: Point) -> u32 {
177 row(table, class).get(at(point)).copied().unwrap_or(0)
178}
179
180fn at(point: Point) -> usize {
181 usize::try_from(point).expect("a point")
182}
183
184fn index(reg: Reg) -> usize {
185 usize::try_from(reg.number().expect("a virtual register")).expect("a register number")
186}
187
188#[cfg(test)]
189mod tests {
190 use rucc_base::Interner;
191 use rucc_mir::{Opcode, Operand};
192 use rucc_target::x86_64::{GPR, RAX, SYSV};
193
194 use super::*;
195
196 fn narrow(count: usize) -> Env {
197 Env::new().with(GPR, &SYSV.int_order[..count], &SYSV.int_order[count..count + 1])
198 }
199
200 fn of(func: &Func, env: &Env) -> (Order, Pressure) {
201 let order = Order::of(func);
202 let live = Live::of(func, &order);
203 let pressure = Pressure::of(func, &order, &live, env);
204 (order, pressure)
205 }
206
207 #[test]
208 fn every_value_live_at_a_point_is_counted_there() {
209 let mut names = Interner::new();
210 let mut func = Func::new(names.intern("f"));
211 let opcode = Opcode::new(names.intern("x64.nop"));
212 let block = func.create_block();
213 let values: Vec<Reg> = (0..3).map(|_| func.new_vreg(GPR)).collect();
214 let defs: Vec<_> = values
215 .iter()
216 .map(|&value| func.build(block, opcode).def(value, GPR).finish())
217 .collect();
218 let reads = func.build(block, opcode);
219 let reads = values.iter().fold(reads, |build, &value| build.uses(value, GPR));
220 let last = reads.finish();
221
222 let (order, pressure) = of(&func, &narrow(2));
223 assert_eq!(pressure.wanted(GPR, order.early(last)), 3);
224 assert_eq!(pressure.room(GPR, order.early(last)), 2);
225 assert_eq!(pressure.excess(GPR, order.early(last)), 1);
226 assert_eq!(pressure.peak(GPR), 3);
227 let over = [order.late(defs[2]), order.early(last)];
229 assert_eq!(pressure.over(GPR).collect::<Vec<_>>(), over);
230 }
231
232 #[test]
233 fn a_register_an_instruction_writes_outright_is_not_room_where_it_writes_it() {
234 let mut names = Interner::new();
235 let mut func = Func::new(names.intern("f"));
236 let opcode = Opcode::new(names.intern("x64.nop"));
237 let block = func.create_block();
238 let value = func.new_vreg(GPR);
239 func.build(block, opcode).def(value, GPR).finish();
240 let call =
241 func.build(block, opcode).operand(Operand::write(Reg::physical(RAX), GPR)).finish();
242 func.build(block, opcode).uses(value, GPR).finish();
243
244 let (order, pressure) = of(&func, &narrow(2));
245 assert_eq!(pressure.room(GPR, order.early(call)), 2);
246 assert_eq!(pressure.room(GPR, order.late(call)), 1);
247 assert_eq!(pressure.wanted(GPR, order.late(call)), 1);
248 assert_eq!(pressure.over(GPR).count(), 0);
249 }
250
251 #[test]
252 fn a_value_sent_to_memory_is_taken_off_every_point_it_was_live_at() {
253 let mut names = Interner::new();
254 let mut func = Func::new(names.intern("f"));
255 let opcode = Opcode::new(names.intern("x64.nop"));
256 let block = func.create_block();
257 let first = func.new_vreg(GPR);
258 let second = func.new_vreg(GPR);
259 func.build(block, opcode).def(first, GPR).finish();
260 func.build(block, opcode).def(second, GPR).finish();
261 let last = func.build(block, opcode).uses(first, GPR).uses(second, GPR).finish();
262
263 let order = Order::of(&func);
264 let live = Live::of(&func, &order);
265 let mut pressure = Pressure::of(&func, &order, &live, &narrow(1));
266 assert_eq!(pressure.excess(GPR, order.early(last)), 1);
267 pressure.lift(GPR, live.area(first).expect("live"));
268 assert_eq!(pressure.over(GPR).count(), 0);
269 assert_eq!(pressure.wanted(GPR, order.early(last)), 1);
270 }
271}