1 // Simple fixed-point representation of fractional costs
2 // Copyright (C) 2021-2024 Free Software Foundation, Inc.
4 // This file is part of GCC.
6 // GCC is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation; either version 3, or (at your option) any later
11 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 // You should have received a copy of the GNU General Public License
17 // along with GCC; see the file COPYING3. If not see
18 // <http://www.gnu.org/licenses/>.
20 // A simple saturating fixed-point type for representing fractional
21 // intermediate results in cost calculations. The input and result
22 // costs are assumed to be uint32_ts. Unlike sreal, the class can
23 // represent most values that we care about exactly (without rounding).
24 // See the comment above the SCALE field for the current set of
25 // exactly-representable reciprocals.
29 // Construct an object equal to INT_VALUE.
30 constexpr fractional_cost (uint32_t int_value
= 0)
31 : m_value (uint64_t (int_value
) * SCALE
) {}
33 fractional_cost (uint32_t a
, uint32_t b
);
35 fractional_cost
operator+ (const fractional_cost
&) const;
36 fractional_cost
operator- (const fractional_cost
&) const;
37 fractional_cost
operator* (uint32_t) const;
39 fractional_cost
&operator+= (const fractional_cost
&);
40 fractional_cost
&operator-= (const fractional_cost
&);
41 fractional_cost
&operator*= (uint32_t);
43 bool operator== (const fractional_cost
&) const;
44 bool operator!= (const fractional_cost
&) const;
45 bool operator< (const fractional_cost
&) const;
46 bool operator<= (const fractional_cost
&) const;
47 bool operator>= (const fractional_cost
&) const;
48 bool operator> (const fractional_cost
&) const;
50 uint32_t ceil () const;
52 static uint32_t scale (uint32_t, fractional_cost
, fractional_cost
);
54 explicit operator bool () const { return m_value
!= 0; }
56 // Convert the value to a double.
57 double as_double () const { return double (m_value
) / SCALE
; }
61 constexpr fractional_cost (uint64_t value
, raw
) : m_value (value
) {}
63 // A multiple of [1, 16] * 16. This ensures that 1/N is representable
64 // for every possible SVE element count N, or for any "X per cycle"
65 // value N in the range [1, 16].
66 static const uint32_t SCALE
= 11531520;
68 // The value multiplied by BIAS.
72 // Construct a representation of A / B, rounding up if (contrary to
73 // expectations) we can't represent the value exactly. For now we
74 // treat inexact values as a bug, since all values of B should come
75 // from a small set of values that are known at compile time.
76 inline fractional_cost::fractional_cost (uint32_t a
, uint32_t b
)
77 : m_value (CEIL (uint64_t (a
) * SCALE
, uint64_t (b
)))
79 gcc_checking_assert (SCALE
% b
== 0);
82 inline fractional_cost
83 fractional_cost::operator+ (const fractional_cost
&other
) const
85 uint64_t sum
= m_value
+ other
.m_value
;
86 return { sum
>= m_value
? sum
: ~uint64_t (0), RAW
};
89 inline fractional_cost
&
90 fractional_cost::operator+= (const fractional_cost
&other
)
92 *this = *this + other
;
96 inline fractional_cost
97 fractional_cost::operator- (const fractional_cost
&other
) const
99 uint64_t diff
= m_value
- other
.m_value
;
100 return { diff
<= m_value
? diff
: 0, RAW
};
103 inline fractional_cost
&
104 fractional_cost::operator-= (const fractional_cost
&other
)
106 *this = *this - other
;
110 inline fractional_cost
111 fractional_cost::operator* (uint32_t other
) const
116 uint64_t max
= ~uint64_t (0);
117 return { m_value
<= max
/ other
? m_value
* other
: max
, RAW
};
120 inline fractional_cost
&
121 fractional_cost::operator*= (uint32_t other
)
123 *this = *this * other
;
128 fractional_cost::operator== (const fractional_cost
&other
) const
130 return m_value
== other
.m_value
;
134 fractional_cost::operator!= (const fractional_cost
&other
) const
136 return m_value
!= other
.m_value
;
140 fractional_cost::operator< (const fractional_cost
&other
) const
142 return m_value
< other
.m_value
;
146 fractional_cost::operator<= (const fractional_cost
&other
) const
148 return m_value
<= other
.m_value
;
152 fractional_cost::operator>= (const fractional_cost
&other
) const
154 return m_value
>= other
.m_value
;
158 fractional_cost::operator> (const fractional_cost
&other
) const
160 return m_value
> other
.m_value
;
163 // Round the value up to the nearest integer and saturate to a uint32_t.
165 fractional_cost::ceil () const
167 uint32_t max
= ~uint32_t (0);
168 if (m_value
<= uint64_t (max
- 1) * SCALE
)
169 return (m_value
+ SCALE
- 1) / SCALE
;
173 // Round (COST * A) / B up to the nearest integer and saturate to a uint32_t.
175 fractional_cost::scale (uint32_t cost
, fractional_cost a
, fractional_cost b
)
177 widest_int result
= wi::div_ceil (widest_int (cost
) * a
.m_value
,
179 if (result
< ~uint32_t (0))
180 return result
.to_shwi ();
181 return ~uint32_t (0);
184 inline fractional_cost
185 operator+ (uint32_t a
, const fractional_cost
&b
)
187 return b
.operator+ (a
);
190 inline fractional_cost
191 operator- (uint32_t a
, const fractional_cost
&b
)
193 return fractional_cost (a
).operator- (b
);
196 inline fractional_cost
197 operator* (uint32_t a
, const fractional_cost
&b
)
199 return b
.operator* (a
);
203 operator== (uint32_t a
, const fractional_cost
&b
)
205 return b
.operator== (a
);
209 operator!= (uint32_t a
, const fractional_cost
&b
)
211 return b
.operator!= (a
);
215 operator< (uint32_t a
, const fractional_cost
&b
)
217 return b
.operator> (a
);
221 operator<= (uint32_t a
, const fractional_cost
&b
)
223 return b
.operator>= (a
);
227 operator>= (uint32_t a
, const fractional_cost
&b
)
229 return b
.operator<= (a
);
233 operator> (uint32_t a
, const fractional_cost
&b
)
235 return b
.operator< (a
);