/rust/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/machinst/valueregs.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! Data structure for tracking the (possibly multiple) registers that hold one |
2 | | //! SSA `Value`. |
3 | | |
4 | | use regalloc2::{PReg, VReg}; |
5 | | |
6 | | use super::{RealReg, Reg, VirtualReg, Writable}; |
7 | | use std::fmt::Debug; |
8 | | |
9 | | const VALUE_REGS_PARTS: usize = 2; |
10 | | |
11 | | /// Location at which a `Value` is stored in register(s): the value is located |
12 | | /// in one or more registers, depending on its width. A value may be stored in |
13 | | /// more than one register if the machine has no registers wide enough |
14 | | /// otherwise: for example, on a 32-bit architecture, we may store `I64` values |
15 | | /// in two registers, and `I128` values in four. |
16 | | /// |
17 | | /// By convention, the register parts are kept in machine-endian order here. |
18 | | /// |
19 | | /// N.B.: we cap the capacity of this at four (when any 32-bit target is |
20 | | /// enabled) or two (otherwise), and we use special in-band sentinal `Reg` |
21 | | /// values (`Reg::invalid()`) to avoid the need to carry a separate length. This |
22 | | /// allows the struct to be `Copy` (no heap or drop overhead) and be only 16 or |
23 | | /// 8 bytes, which is important for compiler performance. |
24 | | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
25 | | pub struct ValueRegs<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> { |
26 | | parts: [R; VALUE_REGS_PARTS], |
27 | | } |
28 | | |
29 | | /// A type with an "invalid" sentinel value. |
30 | | pub trait InvalidSentinel: Copy + Eq { |
31 | | /// The invalid sentinel value. |
32 | | fn invalid_sentinel() -> Self; |
33 | | /// Is this the invalid sentinel? |
34 | 2.69M | fn is_invalid_sentinel(self) -> bool { |
35 | 2.69M | self == Self::invalid_sentinel() |
36 | 2.69M | } <cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg> as cranelift_codegen::machinst::valueregs::InvalidSentinel>::is_invalid_sentinel Line | Count | Source | 34 | 36.3k | fn is_invalid_sentinel(self) -> bool { | 35 | 36.3k | self == Self::invalid_sentinel() | 36 | 36.3k | } |
Unexecuted instantiation: <cranelift_codegen::machinst::reg::VirtualReg as cranelift_codegen::machinst::valueregs::InvalidSentinel>::is_invalid_sentinel <cranelift_codegen::machinst::reg::Reg as cranelift_codegen::machinst::valueregs::InvalidSentinel>::is_invalid_sentinel Line | Count | Source | 34 | 2.65M | fn is_invalid_sentinel(self) -> bool { | 35 | 2.65M | self == Self::invalid_sentinel() | 36 | 2.65M | } |
Unexecuted instantiation: <cranelift_codegen::machinst::reg::RealReg as cranelift_codegen::machinst::valueregs::InvalidSentinel>::is_invalid_sentinel |
37 | | } |
38 | | impl InvalidSentinel for Reg { |
39 | 18.5M | fn invalid_sentinel() -> Self { |
40 | 18.5M | Reg::from(VReg::invalid()) |
41 | 18.5M | } |
42 | | } |
43 | | impl InvalidSentinel for VirtualReg { |
44 | 0 | fn invalid_sentinel() -> Self { |
45 | 0 | VirtualReg::from(VReg::invalid()) |
46 | 0 | } |
47 | | } |
48 | | impl InvalidSentinel for RealReg { |
49 | 0 | fn invalid_sentinel() -> Self { |
50 | 0 | RealReg::from(PReg::invalid()) |
51 | 0 | } |
52 | | } |
53 | | impl InvalidSentinel for Writable<Reg> { |
54 | 4.74M | fn invalid_sentinel() -> Self { |
55 | 4.74M | Writable::from_reg(Reg::invalid_sentinel()) |
56 | 4.74M | } |
57 | | } |
58 | | |
59 | | impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> { |
60 | | /// Create an invalid Value-in-Reg. |
61 | 139k | pub fn invalid() -> Self { |
62 | 139k | ValueRegs { |
63 | 139k | parts: [R::invalid_sentinel(); VALUE_REGS_PARTS], |
64 | 139k | } |
65 | 139k | } |
66 | | |
67 | | /// Is this Value-to-Reg mapping valid? |
68 | 928k | pub fn is_valid(self) -> bool { |
69 | 928k | !self.parts[0].is_invalid_sentinel() |
70 | 928k | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::is_valid Line | Count | Source | 68 | 36.3k | pub fn is_valid(self) -> bool { | 69 | 36.3k | !self.parts[0].is_invalid_sentinel() | 70 | 36.3k | } |
<cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::is_valid Line | Count | Source | 68 | 892k | pub fn is_valid(self) -> bool { | 69 | 892k | !self.parts[0].is_invalid_sentinel() | 70 | 892k | } |
|
71 | | /// Is this Value-to-Reg mapping invalid? |
72 | 1.10M | pub fn is_invalid(self) -> bool { |
73 | 1.10M | self.parts[0].is_invalid_sentinel() |
74 | 1.10M | } |
75 | | |
76 | | /// Return the single register used for this value, if any. |
77 | 1.59M | pub fn only_reg(self) -> Option<R> { |
78 | 1.59M | if self.len() == 1 { |
79 | 1.59M | Some(self.parts[0]) |
80 | | } else { |
81 | 0 | None |
82 | | } |
83 | 1.59M | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::only_reg Line | Count | Source | 77 | 748k | pub fn only_reg(self) -> Option<R> { | 78 | 748k | if self.len() == 1 { | 79 | 748k | Some(self.parts[0]) | 80 | | } else { | 81 | 0 | None | 82 | | } | 83 | 748k | } |
<cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::only_reg Line | Count | Source | 77 | 843k | pub fn only_reg(self) -> Option<R> { | 78 | 843k | if self.len() == 1 { | 79 | 843k | Some(self.parts[0]) | 80 | | } else { | 81 | 0 | None | 82 | | } | 83 | 843k | } |
|
84 | | |
85 | | /// Return an iterator over the registers storing this value. |
86 | 4.07M | pub fn regs(&self) -> &[R] { |
87 | 4.07M | &self.parts[0..self.len()] |
88 | 4.07M | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::regs Line | Count | Source | 86 | 1.02M | pub fn regs(&self) -> &[R] { | 87 | 1.02M | &self.parts[0..self.len()] | 88 | 1.02M | } |
<cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::regs Line | Count | Source | 86 | 3.05M | pub fn regs(&self) -> &[R] { | 87 | 3.05M | &self.parts[0..self.len()] | 88 | 3.05M | } |
|
89 | | } |
90 | | |
91 | | impl<R: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel> ValueRegs<R> { |
92 | | /// Create a Value-in-R location for a value stored in one register. |
93 | 2.32M | pub fn one(reg: R) -> Self { |
94 | 2.32M | ValueRegs { |
95 | 2.32M | parts: [reg, R::invalid_sentinel()], |
96 | 2.32M | } |
97 | 2.32M | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::one Line | Count | Source | 93 | 2.27M | pub fn one(reg: R) -> Self { | 94 | 2.27M | ValueRegs { | 95 | 2.27M | parts: [reg, R::invalid_sentinel()], | 96 | 2.27M | } | 97 | 2.27M | } |
<cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::one Line | Count | Source | 93 | 49.6k | pub fn one(reg: R) -> Self { | 94 | 49.6k | ValueRegs { | 95 | 49.6k | parts: [reg, R::invalid_sentinel()], | 96 | 49.6k | } | 97 | 49.6k | } |
|
98 | | /// Create a Value-in-R location for a value stored in two registers. |
99 | 564 | pub fn two(r1: R, r2: R) -> Self { |
100 | 564 | ValueRegs { parts: [r1, r2] } |
101 | 564 | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::two Line | Count | Source | 99 | 564 | pub fn two(r1: R, r2: R) -> Self { | 100 | 564 | ValueRegs { parts: [r1, r2] } | 101 | 564 | } |
Unexecuted instantiation: <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::two |
102 | | |
103 | | /// Return the number of registers used. |
104 | 6.58M | pub fn len(self) -> usize { |
105 | 6.58M | // If rustc/LLVM is smart enough, this might even be vectorized... |
106 | 6.58M | (self.parts[0] != R::invalid_sentinel()) as usize |
107 | 6.58M | + (self.parts[1] != R::invalid_sentinel()) as usize |
108 | 6.58M | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::len Line | Count | Source | 104 | 2.33M | pub fn len(self) -> usize { | 105 | 2.33M | // If rustc/LLVM is smart enough, this might even be vectorized... | 106 | 2.33M | (self.parts[0] != R::invalid_sentinel()) as usize | 107 | 2.33M | + (self.parts[1] != R::invalid_sentinel()) as usize | 108 | 2.33M | } |
<cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::len Line | Count | Source | 104 | 4.25M | pub fn len(self) -> usize { | 105 | 4.25M | // If rustc/LLVM is smart enough, this might even be vectorized... | 106 | 4.25M | (self.parts[0] != R::invalid_sentinel()) as usize | 107 | 4.25M | + (self.parts[1] != R::invalid_sentinel()) as usize | 108 | 4.25M | } |
|
109 | | |
110 | | /// Map individual registers via a map function. |
111 | 1.80M | pub fn map<NewR, F>(self, f: F) -> ValueRegs<NewR> |
112 | 1.80M | where |
113 | 1.80M | NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel, |
114 | 1.80M | F: Fn(R) -> NewR, |
115 | 1.80M | { |
116 | 1.80M | ValueRegs { |
117 | 1.80M | parts: [f(self.parts[0]), f(self.parts[1])], |
118 | 1.80M | } |
119 | 1.80M | } <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::map::<cranelift_codegen::machinst::reg::Reg, cranelift_codegen::machinst::valueregs::non_writable_value_regs::{closure#0}> Line | Count | Source | 111 | 86.4k | pub fn map<NewR, F>(self, f: F) -> ValueRegs<NewR> | 112 | 86.4k | where | 113 | 86.4k | NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel, | 114 | 86.4k | F: Fn(R) -> NewR, | 115 | 86.4k | { | 116 | 86.4k | ValueRegs { | 117 | 86.4k | parts: [f(self.parts[0]), f(self.parts[1])], | 118 | 86.4k | } | 119 | 86.4k | } |
Unexecuted instantiation: <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>>>::map::<cranelift_codegen::machinst::reg::Reg, <cranelift_codegen::machinst::isle::IsleContext<cranelift_codegen::isa::riscv64::lower::isle::generated_code::MInst, cranelift_codegen::settings::Flags, cranelift_codegen::isa::riscv64::settings::Flags, 6> as cranelift_codegen::isa::riscv64::lower::isle::generated_code::Context>::gen_moves::{closure#2}> <cranelift_codegen::machinst::valueregs::ValueRegs<cranelift_codegen::machinst::reg::Reg>>::map::<cranelift_codegen::machinst::reg::Writable<cranelift_codegen::machinst::reg::Reg>, cranelift_codegen::machinst::valueregs::writable_value_regs::{closure#0}> Line | Count | Source | 111 | 1.72M | pub fn map<NewR, F>(self, f: F) -> ValueRegs<NewR> | 112 | 1.72M | where | 113 | 1.72M | NewR: Clone + Copy + Debug + PartialEq + Eq + InvalidSentinel, | 114 | 1.72M | F: Fn(R) -> NewR, | 115 | 1.72M | { | 116 | 1.72M | ValueRegs { | 117 | 1.72M | parts: [f(self.parts[0]), f(self.parts[1])], | 118 | 1.72M | } | 119 | 1.72M | } |
|
120 | | } |
121 | | |
122 | | /// Create a writable ValueRegs. |
123 | | #[allow(dead_code)] |
124 | 1.72M | pub(crate) fn writable_value_regs(regs: ValueRegs<Reg>) -> ValueRegs<Writable<Reg>> { |
125 | 3.44M | regs.map(|r| Writable::from_reg(r)) |
126 | 1.72M | } |
127 | | |
128 | | /// Strip a writable ValueRegs down to a readonly ValueRegs. |
129 | | #[allow(dead_code)] |
130 | 86.4k | pub(crate) fn non_writable_value_regs(regs: ValueRegs<Writable<Reg>>) -> ValueRegs<Reg> { |
131 | 172k | regs.map(|r| r.to_reg()) |
132 | 86.4k | } |