regalloc2/ion/
reg_traversal.rs1use crate::{MachineEnv, PReg, RegClass};
4
5struct Cursor<'a> {
7 registers: &'a [PReg],
8 index: usize,
9 offset: usize,
10}
11
12impl<'a> Cursor<'a> {
13 #[inline]
14 fn new(registers: &'a [PReg], offset_hint: usize) -> Self {
15 let offset = if registers.len() > 0 {
16 offset_hint % registers.len()
17 } else {
18 0
19 };
20 Self {
21 registers,
22 index: 0,
23 offset,
24 }
25 }
26
27 #[inline]
30 fn wrap(index: usize, end: usize) -> usize {
31 if index >= end {
32 index - end
33 } else {
34 index
35 }
36 }
37
38 #[inline]
40 fn advance(&mut self) -> PReg {
41 let loc = Self::wrap(self.index + self.offset, self.registers.len());
42 let reg = self.registers[loc];
43 self.index += 1;
44 reg
45 }
46
47 #[inline]
49 fn done(&self) -> bool {
50 self.index >= self.registers.len()
51 }
52}
53
54pub struct RegTraversalIter<'a> {
69 is_fixed: bool,
70 fixed: Option<PReg>,
71 use_hint: bool,
72 hint: Option<PReg>,
73 preferred: Cursor<'a>,
74 non_preferred: Cursor<'a>,
75 limit: Option<usize>,
76}
77
78impl<'a> RegTraversalIter<'a> {
79 pub fn new(
80 env: &'a MachineEnv,
81 class: RegClass,
82 fixed: Option<PReg>,
83 hint: Option<PReg>,
84 offset: usize,
85 limit: Option<usize>,
86 ) -> Self {
87 debug_assert!(fixed != Some(PReg::invalid()));
88 debug_assert!(hint != Some(PReg::invalid()));
89
90 let class = class as u8 as usize;
91 let preferred = Cursor::new(&env.preferred_regs_by_class[class], offset);
92 let non_preferred = Cursor::new(&env.non_preferred_regs_by_class[class], offset);
93
94 Self {
95 is_fixed: fixed.is_some(),
96 fixed,
97 use_hint: hint.is_some(),
98 hint,
99 preferred,
100 non_preferred,
101 limit,
102 }
103 }
104}
105
106impl<'a> core::iter::Iterator for RegTraversalIter<'a> {
107 type Item = PReg;
108
109 fn next(&mut self) -> Option<PReg> {
110 if self.is_fixed {
111 return self.fixed.take();
112 }
113
114 if self.use_hint {
115 self.use_hint = false;
116 if self.hint.unwrap().hw_enc() < self.limit.unwrap_or(usize::MAX) {
117 return self.hint;
118 }
119 }
120
121 while !self.preferred.done() {
122 let reg = self.preferred.advance();
123 if Some(reg) == self.hint || reg.hw_enc() >= self.limit.unwrap_or(usize::MAX) {
124 continue; }
126 return Some(reg);
127 }
128
129 while !self.non_preferred.done() {
130 let reg = self.non_preferred.advance();
131 if Some(reg) == self.hint || reg.hw_enc() >= self.limit.unwrap_or(usize::MAX) {
132 continue; }
134 return Some(reg);
135 }
136
137 None
138 }
139}