1*38fd1498Szrj /* A class for building vector constant patterns.
2*38fd1498Szrj Copyright (C) 2017-2018 Free Software Foundation, Inc.
3*38fd1498Szrj
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3. If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>. */
19*38fd1498Szrj
20*38fd1498Szrj #ifndef GCC_VECTOR_BUILDER_H
21*38fd1498Szrj #define GCC_VECTOR_BUILDER_H
22*38fd1498Szrj
23*38fd1498Szrj /* This class is a wrapper around auto_vec<T> for building vectors of T.
24*38fd1498Szrj It aims to encode each vector as npatterns interleaved patterns,
25*38fd1498Szrj where each pattern represents a sequence:
26*38fd1498Szrj
27*38fd1498Szrj { BASE0, BASE1, BASE1 + STEP, BASE1 + STEP*2, BASE1 + STEP*3, ... }
28*38fd1498Szrj
29*38fd1498Szrj The first three elements in each pattern provide enough information
30*38fd1498Szrj to derive the other elements. If all patterns have a STEP of zero,
31*38fd1498Szrj we only need to encode the first two elements in each pattern.
32*38fd1498Szrj If BASE1 is also equal to BASE0 for all patterns, we only need to
33*38fd1498Szrj encode the first element in each pattern. The number of encoded
34*38fd1498Szrj elements per pattern is given by nelts_per_pattern.
35*38fd1498Szrj
36*38fd1498Szrj The class can be used in two ways:
37*38fd1498Szrj
38*38fd1498Szrj 1. It can be used to build a full image of the vector, which is then
39*38fd1498Szrj canonicalized by finalize (). In this case npatterns is initially
40*38fd1498Szrj the number of elements in the vector and nelts_per_pattern is
41*38fd1498Szrj initially 1.
42*38fd1498Szrj
43*38fd1498Szrj 2. It can be used to build a vector that already has a known encoding.
44*38fd1498Szrj This is preferred since it is more efficient and copes with
45*38fd1498Szrj variable-length vectors. finalize () then canonicalizes the encoding
46*38fd1498Szrj to a simpler form if possible.
47*38fd1498Szrj
48*38fd1498Szrj The derived class Derived provides this functionality for specific Ts.
49*38fd1498Szrj Derived needs to provide the following interface:
50*38fd1498Szrj
51*38fd1498Szrj bool equal_p (T elt1, T elt2) const;
52*38fd1498Szrj
53*38fd1498Szrj Return true if elements ELT1 and ELT2 are equal.
54*38fd1498Szrj
55*38fd1498Szrj bool allow_steps_p () const;
56*38fd1498Szrj
57*38fd1498Szrj Return true if a stepped representation is OK. We don't allow
58*38fd1498Szrj linear series for anything other than integers, to avoid problems
59*38fd1498Szrj with rounding.
60*38fd1498Szrj
61*38fd1498Szrj bool integral_p (T elt) const;
62*38fd1498Szrj
63*38fd1498Szrj Return true if element ELT can be interpreted as an integer.
64*38fd1498Szrj
65*38fd1498Szrj StepType step (T elt1, T elt2) const;
66*38fd1498Szrj
67*38fd1498Szrj Return the value of element ELT2 minus the value of element ELT1,
68*38fd1498Szrj given integral_p (ELT1) && integral_p (ELT2). There is no fixed
69*38fd1498Szrj choice of StepType.
70*38fd1498Szrj
71*38fd1498Szrj T apply_step (T base, unsigned int factor, StepType step) const;
72*38fd1498Szrj
73*38fd1498Szrj Return a vector element with the value BASE + FACTOR * STEP.
74*38fd1498Szrj
75*38fd1498Szrj bool can_elide_p (T elt) const;
76*38fd1498Szrj
77*38fd1498Szrj Return true if we can drop element ELT, even if the retained
78*38fd1498Szrj elements are different. This is provided for TREE_OVERFLOW
79*38fd1498Szrj handling.
80*38fd1498Szrj
81*38fd1498Szrj void note_representative (T *elt1_ptr, T elt2);
82*38fd1498Szrj
83*38fd1498Szrj Record that ELT2 is being elided, given that ELT1_PTR points to
84*38fd1498Szrj the last encoded element for the containing pattern. This is
85*38fd1498Szrj again provided for TREE_OVERFLOW handling. */
86*38fd1498Szrj
87*38fd1498Szrj template<typename T, typename Derived>
88*38fd1498Szrj class vector_builder : public auto_vec<T, 32>
89*38fd1498Szrj {
90*38fd1498Szrj public:
91*38fd1498Szrj vector_builder ();
92*38fd1498Szrj
full_nelts()93*38fd1498Szrj poly_uint64 full_nelts () const { return m_full_nelts; }
npatterns()94*38fd1498Szrj unsigned int npatterns () const { return m_npatterns; }
nelts_per_pattern()95*38fd1498Szrj unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; }
96*38fd1498Szrj unsigned int encoded_nelts () const;
97*38fd1498Szrj bool encoded_full_vector_p () const;
98*38fd1498Szrj T elt (unsigned int) const;
99*38fd1498Szrj
100*38fd1498Szrj bool operator == (const Derived &) const;
101*38fd1498Szrj bool operator != (const Derived &x) const { return !operator == (x); }
102*38fd1498Szrj
103*38fd1498Szrj void finalize ();
104*38fd1498Szrj
105*38fd1498Szrj protected:
106*38fd1498Szrj void new_vector (poly_uint64, unsigned int, unsigned int);
107*38fd1498Szrj void reshape (unsigned int, unsigned int);
108*38fd1498Szrj bool repeating_sequence_p (unsigned int, unsigned int, unsigned int);
109*38fd1498Szrj bool stepped_sequence_p (unsigned int, unsigned int, unsigned int);
110*38fd1498Szrj bool try_npatterns (unsigned int);
111*38fd1498Szrj
112*38fd1498Szrj private:
113*38fd1498Szrj vector_builder (const vector_builder &);
114*38fd1498Szrj vector_builder &operator= (const vector_builder &);
derived()115*38fd1498Szrj Derived *derived () { return static_cast<Derived *> (this); }
116*38fd1498Szrj const Derived *derived () const;
117*38fd1498Szrj
118*38fd1498Szrj poly_uint64 m_full_nelts;
119*38fd1498Szrj unsigned int m_npatterns;
120*38fd1498Szrj unsigned int m_nelts_per_pattern;
121*38fd1498Szrj };
122*38fd1498Szrj
123*38fd1498Szrj template<typename T, typename Derived>
124*38fd1498Szrj inline const Derived *
derived()125*38fd1498Szrj vector_builder<T, Derived>::derived () const
126*38fd1498Szrj {
127*38fd1498Szrj return static_cast<const Derived *> (this);
128*38fd1498Szrj }
129*38fd1498Szrj
130*38fd1498Szrj template<typename T, typename Derived>
131*38fd1498Szrj inline
vector_builder()132*38fd1498Szrj vector_builder<T, Derived>::vector_builder ()
133*38fd1498Szrj : m_full_nelts (0),
134*38fd1498Szrj m_npatterns (0),
135*38fd1498Szrj m_nelts_per_pattern (0)
136*38fd1498Szrj {}
137*38fd1498Szrj
138*38fd1498Szrj /* Return the number of elements that are explicitly encoded. The vec
139*38fd1498Szrj starts with these explicitly-encoded elements and may contain additional
140*38fd1498Szrj elided elements. */
141*38fd1498Szrj
142*38fd1498Szrj template<typename T, typename Derived>
143*38fd1498Szrj inline unsigned int
encoded_nelts()144*38fd1498Szrj vector_builder<T, Derived>::encoded_nelts () const
145*38fd1498Szrj {
146*38fd1498Szrj return m_npatterns * m_nelts_per_pattern;
147*38fd1498Szrj }
148*38fd1498Szrj
149*38fd1498Szrj /* Return true if every element of the vector is explicitly encoded. */
150*38fd1498Szrj
151*38fd1498Szrj template<typename T, typename Derived>
152*38fd1498Szrj inline bool
encoded_full_vector_p()153*38fd1498Szrj vector_builder<T, Derived>::encoded_full_vector_p () const
154*38fd1498Szrj {
155*38fd1498Szrj return known_eq (m_npatterns * m_nelts_per_pattern, m_full_nelts);
156*38fd1498Szrj }
157*38fd1498Szrj
158*38fd1498Szrj /* Start building a vector that has FULL_NELTS elements. Initially
159*38fd1498Szrj encode it using NPATTERNS patterns with NELTS_PER_PATTERN each. */
160*38fd1498Szrj
161*38fd1498Szrj template<typename T, typename Derived>
162*38fd1498Szrj void
new_vector(poly_uint64 full_nelts,unsigned int npatterns,unsigned int nelts_per_pattern)163*38fd1498Szrj vector_builder<T, Derived>::new_vector (poly_uint64 full_nelts,
164*38fd1498Szrj unsigned int npatterns,
165*38fd1498Szrj unsigned int nelts_per_pattern)
166*38fd1498Szrj {
167*38fd1498Szrj m_full_nelts = full_nelts;
168*38fd1498Szrj m_npatterns = npatterns;
169*38fd1498Szrj m_nelts_per_pattern = nelts_per_pattern;
170*38fd1498Szrj this->reserve (encoded_nelts ());
171*38fd1498Szrj this->truncate (0);
172*38fd1498Szrj }
173*38fd1498Szrj
174*38fd1498Szrj /* Return true if this vector and OTHER have the same elements and
175*38fd1498Szrj are encoded in the same way. */
176*38fd1498Szrj
177*38fd1498Szrj template<typename T, typename Derived>
178*38fd1498Szrj bool
179*38fd1498Szrj vector_builder<T, Derived>::operator == (const Derived &other) const
180*38fd1498Szrj {
181*38fd1498Szrj if (maybe_ne (m_full_nelts, other.m_full_nelts)
182*38fd1498Szrj || m_npatterns != other.m_npatterns
183*38fd1498Szrj || m_nelts_per_pattern != other.m_nelts_per_pattern)
184*38fd1498Szrj return false;
185*38fd1498Szrj
186*38fd1498Szrj unsigned int nelts = encoded_nelts ();
187*38fd1498Szrj for (unsigned int i = 0; i < nelts; ++i)
188*38fd1498Szrj if (!derived ()->equal_p ((*this)[i], other[i]))
189*38fd1498Szrj return false;
190*38fd1498Szrj
191*38fd1498Szrj return true;
192*38fd1498Szrj }
193*38fd1498Szrj
194*38fd1498Szrj /* Return the value of vector element I, which might or might not be
195*38fd1498Szrj encoded explicitly. */
196*38fd1498Szrj
197*38fd1498Szrj template<typename T, typename Derived>
198*38fd1498Szrj T
elt(unsigned int i)199*38fd1498Szrj vector_builder<T, Derived>::elt (unsigned int i) const
200*38fd1498Szrj {
201*38fd1498Szrj /* This only makes sense if the encoding has been fully populated. */
202*38fd1498Szrj gcc_checking_assert (encoded_nelts () <= this->length ());
203*38fd1498Szrj
204*38fd1498Szrj /* First handle elements that are already present in the underlying
205*38fd1498Szrj vector, regardless of whether they're part of the encoding or not. */
206*38fd1498Szrj if (i < this->length ())
207*38fd1498Szrj return (*this)[i];
208*38fd1498Szrj
209*38fd1498Szrj /* Identify the pattern that contains element I and work out the index of
210*38fd1498Szrj the last encoded element for that pattern. */
211*38fd1498Szrj unsigned int pattern = i % m_npatterns;
212*38fd1498Szrj unsigned int count = i / m_npatterns;
213*38fd1498Szrj unsigned int final_i = encoded_nelts () - m_npatterns + pattern;
214*38fd1498Szrj T final = (*this)[final_i];
215*38fd1498Szrj
216*38fd1498Szrj /* If there are no steps, the final encoded value is the right one. */
217*38fd1498Szrj if (m_nelts_per_pattern <= 2)
218*38fd1498Szrj return final;
219*38fd1498Szrj
220*38fd1498Szrj /* Otherwise work out the value from the last two encoded elements. */
221*38fd1498Szrj T prev = (*this)[final_i - m_npatterns];
222*38fd1498Szrj return derived ()->apply_step (final, count - 2,
223*38fd1498Szrj derived ()->step (prev, final));
224*38fd1498Szrj }
225*38fd1498Szrj
226*38fd1498Szrj /* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
227*38fd1498Szrj but without changing the underlying vector. */
228*38fd1498Szrj
229*38fd1498Szrj template<typename T, typename Derived>
230*38fd1498Szrj void
reshape(unsigned int npatterns,unsigned int nelts_per_pattern)231*38fd1498Szrj vector_builder<T, Derived>::reshape (unsigned int npatterns,
232*38fd1498Szrj unsigned int nelts_per_pattern)
233*38fd1498Szrj {
234*38fd1498Szrj unsigned int old_encoded_nelts = encoded_nelts ();
235*38fd1498Szrj unsigned int new_encoded_nelts = npatterns * nelts_per_pattern;
236*38fd1498Szrj gcc_checking_assert (new_encoded_nelts <= old_encoded_nelts);
237*38fd1498Szrj unsigned int next = new_encoded_nelts - npatterns;
238*38fd1498Szrj for (unsigned int i = new_encoded_nelts; i < old_encoded_nelts; ++i)
239*38fd1498Szrj {
240*38fd1498Szrj derived ()->note_representative (&(*this)[next], (*this)[i]);
241*38fd1498Szrj next += 1;
242*38fd1498Szrj if (next == new_encoded_nelts)
243*38fd1498Szrj next -= npatterns;
244*38fd1498Szrj }
245*38fd1498Szrj m_npatterns = npatterns;
246*38fd1498Szrj m_nelts_per_pattern = nelts_per_pattern;
247*38fd1498Szrj }
248*38fd1498Szrj
249*38fd1498Szrj /* Return true if elements [START, END) contain a repeating sequence of
250*38fd1498Szrj STEP elements. */
251*38fd1498Szrj
252*38fd1498Szrj template<typename T, typename Derived>
253*38fd1498Szrj bool
repeating_sequence_p(unsigned int start,unsigned int end,unsigned int step)254*38fd1498Szrj vector_builder<T, Derived>::repeating_sequence_p (unsigned int start,
255*38fd1498Szrj unsigned int end,
256*38fd1498Szrj unsigned int step)
257*38fd1498Szrj {
258*38fd1498Szrj for (unsigned int i = start; i < end - step; ++i)
259*38fd1498Szrj if (!derived ()->equal_p ((*this)[i], (*this)[i + step]))
260*38fd1498Szrj return false;
261*38fd1498Szrj return true;
262*38fd1498Szrj }
263*38fd1498Szrj
264*38fd1498Szrj /* Return true if elements [START, END) contain STEP interleaved linear
265*38fd1498Szrj series. */
266*38fd1498Szrj
267*38fd1498Szrj template<typename T, typename Derived>
268*38fd1498Szrj bool
stepped_sequence_p(unsigned int start,unsigned int end,unsigned int step)269*38fd1498Szrj vector_builder<T, Derived>::stepped_sequence_p (unsigned int start,
270*38fd1498Szrj unsigned int end,
271*38fd1498Szrj unsigned int step)
272*38fd1498Szrj {
273*38fd1498Szrj if (!derived ()->allow_steps_p ())
274*38fd1498Szrj return false;
275*38fd1498Szrj
276*38fd1498Szrj for (unsigned int i = start + step * 2; i < end; ++i)
277*38fd1498Szrj {
278*38fd1498Szrj T elt1 = (*this)[i - step * 2];
279*38fd1498Szrj T elt2 = (*this)[i - step];
280*38fd1498Szrj T elt3 = (*this)[i];
281*38fd1498Szrj
282*38fd1498Szrj if (!derived ()->integral_p (elt1)
283*38fd1498Szrj || !derived ()->integral_p (elt2)
284*38fd1498Szrj || !derived ()->integral_p (elt3))
285*38fd1498Szrj return false;
286*38fd1498Szrj
287*38fd1498Szrj if (maybe_ne (derived ()->step (elt1, elt2),
288*38fd1498Szrj derived ()->step (elt2, elt3)))
289*38fd1498Szrj return false;
290*38fd1498Szrj
291*38fd1498Szrj if (!derived ()->can_elide_p (elt3))
292*38fd1498Szrj return false;
293*38fd1498Szrj }
294*38fd1498Szrj return true;
295*38fd1498Szrj }
296*38fd1498Szrj
297*38fd1498Szrj /* Try to change the number of encoded patterns to NPATTERNS, returning
298*38fd1498Szrj true on success. */
299*38fd1498Szrj
300*38fd1498Szrj template<typename T, typename Derived>
301*38fd1498Szrj bool
try_npatterns(unsigned int npatterns)302*38fd1498Szrj vector_builder<T, Derived>::try_npatterns (unsigned int npatterns)
303*38fd1498Szrj {
304*38fd1498Szrj if (m_nelts_per_pattern == 1)
305*38fd1498Szrj {
306*38fd1498Szrj /* See whether NPATTERNS is valid with the current 1-element-per-pattern
307*38fd1498Szrj encoding. */
308*38fd1498Szrj if (repeating_sequence_p (0, encoded_nelts (), npatterns))
309*38fd1498Szrj {
310*38fd1498Szrj reshape (npatterns, 1);
311*38fd1498Szrj return true;
312*38fd1498Szrj }
313*38fd1498Szrj
314*38fd1498Szrj /* We can only increase the number of elements per pattern if all
315*38fd1498Szrj elements are still encoded explicitly. */
316*38fd1498Szrj if (!encoded_full_vector_p ())
317*38fd1498Szrj return false;
318*38fd1498Szrj }
319*38fd1498Szrj
320*38fd1498Szrj if (m_nelts_per_pattern <= 2)
321*38fd1498Szrj {
322*38fd1498Szrj /* See whether NPATTERNS is valid with a 2-element-per-pattern
323*38fd1498Szrj encoding. */
324*38fd1498Szrj if (repeating_sequence_p (npatterns, encoded_nelts (), npatterns))
325*38fd1498Szrj {
326*38fd1498Szrj reshape (npatterns, 2);
327*38fd1498Szrj return true;
328*38fd1498Szrj }
329*38fd1498Szrj
330*38fd1498Szrj /* We can only increase the number of elements per pattern if all
331*38fd1498Szrj elements are still encoded explicitly. */
332*38fd1498Szrj if (!encoded_full_vector_p ())
333*38fd1498Szrj return false;
334*38fd1498Szrj }
335*38fd1498Szrj
336*38fd1498Szrj if (m_nelts_per_pattern <= 3)
337*38fd1498Szrj {
338*38fd1498Szrj /* See whether we have NPATTERNS interleaved linear series,
339*38fd1498Szrj giving a 3-element-per-pattern encoding. */
340*38fd1498Szrj if (stepped_sequence_p (npatterns, encoded_nelts (), npatterns))
341*38fd1498Szrj {
342*38fd1498Szrj reshape (npatterns, 3);
343*38fd1498Szrj return true;
344*38fd1498Szrj }
345*38fd1498Szrj return false;
346*38fd1498Szrj }
347*38fd1498Szrj
348*38fd1498Szrj gcc_unreachable ();
349*38fd1498Szrj }
350*38fd1498Szrj
351*38fd1498Szrj /* Replace the current encoding with the canonical form. */
352*38fd1498Szrj
353*38fd1498Szrj template<typename T, typename Derived>
354*38fd1498Szrj void
finalize()355*38fd1498Szrj vector_builder<T, Derived>::finalize ()
356*38fd1498Szrj {
357*38fd1498Szrj /* The encoding requires the same number of elements to come from each
358*38fd1498Szrj pattern. */
359*38fd1498Szrj gcc_assert (multiple_p (m_full_nelts, m_npatterns));
360*38fd1498Szrj
361*38fd1498Szrj /* Allow the caller to build more elements than necessary. For example,
362*38fd1498Szrj it's often convenient to build a stepped vector from the natural
363*38fd1498Szrj encoding of three elements even if the vector itself only has two. */
364*38fd1498Szrj unsigned HOST_WIDE_INT const_full_nelts;
365*38fd1498Szrj if (m_full_nelts.is_constant (&const_full_nelts)
366*38fd1498Szrj && const_full_nelts <= encoded_nelts ())
367*38fd1498Szrj {
368*38fd1498Szrj m_npatterns = const_full_nelts;
369*38fd1498Szrj m_nelts_per_pattern = 1;
370*38fd1498Szrj }
371*38fd1498Szrj
372*38fd1498Szrj /* Try to whittle down the number of elements per pattern. That is:
373*38fd1498Szrj
374*38fd1498Szrj 1. If we have stepped patterns whose steps are all 0, reduce the
375*38fd1498Szrj number of elements per pattern from 3 to 2.
376*38fd1498Szrj
377*38fd1498Szrj 2. If we have background fill values that are the same as the
378*38fd1498Szrj foreground values, reduce the number of elements per pattern
379*38fd1498Szrj from 2 to 1. */
380*38fd1498Szrj while (m_nelts_per_pattern > 1
381*38fd1498Szrj && repeating_sequence_p (encoded_nelts () - m_npatterns * 2,
382*38fd1498Szrj encoded_nelts (), m_npatterns))
383*38fd1498Szrj /* The last two sequences of M_NPATTERNS elements are equal,
384*38fd1498Szrj so remove the last one. */
385*38fd1498Szrj reshape (m_npatterns, m_nelts_per_pattern - 1);
386*38fd1498Szrj
387*38fd1498Szrj if (pow2p_hwi (m_npatterns))
388*38fd1498Szrj {
389*38fd1498Szrj /* Try to halve the number of patterns while doing so gives a
390*38fd1498Szrj valid pattern. This approach is linear in the number of
391*38fd1498Szrj elements, whereas searcing from 1 up would be O(n*log(n)).
392*38fd1498Szrj
393*38fd1498Szrj Each halving step tries to keep the number of elements per pattern
394*38fd1498Szrj the same. If that isn't possible, and if all elements are still
395*38fd1498Szrj explicitly encoded, the halving step can instead increase the number
396*38fd1498Szrj of elements per pattern.
397*38fd1498Szrj
398*38fd1498Szrj E.g. for:
399*38fd1498Szrj
400*38fd1498Szrj { 0, 2, 3, 4, 5, 6, 7, 8 } npatterns == 8 full_nelts == 8
401*38fd1498Szrj
402*38fd1498Szrj we first realize that the second half of the sequence is not
403*38fd1498Szrj equal to the first, so we cannot maintain 1 element per pattern
404*38fd1498Szrj for npatterns == 4. Instead we halve the number of patterns
405*38fd1498Szrj and double the number of elements per pattern, treating this
406*38fd1498Szrj as a "foreground" { 0, 2, 3, 4 } against a "background" of
407*38fd1498Szrj { 5, 6, 7, 8 | 5, 6, 7, 8 ... }:
408*38fd1498Szrj
409*38fd1498Szrj { 0, 2, 3, 4 | 5, 6, 7, 8 } npatterns == 4
410*38fd1498Szrj
411*38fd1498Szrj Next we realize that this is *not* a foreround of { 0, 2 }
412*38fd1498Szrj against a background of { 3, 4 | 3, 4 ... }, so the only
413*38fd1498Szrj remaining option for reducing the number of patterns is
414*38fd1498Szrj to use a foreground of { 0, 2 } against a stepped background
415*38fd1498Szrj of { 1, 2 | 3, 4 | 5, 6 ... }. This is valid because we still
416*38fd1498Szrj haven't elided any elements:
417*38fd1498Szrj
418*38fd1498Szrj { 0, 2 | 3, 4 | 5, 6 } npatterns == 2
419*38fd1498Szrj
420*38fd1498Szrj This in turn can be reduced to a foreground of { 0 } against a
421*38fd1498Szrj stepped background of { 1 | 2 | 3 ... }:
422*38fd1498Szrj
423*38fd1498Szrj { 0 | 2 | 3 } npatterns == 1
424*38fd1498Szrj
425*38fd1498Szrj This last step would not have been possible for:
426*38fd1498Szrj
427*38fd1498Szrj { 0, 0 | 3, 4 | 5, 6 } npatterns == 2. */
428*38fd1498Szrj while ((m_npatterns & 1) == 0 && try_npatterns (m_npatterns / 2))
429*38fd1498Szrj continue;
430*38fd1498Szrj
431*38fd1498Szrj /* Builders of arbitrary fixed-length vectors can use:
432*38fd1498Szrj
433*38fd1498Szrj new_vector (x, x, 1)
434*38fd1498Szrj
435*38fd1498Szrj so that every element is specified explicitly. Handle cases
436*38fd1498Szrj that are actually wrapping series, like { 0, 1, 2, 3, 0, 1, 2, 3 }
437*38fd1498Szrj would be for 2-bit elements. We'll have treated them as
438*38fd1498Szrj duplicates in the loop above. */
439*38fd1498Szrj if (m_nelts_per_pattern == 1
440*38fd1498Szrj && m_full_nelts.is_constant (&const_full_nelts)
441*38fd1498Szrj && this->length () >= const_full_nelts
442*38fd1498Szrj && (m_npatterns & 3) == 0
443*38fd1498Szrj && stepped_sequence_p (m_npatterns / 4, const_full_nelts,
444*38fd1498Szrj m_npatterns / 4))
445*38fd1498Szrj {
446*38fd1498Szrj reshape (m_npatterns / 4, 3);
447*38fd1498Szrj while ((m_npatterns & 1) == 0 && try_npatterns (m_npatterns / 2))
448*38fd1498Szrj continue;
449*38fd1498Szrj }
450*38fd1498Szrj }
451*38fd1498Szrj else
452*38fd1498Szrj /* For the non-power-of-2 case, do a simple search up from 1. */
453*38fd1498Szrj for (unsigned int i = 1; i <= m_npatterns / 2; ++i)
454*38fd1498Szrj if (m_npatterns % i == 0 && try_npatterns (i))
455*38fd1498Szrj break;
456*38fd1498Szrj }
457*38fd1498Szrj
458*38fd1498Szrj #endif
459