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