1use crate::{RealReg, RegUsageMapper, VirtualReg};
2use smallvec::SmallVec;
3use std::mem;
4
5#[derive(Debug)]
14pub struct VrangeRegUsageMapper {
15 slots: Vec<RealReg>,
18
19 overlay: SmallVec<[(VirtualReg, RealReg); 16]>,
24}
25
26impl VrangeRegUsageMapper {
27 pub(crate) fn new(vreg_capacity: usize) -> VrangeRegUsageMapper {
29 VrangeRegUsageMapper {
30 slots: Vec::with_capacity(vreg_capacity),
31 overlay: SmallVec::new(),
32 }
33 }
34
35 fn is_overlay_large_enough_to_sort(&self) -> bool {
37 self.overlay.spilled()
43 }
44
45 pub(crate) fn set_overlay(&mut self, vreg: VirtualReg, rreg: Option<RealReg>) {
47 let rreg = rreg.unwrap_or(RealReg::invalid());
48 self.overlay.push((vreg, rreg));
49 }
50
51 pub(crate) fn finish_overlay(&mut self) {
53 if self.overlay.len() == 0 || !self.is_overlay_large_enough_to_sort() {
54 return;
55 }
56
57 self.overlay.sort_by_key(|pair| pair.0);
60 let mut last_vreg = self.overlay[0].0;
63 let mut out = 0;
64 for i in 1..self.overlay.len() {
65 let this_vreg = self.overlay[i].0;
66 if this_vreg != last_vreg {
67 out += 1;
68 }
69 if i != out {
70 self.overlay[out] = self.overlay[i];
71 }
72 last_vreg = this_vreg;
73 }
74 let new_len = out + 1;
75 self.overlay.truncate(new_len);
76 }
77
78 pub(crate) fn merge_overlay(&mut self) {
80 let mappings = mem::replace(&mut self.overlay, SmallVec::new());
83 for (vreg, rreg) in mappings.into_iter() {
84 self.set_direct_internal(vreg, rreg);
85 }
86 }
87
88 pub(crate) fn set_direct(&mut self, vreg: VirtualReg, rreg: Option<RealReg>) {
91 debug_assert!(self.overlay.is_empty());
92 let rreg = rreg.unwrap_or(RealReg::invalid());
93 self.set_direct_internal(vreg, rreg);
94 }
95
96 fn set_direct_internal(&mut self, vreg: VirtualReg, rreg: RealReg) {
97 let idx = vreg.get_index();
98 if idx >= self.slots.len() {
99 self.slots.resize(idx + 1, RealReg::invalid());
100 }
101 self.slots[idx] = rreg;
102 }
103
104 fn lookup_direct(&self, vreg: VirtualReg) -> Option<RealReg> {
107 let idx = vreg.get_index();
108 if idx >= self.slots.len() {
109 None
110 } else {
111 Some(self.slots[idx])
112 }
113 }
114
115 fn lookup_overlay(&self, vreg: VirtualReg) -> Option<RealReg> {
120 if self.is_overlay_large_enough_to_sort() {
121 if let Ok(idx) = self.overlay.binary_search_by_key(&vreg, |pair| pair.0) {
124 return Some(self.overlay[idx].1);
125 }
126 } else {
127 for &(this_vreg, this_rreg) in self.overlay.iter().rev() {
129 if this_vreg == vreg {
130 return Some(this_rreg);
131 }
132 }
133 }
134 None
135 }
136
137 pub(crate) fn is_empty(&self) -> bool {
140 self.overlay.iter().all(|pair| pair.1.is_invalid())
141 && self.slots.iter().all(|rreg| rreg.is_invalid())
142 }
143}
144
145impl RegUsageMapper for VrangeRegUsageMapper {
146 fn get_use(&self, vreg: VirtualReg) -> Option<RealReg> {
149 self.lookup_direct(vreg)
150 .and_then(|reg| reg.maybe_valid())
152 }
153
154 fn get_def(&self, vreg: VirtualReg) -> Option<RealReg> {
157 self.lookup_overlay(vreg)
158 .or_else(|| self.lookup_direct(vreg))
159 .and_then(|reg| reg.maybe_valid())
161 }
162
163 fn get_mod(&self, vreg: VirtualReg) -> Option<RealReg> {
166 let result = self.get_use(vreg);
167 debug_assert_eq!(result, self.get_def(vreg));
168 result
169 }
170}
171
172#[cfg(test)]
173mod test {
174 use super::*;
175 use crate::{Reg, RegClass, VirtualReg};
176
177 fn vreg(idx: u32) -> VirtualReg {
178 Reg::new_virtual(RegClass::I64, idx).to_virtual_reg()
179 }
180 fn rreg(idx: u8) -> RealReg {
181 Reg::new_real(RegClass::I64, 0, idx).to_real_reg()
182 }
183
184 #[test]
185 fn test_reg_use_mapper() {
186 let mut mapper = VrangeRegUsageMapper::new(16);
187 assert_eq!(None, mapper.get_use(vreg(0)));
188 assert_eq!(None, mapper.get_def(vreg(0)));
189 assert_eq!(None, mapper.get_mod(vreg(0)));
190
191 mapper.set_direct(vreg(0), Some(rreg(1)));
192 mapper.set_direct(vreg(1), Some(rreg(2)));
193
194 assert_eq!(Some(rreg(1)), mapper.get_use(vreg(0)));
195 assert_eq!(Some(rreg(1)), mapper.get_def(vreg(0)));
196 assert_eq!(Some(rreg(1)), mapper.get_mod(vreg(0)));
197 assert_eq!(Some(rreg(2)), mapper.get_use(vreg(1)));
198 assert_eq!(Some(rreg(2)), mapper.get_def(vreg(1)));
199 assert_eq!(Some(rreg(2)), mapper.get_mod(vreg(1)));
200
201 mapper.set_overlay(vreg(0), Some(rreg(3)));
202 mapper.set_overlay(vreg(2), Some(rreg(4)));
203 mapper.finish_overlay();
204
205 assert_eq!(Some(rreg(1)), mapper.get_use(vreg(0)));
206 assert_eq!(Some(rreg(3)), mapper.get_def(vreg(0)));
207 assert_eq!(Some(rreg(2)), mapper.get_use(vreg(1)));
209 assert_eq!(Some(rreg(2)), mapper.get_def(vreg(1)));
210 assert_eq!(Some(rreg(2)), mapper.get_mod(vreg(1)));
211 assert_eq!(None, mapper.get_use(vreg(2)));
212 assert_eq!(Some(rreg(4)), mapper.get_def(vreg(2)));
213 mapper.merge_overlay();
216 assert_eq!(Some(rreg(3)), mapper.get_use(vreg(0)));
217 assert_eq!(Some(rreg(2)), mapper.get_use(vreg(1)));
218 assert_eq!(Some(rreg(4)), mapper.get_use(vreg(2)));
219 assert_eq!(None, mapper.get_use(vreg(3)));
220
221 mapper.set_overlay(vreg(0), None);
223 mapper.finish_overlay();
224 assert_eq!(Some(rreg(3)), mapper.get_use(vreg(0)));
225 assert_eq!(None, mapper.get_def(vreg(0)));
226 mapper.merge_overlay();
227
228 for i in (2..50).rev() {
230 mapper.set_overlay(vreg(i), Some(rreg((i + 100) as u8)));
231 }
232 mapper.finish_overlay();
233 assert_eq!(None, mapper.get_use(vreg(0)));
234 assert_eq!(Some(rreg(2)), mapper.get_use(vreg(1)));
235 assert_eq!(Some(rreg(4)), mapper.get_use(vreg(2)));
236 for i in 2..50 {
237 assert_eq!(Some(rreg((i + 100) as u8)), mapper.get_def(vreg(i)));
238 }
239 mapper.merge_overlay();
240
241 for i in (0..100).rev() {
242 mapper.set_overlay(vreg(i), None);
243 }
244 mapper.finish_overlay();
245 for i in 0..100 {
246 assert_eq!(None, mapper.get_def(vreg(i)));
247 }
248 assert_eq!(false, mapper.is_empty());
249 mapper.merge_overlay();
250 assert_eq!(true, mapper.is_empty());
251
252 mapper.set_overlay(vreg(1), Some(rreg(1)));
254 mapper.set_overlay(vreg(1), Some(rreg(2)));
255 mapper.finish_overlay();
256 assert_eq!(Some(rreg(2)), mapper.get_def(vreg(1)));
257 mapper.merge_overlay();
258 assert_eq!(Some(rreg(2)), mapper.get_use(vreg(1)));
259
260 mapper.set_overlay(vreg(1), Some(rreg(2)));
261 mapper.set_overlay(vreg(1), None);
262 mapper.finish_overlay();
263 assert_eq!(None, mapper.get_def(vreg(1)));
264 mapper.merge_overlay();
265 assert_eq!(None, mapper.get_use(vreg(1)));
266
267 for i in 0..100 {
269 mapper.set_overlay(vreg(2), Some(rreg(i)));
270 }
271 for i in 0..100 {
272 mapper.set_overlay(vreg(2), Some(rreg(2 * i)));
273 }
274 mapper.finish_overlay();
275 assert_eq!(Some(rreg(198)), mapper.get_def(vreg(2)));
276 mapper.merge_overlay();
277 assert_eq!(Some(rreg(198)), mapper.get_use(vreg(2)));
278
279 for i in 0..100 {
280 mapper.set_overlay(vreg(2), Some(rreg(i)));
281 }
282 for _ in 0..100 {
283 mapper.set_overlay(vreg(2), None);
284 }
285 mapper.finish_overlay();
286 assert_eq!(None, mapper.get_def(vreg(50)));
287 mapper.merge_overlay();
288 assert_eq!(None, mapper.get_use(vreg(50)));
289 }
290}
291
292#[derive(Debug)]
302pub struct MentionRegUsageMapper {
303 uses: SmallVec<[(VirtualReg, RealReg); 8]>,
305
306 defs: SmallVec<[(VirtualReg, RealReg); 8]>,
308}
309
310impl MentionRegUsageMapper {
311 pub(crate) fn new() -> Self {
312 Self {
313 uses: SmallVec::new(),
314 defs: SmallVec::new(),
315 }
316 }
317 pub(crate) fn clear(&mut self) {
318 self.uses.clear();
319 self.defs.clear();
320 }
321 pub(crate) fn lookup_use(&self, vreg: VirtualReg) -> Option<RealReg> {
322 self.uses.iter().find(|&pair| pair.0 == vreg).map(|x| x.1)
323 }
324 pub(crate) fn lookup_def(&self, vreg: VirtualReg) -> Option<RealReg> {
325 self.defs.iter().find(|&pair| pair.0 == vreg).map(|x| x.1)
326 }
327 pub(crate) fn set_use(&mut self, vreg: VirtualReg, rreg: RealReg) {
328 self.uses.push((vreg, rreg));
329 }
330 pub(crate) fn set_def(&mut self, vreg: VirtualReg, rreg: RealReg) {
331 self.defs.push((vreg, rreg));
332 }
333}
334
335impl RegUsageMapper for MentionRegUsageMapper {
336 fn get_use(&self, vreg: VirtualReg) -> Option<RealReg> {
337 return self.lookup_use(vreg);
338 }
339 fn get_def(&self, vreg: VirtualReg) -> Option<RealReg> {
340 return self.lookup_def(vreg);
341 }
342 fn get_mod(&self, vreg: VirtualReg) -> Option<RealReg> {
343 let result = self.lookup_use(vreg);
344 debug_assert_eq!(result, self.lookup_def(vreg));
345 return result;
346 }
347}