1 /* A class for building vector constant patterns.
2 Copyright (C) 2017 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 #ifndef GCC_VECTOR_BUILDER_H
21 #define GCC_VECTOR_BUILDER_H
23 /* This class is a wrapper around auto_vec<T> for building vectors of T.
24 It aims to encode each vector as npatterns interleaved patterns,
25 where each pattern represents a sequence:
27 { BASE0, BASE1, BASE1 + STEP, BASE1 + STEP*2, BASE1 + STEP*3, ... }
29 The first three elements in each pattern provide enough information
30 to derive the other elements. If all patterns have a STEP of zero,
31 we only need to encode the first two elements in each pattern.
32 If BASE1 is also equal to BASE0 for all patterns, we only need to
33 encode the first element in each pattern. The number of encoded
34 elements per pattern is given by nelts_per_pattern.
36 The class can be used in two ways:
38 1. It can be used to build a full image of the vector, which is then
39 canonicalized by finalize (). In this case npatterns is initially
40 the number of elements in the vector and nelts_per_pattern is
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
45 variable-length vectors. finalize () then canonicalizes the encoding
46 to a simpler form if possible.
48 The derived class Derived provides this functionality for specific Ts.
49 Derived needs to provide the following interface:
51 bool equal_p (T elt1, T elt2) const;
53 Return true if elements ELT1 and ELT2 are equal.
55 bool allow_steps_p () const;
57 Return true if a stepped representation is OK. We don't allow
58 linear series for anything other than integers, to avoid problems
61 bool integral_p (T elt) const;
63 Return true if element ELT can be interpreted as an integer.
65 StepType step (T elt1, T elt2) const;
67 Return the value of element ELT2 minus the value of element ELT1,
68 given integral_p (ELT1) && integral_p (ELT2). There is no fixed
71 bool can_elide_p (T elt) const;
73 Return true if we can drop element ELT, even if the retained
74 elements are different. This is provided for TREE_OVERFLOW
77 void note_representative (T *elt1_ptr, T elt2);
79 Record that ELT2 is being elided, given that ELT1_PTR points to
80 the last encoded element for the containing pattern. This is
81 again provided for TREE_OVERFLOW handling. */
83 template<typename T
, typename Derived
>
84 class vector_builder
: public auto_vec
<T
, 32>
89 unsigned int full_nelts () const { return m_full_nelts
; }
90 unsigned int npatterns () const { return m_npatterns
; }
91 unsigned int nelts_per_pattern () const { return m_nelts_per_pattern
; }
92 unsigned int encoded_nelts () const;
93 bool encoded_full_vector_p () const;
98 void new_vector (unsigned int, unsigned int, unsigned int);
99 void reshape (unsigned int, unsigned int);
100 bool repeating_sequence_p (unsigned int, unsigned int, unsigned int);
101 bool stepped_sequence_p (unsigned int, unsigned int, unsigned int);
102 bool try_npatterns (unsigned int);
105 vector_builder (const vector_builder
&);
106 vector_builder
&operator= (const vector_builder
&);
107 Derived
*derived () { return static_cast<Derived
*> (this); }
108 const Derived
*derived () const;
110 unsigned int m_full_nelts
;
111 unsigned int m_npatterns
;
112 unsigned int m_nelts_per_pattern
;
115 template<typename T
, typename Derived
>
116 inline const Derived
*
117 vector_builder
<T
, Derived
>::derived () const
119 return static_cast<const Derived
*> (this);
122 template<typename T
, typename Derived
>
124 vector_builder
<T
, Derived
>::vector_builder ()
127 m_nelts_per_pattern (0)
130 /* Return the number of elements that are explicitly encoded. The vec
131 starts with these explicitly-encoded elements and may contain additional
134 template<typename T
, typename Derived
>
136 vector_builder
<T
, Derived
>::encoded_nelts () const
138 return m_npatterns
* m_nelts_per_pattern
;
141 /* Return true if every element of the vector is explicitly encoded. */
143 template<typename T
, typename Derived
>
145 vector_builder
<T
, Derived
>::encoded_full_vector_p () const
147 return m_npatterns
* m_nelts_per_pattern
== m_full_nelts
;
150 /* Start building a vector that has FULL_NELTS elements. Initially
151 encode it using NPATTERNS patterns with NELTS_PER_PATTERN each. */
153 template<typename T
, typename Derived
>
155 vector_builder
<T
, Derived
>::new_vector (unsigned int full_nelts
,
156 unsigned int npatterns
,
157 unsigned int nelts_per_pattern
)
159 m_full_nelts
= full_nelts
;
160 m_npatterns
= npatterns
;
161 m_nelts_per_pattern
= nelts_per_pattern
;
162 this->reserve (encoded_nelts ());
166 /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
167 but without changing the underlying vector. */
169 template<typename T
, typename Derived
>
171 vector_builder
<T
, Derived
>::reshape (unsigned int npatterns
,
172 unsigned int nelts_per_pattern
)
174 unsigned int old_encoded_nelts
= encoded_nelts ();
175 unsigned int new_encoded_nelts
= npatterns
* nelts_per_pattern
;
176 gcc_checking_assert (new_encoded_nelts
<= old_encoded_nelts
);
177 unsigned int next
= new_encoded_nelts
- npatterns
;
178 for (unsigned int i
= new_encoded_nelts
; i
< old_encoded_nelts
; ++i
)
180 derived ()->note_representative (&(*this)[next
], (*this)[i
]);
182 if (next
== new_encoded_nelts
)
185 m_npatterns
= npatterns
;
186 m_nelts_per_pattern
= nelts_per_pattern
;
189 /* Return true if elements [START, END) contain a repeating sequence of
192 template<typename T
, typename Derived
>
194 vector_builder
<T
, Derived
>::repeating_sequence_p (unsigned int start
,
198 for (unsigned int i
= start
; i
< end
- step
; ++i
)
199 if (!derived ()->equal_p ((*this)[i
], (*this)[i
+ step
]))
204 /* Return true if elements [START, END) contain STEP interleaved linear
207 template<typename T
, typename Derived
>
209 vector_builder
<T
, Derived
>::stepped_sequence_p (unsigned int start
,
213 if (!derived ()->allow_steps_p ())
216 for (unsigned int i
= start
+ step
* 2; i
< end
; ++i
)
218 T elt1
= (*this)[i
- step
* 2];
219 T elt2
= (*this)[i
- step
];
222 if (!derived ()->integral_p (elt1
)
223 || !derived ()->integral_p (elt2
)
224 || !derived ()->integral_p (elt3
))
227 if (derived ()->step (elt1
, elt2
) != derived ()->step (elt2
, elt3
))
230 if (!derived ()->can_elide_p (elt3
))
236 /* Try to change the number of encoded patterns to NPATTERNS, returning
239 template<typename T
, typename Derived
>
241 vector_builder
<T
, Derived
>::try_npatterns (unsigned int npatterns
)
243 if (m_nelts_per_pattern
== 1)
245 /* See whether NPATTERNS is valid with the current 1-element-per-pattern
247 if (repeating_sequence_p (0, encoded_nelts (), npatterns
))
249 reshape (npatterns
, 1);
253 /* We can only increase the number of elements per pattern if all
254 elements are still encoded explicitly. */
255 if (!encoded_full_vector_p ())
259 if (m_nelts_per_pattern
<= 2)
261 /* See whether NPATTERNS is valid with a 2-element-per-pattern
263 if (repeating_sequence_p (npatterns
, encoded_nelts (), npatterns
))
265 reshape (npatterns
, 2);
269 /* We can only increase the number of elements per pattern if all
270 elements are still encoded explicitly. */
271 if (!encoded_full_vector_p ())
275 if (m_nelts_per_pattern
<= 3)
277 /* See whether we have NPATTERNS interleaved linear series,
278 giving a 3-element-per-pattern encoding. */
279 if (stepped_sequence_p (npatterns
, encoded_nelts (), npatterns
))
281 reshape (npatterns
, 3);
290 /* Replace the current encoding with the canonical form. */
292 template<typename T
, typename Derived
>
294 vector_builder
<T
, Derived
>::finalize ()
296 /* The encoding requires the same number of elements to come from each
298 gcc_assert (m_full_nelts
% m_npatterns
== 0);
300 /* Allow the caller to build more elements than necessary. For example,
301 it's often convenient to build a stepped vector from the natural
302 encoding of three elements even if the vector itself only has two. */
303 if (m_full_nelts
<= encoded_nelts ())
305 m_npatterns
= m_full_nelts
;
306 m_nelts_per_pattern
= 1;
309 /* Try to whittle down the number of elements per pattern. That is:
311 1. If we have stepped patterns whose steps are all 0, reduce the
312 number of elements per pattern from 3 to 2.
314 2. If we have background fill values that are the same as the
315 foreground values, reduce the number of elements per pattern
317 while (m_nelts_per_pattern
> 1
318 && repeating_sequence_p (encoded_nelts () - m_npatterns
* 2,
319 encoded_nelts (), m_npatterns
))
320 /* The last two sequences of M_NPATTERNS elements are equal,
321 so remove the last one. */
322 reshape (m_npatterns
, m_nelts_per_pattern
- 1);
324 if (pow2p_hwi (m_npatterns
))
326 /* Try to halve the number of patterns while doing so gives a
327 valid pattern. This approach is linear in the number of
328 elements, whereas searcing from 1 up would be O(n*log(n)).
330 Each halving step tries to keep the number of elements per pattern
331 the same. If that isn't possible, and if all elements are still
332 explicitly encoded, the halving step can instead increase the number
333 of elements per pattern.
337 { 0, 2, 3, 4, 5, 6, 7, 8 } npatterns == 8 full_nelts == 8
339 we first realize that the second half of the sequence is not
340 equal to the first, so we cannot maintain 1 element per pattern
341 for npatterns == 4. Instead we halve the number of patterns
342 and double the number of elements per pattern, treating this
343 as a "foreground" { 0, 2, 3, 4 } against a "background" of
344 { 5, 6, 7, 8 | 5, 6, 7, 8 ... }:
346 { 0, 2, 3, 4 | 5, 6, 7, 8 } npatterns == 4
348 Next we realize that this is *not* a foreround of { 0, 2 }
349 against a background of { 3, 4 | 3, 4 ... }, so the only
350 remaining option for reducing the number of patterns is
351 to use a foreground of { 0, 2 } against a stepped background
352 of { 1, 2 | 3, 4 | 5, 6 ... }. This is valid because we still
353 haven't elided any elements:
355 { 0, 2 | 3, 4 | 5, 6 } npatterns == 2
357 This in turn can be reduced to a foreground of { 0 } against a
358 stepped background of { 1 | 2 | 3 ... }:
360 { 0 | 2 | 3 } npatterns == 1
362 This last step would not have been possible for:
364 { 0, 0 | 3, 4 | 5, 6 } npatterns == 2. */
365 while ((m_npatterns
& 1) == 0 && try_npatterns (m_npatterns
/ 2))
368 /* Builders of arbitrary fixed-length vectors can use:
372 so that every element is specified explicitly. Handle cases
373 that are actually wrapping series, like { 0, 1, 2, 3, 0, 1, 2, 3 }
374 would be for 2-bit elements. We'll have treated them as
375 duplicates in the loop above. */
376 if (m_nelts_per_pattern
== 1
377 && this->length () >= m_full_nelts
378 && (m_npatterns
& 3) == 0
379 && stepped_sequence_p (m_npatterns
/ 4, m_full_nelts
,
382 reshape (m_npatterns
/ 4, 3);
383 while ((m_npatterns
& 1) == 0 && try_npatterns (m_npatterns
/ 2))
388 /* For the non-power-of-2 case, do a simple search up from 1. */
389 for (unsigned int i
= 1; i
<= m_npatterns
/ 2; ++i
)
390 if (m_npatterns
% i
== 0 && try_npatterns (i
))