fractional-cost.h revision 1.1 1 1.1 mrg // Simple fixed-point representation of fractional costs
2 1.1 mrg // Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 1.1 mrg //
4 1.1 mrg // This file is part of GCC.
5 1.1 mrg //
6 1.1 mrg // GCC is free software; you can redistribute it and/or modify it under
7 1.1 mrg // the terms of the GNU General Public License as published by the Free
8 1.1 mrg // Software Foundation; either version 3, or (at your option) any later
9 1.1 mrg // version.
10 1.1 mrg //
11 1.1 mrg // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 1.1 mrg // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 1.1 mrg // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 1.1 mrg // for more details.
15 1.1 mrg //
16 1.1 mrg // You should have received a copy of the GNU General Public License
17 1.1 mrg // along with GCC; see the file COPYING3. If not see
18 1.1 mrg // <http://www.gnu.org/licenses/>.
19 1.1 mrg
20 1.1 mrg // A simple saturating fixed-point type for representing fractional
21 1.1 mrg // intermediate results in cost calculations. The input and result
22 1.1 mrg // costs are assumed to be uint32_ts. Unlike sreal, the class can
23 1.1 mrg // represent most values that we care about exactly (without rounding).
24 1.1 mrg // See the comment above the SCALE field for the current set of
25 1.1 mrg // exactly-representable reciprocals.
26 1.1 mrg class fractional_cost
27 1.1 mrg {
28 1.1 mrg public:
29 1.1 mrg // Construct an object equal to INT_VALUE.
30 1.1 mrg constexpr fractional_cost (uint32_t int_value = 0)
31 1.1 mrg : m_value (uint64_t (int_value) * SCALE) {}
32 1.1 mrg
33 1.1 mrg fractional_cost (uint32_t a, uint32_t b);
34 1.1 mrg
35 1.1 mrg fractional_cost operator+ (const fractional_cost &) const;
36 1.1 mrg fractional_cost operator- (const fractional_cost &) const;
37 1.1 mrg fractional_cost operator* (uint32_t) const;
38 1.1 mrg
39 1.1 mrg fractional_cost &operator+= (const fractional_cost &);
40 1.1 mrg fractional_cost &operator-= (const fractional_cost &);
41 1.1 mrg fractional_cost &operator*= (uint32_t);
42 1.1 mrg
43 1.1 mrg bool operator== (const fractional_cost &) const;
44 1.1 mrg bool operator!= (const fractional_cost &) const;
45 1.1 mrg bool operator< (const fractional_cost &) const;
46 1.1 mrg bool operator<= (const fractional_cost &) const;
47 1.1 mrg bool operator>= (const fractional_cost &) const;
48 1.1 mrg bool operator> (const fractional_cost &) const;
49 1.1 mrg
50 1.1 mrg uint32_t ceil () const;
51 1.1 mrg
52 1.1 mrg static uint32_t scale (uint32_t, fractional_cost, fractional_cost);
53 1.1 mrg
54 1.1 mrg explicit operator bool () const { return m_value != 0; }
55 1.1 mrg
56 1.1 mrg // Convert the value to a double.
57 1.1 mrg double as_double () const { return double (m_value) / SCALE; }
58 1.1 mrg
59 1.1 mrg private:
60 1.1 mrg enum raw { RAW };
61 1.1 mrg constexpr fractional_cost (uint64_t value, raw) : m_value (value) {}
62 1.1 mrg
63 1.1 mrg // A multiple of [1, 16] * 16. This ensures that 1/N is representable
64 1.1 mrg // for every possible SVE element count N, or for any "X per cycle"
65 1.1 mrg // value N in the range [1, 16].
66 1.1 mrg static const uint32_t SCALE = 11531520;
67 1.1 mrg
68 1.1 mrg // The value multiplied by BIAS.
69 1.1 mrg uint64_t m_value;
70 1.1 mrg };
71 1.1 mrg
72 1.1 mrg // Construct a representation of A / B, rounding up if (contrary to
73 1.1 mrg // expectations) we can't represent the value exactly. For now we
74 1.1 mrg // treat inexact values as a bug, since all values of B should come
75 1.1 mrg // from a small set of values that are known at compile time.
76 1.1 mrg inline fractional_cost::fractional_cost (uint32_t a, uint32_t b)
77 1.1 mrg : m_value (CEIL (uint64_t (a) * SCALE, uint64_t (b)))
78 1.1 mrg {
79 1.1 mrg gcc_checking_assert (SCALE % b == 0);
80 1.1 mrg }
81 1.1 mrg
82 1.1 mrg inline fractional_cost
83 1.1 mrg fractional_cost::operator+ (const fractional_cost &other) const
84 1.1 mrg {
85 1.1 mrg uint64_t sum = m_value + other.m_value;
86 1.1 mrg return { sum >= m_value ? sum : ~uint64_t (0), RAW };
87 1.1 mrg }
88 1.1 mrg
89 1.1 mrg inline fractional_cost &
90 1.1 mrg fractional_cost::operator+= (const fractional_cost &other)
91 1.1 mrg {
92 1.1 mrg *this = *this + other;
93 1.1 mrg return *this;
94 1.1 mrg }
95 1.1 mrg
96 1.1 mrg inline fractional_cost
97 1.1 mrg fractional_cost::operator- (const fractional_cost &other) const
98 1.1 mrg {
99 1.1 mrg uint64_t diff = m_value - other.m_value;
100 1.1 mrg return { diff <= m_value ? diff : 0, RAW };
101 1.1 mrg }
102 1.1 mrg
103 1.1 mrg inline fractional_cost &
104 1.1 mrg fractional_cost::operator-= (const fractional_cost &other)
105 1.1 mrg {
106 1.1 mrg *this = *this - other;
107 1.1 mrg return *this;
108 1.1 mrg }
109 1.1 mrg
110 1.1 mrg inline fractional_cost
111 1.1 mrg fractional_cost::operator* (uint32_t other) const
112 1.1 mrg {
113 1.1 mrg if (other == 0)
114 1.1 mrg return 0;
115 1.1 mrg
116 1.1 mrg uint64_t max = ~uint64_t (0);
117 1.1 mrg return { m_value <= max / other ? m_value * other : max, RAW };
118 1.1 mrg }
119 1.1 mrg
120 1.1 mrg inline fractional_cost &
121 1.1 mrg fractional_cost::operator*= (uint32_t other)
122 1.1 mrg {
123 1.1 mrg *this = *this * other;
124 1.1 mrg return *this;
125 1.1 mrg }
126 1.1 mrg
127 1.1 mrg inline bool
128 1.1 mrg fractional_cost::operator== (const fractional_cost &other) const
129 1.1 mrg {
130 1.1 mrg return m_value == other.m_value;
131 1.1 mrg }
132 1.1 mrg
133 1.1 mrg inline bool
134 1.1 mrg fractional_cost::operator!= (const fractional_cost &other) const
135 1.1 mrg {
136 1.1 mrg return m_value != other.m_value;
137 1.1 mrg }
138 1.1 mrg
139 1.1 mrg inline bool
140 1.1 mrg fractional_cost::operator< (const fractional_cost &other) const
141 1.1 mrg {
142 1.1 mrg return m_value < other.m_value;
143 1.1 mrg }
144 1.1 mrg
145 1.1 mrg inline bool
146 1.1 mrg fractional_cost::operator<= (const fractional_cost &other) const
147 1.1 mrg {
148 1.1 mrg return m_value <= other.m_value;
149 1.1 mrg }
150 1.1 mrg
151 1.1 mrg inline bool
152 1.1 mrg fractional_cost::operator>= (const fractional_cost &other) const
153 1.1 mrg {
154 1.1 mrg return m_value >= other.m_value;
155 1.1 mrg }
156 1.1 mrg
157 1.1 mrg inline bool
158 1.1 mrg fractional_cost::operator> (const fractional_cost &other) const
159 1.1 mrg {
160 1.1 mrg return m_value > other.m_value;
161 1.1 mrg }
162 1.1 mrg
163 1.1 mrg // Round the value up to the nearest integer and saturate to a uint32_t.
164 1.1 mrg inline uint32_t
165 1.1 mrg fractional_cost::ceil () const
166 1.1 mrg {
167 1.1 mrg uint32_t max = ~uint32_t (0);
168 1.1 mrg if (m_value <= uint64_t (max - 1) * SCALE)
169 1.1 mrg return (m_value + SCALE - 1) / SCALE;
170 1.1 mrg return max;
171 1.1 mrg }
172 1.1 mrg
173 1.1 mrg // Round (COST * A) / B up to the nearest integer and saturate to a uint32_t.
174 1.1 mrg inline uint32_t
175 1.1 mrg fractional_cost::scale (uint32_t cost, fractional_cost a, fractional_cost b)
176 1.1 mrg {
177 1.1 mrg widest_int result = wi::div_ceil (widest_int (cost) * a.m_value,
178 1.1 mrg b.m_value, SIGNED);
179 1.1 mrg if (result < ~uint32_t (0))
180 1.1 mrg return result.to_shwi ();
181 1.1 mrg return ~uint32_t (0);
182 1.1 mrg }
183 1.1 mrg
184 1.1 mrg inline fractional_cost
185 1.1 mrg operator+ (uint32_t a, const fractional_cost &b)
186 1.1 mrg {
187 1.1 mrg return b.operator+ (a);
188 1.1 mrg }
189 1.1 mrg
190 1.1 mrg inline fractional_cost
191 1.1 mrg operator- (uint32_t a, const fractional_cost &b)
192 1.1 mrg {
193 1.1 mrg return fractional_cost (a).operator- (b);
194 1.1 mrg }
195 1.1 mrg
196 1.1 mrg inline fractional_cost
197 1.1 mrg operator* (uint32_t a, const fractional_cost &b)
198 1.1 mrg {
199 1.1 mrg return b.operator* (a);
200 1.1 mrg }
201 1.1 mrg
202 1.1 mrg inline bool
203 1.1 mrg operator== (uint32_t a, const fractional_cost &b)
204 1.1 mrg {
205 1.1 mrg return b.operator== (a);
206 1.1 mrg }
207 1.1 mrg
208 1.1 mrg inline bool
209 1.1 mrg operator!= (uint32_t a, const fractional_cost &b)
210 1.1 mrg {
211 1.1 mrg return b.operator!= (a);
212 1.1 mrg }
213 1.1 mrg
214 1.1 mrg inline bool
215 1.1 mrg operator< (uint32_t a, const fractional_cost &b)
216 1.1 mrg {
217 1.1 mrg return b.operator> (a);
218 1.1 mrg }
219 1.1 mrg
220 1.1 mrg inline bool
221 1.1 mrg operator<= (uint32_t a, const fractional_cost &b)
222 1.1 mrg {
223 1.1 mrg return b.operator>= (a);
224 1.1 mrg }
225 1.1 mrg
226 1.1 mrg inline bool
227 1.1 mrg operator>= (uint32_t a, const fractional_cost &b)
228 1.1 mrg {
229 1.1 mrg return b.operator<= (a);
230 1.1 mrg }
231 1.1 mrg
232 1.1 mrg inline bool
233 1.1 mrg operator> (uint32_t a, const fractional_cost &b)
234 1.1 mrg {
235 1.1 mrg return b.operator< (a);
236 1.1 mrg }
237