/rust/registry/src/index.crates.io-6f17d22bba15001f/regalloc2-0.5.1/src/ion/reg_traversal.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::{MachineEnv, PReg, RegClass}; |
2 | | |
3 | | /// This iterator represents a traversal through all allocatable |
4 | | /// registers of a given class, in a certain order designed to |
5 | | /// minimize allocation contention. |
6 | | /// |
7 | | /// The order in which we try registers is somewhat complex: |
8 | | /// - First, if there is a hint, we try that. |
9 | | /// - Then, we try registers in a traversal order that is based on an |
10 | | /// "offset" (usually the bundle index) spreading pressure evenly |
11 | | /// among registers to reduce commitment-map contention. |
12 | | /// - Within that scan, we try registers in two groups: first, |
13 | | /// prferred registers; then, non-preferred registers. (In normal |
14 | | /// usage, these consist of caller-save and callee-save registers |
15 | | /// respectively, to minimize clobber-saves; but they need not.) |
16 | | |
17 | | pub struct RegTraversalIter<'a> { |
18 | | env: &'a MachineEnv, |
19 | | class: usize, |
20 | | hints: [Option<PReg>; 2], |
21 | | hint_idx: usize, |
22 | | pref_idx: usize, |
23 | | non_pref_idx: usize, |
24 | | offset_pref: usize, |
25 | | offset_non_pref: usize, |
26 | | is_fixed: bool, |
27 | | fixed: Option<PReg>, |
28 | | } |
29 | | |
30 | | impl<'a> RegTraversalIter<'a> { |
31 | 1.88M | pub fn new( |
32 | 1.88M | env: &'a MachineEnv, |
33 | 1.88M | class: RegClass, |
34 | 1.88M | hint_reg: PReg, |
35 | 1.88M | hint2_reg: PReg, |
36 | 1.88M | offset: usize, |
37 | 1.88M | fixed: Option<PReg>, |
38 | 1.88M | ) -> Self { |
39 | 1.88M | let mut hint_reg = if hint_reg != PReg::invalid() { |
40 | 291k | Some(hint_reg) |
41 | | } else { |
42 | 1.59M | None |
43 | | }; |
44 | 1.88M | let mut hint2_reg = if hint2_reg != PReg::invalid() { |
45 | 0 | Some(hint2_reg) |
46 | | } else { |
47 | 1.88M | None |
48 | | }; |
49 | | |
50 | 1.88M | if hint_reg.is_none() { |
51 | 1.59M | hint_reg = hint2_reg; |
52 | 1.59M | hint2_reg = None; |
53 | 1.59M | } |
54 | 1.88M | let hints = [hint_reg, hint2_reg]; |
55 | 1.88M | let class = class as u8 as usize; |
56 | 1.88M | let offset_pref = if env.preferred_regs_by_class[class].len() > 0 { |
57 | 1.88M | offset % env.preferred_regs_by_class[class].len() |
58 | | } else { |
59 | 0 | 0 |
60 | | }; |
61 | 1.88M | let offset_non_pref = if env.non_preferred_regs_by_class[class].len() > 0 { |
62 | 1.32M | offset % env.non_preferred_regs_by_class[class].len() |
63 | | } else { |
64 | 563k | 0 |
65 | | }; |
66 | 1.88M | Self { |
67 | 1.88M | env, |
68 | 1.88M | class, |
69 | 1.88M | hints, |
70 | 1.88M | hint_idx: 0, |
71 | 1.88M | pref_idx: 0, |
72 | 1.88M | non_pref_idx: 0, |
73 | 1.88M | offset_pref, |
74 | 1.88M | offset_non_pref, |
75 | 1.88M | is_fixed: fixed.is_some(), |
76 | 1.88M | fixed, |
77 | 1.88M | } |
78 | 1.88M | } |
79 | | } |
80 | | |
81 | | impl<'a> std::iter::Iterator for RegTraversalIter<'a> { |
82 | | type Item = PReg; |
83 | | |
84 | 2.61M | fn next(&mut self) -> Option<PReg> { |
85 | 2.61M | if self.is_fixed { |
86 | 919k | let ret = self.fixed; |
87 | 919k | self.fixed = None; |
88 | 919k | return ret; |
89 | 1.69M | } |
90 | 1.69M | |
91 | 1.69M | fn wrap(idx: usize, limit: usize) -> usize { |
92 | 1.57M | if idx >= limit { |
93 | 1.69M | idx - limit |
94 | 1.69M | } else { |
95 | 1.69M | idx |
96 | 1.69M | } |
97 | 1.69M | } |
98 | 1.69M | if self.hint_idx < 2 && self.hints[self.hint_idx].is_some() { |
99 | 176k | let h = self.hints[self.hint_idx]; |
100 | 176k | self.hint_idx += 1; |
101 | 176k | return h; |
102 | 1.51M | } |
103 | 1.59M | while self.pref_idx < self.env.preferred_regs_by_class[self.class].len() { |
104 | 1.42M | let arr = &self.env.preferred_regs_by_class[self.class][..]; |
105 | 1.42M | let r = arr[wrap(self.pref_idx + self.offset_pref, arr.len())]; |
106 | 1.42M | self.pref_idx += 1; |
107 | 1.42M | if Some(r) == self.hints[0] || Some(r) == self.hints[1] { |
108 | 79.9k | continue; |
109 | 1.34M | } |
110 | 1.34M | return Some(r); |
111 | | } |
112 | 171k | while self.non_pref_idx < self.env.non_preferred_regs_by_class[self.class].len() { |
113 | 146k | let arr = &self.env.non_preferred_regs_by_class[self.class][..]; |
114 | 146k | let r = arr[wrap(self.non_pref_idx + self.offset_non_pref, arr.len())]; |
115 | 146k | self.non_pref_idx += 1; |
116 | 146k | if Some(r) == self.hints[0] || Some(r) == self.hints[1] { |
117 | 318 | continue; |
118 | 145k | } |
119 | 145k | return Some(r); |
120 | | } |
121 | 25.1k | None |
122 | 2.61M | } |
123 | | } |