Mercurial > hg > CbC > CbC_gcc
comparison gcc/vector-builder.h @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* A class for building vector constant patterns. | 1 /* A class for building vector constant patterns. |
2 Copyright (C) 2017-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2017-2020 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 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 | 7 the terms of the GNU General Public License as published by the Free |
43 2. It can be used to build a vector that already has a known encoding. | 43 2. It can be used to build a vector that already has a known encoding. |
44 This is preferred since it is more efficient and copes with | 44 This is preferred since it is more efficient and copes with |
45 variable-length vectors. finalize () then canonicalizes the encoding | 45 variable-length vectors. finalize () then canonicalizes the encoding |
46 to a simpler form if possible. | 46 to a simpler form if possible. |
47 | 47 |
48 The derived class Derived provides this functionality for specific Ts. | 48 Shape is the type that specifies the number of elements in the vector |
49 Derived needs to provide the following interface: | 49 and (where relevant) the type of each element. |
50 | |
51 The derived class Derived provides the functionality of this class | |
52 for specific Ts. Derived needs to provide the following interface: | |
50 | 53 |
51 bool equal_p (T elt1, T elt2) const; | 54 bool equal_p (T elt1, T elt2) const; |
52 | 55 |
53 Return true if elements ELT1 and ELT2 are equal. | 56 Return true if elements ELT1 and ELT2 are equal. |
54 | 57 |
80 | 83 |
81 void note_representative (T *elt1_ptr, T elt2); | 84 void note_representative (T *elt1_ptr, T elt2); |
82 | 85 |
83 Record that ELT2 is being elided, given that ELT1_PTR points to | 86 Record that ELT2 is being elided, given that ELT1_PTR points to |
84 the last encoded element for the containing pattern. This is | 87 the last encoded element for the containing pattern. This is |
85 again provided for TREE_OVERFLOW handling. */ | 88 again provided for TREE_OVERFLOW handling. |
86 | 89 |
87 template<typename T, typename Derived> | 90 static poly_uint64 shape_nelts (Shape shape); |
91 | |
92 Return the number of elements in SHAPE. | |
93 | |
94 The class provides additional functionality for the case in which | |
95 T can describe a vector constant as well as an individual element. | |
96 This functionality requires: | |
97 | |
98 static poly_uint64 nelts_of (T x); | |
99 | |
100 Return the number of elements in vector constant X. | |
101 | |
102 static unsigned int npatterns_of (T x); | |
103 | |
104 Return the number of patterns used to encode vector constant X. | |
105 | |
106 static unsigned int nelts_per_pattern_of (T x); | |
107 | |
108 Return the number of elements used to encode each pattern | |
109 in vector constant X. */ | |
110 | |
111 template<typename T, typename Shape, typename Derived> | |
88 class vector_builder : public auto_vec<T, 32> | 112 class vector_builder : public auto_vec<T, 32> |
89 { | 113 { |
90 public: | 114 public: |
91 vector_builder (); | 115 vector_builder (); |
92 | 116 |
94 unsigned int npatterns () const { return m_npatterns; } | 118 unsigned int npatterns () const { return m_npatterns; } |
95 unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; } | 119 unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; } |
96 unsigned int encoded_nelts () const; | 120 unsigned int encoded_nelts () const; |
97 bool encoded_full_vector_p () const; | 121 bool encoded_full_vector_p () const; |
98 T elt (unsigned int) const; | 122 T elt (unsigned int) const; |
123 unsigned int count_dups (int, int, int) const; | |
99 | 124 |
100 bool operator == (const Derived &) const; | 125 bool operator == (const Derived &) const; |
101 bool operator != (const Derived &x) const { return !operator == (x); } | 126 bool operator != (const Derived &x) const { return !operator == (x); } |
102 | 127 |
128 bool new_unary_operation (Shape, T, bool); | |
129 bool new_binary_operation (Shape, T, T, bool); | |
130 | |
103 void finalize (); | 131 void finalize (); |
132 | |
133 static unsigned int binary_encoded_nelts (T, T); | |
104 | 134 |
105 protected: | 135 protected: |
106 void new_vector (poly_uint64, unsigned int, unsigned int); | 136 void new_vector (poly_uint64, unsigned int, unsigned int); |
107 void reshape (unsigned int, unsigned int); | 137 void reshape (unsigned int, unsigned int); |
108 bool repeating_sequence_p (unsigned int, unsigned int, unsigned int); | 138 bool repeating_sequence_p (unsigned int, unsigned int, unsigned int); |
118 poly_uint64 m_full_nelts; | 148 poly_uint64 m_full_nelts; |
119 unsigned int m_npatterns; | 149 unsigned int m_npatterns; |
120 unsigned int m_nelts_per_pattern; | 150 unsigned int m_nelts_per_pattern; |
121 }; | 151 }; |
122 | 152 |
123 template<typename T, typename Derived> | 153 template<typename T, typename Shape, typename Derived> |
124 inline const Derived * | 154 inline const Derived * |
125 vector_builder<T, Derived>::derived () const | 155 vector_builder<T, Shape, Derived>::derived () const |
126 { | 156 { |
127 return static_cast<const Derived *> (this); | 157 return static_cast<const Derived *> (this); |
128 } | 158 } |
129 | 159 |
130 template<typename T, typename Derived> | 160 template<typename T, typename Shape, typename Derived> |
131 inline | 161 inline |
132 vector_builder<T, Derived>::vector_builder () | 162 vector_builder<T, Shape, Derived>::vector_builder () |
133 : m_full_nelts (0), | 163 : m_full_nelts (0), |
134 m_npatterns (0), | 164 m_npatterns (0), |
135 m_nelts_per_pattern (0) | 165 m_nelts_per_pattern (0) |
136 {} | 166 {} |
137 | 167 |
138 /* Return the number of elements that are explicitly encoded. The vec | 168 /* Return the number of elements that are explicitly encoded. The vec |
139 starts with these explicitly-encoded elements and may contain additional | 169 starts with these explicitly-encoded elements and may contain additional |
140 elided elements. */ | 170 elided elements. */ |
141 | 171 |
142 template<typename T, typename Derived> | 172 template<typename T, typename Shape, typename Derived> |
143 inline unsigned int | 173 inline unsigned int |
144 vector_builder<T, Derived>::encoded_nelts () const | 174 vector_builder<T, Shape, Derived>::encoded_nelts () const |
145 { | 175 { |
146 return m_npatterns * m_nelts_per_pattern; | 176 return m_npatterns * m_nelts_per_pattern; |
147 } | 177 } |
148 | 178 |
149 /* Return true if every element of the vector is explicitly encoded. */ | 179 /* Return true if every element of the vector is explicitly encoded. */ |
150 | 180 |
151 template<typename T, typename Derived> | 181 template<typename T, typename Shape, typename Derived> |
152 inline bool | 182 inline bool |
153 vector_builder<T, Derived>::encoded_full_vector_p () const | 183 vector_builder<T, Shape, Derived>::encoded_full_vector_p () const |
154 { | 184 { |
155 return known_eq (m_npatterns * m_nelts_per_pattern, m_full_nelts); | 185 return known_eq (m_npatterns * m_nelts_per_pattern, m_full_nelts); |
156 } | 186 } |
157 | 187 |
158 /* Start building a vector that has FULL_NELTS elements. Initially | 188 /* Start building a vector that has FULL_NELTS elements. Initially |
159 encode it using NPATTERNS patterns with NELTS_PER_PATTERN each. */ | 189 encode it using NPATTERNS patterns with NELTS_PER_PATTERN each. */ |
160 | 190 |
161 template<typename T, typename Derived> | 191 template<typename T, typename Shape, typename Derived> |
162 void | 192 void |
163 vector_builder<T, Derived>::new_vector (poly_uint64 full_nelts, | 193 vector_builder<T, Shape, Derived>::new_vector (poly_uint64 full_nelts, |
164 unsigned int npatterns, | 194 unsigned int npatterns, |
165 unsigned int nelts_per_pattern) | 195 unsigned int nelts_per_pattern) |
166 { | 196 { |
167 m_full_nelts = full_nelts; | 197 m_full_nelts = full_nelts; |
168 m_npatterns = npatterns; | 198 m_npatterns = npatterns; |
169 m_nelts_per_pattern = nelts_per_pattern; | 199 m_nelts_per_pattern = nelts_per_pattern; |
170 this->reserve (encoded_nelts ()); | 200 this->reserve (encoded_nelts ()); |
172 } | 202 } |
173 | 203 |
174 /* Return true if this vector and OTHER have the same elements and | 204 /* Return true if this vector and OTHER have the same elements and |
175 are encoded in the same way. */ | 205 are encoded in the same way. */ |
176 | 206 |
177 template<typename T, typename Derived> | 207 template<typename T, typename Shape, typename Derived> |
178 bool | 208 bool |
179 vector_builder<T, Derived>::operator == (const Derived &other) const | 209 vector_builder<T, Shape, Derived>::operator == (const Derived &other) const |
180 { | 210 { |
181 if (maybe_ne (m_full_nelts, other.m_full_nelts) | 211 if (maybe_ne (m_full_nelts, other.m_full_nelts) |
182 || m_npatterns != other.m_npatterns | 212 || m_npatterns != other.m_npatterns |
183 || m_nelts_per_pattern != other.m_nelts_per_pattern) | 213 || m_nelts_per_pattern != other.m_nelts_per_pattern) |
184 return false; | 214 return false; |
192 } | 222 } |
193 | 223 |
194 /* Return the value of vector element I, which might or might not be | 224 /* Return the value of vector element I, which might or might not be |
195 encoded explicitly. */ | 225 encoded explicitly. */ |
196 | 226 |
197 template<typename T, typename Derived> | 227 template<typename T, typename Shape, typename Derived> |
198 T | 228 T |
199 vector_builder<T, Derived>::elt (unsigned int i) const | 229 vector_builder<T, Shape, Derived>::elt (unsigned int i) const |
200 { | 230 { |
201 /* This only makes sense if the encoding has been fully populated. */ | |
202 gcc_checking_assert (encoded_nelts () <= this->length ()); | |
203 | |
204 /* First handle elements that are already present in the underlying | 231 /* First handle elements that are already present in the underlying |
205 vector, regardless of whether they're part of the encoding or not. */ | 232 vector, regardless of whether they're part of the encoding or not. */ |
206 if (i < this->length ()) | 233 if (i < this->length ()) |
207 return (*this)[i]; | 234 return (*this)[i]; |
235 | |
236 /* Extrapolation is only possible if the encoding has been fully | |
237 populated. */ | |
238 gcc_checking_assert (encoded_nelts () <= this->length ()); | |
208 | 239 |
209 /* Identify the pattern that contains element I and work out the index of | 240 /* Identify the pattern that contains element I and work out the index of |
210 the last encoded element for that pattern. */ | 241 the last encoded element for that pattern. */ |
211 unsigned int pattern = i % m_npatterns; | 242 unsigned int pattern = i % m_npatterns; |
212 unsigned int count = i / m_npatterns; | 243 unsigned int count = i / m_npatterns; |
221 T prev = (*this)[final_i - m_npatterns]; | 252 T prev = (*this)[final_i - m_npatterns]; |
222 return derived ()->apply_step (final, count - 2, | 253 return derived ()->apply_step (final, count - 2, |
223 derived ()->step (prev, final)); | 254 derived ()->step (prev, final)); |
224 } | 255 } |
225 | 256 |
257 /* Try to start building a new vector of shape SHAPE that holds the result of | |
258 a unary operation on vector constant VEC. ALLOW_STEPPED_P is true if the | |
259 operation can handle stepped encodings directly, without having to expand | |
260 the full sequence. | |
261 | |
262 Return true if the operation is possible, which it always is when | |
263 ALLOW_STEPPED_P is true. Leave the builder unchanged otherwise. */ | |
264 | |
265 template<typename T, typename Shape, typename Derived> | |
266 bool | |
267 vector_builder<T, Shape, Derived>::new_unary_operation (Shape shape, T vec, | |
268 bool allow_stepped_p) | |
269 { | |
270 poly_uint64 full_nelts = Derived::shape_nelts (shape); | |
271 gcc_assert (known_eq (full_nelts, Derived::nelts_of (vec))); | |
272 unsigned int npatterns = Derived::npatterns_of (vec); | |
273 unsigned int nelts_per_pattern = Derived::nelts_per_pattern_of (vec); | |
274 if (!allow_stepped_p && nelts_per_pattern > 2) | |
275 { | |
276 if (!full_nelts.is_constant ()) | |
277 return false; | |
278 npatterns = full_nelts.to_constant (); | |
279 nelts_per_pattern = 1; | |
280 } | |
281 derived ()->new_vector (shape, npatterns, nelts_per_pattern); | |
282 return true; | |
283 } | |
284 | |
285 /* Try to start building a new vector of shape SHAPE that holds the result of | |
286 a binary operation on vector constants VEC1 and VEC2. ALLOW_STEPPED_P is | |
287 true if the operation can handle stepped encodings directly, without | |
288 having to expand the full sequence. | |
289 | |
290 Return true if the operation is possible. Leave the builder unchanged | |
291 otherwise. */ | |
292 | |
293 template<typename T, typename Shape, typename Derived> | |
294 bool | |
295 vector_builder<T, Shape, Derived>::new_binary_operation (Shape shape, | |
296 T vec1, T vec2, | |
297 bool allow_stepped_p) | |
298 { | |
299 poly_uint64 full_nelts = Derived::shape_nelts (shape); | |
300 gcc_assert (known_eq (full_nelts, Derived::nelts_of (vec1)) | |
301 && known_eq (full_nelts, Derived::nelts_of (vec2))); | |
302 /* Conceptually we split the patterns in VEC1 and VEC2 until we have | |
303 an equal number for both. Each split pattern requires the same | |
304 number of elements per pattern as the original. E.g. splitting: | |
305 | |
306 { 1, 2, 3, ... } | |
307 | |
308 into two gives: | |
309 | |
310 { 1, 3, 5, ... } | |
311 { 2, 4, 6, ... } | |
312 | |
313 while splitting: | |
314 | |
315 { 1, 0, ... } | |
316 | |
317 into two gives: | |
318 | |
319 { 1, 0, ... } | |
320 { 0, 0, ... }. */ | |
321 unsigned int npatterns | |
322 = least_common_multiple (Derived::npatterns_of (vec1), | |
323 Derived::npatterns_of (vec2)); | |
324 unsigned int nelts_per_pattern | |
325 = MAX (Derived::nelts_per_pattern_of (vec1), | |
326 Derived::nelts_per_pattern_of (vec2)); | |
327 if (!allow_stepped_p && nelts_per_pattern > 2) | |
328 { | |
329 if (!full_nelts.is_constant ()) | |
330 return false; | |
331 npatterns = full_nelts.to_constant (); | |
332 nelts_per_pattern = 1; | |
333 } | |
334 derived ()->new_vector (shape, npatterns, nelts_per_pattern); | |
335 return true; | |
336 } | |
337 | |
338 /* Return the number of elements that the caller needs to operate on in | |
339 order to handle a binary operation on vector constants VEC1 and VEC2. | |
340 This static function is used instead of new_binary_operation if the | |
341 result of the operation is not a constant vector. */ | |
342 | |
343 template<typename T, typename Shape, typename Derived> | |
344 unsigned int | |
345 vector_builder<T, Shape, Derived>::binary_encoded_nelts (T vec1, T vec2) | |
346 { | |
347 poly_uint64 nelts = Derived::nelts_of (vec1); | |
348 gcc_assert (known_eq (nelts, Derived::nelts_of (vec2))); | |
349 /* See new_binary_operation for details. */ | |
350 unsigned int npatterns | |
351 = least_common_multiple (Derived::npatterns_of (vec1), | |
352 Derived::npatterns_of (vec2)); | |
353 unsigned int nelts_per_pattern | |
354 = MAX (Derived::nelts_per_pattern_of (vec1), | |
355 Derived::nelts_per_pattern_of (vec2)); | |
356 unsigned HOST_WIDE_INT const_nelts; | |
357 if (nelts.is_constant (&const_nelts)) | |
358 return MIN (npatterns * nelts_per_pattern, const_nelts); | |
359 return npatterns * nelts_per_pattern; | |
360 } | |
361 | |
362 /* Return the number of leading duplicate elements in the range | |
363 [START:END:STEP]. The value is always at least 1. */ | |
364 | |
365 template<typename T, typename Shape, typename Derived> | |
366 unsigned int | |
367 vector_builder<T, Shape, Derived>::count_dups (int start, int end, | |
368 int step) const | |
369 { | |
370 gcc_assert ((end - start) % step == 0); | |
371 | |
372 unsigned int ndups = 1; | |
373 for (int i = start + step; | |
374 i != end && derived ()->equal_p (elt (i), elt (start)); | |
375 i += step) | |
376 ndups++; | |
377 return ndups; | |
378 } | |
379 | |
226 /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each, | 380 /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each, |
227 but without changing the underlying vector. */ | 381 but without changing the underlying vector. */ |
228 | 382 |
229 template<typename T, typename Derived> | 383 template<typename T, typename Shape, typename Derived> |
230 void | 384 void |
231 vector_builder<T, Derived>::reshape (unsigned int npatterns, | 385 vector_builder<T, Shape, Derived>::reshape (unsigned int npatterns, |
232 unsigned int nelts_per_pattern) | 386 unsigned int nelts_per_pattern) |
233 { | 387 { |
234 unsigned int old_encoded_nelts = encoded_nelts (); | 388 unsigned int old_encoded_nelts = encoded_nelts (); |
235 unsigned int new_encoded_nelts = npatterns * nelts_per_pattern; | 389 unsigned int new_encoded_nelts = npatterns * nelts_per_pattern; |
236 gcc_checking_assert (new_encoded_nelts <= old_encoded_nelts); | 390 gcc_checking_assert (new_encoded_nelts <= old_encoded_nelts); |
237 unsigned int next = new_encoded_nelts - npatterns; | 391 unsigned int next = new_encoded_nelts - npatterns; |
247 } | 401 } |
248 | 402 |
249 /* Return true if elements [START, END) contain a repeating sequence of | 403 /* Return true if elements [START, END) contain a repeating sequence of |
250 STEP elements. */ | 404 STEP elements. */ |
251 | 405 |
252 template<typename T, typename Derived> | 406 template<typename T, typename Shape, typename Derived> |
253 bool | 407 bool |
254 vector_builder<T, Derived>::repeating_sequence_p (unsigned int start, | 408 vector_builder<T, Shape, Derived>::repeating_sequence_p (unsigned int start, |
255 unsigned int end, | 409 unsigned int end, |
256 unsigned int step) | 410 unsigned int step) |
257 { | 411 { |
258 for (unsigned int i = start; i < end - step; ++i) | 412 for (unsigned int i = start; i < end - step; ++i) |
259 if (!derived ()->equal_p ((*this)[i], (*this)[i + step])) | 413 if (!derived ()->equal_p ((*this)[i], (*this)[i + step])) |
260 return false; | 414 return false; |
261 return true; | 415 return true; |
262 } | 416 } |
263 | 417 |
264 /* Return true if elements [START, END) contain STEP interleaved linear | 418 /* Return true if elements [START, END) contain STEP interleaved linear |
265 series. */ | 419 series. */ |
266 | 420 |
267 template<typename T, typename Derived> | 421 template<typename T, typename Shape, typename Derived> |
268 bool | 422 bool |
269 vector_builder<T, Derived>::stepped_sequence_p (unsigned int start, | 423 vector_builder<T, Shape, Derived>::stepped_sequence_p (unsigned int start, |
270 unsigned int end, | 424 unsigned int end, |
271 unsigned int step) | 425 unsigned int step) |
272 { | 426 { |
273 if (!derived ()->allow_steps_p ()) | 427 if (!derived ()->allow_steps_p ()) |
274 return false; | 428 return false; |
275 | 429 |
276 for (unsigned int i = start + step * 2; i < end; ++i) | 430 for (unsigned int i = start + step * 2; i < end; ++i) |
295 } | 449 } |
296 | 450 |
297 /* Try to change the number of encoded patterns to NPATTERNS, returning | 451 /* Try to change the number of encoded patterns to NPATTERNS, returning |
298 true on success. */ | 452 true on success. */ |
299 | 453 |
300 template<typename T, typename Derived> | 454 template<typename T, typename Shape, typename Derived> |
301 bool | 455 bool |
302 vector_builder<T, Derived>::try_npatterns (unsigned int npatterns) | 456 vector_builder<T, Shape, Derived>::try_npatterns (unsigned int npatterns) |
303 { | 457 { |
304 if (m_nelts_per_pattern == 1) | 458 if (m_nelts_per_pattern == 1) |
305 { | 459 { |
306 /* See whether NPATTERNS is valid with the current 1-element-per-pattern | 460 /* See whether NPATTERNS is valid with the current 1-element-per-pattern |
307 encoding. */ | 461 encoding. */ |
348 gcc_unreachable (); | 502 gcc_unreachable (); |
349 } | 503 } |
350 | 504 |
351 /* Replace the current encoding with the canonical form. */ | 505 /* Replace the current encoding with the canonical form. */ |
352 | 506 |
353 template<typename T, typename Derived> | 507 template<typename T, typename Shape, typename Derived> |
354 void | 508 void |
355 vector_builder<T, Derived>::finalize () | 509 vector_builder<T, Shape, Derived>::finalize () |
356 { | 510 { |
357 /* The encoding requires the same number of elements to come from each | 511 /* The encoding requires the same number of elements to come from each |
358 pattern. */ | 512 pattern. */ |
359 gcc_assert (multiple_p (m_full_nelts, m_npatterns)); | 513 gcc_assert (multiple_p (m_full_nelts, m_npatterns)); |
360 | 514 |