annotate gcc/vec-perm-indices.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* A representation of vector permutation indices.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "vec-perm-indices.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "fold-const.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "tree-vector-builder.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "memmodel.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "emit-rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "selftest.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "rtx-vector-builder.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 /* Switch to a new permutation vector that selects between NINPUTS vector
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 inputs that have NELTS_PER_INPUT elements each. Take the elements of the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 new permutation vector from ELEMENTS, clamping each one to be in range. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 vec_perm_indices::new_vector (const vec_perm_builder &elements,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 unsigned int ninputs,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 poly_uint64 nelts_per_input)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 m_ninputs = ninputs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 m_nelts_per_input = nelts_per_input;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 /* If the vector has a constant number of elements, expand the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46 encoding and clamp each element. E.g. { 0, 2, 4, ... } might
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 wrap halfway if there is only one vector input, and we want
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 the wrapped form to be the canonical one.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 If the vector has a variable number of elements, just copy
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 the encoding. In that case the unwrapped form is canonical
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 and there is no way of representing the wrapped form. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 poly_uint64 full_nelts = elements.full_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 unsigned HOST_WIDE_INT copy_nelts;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 if (full_nelts.is_constant (&copy_nelts))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 m_encoding.new_vector (full_nelts, copy_nelts, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 copy_nelts = elements.encoded_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60 m_encoding.new_vector (full_nelts, elements.npatterns (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 elements.nelts_per_pattern ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 unsigned int npatterns = m_encoding.npatterns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 for (unsigned int i = 0; i < npatterns; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 m_encoding.quick_push (clamp (elements.elt (i)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 /* Use the fact that:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 (a + b) % c == ((a % c) + (b % c)) % c
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 to simplify the clamping of variable-length vectors. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 for (unsigned int i = npatterns; i < copy_nelts; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 element_type step = clamp (elements.elt (i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 - elements.elt (i - npatterns));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 m_encoding.quick_push (clamp (m_encoding[i - npatterns] + step));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 m_encoding.finalize ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 /* Switch to a new permutation vector that selects the same input elements
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81 as ORIG, but with each element split into FACTOR pieces. For example,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 if ORIG is { 1, 2, 0, 3 } and FACTOR is 2, the new permutation is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 { 2, 3, 4, 5, 0, 1, 6, 7 }. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 vec_perm_indices::new_expanded_vector (const vec_perm_indices &orig,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 unsigned int factor)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 m_ninputs = orig.m_ninputs;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 m_nelts_per_input = orig.m_nelts_per_input * factor;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 m_encoding.new_vector (orig.m_encoding.full_nelts () * factor,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 orig.m_encoding.npatterns () * factor,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 orig.m_encoding.nelts_per_pattern ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 unsigned int encoded_nelts = orig.m_encoding.encoded_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 for (unsigned int i = 0; i < encoded_nelts; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 element_type base = orig.m_encoding[i] * factor;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 for (unsigned int j = 0; j < factor; ++j)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99 m_encoding.quick_push (base + j);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 m_encoding.finalize ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 /* Rotate the inputs of the permutation right by DELTA inputs. This changes
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 the values of the permutation vector but it doesn't change the way that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106 the elements are encoded. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109 vec_perm_indices::rotate_inputs (int delta)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111 element_type element_delta = delta * m_nelts_per_input;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 for (unsigned int i = 0; i < m_encoding.length (); ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113 m_encoding[i] = clamp (m_encoding[i] + element_delta);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 /* Return true if index OUT_BASE + I * OUT_STEP selects input
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 element IN_BASE + I * IN_STEP. For example, the call to test
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 whether a permute reverses a vector of N elements would be:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 series_p (0, 1, N - 1, -1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 which would return true for { N - 1, N - 2, N - 3, ... }.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 The calls to test for an interleaving of elements starting
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 at N1 and N2 would be:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 series_p (0, 2, N1, 1) && series_p (1, 2, N2, 1).
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 which would return true for { N1, N2, N1 + 1, N2 + 1, ... }. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 vec_perm_indices::series_p (unsigned int out_base, unsigned int out_step,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 element_type in_base, element_type in_step) const
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 /* Check the base value. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 if (maybe_ne (clamp (m_encoding.elt (out_base)), clamp (in_base)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 element_type full_nelts = m_encoding.full_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139 unsigned int npatterns = m_encoding.npatterns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141 /* Calculate which multiple of OUT_STEP elements we need to get
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 back to the same pattern. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 unsigned int cycle_length = least_common_multiple (out_step, npatterns);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 /* Check the steps. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 in_step = clamp (in_step);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 out_base += out_step;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 unsigned int limit = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 for (;;)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151 /* Succeed if we've checked all the elements in the vector. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 if (known_ge (out_base, full_nelts))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 if (out_base >= npatterns)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 /* We've got to the end of the "foreground" values. Check
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 2 elements from each pattern in the "background" values. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 if (limit == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 limit = out_base + cycle_length * 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 else if (out_base >= limit)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 element_type v0 = m_encoding.elt (out_base - out_step);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 element_type v1 = m_encoding.elt (out_base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 if (maybe_ne (clamp (v1 - v0), in_step))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 out_base += out_step;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 /* Return true if all elements of the permutation vector are in the range
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 [START, START + SIZE). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 vec_perm_indices::all_in_range_p (element_type start, element_type size) const
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 /* Check the first two elements of each pattern. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182 unsigned int npatterns = m_encoding.npatterns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 unsigned int nelts_per_pattern = m_encoding.nelts_per_pattern ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 unsigned int base_nelts = npatterns * MIN (nelts_per_pattern, 2);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 for (unsigned int i = 0; i < base_nelts; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186 if (!known_in_range_p (m_encoding[i], start, size))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189 /* For stepped encodings, check the full range of the series. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 if (nelts_per_pattern == 3)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 element_type limit = input_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 /* The number of elements in each pattern beyond the first two
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 that we checked above. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 poly_int64 step_nelts = exact_div (m_encoding.full_nelts (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 npatterns) - 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 for (unsigned int i = 0; i < npatterns; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 /* BASE1 has been checked but BASE2 hasn't. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201 element_type base1 = m_encoding[i + npatterns];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 element_type base2 = m_encoding[i + base_nelts];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 /* The step to add to get from BASE1 to each subsequent value. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205 element_type step = clamp (base2 - base1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 /* STEP has no inherent sign, so a value near LIMIT can
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208 act as a negative step. The series is in range if it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 is in range according to one of the two interpretations.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 Since we're dealing with clamped values, ELEMENT_TYPE is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 wide enough for overflow not to be a problem. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213 element_type headroom_down = base1 - start;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 element_type headroom_up = size - headroom_down - 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 HOST_WIDE_INT diff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 if ((!step.is_constant (&diff)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 || maybe_lt (headroom_up, diff * step_nelts))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 && (!(limit - step).is_constant (&diff)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219 || maybe_lt (headroom_down, diff * step_nelts)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 /* Try to read the contents of VECTOR_CST CST as a constant permutation
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 vector. Return true and add the elements to BUILDER on success,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 otherwise return false without modifying BUILDER. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 tree_to_vec_perm_builder (vec_perm_builder *builder, tree cst)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 unsigned int encoded_nelts = vector_cst_encoded_nelts (cst);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 for (unsigned int i = 0; i < encoded_nelts; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 if (!tree_fits_poly_int64_p (VECTOR_CST_ENCODED_ELT (cst, i)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 builder->new_vector (TYPE_VECTOR_SUBPARTS (TREE_TYPE (cst)),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 VECTOR_CST_NPATTERNS (cst),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 VECTOR_CST_NELTS_PER_PATTERN (cst));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 for (unsigned int i = 0; i < encoded_nelts; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 builder->quick_push (tree_to_poly_int64 (VECTOR_CST_ENCODED_ELT (cst, i)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 /* Return a VECTOR_CST of type TYPE for the permutation vector in INDICES. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248 tree
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 vec_perm_indices_to_tree (tree type, const vec_perm_indices &indices)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), indices.length ()));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 tree_vector_builder sel (type, indices.encoding ().npatterns (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 indices.encoding ().nelts_per_pattern ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 unsigned int encoded_nelts = sel.encoded_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 for (unsigned int i = 0; i < encoded_nelts; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256 sel.quick_push (build_int_cst (TREE_TYPE (type), indices[i]));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257 return sel.build ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 /* Return a CONST_VECTOR of mode MODE that contains the elements of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 INDICES. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 rtx
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 vec_perm_indices_to_rtx (machine_mode mode, const vec_perm_indices &indices)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 && known_eq (GET_MODE_NUNITS (mode), indices.length ()));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268 rtx_vector_builder sel (mode, indices.encoding ().npatterns (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 indices.encoding ().nelts_per_pattern ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 unsigned int encoded_nelts = sel.encoded_nelts ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 for (unsigned int i = 0; i < encoded_nelts; i++)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 sel.quick_push (gen_int_mode (indices[i], GET_MODE_INNER (mode)));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 return sel.build ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 #if CHECKING_P
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 namespace selftest {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 /* Test a 12-element vector. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 test_vec_perm_12 (void)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 vec_perm_builder builder (12, 12, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 for (unsigned int i = 0; i < 4; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 builder.quick_push (i * 5);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 builder.quick_push (3 + i);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 builder.quick_push (2 + 3 * i);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292 vec_perm_indices indices (builder, 1, 12);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 ASSERT_TRUE (indices.series_p (0, 3, 0, 5));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294 ASSERT_FALSE (indices.series_p (0, 3, 3, 5));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295 ASSERT_FALSE (indices.series_p (0, 3, 0, 8));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 ASSERT_TRUE (indices.series_p (1, 3, 3, 1));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 ASSERT_TRUE (indices.series_p (2, 3, 2, 3));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 ASSERT_TRUE (indices.series_p (0, 4, 0, 4));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 ASSERT_FALSE (indices.series_p (1, 4, 3, 4));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 ASSERT_TRUE (indices.series_p (0, 6, 0, 10));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 ASSERT_FALSE (indices.series_p (0, 6, 0, 100));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 ASSERT_FALSE (indices.series_p (1, 10, 3, 7));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306 ASSERT_TRUE (indices.series_p (1, 10, 3, 8));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 ASSERT_TRUE (indices.series_p (0, 12, 0, 10));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 ASSERT_TRUE (indices.series_p (0, 12, 0, 11));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310 ASSERT_TRUE (indices.series_p (0, 12, 0, 100));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313 /* Run selftests for this file. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316 vec_perm_indices_c_tests ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 test_vec_perm_12 ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321 } // namespace selftest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323 #endif