Coverage Report

Created: 2024-10-16 07:58

/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
}