tree-vect-generic.cc revision 1.1 1 1.1 mrg /* Lower vector operations to scalar operations.
2 1.1 mrg Copyright (C) 2004-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
7 1.1 mrg under the terms of the GNU General Public License as published by the
8 1.1 mrg Free Software Foundation; either version 3, or (at your option) any
9 1.1 mrg later version.
10 1.1 mrg
11 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT
12 1.1 mrg ANY 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 #include "config.h"
21 1.1 mrg #include "system.h"
22 1.1 mrg #include "coretypes.h"
23 1.1 mrg #include "backend.h"
24 1.1 mrg #include "rtl.h"
25 1.1 mrg #include "tree.h"
26 1.1 mrg #include "gimple.h"
27 1.1 mrg #include "tree-pass.h"
28 1.1 mrg #include "ssa.h"
29 1.1 mrg #include "expmed.h"
30 1.1 mrg #include "optabs-tree.h"
31 1.1 mrg #include "diagnostic.h"
32 1.1 mrg #include "fold-const.h"
33 1.1 mrg #include "stor-layout.h"
34 1.1 mrg #include "langhooks.h"
35 1.1 mrg #include "tree-eh.h"
36 1.1 mrg #include "gimple-iterator.h"
37 1.1 mrg #include "gimplify-me.h"
38 1.1 mrg #include "gimplify.h"
39 1.1 mrg #include "tree-cfg.h"
40 1.1 mrg #include "tree-vector-builder.h"
41 1.1 mrg #include "vec-perm-indices.h"
42 1.1 mrg #include "insn-config.h"
43 1.1 mrg #include "tree-ssa-dce.h"
44 1.1 mrg #include "gimple-fold.h"
45 1.1 mrg #include "gimple-match.h"
46 1.1 mrg #include "recog.h" /* FIXME: for insn_data */
47 1.1 mrg
48 1.1 mrg
49 1.1 mrg /* Build a ternary operation and gimplify it. Emit code before GSI.
50 1.1 mrg Return the gimple_val holding the result. */
51 1.1 mrg
52 1.1 mrg static tree
53 1.1 mrg gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
54 1.1 mrg tree type, tree a, tree b, tree c)
55 1.1 mrg {
56 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
57 1.1 mrg gimple_seq stmts = NULL;
58 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a, b, c);
59 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
60 1.1 mrg return ret;
61 1.1 mrg }
62 1.1 mrg
63 1.1 mrg /* Build a binary operation and gimplify it. Emit code before GSI.
64 1.1 mrg Return the gimple_val holding the result. */
65 1.1 mrg
66 1.1 mrg static tree
67 1.1 mrg gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
68 1.1 mrg tree type, tree a, tree b)
69 1.1 mrg {
70 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
71 1.1 mrg gimple_seq stmts = NULL;
72 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a, b);
73 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
74 1.1 mrg return ret;
75 1.1 mrg }
76 1.1 mrg
77 1.1 mrg /* Build a unary operation and gimplify it. Emit code before GSI.
78 1.1 mrg Return the gimple_val holding the result. */
79 1.1 mrg
80 1.1 mrg static tree
81 1.1 mrg gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
82 1.1 mrg tree a)
83 1.1 mrg {
84 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
85 1.1 mrg gimple_seq stmts = NULL;
86 1.1 mrg tree ret = gimple_build (&stmts, loc, code, type, a);
87 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
88 1.1 mrg return ret;
89 1.1 mrg }
90 1.1 mrg
91 1.1 mrg
92 1.1 mrg static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap);
93 1.1 mrg
94 1.1 mrg /* Return the number of elements in a vector type TYPE that we have
95 1.1 mrg already decided needs to be expanded piecewise. We don't support
96 1.1 mrg this kind of expansion for variable-length vectors, since we should
97 1.1 mrg always check for target support before introducing uses of those. */
98 1.1 mrg static unsigned int
99 1.1 mrg nunits_for_known_piecewise_op (const_tree type)
100 1.1 mrg {
101 1.1 mrg return TYPE_VECTOR_SUBPARTS (type).to_constant ();
102 1.1 mrg }
103 1.1 mrg
104 1.1 mrg /* Return true if TYPE1 has more elements than TYPE2, where either
105 1.1 mrg type may be a vector or a scalar. */
106 1.1 mrg
107 1.1 mrg static inline bool
108 1.1 mrg subparts_gt (tree type1, tree type2)
109 1.1 mrg {
110 1.1 mrg poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
111 1.1 mrg poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
112 1.1 mrg return known_gt (n1, n2);
113 1.1 mrg }
114 1.1 mrg
115 1.1 mrg /* Build a constant of type TYPE, made of VALUE's bits replicated
116 1.1 mrg every WIDTH bits to fit TYPE's precision. */
117 1.1 mrg static tree
118 1.1 mrg build_replicated_const (tree type, unsigned int width, HOST_WIDE_INT value)
119 1.1 mrg {
120 1.1 mrg int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
121 1.1 mrg / HOST_BITS_PER_WIDE_INT;
122 1.1 mrg unsigned HOST_WIDE_INT low, mask;
123 1.1 mrg HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
124 1.1 mrg int i;
125 1.1 mrg
126 1.1 mrg gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
127 1.1 mrg
128 1.1 mrg if (width == HOST_BITS_PER_WIDE_INT)
129 1.1 mrg low = value;
130 1.1 mrg else
131 1.1 mrg {
132 1.1 mrg mask = ((HOST_WIDE_INT)1 << width) - 1;
133 1.1 mrg low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
134 1.1 mrg }
135 1.1 mrg
136 1.1 mrg for (i = 0; i < n; i++)
137 1.1 mrg a[i] = low;
138 1.1 mrg
139 1.1 mrg gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
140 1.1 mrg return wide_int_to_tree
141 1.1 mrg (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
142 1.1 mrg }
143 1.1 mrg
144 1.1 mrg static GTY(()) tree vector_inner_type;
145 1.1 mrg static GTY(()) tree vector_last_type;
146 1.1 mrg static GTY(()) int vector_last_nunits;
147 1.1 mrg
148 1.1 mrg /* Return a suitable vector types made of SUBPARTS units each of mode
149 1.1 mrg "word_mode" (the global variable). */
150 1.1 mrg static tree
151 1.1 mrg build_word_mode_vector_type (int nunits)
152 1.1 mrg {
153 1.1 mrg if (!vector_inner_type)
154 1.1 mrg vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
155 1.1 mrg else if (vector_last_nunits == nunits)
156 1.1 mrg {
157 1.1 mrg gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
158 1.1 mrg return vector_last_type;
159 1.1 mrg }
160 1.1 mrg
161 1.1 mrg vector_last_nunits = nunits;
162 1.1 mrg vector_last_type = build_vector_type (vector_inner_type, nunits);
163 1.1 mrg return vector_last_type;
164 1.1 mrg }
165 1.1 mrg
166 1.1 mrg typedef tree (*elem_op_func) (gimple_stmt_iterator *,
167 1.1 mrg tree, tree, tree, tree, tree, enum tree_code,
168 1.1 mrg tree);
169 1.1 mrg
170 1.1 mrg /* Extract the vector element of type TYPE at BITPOS with BITSIZE from T
171 1.1 mrg and return it. */
172 1.1 mrg
173 1.1 mrg tree
174 1.1 mrg tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
175 1.1 mrg tree t, tree bitsize, tree bitpos)
176 1.1 mrg {
177 1.1 mrg /* We're using the resimplify API and maybe_push_res_to_seq to
178 1.1 mrg simplify the BIT_FIELD_REF but restrict the simplification to
179 1.1 mrg a single stmt while at the same time following SSA edges for
180 1.1 mrg simplification with already emitted CTORs. */
181 1.1 mrg gimple_match_op opr;
182 1.1 mrg opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
183 1.1 mrg opr.resimplify (NULL, follow_all_ssa_edges);
184 1.1 mrg gimple_seq stmts = NULL;
185 1.1 mrg tree res = maybe_push_res_to_seq (&opr, &stmts);
186 1.1 mrg if (!res)
187 1.1 mrg {
188 1.1 mrg /* This can happen if SSA_NAME_OCCURS_IN_ABNORMAL_PHI are
189 1.1 mrg used. Build BIT_FIELD_REF manually otherwise. */
190 1.1 mrg t = build3 (BIT_FIELD_REF, type, t, bitsize, bitpos);
191 1.1 mrg res = make_ssa_name (type);
192 1.1 mrg gimple *g = gimple_build_assign (res, t);
193 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT);
194 1.1 mrg return res;
195 1.1 mrg }
196 1.1 mrg gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
197 1.1 mrg return res;
198 1.1 mrg }
199 1.1 mrg
200 1.1 mrg static tree
201 1.1 mrg do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
202 1.1 mrg tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
203 1.1 mrg enum tree_code code, tree type ATTRIBUTE_UNUSED)
204 1.1 mrg {
205 1.1 mrg tree rhs_type = inner_type;
206 1.1 mrg
207 1.1 mrg /* For ABSU_EXPR, use the signed type for the rhs if the rhs was signed. */
208 1.1 mrg if (code == ABSU_EXPR
209 1.1 mrg && ANY_INTEGRAL_TYPE_P (TREE_TYPE (a))
210 1.1 mrg && !TYPE_UNSIGNED (TREE_TYPE (a)))
211 1.1 mrg rhs_type = signed_type_for (rhs_type);
212 1.1 mrg
213 1.1 mrg a = tree_vec_extract (gsi, rhs_type, a, bitsize, bitpos);
214 1.1 mrg return gimplify_build1 (gsi, code, inner_type, a);
215 1.1 mrg }
216 1.1 mrg
217 1.1 mrg static tree
218 1.1 mrg do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
219 1.1 mrg tree bitpos, tree bitsize, enum tree_code code,
220 1.1 mrg tree type ATTRIBUTE_UNUSED)
221 1.1 mrg {
222 1.1 mrg if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
223 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
224 1.1 mrg if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
225 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
226 1.1 mrg return gimplify_build2 (gsi, code, inner_type, a, b);
227 1.1 mrg }
228 1.1 mrg
229 1.1 mrg /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
230 1.1 mrg
231 1.1 mrg INNER_TYPE is the type of A and B elements
232 1.1 mrg
233 1.1 mrg returned expression is of signed integer type with the
234 1.1 mrg size equal to the size of INNER_TYPE. */
235 1.1 mrg static tree
236 1.1 mrg do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
237 1.1 mrg tree bitpos, tree bitsize, enum tree_code code, tree type)
238 1.1 mrg {
239 1.1 mrg tree stype = TREE_TYPE (type);
240 1.1 mrg tree cst_false = build_zero_cst (stype);
241 1.1 mrg tree cst_true = build_all_ones_cst (stype);
242 1.1 mrg tree cmp;
243 1.1 mrg
244 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
245 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
246 1.1 mrg
247 1.1 mrg cmp = build2 (code, boolean_type_node, a, b);
248 1.1 mrg return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
249 1.1 mrg }
250 1.1 mrg
251 1.1 mrg /* Expand vector addition to scalars. This does bit twiddling
252 1.1 mrg in order to increase parallelism:
253 1.1 mrg
254 1.1 mrg a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
255 1.1 mrg (a ^ b) & 0x80808080
256 1.1 mrg
257 1.1 mrg a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
258 1.1 mrg (a ^ ~b) & 0x80808080
259 1.1 mrg
260 1.1 mrg -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
261 1.1 mrg
262 1.1 mrg This optimization should be done only if 4 vector items or more
263 1.1 mrg fit into a word. */
264 1.1 mrg static tree
265 1.1 mrg do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
266 1.1 mrg tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
267 1.1 mrg enum tree_code code, tree type ATTRIBUTE_UNUSED)
268 1.1 mrg {
269 1.1 mrg unsigned int width = vector_element_bits (TREE_TYPE (a));
270 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (a));
271 1.1 mrg unsigned HOST_WIDE_INT max;
272 1.1 mrg tree low_bits, high_bits, a_low, b_low, result_low, signs;
273 1.1 mrg
274 1.1 mrg max = GET_MODE_MASK (TYPE_MODE (inner_type));
275 1.1 mrg low_bits = build_replicated_const (word_type, width, max >> 1);
276 1.1 mrg high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
277 1.1 mrg
278 1.1 mrg a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
279 1.1 mrg b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
280 1.1 mrg
281 1.1 mrg signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
282 1.1 mrg b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
283 1.1 mrg if (code == PLUS_EXPR)
284 1.1 mrg a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
285 1.1 mrg else
286 1.1 mrg {
287 1.1 mrg a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
288 1.1 mrg signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
289 1.1 mrg }
290 1.1 mrg
291 1.1 mrg signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
292 1.1 mrg result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
293 1.1 mrg return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
294 1.1 mrg }
295 1.1 mrg
296 1.1 mrg static tree
297 1.1 mrg do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
298 1.1 mrg tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
299 1.1 mrg tree bitsize ATTRIBUTE_UNUSED,
300 1.1 mrg enum tree_code code ATTRIBUTE_UNUSED,
301 1.1 mrg tree type ATTRIBUTE_UNUSED)
302 1.1 mrg {
303 1.1 mrg unsigned int width = vector_element_bits (TREE_TYPE (b));
304 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (b));
305 1.1 mrg HOST_WIDE_INT max;
306 1.1 mrg tree low_bits, high_bits, b_low, result_low, signs;
307 1.1 mrg
308 1.1 mrg max = GET_MODE_MASK (TYPE_MODE (inner_type));
309 1.1 mrg low_bits = build_replicated_const (word_type, width, max >> 1);
310 1.1 mrg high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
311 1.1 mrg
312 1.1 mrg b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
313 1.1 mrg
314 1.1 mrg b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
315 1.1 mrg signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
316 1.1 mrg signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
317 1.1 mrg result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
318 1.1 mrg return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
319 1.1 mrg }
320 1.1 mrg
321 1.1 mrg /* Expand a vector operation to scalars, by using many operations
322 1.1 mrg whose type is the vector type's inner type. */
323 1.1 mrg static tree
324 1.1 mrg expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
325 1.1 mrg tree type, tree inner_type,
326 1.1 mrg tree a, tree b, enum tree_code code,
327 1.1 mrg bool parallel_p, tree ret_type = NULL_TREE)
328 1.1 mrg {
329 1.1 mrg vec<constructor_elt, va_gc> *v;
330 1.1 mrg tree part_width = TYPE_SIZE (inner_type);
331 1.1 mrg tree index = bitsize_int (0);
332 1.1 mrg int nunits = nunits_for_known_piecewise_op (type);
333 1.1 mrg int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
334 1.1 mrg int i;
335 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
336 1.1 mrg
337 1.1 mrg if (nunits == 1
338 1.1 mrg || warning_suppressed_p (gsi_stmt (*gsi),
339 1.1 mrg OPT_Wvector_operation_performance))
340 1.1 mrg /* Do not diagnose decomposing single element vectors or when
341 1.1 mrg decomposing vectorizer produced operations. */
342 1.1 mrg ;
343 1.1 mrg else if (ret_type || !parallel_p)
344 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
345 1.1 mrg "vector operation will be expanded piecewise");
346 1.1 mrg else
347 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
348 1.1 mrg "vector operation will be expanded in parallel");
349 1.1 mrg
350 1.1 mrg if (!ret_type)
351 1.1 mrg ret_type = type;
352 1.1 mrg vec_alloc (v, (nunits + delta - 1) / delta);
353 1.1 mrg bool constant_p = true;
354 1.1 mrg for (i = 0; i < nunits;
355 1.1 mrg i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
356 1.1 mrg {
357 1.1 mrg tree result = f (gsi, inner_type, a, b, index, part_width, code,
358 1.1 mrg ret_type);
359 1.1 mrg if (!CONSTANT_CLASS_P (result))
360 1.1 mrg constant_p = false;
361 1.1 mrg constructor_elt ce = {NULL_TREE, result};
362 1.1 mrg v->quick_push (ce);
363 1.1 mrg }
364 1.1 mrg
365 1.1 mrg if (constant_p)
366 1.1 mrg return build_vector_from_ctor (ret_type, v);
367 1.1 mrg else
368 1.1 mrg return build_constructor (ret_type, v);
369 1.1 mrg }
370 1.1 mrg
371 1.1 mrg /* Expand a vector operation to scalars with the freedom to use
372 1.1 mrg a scalar integer type, or to use a different size for the items
373 1.1 mrg in the vector type. */
374 1.1 mrg static tree
375 1.1 mrg expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
376 1.1 mrg tree a, tree b, enum tree_code code)
377 1.1 mrg {
378 1.1 mrg tree result, compute_type;
379 1.1 mrg int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
380 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
381 1.1 mrg
382 1.1 mrg /* We have three strategies. If the type is already correct, just do
383 1.1 mrg the operation an element at a time. Else, if the vector is wider than
384 1.1 mrg one word, do it a word at a time; finally, if the vector is smaller
385 1.1 mrg than one word, do it as a scalar. */
386 1.1 mrg if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
387 1.1 mrg return expand_vector_piecewise (gsi, f,
388 1.1 mrg type, TREE_TYPE (type),
389 1.1 mrg a, b, code, true);
390 1.1 mrg else if (n_words > 1)
391 1.1 mrg {
392 1.1 mrg tree word_type = build_word_mode_vector_type (n_words);
393 1.1 mrg result = expand_vector_piecewise (gsi, f,
394 1.1 mrg word_type, TREE_TYPE (word_type),
395 1.1 mrg a, b, code, true);
396 1.1 mrg result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
397 1.1 mrg GSI_SAME_STMT);
398 1.1 mrg }
399 1.1 mrg else
400 1.1 mrg {
401 1.1 mrg /* Use a single scalar operation with a mode no wider than word_mode. */
402 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi),
403 1.1 mrg OPT_Wvector_operation_performance))
404 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
405 1.1 mrg "vector operation will be expanded with a "
406 1.1 mrg "single scalar operation");
407 1.1 mrg scalar_int_mode mode
408 1.1 mrg = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
409 1.1 mrg compute_type = lang_hooks.types.type_for_mode (mode, 1);
410 1.1 mrg result = f (gsi, compute_type, a, b, bitsize_zero_node,
411 1.1 mrg TYPE_SIZE (compute_type), code, type);
412 1.1 mrg }
413 1.1 mrg
414 1.1 mrg return result;
415 1.1 mrg }
416 1.1 mrg
417 1.1 mrg /* Expand a vector operation to scalars; for integer types we can use
418 1.1 mrg special bit twiddling tricks to do the sums a word at a time, using
419 1.1 mrg function F_PARALLEL instead of F. These tricks are done only if
420 1.1 mrg they can process at least four items, that is, only if the vector
421 1.1 mrg holds at least four items and if a word can hold four items. */
422 1.1 mrg static tree
423 1.1 mrg expand_vector_addition (gimple_stmt_iterator *gsi,
424 1.1 mrg elem_op_func f, elem_op_func f_parallel,
425 1.1 mrg tree type, tree a, tree b, enum tree_code code)
426 1.1 mrg {
427 1.1 mrg int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
428 1.1 mrg
429 1.1 mrg if (INTEGRAL_TYPE_P (TREE_TYPE (type))
430 1.1 mrg && parts_per_word >= 4
431 1.1 mrg && nunits_for_known_piecewise_op (type) >= 4)
432 1.1 mrg return expand_vector_parallel (gsi, f_parallel,
433 1.1 mrg type, a, b, code);
434 1.1 mrg else
435 1.1 mrg return expand_vector_piecewise (gsi, f,
436 1.1 mrg type, TREE_TYPE (type),
437 1.1 mrg a, b, code, false);
438 1.1 mrg }
439 1.1 mrg
440 1.1 mrg static bool
441 1.1 mrg expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names);
442 1.1 mrg
443 1.1 mrg /* Try to expand vector comparison expression OP0 CODE OP1 by
444 1.1 mrg querying optab if the following expression:
445 1.1 mrg VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
446 1.1 mrg can be expanded. */
447 1.1 mrg static tree
448 1.1 mrg expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
449 1.1 mrg tree op1, enum tree_code code,
450 1.1 mrg bitmap dce_ssa_names)
451 1.1 mrg {
452 1.1 mrg tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
453 1.1 mrg use_operand_p use_p;
454 1.1 mrg imm_use_iterator iterator;
455 1.1 mrg bool vec_cond_expr_only = true;
456 1.1 mrg
457 1.1 mrg /* As seen in PR95830, we should not expand comparisons that are only
458 1.1 mrg feeding a VEC_COND_EXPR statement. */
459 1.1 mrg auto_vec<gimple *> uses;
460 1.1 mrg FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs)
461 1.1 mrg {
462 1.1 mrg gimple *use = USE_STMT (use_p);
463 1.1 mrg if (is_gimple_debug (use))
464 1.1 mrg continue;
465 1.1 mrg if (is_gimple_assign (use)
466 1.1 mrg && gimple_assign_rhs_code (use) == VEC_COND_EXPR
467 1.1 mrg && gimple_assign_rhs1 (use) == lhs
468 1.1 mrg && gimple_assign_rhs2 (use) != lhs
469 1.1 mrg && gimple_assign_rhs3 (use) != lhs)
470 1.1 mrg uses.safe_push (use);
471 1.1 mrg else
472 1.1 mrg vec_cond_expr_only = false;
473 1.1 mrg }
474 1.1 mrg
475 1.1 mrg if (vec_cond_expr_only)
476 1.1 mrg for (gimple *use : uses)
477 1.1 mrg {
478 1.1 mrg gimple_stmt_iterator it = gsi_for_stmt (use);
479 1.1 mrg if (!expand_vector_condition (&it, dce_ssa_names))
480 1.1 mrg {
481 1.1 mrg vec_cond_expr_only = false;
482 1.1 mrg break;
483 1.1 mrg }
484 1.1 mrg }
485 1.1 mrg
486 1.1 mrg if (!uses.is_empty () && vec_cond_expr_only)
487 1.1 mrg return NULL_TREE;
488 1.1 mrg
489 1.1 mrg tree t;
490 1.1 mrg if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
491 1.1 mrg {
492 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type)
493 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (type))
494 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
495 1.1 mrg TYPE_VECTOR_SUBPARTS (type)
496 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
497 1.1 mrg (TREE_TYPE (type)))))
498 1.1 mrg {
499 1.1 mrg tree inner_type = TREE_TYPE (TREE_TYPE (op0));
500 1.1 mrg tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
501 1.1 mrg tree index = bitsize_int (0);
502 1.1 mrg int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
503 1.1 mrg int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
504 1.1 mrg tree ret_type = build_nonstandard_integer_type (prec, 1);
505 1.1 mrg tree ret_inner_type = boolean_type_node;
506 1.1 mrg int i;
507 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
508 1.1 mrg t = build_zero_cst (ret_type);
509 1.1 mrg
510 1.1 mrg if (TYPE_PRECISION (ret_inner_type) != 1)
511 1.1 mrg ret_inner_type = build_nonstandard_integer_type (1, 1);
512 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi),
513 1.1 mrg OPT_Wvector_operation_performance))
514 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
515 1.1 mrg "vector operation will be expanded piecewise");
516 1.1 mrg for (i = 0; i < nunits;
517 1.1 mrg i++, index = int_const_binop (PLUS_EXPR, index, part_width))
518 1.1 mrg {
519 1.1 mrg tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
520 1.1 mrg index);
521 1.1 mrg tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
522 1.1 mrg index);
523 1.1 mrg tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
524 1.1 mrg t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
525 1.1 mrg bitsize_int (i));
526 1.1 mrg }
527 1.1 mrg t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
528 1.1 mrg }
529 1.1 mrg else
530 1.1 mrg t = expand_vector_piecewise (gsi, do_compare, type,
531 1.1 mrg TREE_TYPE (TREE_TYPE (op0)), op0, op1,
532 1.1 mrg code, false);
533 1.1 mrg }
534 1.1 mrg else
535 1.1 mrg t = NULL_TREE;
536 1.1 mrg
537 1.1 mrg return t;
538 1.1 mrg }
539 1.1 mrg
540 1.1 mrg /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
541 1.1 mrg of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
542 1.1 mrg the result if successful, otherwise return NULL_TREE. */
543 1.1 mrg static tree
544 1.1 mrg add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
545 1.1 mrg {
546 1.1 mrg optab op;
547 1.1 mrg unsigned int i, nunits = nunits_for_known_piecewise_op (type);
548 1.1 mrg bool scalar_shift = true;
549 1.1 mrg
550 1.1 mrg for (i = 1; i < nunits; i++)
551 1.1 mrg {
552 1.1 mrg if (shiftcnts[i] != shiftcnts[0])
553 1.1 mrg scalar_shift = false;
554 1.1 mrg }
555 1.1 mrg
556 1.1 mrg if (scalar_shift && shiftcnts[0] == 0)
557 1.1 mrg return op0;
558 1.1 mrg
559 1.1 mrg if (scalar_shift)
560 1.1 mrg {
561 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
562 1.1 mrg if (op != unknown_optab
563 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
564 1.1 mrg return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
565 1.1 mrg build_int_cst (NULL_TREE, shiftcnts[0]));
566 1.1 mrg }
567 1.1 mrg
568 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
569 1.1 mrg if (op != unknown_optab
570 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
571 1.1 mrg {
572 1.1 mrg tree_vector_builder vec (type, nunits, 1);
573 1.1 mrg for (i = 0; i < nunits; i++)
574 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
575 1.1 mrg return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
576 1.1 mrg }
577 1.1 mrg
578 1.1 mrg return NULL_TREE;
579 1.1 mrg }
580 1.1 mrg
581 1.1 mrg /* Try to expand integer vector division by constant using
582 1.1 mrg widening multiply, shifts and additions. */
583 1.1 mrg static tree
584 1.1 mrg expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
585 1.1 mrg tree op1, enum tree_code code)
586 1.1 mrg {
587 1.1 mrg bool use_pow2 = true;
588 1.1 mrg bool has_vector_shift = true;
589 1.1 mrg bool use_abs_op1 = false;
590 1.1 mrg int mode = -1, this_mode;
591 1.1 mrg int pre_shift = -1, post_shift;
592 1.1 mrg unsigned int nunits = nunits_for_known_piecewise_op (type);
593 1.1 mrg int *shifts = XALLOCAVEC (int, nunits * 4);
594 1.1 mrg int *pre_shifts = shifts + nunits;
595 1.1 mrg int *post_shifts = pre_shifts + nunits;
596 1.1 mrg int *shift_temps = post_shifts + nunits;
597 1.1 mrg unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
598 1.1 mrg int prec = TYPE_PRECISION (TREE_TYPE (type));
599 1.1 mrg int dummy_int;
600 1.1 mrg unsigned int i;
601 1.1 mrg signop sign_p = TYPE_SIGN (TREE_TYPE (type));
602 1.1 mrg unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
603 1.1 mrg tree cur_op, mulcst, tem;
604 1.1 mrg optab op;
605 1.1 mrg
606 1.1 mrg if (prec > HOST_BITS_PER_WIDE_INT)
607 1.1 mrg return NULL_TREE;
608 1.1 mrg
609 1.1 mrg op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
610 1.1 mrg if (op == unknown_optab
611 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
612 1.1 mrg has_vector_shift = false;
613 1.1 mrg
614 1.1 mrg /* Analysis phase. Determine if all op1 elements are either power
615 1.1 mrg of two and it is possible to expand it using shifts (or for remainder
616 1.1 mrg using masking). Additionally compute the multiplicative constants
617 1.1 mrg and pre and post shifts if the division is to be expanded using
618 1.1 mrg widening or high part multiplication plus shifts. */
619 1.1 mrg for (i = 0; i < nunits; i++)
620 1.1 mrg {
621 1.1 mrg tree cst = VECTOR_CST_ELT (op1, i);
622 1.1 mrg unsigned HOST_WIDE_INT ml;
623 1.1 mrg
624 1.1 mrg if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
625 1.1 mrg return NULL_TREE;
626 1.1 mrg pre_shifts[i] = 0;
627 1.1 mrg post_shifts[i] = 0;
628 1.1 mrg mulc[i] = 0;
629 1.1 mrg if (use_pow2
630 1.1 mrg && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
631 1.1 mrg use_pow2 = false;
632 1.1 mrg if (use_pow2)
633 1.1 mrg {
634 1.1 mrg shifts[i] = tree_log2 (cst);
635 1.1 mrg if (shifts[i] != shifts[0]
636 1.1 mrg && code == TRUNC_DIV_EXPR
637 1.1 mrg && !has_vector_shift)
638 1.1 mrg use_pow2 = false;
639 1.1 mrg }
640 1.1 mrg if (mode == -2)
641 1.1 mrg continue;
642 1.1 mrg if (sign_p == UNSIGNED)
643 1.1 mrg {
644 1.1 mrg unsigned HOST_WIDE_INT mh;
645 1.1 mrg unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
646 1.1 mrg
647 1.1 mrg if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
648 1.1 mrg /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
649 1.1 mrg return NULL_TREE;
650 1.1 mrg
651 1.1 mrg if (d <= 1)
652 1.1 mrg {
653 1.1 mrg mode = -2;
654 1.1 mrg continue;
655 1.1 mrg }
656 1.1 mrg
657 1.1 mrg /* Find a suitable multiplier and right shift count
658 1.1 mrg instead of multiplying with D. */
659 1.1 mrg mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
660 1.1 mrg
661 1.1 mrg /* If the suggested multiplier is more than SIZE bits, we can
662 1.1 mrg do better for even divisors, using an initial right shift. */
663 1.1 mrg if ((mh != 0 && (d & 1) == 0)
664 1.1 mrg || (!has_vector_shift && pre_shift != -1))
665 1.1 mrg {
666 1.1 mrg if (has_vector_shift)
667 1.1 mrg pre_shift = ctz_or_zero (d);
668 1.1 mrg else if (pre_shift == -1)
669 1.1 mrg {
670 1.1 mrg unsigned int j;
671 1.1 mrg for (j = 0; j < nunits; j++)
672 1.1 mrg {
673 1.1 mrg tree cst2 = VECTOR_CST_ELT (op1, j);
674 1.1 mrg unsigned HOST_WIDE_INT d2;
675 1.1 mrg int this_pre_shift;
676 1.1 mrg
677 1.1 mrg if (!tree_fits_uhwi_p (cst2))
678 1.1 mrg return NULL_TREE;
679 1.1 mrg d2 = tree_to_uhwi (cst2) & mask;
680 1.1 mrg if (d2 == 0)
681 1.1 mrg return NULL_TREE;
682 1.1 mrg this_pre_shift = floor_log2 (d2 & -d2);
683 1.1 mrg if (pre_shift == -1 || this_pre_shift < pre_shift)
684 1.1 mrg pre_shift = this_pre_shift;
685 1.1 mrg }
686 1.1 mrg if (i != 0 && pre_shift != 0)
687 1.1 mrg {
688 1.1 mrg /* Restart. */
689 1.1 mrg i = -1U;
690 1.1 mrg mode = -1;
691 1.1 mrg continue;
692 1.1 mrg }
693 1.1 mrg }
694 1.1 mrg if (pre_shift != 0)
695 1.1 mrg {
696 1.1 mrg if ((d >> pre_shift) <= 1)
697 1.1 mrg {
698 1.1 mrg mode = -2;
699 1.1 mrg continue;
700 1.1 mrg }
701 1.1 mrg mh = choose_multiplier (d >> pre_shift, prec,
702 1.1 mrg prec - pre_shift,
703 1.1 mrg &ml, &post_shift, &dummy_int);
704 1.1 mrg gcc_assert (!mh);
705 1.1 mrg pre_shifts[i] = pre_shift;
706 1.1 mrg }
707 1.1 mrg }
708 1.1 mrg if (!mh)
709 1.1 mrg this_mode = 0;
710 1.1 mrg else
711 1.1 mrg this_mode = 1;
712 1.1 mrg }
713 1.1 mrg else
714 1.1 mrg {
715 1.1 mrg HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
716 1.1 mrg unsigned HOST_WIDE_INT abs_d;
717 1.1 mrg
718 1.1 mrg if (d == -1)
719 1.1 mrg return NULL_TREE;
720 1.1 mrg
721 1.1 mrg /* Since d might be INT_MIN, we have to cast to
722 1.1 mrg unsigned HOST_WIDE_INT before negating to avoid
723 1.1 mrg undefined signed overflow. */
724 1.1 mrg abs_d = (d >= 0
725 1.1 mrg ? (unsigned HOST_WIDE_INT) d
726 1.1 mrg : - (unsigned HOST_WIDE_INT) d);
727 1.1 mrg
728 1.1 mrg /* n rem d = n rem -d */
729 1.1 mrg if (code == TRUNC_MOD_EXPR && d < 0)
730 1.1 mrg {
731 1.1 mrg d = abs_d;
732 1.1 mrg use_abs_op1 = true;
733 1.1 mrg }
734 1.1 mrg if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
735 1.1 mrg {
736 1.1 mrg /* This case is not handled correctly below. */
737 1.1 mrg mode = -2;
738 1.1 mrg continue;
739 1.1 mrg }
740 1.1 mrg if (abs_d <= 1)
741 1.1 mrg {
742 1.1 mrg mode = -2;
743 1.1 mrg continue;
744 1.1 mrg }
745 1.1 mrg
746 1.1 mrg choose_multiplier (abs_d, prec, prec - 1, &ml,
747 1.1 mrg &post_shift, &dummy_int);
748 1.1 mrg if (ml >= HOST_WIDE_INT_1U << (prec - 1))
749 1.1 mrg {
750 1.1 mrg this_mode = 4 + (d < 0);
751 1.1 mrg ml |= HOST_WIDE_INT_M1U << (prec - 1);
752 1.1 mrg }
753 1.1 mrg else
754 1.1 mrg this_mode = 2 + (d < 0);
755 1.1 mrg }
756 1.1 mrg mulc[i] = ml;
757 1.1 mrg post_shifts[i] = post_shift;
758 1.1 mrg if ((i && !has_vector_shift && post_shifts[0] != post_shift)
759 1.1 mrg || post_shift >= prec
760 1.1 mrg || pre_shifts[i] >= prec)
761 1.1 mrg this_mode = -2;
762 1.1 mrg
763 1.1 mrg if (i == 0)
764 1.1 mrg mode = this_mode;
765 1.1 mrg else if (mode != this_mode)
766 1.1 mrg mode = -2;
767 1.1 mrg }
768 1.1 mrg
769 1.1 mrg if (use_pow2)
770 1.1 mrg {
771 1.1 mrg tree addend = NULL_TREE;
772 1.1 mrg if (sign_p == SIGNED)
773 1.1 mrg {
774 1.1 mrg tree uns_type;
775 1.1 mrg
776 1.1 mrg /* Both division and remainder sequences need
777 1.1 mrg op0 < 0 ? mask : 0 computed. It can be either computed as
778 1.1 mrg (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
779 1.1 mrg if none of the shifts is 0, or as the conditional. */
780 1.1 mrg for (i = 0; i < nunits; i++)
781 1.1 mrg if (shifts[i] == 0)
782 1.1 mrg break;
783 1.1 mrg uns_type
784 1.1 mrg = build_vector_type (build_nonstandard_integer_type (prec, 1),
785 1.1 mrg nunits);
786 1.1 mrg if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
787 1.1 mrg {
788 1.1 mrg for (i = 0; i < nunits; i++)
789 1.1 mrg shift_temps[i] = prec - 1;
790 1.1 mrg cur_op = add_rshift (gsi, type, op0, shift_temps);
791 1.1 mrg if (cur_op != NULL_TREE)
792 1.1 mrg {
793 1.1 mrg cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
794 1.1 mrg uns_type, cur_op);
795 1.1 mrg for (i = 0; i < nunits; i++)
796 1.1 mrg shift_temps[i] = prec - shifts[i];
797 1.1 mrg cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
798 1.1 mrg if (cur_op != NULL_TREE)
799 1.1 mrg addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
800 1.1 mrg type, cur_op);
801 1.1 mrg }
802 1.1 mrg }
803 1.1 mrg if (addend == NULL_TREE
804 1.1 mrg && expand_vec_cond_expr_p (type, type, LT_EXPR))
805 1.1 mrg {
806 1.1 mrg tree zero, cst, mask_type, mask;
807 1.1 mrg gimple *stmt, *cond;
808 1.1 mrg
809 1.1 mrg mask_type = truth_type_for (type);
810 1.1 mrg zero = build_zero_cst (type);
811 1.1 mrg mask = make_ssa_name (mask_type);
812 1.1 mrg cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
813 1.1 mrg gsi_insert_before (gsi, cond, GSI_SAME_STMT);
814 1.1 mrg tree_vector_builder vec (type, nunits, 1);
815 1.1 mrg for (i = 0; i < nunits; i++)
816 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type),
817 1.1 mrg (HOST_WIDE_INT_1U
818 1.1 mrg << shifts[i]) - 1));
819 1.1 mrg cst = vec.build ();
820 1.1 mrg addend = make_ssa_name (type);
821 1.1 mrg stmt
822 1.1 mrg = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
823 1.1 mrg gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
824 1.1 mrg }
825 1.1 mrg }
826 1.1 mrg if (code == TRUNC_DIV_EXPR)
827 1.1 mrg {
828 1.1 mrg if (sign_p == UNSIGNED)
829 1.1 mrg {
830 1.1 mrg /* q = op0 >> shift; */
831 1.1 mrg cur_op = add_rshift (gsi, type, op0, shifts);
832 1.1 mrg if (cur_op != NULL_TREE)
833 1.1 mrg return cur_op;
834 1.1 mrg }
835 1.1 mrg else if (addend != NULL_TREE)
836 1.1 mrg {
837 1.1 mrg /* t1 = op0 + addend;
838 1.1 mrg q = t1 >> shift; */
839 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
840 1.1 mrg if (op != unknown_optab
841 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
842 1.1 mrg {
843 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
844 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, shifts);
845 1.1 mrg if (cur_op != NULL_TREE)
846 1.1 mrg return cur_op;
847 1.1 mrg }
848 1.1 mrg }
849 1.1 mrg }
850 1.1 mrg else
851 1.1 mrg {
852 1.1 mrg tree mask;
853 1.1 mrg tree_vector_builder vec (type, nunits, 1);
854 1.1 mrg for (i = 0; i < nunits; i++)
855 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type),
856 1.1 mrg (HOST_WIDE_INT_1U
857 1.1 mrg << shifts[i]) - 1));
858 1.1 mrg mask = vec.build ();
859 1.1 mrg op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
860 1.1 mrg if (op != unknown_optab
861 1.1 mrg && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
862 1.1 mrg {
863 1.1 mrg if (sign_p == UNSIGNED)
864 1.1 mrg /* r = op0 & mask; */
865 1.1 mrg return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
866 1.1 mrg else if (addend != NULL_TREE)
867 1.1 mrg {
868 1.1 mrg /* t1 = op0 + addend;
869 1.1 mrg t2 = t1 & mask;
870 1.1 mrg r = t2 - addend; */
871 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
872 1.1 mrg if (op != unknown_optab
873 1.1 mrg && optab_handler (op, TYPE_MODE (type))
874 1.1 mrg != CODE_FOR_nothing)
875 1.1 mrg {
876 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
877 1.1 mrg addend);
878 1.1 mrg cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
879 1.1 mrg cur_op, mask);
880 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type,
881 1.1 mrg optab_default);
882 1.1 mrg if (op != unknown_optab
883 1.1 mrg && optab_handler (op, TYPE_MODE (type))
884 1.1 mrg != CODE_FOR_nothing)
885 1.1 mrg return gimplify_build2 (gsi, MINUS_EXPR, type,
886 1.1 mrg cur_op, addend);
887 1.1 mrg }
888 1.1 mrg }
889 1.1 mrg }
890 1.1 mrg }
891 1.1 mrg }
892 1.1 mrg
893 1.1 mrg if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
894 1.1 mrg return NULL_TREE;
895 1.1 mrg
896 1.1 mrg if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
897 1.1 mrg return NULL_TREE;
898 1.1 mrg
899 1.1 mrg cur_op = op0;
900 1.1 mrg
901 1.1 mrg switch (mode)
902 1.1 mrg {
903 1.1 mrg case 0:
904 1.1 mrg gcc_assert (sign_p == UNSIGNED);
905 1.1 mrg /* t1 = oprnd0 >> pre_shift;
906 1.1 mrg t2 = t1 h* ml;
907 1.1 mrg q = t2 >> post_shift; */
908 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
909 1.1 mrg if (cur_op == NULL_TREE)
910 1.1 mrg return NULL_TREE;
911 1.1 mrg break;
912 1.1 mrg case 1:
913 1.1 mrg gcc_assert (sign_p == UNSIGNED);
914 1.1 mrg for (i = 0; i < nunits; i++)
915 1.1 mrg {
916 1.1 mrg shift_temps[i] = 1;
917 1.1 mrg post_shifts[i]--;
918 1.1 mrg }
919 1.1 mrg break;
920 1.1 mrg case 2:
921 1.1 mrg case 3:
922 1.1 mrg case 4:
923 1.1 mrg case 5:
924 1.1 mrg gcc_assert (sign_p == SIGNED);
925 1.1 mrg for (i = 0; i < nunits; i++)
926 1.1 mrg shift_temps[i] = prec - 1;
927 1.1 mrg break;
928 1.1 mrg default:
929 1.1 mrg return NULL_TREE;
930 1.1 mrg }
931 1.1 mrg
932 1.1 mrg tree_vector_builder vec (type, nunits, 1);
933 1.1 mrg for (i = 0; i < nunits; i++)
934 1.1 mrg vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
935 1.1 mrg mulcst = vec.build ();
936 1.1 mrg
937 1.1 mrg cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
938 1.1 mrg
939 1.1 mrg switch (mode)
940 1.1 mrg {
941 1.1 mrg case 0:
942 1.1 mrg /* t1 = oprnd0 >> pre_shift;
943 1.1 mrg t2 = t1 h* ml;
944 1.1 mrg q = t2 >> post_shift; */
945 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, post_shifts);
946 1.1 mrg break;
947 1.1 mrg case 1:
948 1.1 mrg /* t1 = oprnd0 h* ml;
949 1.1 mrg t2 = oprnd0 - t1;
950 1.1 mrg t3 = t2 >> 1;
951 1.1 mrg t4 = t1 + t3;
952 1.1 mrg q = t4 >> (post_shift - 1); */
953 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
954 1.1 mrg if (op == unknown_optab
955 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
956 1.1 mrg return NULL_TREE;
957 1.1 mrg tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
958 1.1 mrg tem = add_rshift (gsi, type, tem, shift_temps);
959 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
960 1.1 mrg if (op == unknown_optab
961 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
962 1.1 mrg return NULL_TREE;
963 1.1 mrg tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
964 1.1 mrg cur_op = add_rshift (gsi, type, tem, post_shifts);
965 1.1 mrg if (cur_op == NULL_TREE)
966 1.1 mrg return NULL_TREE;
967 1.1 mrg break;
968 1.1 mrg case 2:
969 1.1 mrg case 3:
970 1.1 mrg case 4:
971 1.1 mrg case 5:
972 1.1 mrg /* t1 = oprnd0 h* ml;
973 1.1 mrg t2 = t1; [ iff (mode & 2) != 0 ]
974 1.1 mrg t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
975 1.1 mrg t3 = t2 >> post_shift;
976 1.1 mrg t4 = oprnd0 >> (prec - 1);
977 1.1 mrg q = t3 - t4; [ iff (mode & 1) == 0 ]
978 1.1 mrg q = t4 - t3; [ iff (mode & 1) != 0 ] */
979 1.1 mrg if ((mode & 2) == 0)
980 1.1 mrg {
981 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
982 1.1 mrg if (op == unknown_optab
983 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
984 1.1 mrg return NULL_TREE;
985 1.1 mrg cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
986 1.1 mrg }
987 1.1 mrg cur_op = add_rshift (gsi, type, cur_op, post_shifts);
988 1.1 mrg if (cur_op == NULL_TREE)
989 1.1 mrg return NULL_TREE;
990 1.1 mrg tem = add_rshift (gsi, type, op0, shift_temps);
991 1.1 mrg if (tem == NULL_TREE)
992 1.1 mrg return NULL_TREE;
993 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
994 1.1 mrg if (op == unknown_optab
995 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
996 1.1 mrg return NULL_TREE;
997 1.1 mrg if ((mode & 1) == 0)
998 1.1 mrg cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
999 1.1 mrg else
1000 1.1 mrg cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
1001 1.1 mrg break;
1002 1.1 mrg default:
1003 1.1 mrg gcc_unreachable ();
1004 1.1 mrg }
1005 1.1 mrg
1006 1.1 mrg if (code == TRUNC_DIV_EXPR)
1007 1.1 mrg return cur_op;
1008 1.1 mrg
1009 1.1 mrg /* We divided. Now finish by:
1010 1.1 mrg t1 = q * oprnd1;
1011 1.1 mrg r = oprnd0 - t1; */
1012 1.1 mrg op = optab_for_tree_code (MULT_EXPR, type, optab_default);
1013 1.1 mrg if (op == unknown_optab
1014 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1015 1.1 mrg return NULL_TREE;
1016 1.1 mrg if (use_abs_op1)
1017 1.1 mrg {
1018 1.1 mrg tree_vector_builder elts;
1019 1.1 mrg if (!elts.new_unary_operation (type, op1, false))
1020 1.1 mrg return NULL_TREE;
1021 1.1 mrg unsigned int count = elts.encoded_nelts ();
1022 1.1 mrg for (unsigned int i = 0; i < count; ++i)
1023 1.1 mrg {
1024 1.1 mrg tree elem1 = VECTOR_CST_ELT (op1, i);
1025 1.1 mrg
1026 1.1 mrg tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
1027 1.1 mrg if (elt == NULL_TREE)
1028 1.1 mrg return NULL_TREE;
1029 1.1 mrg elts.quick_push (elt);
1030 1.1 mrg }
1031 1.1 mrg op1 = elts.build ();
1032 1.1 mrg }
1033 1.1 mrg tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
1034 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1035 1.1 mrg if (op == unknown_optab
1036 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1037 1.1 mrg return NULL_TREE;
1038 1.1 mrg return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
1039 1.1 mrg }
1040 1.1 mrg
1041 1.1 mrg /* Expand a vector condition to scalars, by using many conditions
1042 1.1 mrg on the vector's elements. */
1043 1.1 mrg
1044 1.1 mrg static bool
1045 1.1 mrg expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
1046 1.1 mrg {
1047 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1048 1.1 mrg tree type = TREE_TYPE (gimple_assign_lhs (stmt));
1049 1.1 mrg tree a = gimple_assign_rhs1 (stmt);
1050 1.1 mrg tree a1 = a;
1051 1.1 mrg tree a2 = NULL_TREE;
1052 1.1 mrg bool a_is_comparison = false;
1053 1.1 mrg bool a_is_scalar_bitmask = false;
1054 1.1 mrg tree b = gimple_assign_rhs2 (stmt);
1055 1.1 mrg tree c = gimple_assign_rhs3 (stmt);
1056 1.1 mrg vec<constructor_elt, va_gc> *v;
1057 1.1 mrg tree constr;
1058 1.1 mrg tree inner_type = TREE_TYPE (type);
1059 1.1 mrg tree width = vector_element_bits_tree (type);
1060 1.1 mrg tree cond_type = TREE_TYPE (TREE_TYPE (a));
1061 1.1 mrg tree comp_inner_type = cond_type;
1062 1.1 mrg tree index = bitsize_int (0);
1063 1.1 mrg tree comp_width = width;
1064 1.1 mrg tree comp_index = index;
1065 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
1066 1.1 mrg tree_code code = TREE_CODE (a);
1067 1.1 mrg gassign *assign = NULL;
1068 1.1 mrg
1069 1.1 mrg if (code == SSA_NAME)
1070 1.1 mrg {
1071 1.1 mrg assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a));
1072 1.1 mrg if (assign != NULL
1073 1.1 mrg && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison)
1074 1.1 mrg {
1075 1.1 mrg a_is_comparison = true;
1076 1.1 mrg a1 = gimple_assign_rhs1 (assign);
1077 1.1 mrg a2 = gimple_assign_rhs2 (assign);
1078 1.1 mrg code = gimple_assign_rhs_code (assign);
1079 1.1 mrg comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
1080 1.1 mrg comp_width = vector_element_bits_tree (TREE_TYPE (a1));
1081 1.1 mrg }
1082 1.1 mrg }
1083 1.1 mrg
1084 1.1 mrg if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code)
1085 1.1 mrg || (integer_all_onesp (b) && integer_zerop (c)
1086 1.1 mrg && expand_vec_cmp_expr_p (type, TREE_TYPE (a1), code)))
1087 1.1 mrg {
1088 1.1 mrg gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST);
1089 1.1 mrg return true;
1090 1.1 mrg }
1091 1.1 mrg
1092 1.1 mrg /* If a has vector boolean type and is a comparison, above
1093 1.1 mrg expand_vec_cond_expr_p might fail, even if both the comparison and
1094 1.1 mrg VEC_COND_EXPR could be supported individually. See PR109176. */
1095 1.1 mrg if (a_is_comparison
1096 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1097 1.1 mrg && expand_vec_cond_expr_p (type, TREE_TYPE (a), SSA_NAME)
1098 1.1 mrg && expand_vec_cmp_expr_p (TREE_TYPE (a1), TREE_TYPE (a), code))
1099 1.1 mrg return true;
1100 1.1 mrg
1101 1.1 mrg /* Handle vector boolean types with bitmasks. If there is a comparison
1102 1.1 mrg and we can expand the comparison into the vector boolean bitmask,
1103 1.1 mrg or otherwise if it is compatible with type, we can transform
1104 1.1 mrg vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
1105 1.1 mrg into
1106 1.1 mrg tmp_6 = x_2 < y_3;
1107 1.1 mrg tmp_7 = tmp_6 & vbfld_4;
1108 1.1 mrg tmp_8 = ~tmp_6;
1109 1.1 mrg tmp_9 = tmp_8 & vbfld_5;
1110 1.1 mrg vbfld_1 = tmp_7 | tmp_9;
1111 1.1 mrg Similarly for vbfld_10 instead of x_2 < y_3. */
1112 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type)
1113 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (type))
1114 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
1115 1.1 mrg TYPE_VECTOR_SUBPARTS (type)
1116 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
1117 1.1 mrg && (a_is_comparison
1118 1.1 mrg ? useless_type_conversion_p (type, TREE_TYPE (a))
1119 1.1 mrg : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
1120 1.1 mrg {
1121 1.1 mrg if (a_is_comparison)
1122 1.1 mrg a = gimplify_build2 (gsi, code, type, a1, a2);
1123 1.1 mrg a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
1124 1.1 mrg a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
1125 1.1 mrg a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
1126 1.1 mrg a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
1127 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, a);
1128 1.1 mrg update_stmt (gsi_stmt (*gsi));
1129 1.1 mrg return true;
1130 1.1 mrg }
1131 1.1 mrg
1132 1.1 mrg /* TODO: try and find a smaller vector type. */
1133 1.1 mrg
1134 1.1 mrg if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1135 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
1136 1.1 mrg "vector condition will be expanded piecewise");
1137 1.1 mrg
1138 1.1 mrg if (!a_is_comparison
1139 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1140 1.1 mrg && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
1141 1.1 mrg && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
1142 1.1 mrg TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
1143 1.1 mrg * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
1144 1.1 mrg (TREE_TYPE (TREE_TYPE (a))))))
1145 1.1 mrg {
1146 1.1 mrg a_is_scalar_bitmask = true;
1147 1.1 mrg int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
1148 1.1 mrg tree atype = build_nonstandard_integer_type (prec, 1);
1149 1.1 mrg a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
1150 1.1 mrg }
1151 1.1 mrg else if (!a_is_comparison
1152 1.1 mrg && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)))
1153 1.1 mrg comp_width = vector_element_bits_tree (TREE_TYPE (a));
1154 1.1 mrg
1155 1.1 mrg int nunits = nunits_for_known_piecewise_op (type);
1156 1.1 mrg vec_alloc (v, nunits);
1157 1.1 mrg bool constant_p = true;
1158 1.1 mrg for (int i = 0; i < nunits; i++)
1159 1.1 mrg {
1160 1.1 mrg tree aa, result;
1161 1.1 mrg tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
1162 1.1 mrg tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
1163 1.1 mrg if (a_is_comparison)
1164 1.1 mrg {
1165 1.1 mrg tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
1166 1.1 mrg comp_width, comp_index);
1167 1.1 mrg tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
1168 1.1 mrg comp_width, comp_index);
1169 1.1 mrg aa = build2 (code, cond_type, aa1, aa2);
1170 1.1 mrg }
1171 1.1 mrg else if (a_is_scalar_bitmask)
1172 1.1 mrg {
1173 1.1 mrg wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
1174 1.1 mrg result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
1175 1.1 mrg a, wide_int_to_tree (TREE_TYPE (a), w));
1176 1.1 mrg aa = build2 (NE_EXPR, boolean_type_node, result,
1177 1.1 mrg build_zero_cst (TREE_TYPE (a)));
1178 1.1 mrg }
1179 1.1 mrg else
1180 1.1 mrg aa = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index);
1181 1.1 mrg result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
1182 1.1 mrg if (!CONSTANT_CLASS_P (result))
1183 1.1 mrg constant_p = false;
1184 1.1 mrg constructor_elt ce = {NULL_TREE, result};
1185 1.1 mrg v->quick_push (ce);
1186 1.1 mrg index = int_const_binop (PLUS_EXPR, index, width);
1187 1.1 mrg if (width == comp_width)
1188 1.1 mrg comp_index = index;
1189 1.1 mrg else
1190 1.1 mrg comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
1191 1.1 mrg }
1192 1.1 mrg
1193 1.1 mrg if (constant_p)
1194 1.1 mrg constr = build_vector_from_ctor (type, v);
1195 1.1 mrg else
1196 1.1 mrg constr = build_constructor (type, v);
1197 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, constr);
1198 1.1 mrg update_stmt (gsi_stmt (*gsi));
1199 1.1 mrg
1200 1.1 mrg if (a_is_comparison)
1201 1.1 mrg bitmap_set_bit (dce_ssa_names,
1202 1.1 mrg SSA_NAME_VERSION (gimple_assign_lhs (assign)));
1203 1.1 mrg
1204 1.1 mrg return false;
1205 1.1 mrg }
1206 1.1 mrg
1207 1.1 mrg static tree
1208 1.1 mrg expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1209 1.1 mrg gassign *assign, enum tree_code code,
1210 1.1 mrg bitmap dce_ssa_names)
1211 1.1 mrg {
1212 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type);
1213 1.1 mrg
1214 1.1 mrg /* If the compute mode is not a vector mode (hence we are not decomposing
1215 1.1 mrg a BLKmode vector to smaller, hardware-supported vectors), we may want
1216 1.1 mrg to expand the operations in parallel. */
1217 1.1 mrg if (!VECTOR_MODE_P (compute_mode))
1218 1.1 mrg switch (code)
1219 1.1 mrg {
1220 1.1 mrg case PLUS_EXPR:
1221 1.1 mrg case MINUS_EXPR:
1222 1.1 mrg if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1223 1.1 mrg return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
1224 1.1 mrg gimple_assign_rhs1 (assign),
1225 1.1 mrg gimple_assign_rhs2 (assign), code);
1226 1.1 mrg break;
1227 1.1 mrg
1228 1.1 mrg case NEGATE_EXPR:
1229 1.1 mrg if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1230 1.1 mrg return expand_vector_addition (gsi, do_unop, do_negate, type,
1231 1.1 mrg gimple_assign_rhs1 (assign),
1232 1.1 mrg NULL_TREE, code);
1233 1.1 mrg break;
1234 1.1 mrg
1235 1.1 mrg case BIT_AND_EXPR:
1236 1.1 mrg case BIT_IOR_EXPR:
1237 1.1 mrg case BIT_XOR_EXPR:
1238 1.1 mrg return expand_vector_parallel (gsi, do_binop, type,
1239 1.1 mrg gimple_assign_rhs1 (assign),
1240 1.1 mrg gimple_assign_rhs2 (assign), code);
1241 1.1 mrg
1242 1.1 mrg case BIT_NOT_EXPR:
1243 1.1 mrg return expand_vector_parallel (gsi, do_unop, type,
1244 1.1 mrg gimple_assign_rhs1 (assign),
1245 1.1 mrg NULL_TREE, code);
1246 1.1 mrg case EQ_EXPR:
1247 1.1 mrg case NE_EXPR:
1248 1.1 mrg case GT_EXPR:
1249 1.1 mrg case LT_EXPR:
1250 1.1 mrg case GE_EXPR:
1251 1.1 mrg case LE_EXPR:
1252 1.1 mrg case UNEQ_EXPR:
1253 1.1 mrg case UNGT_EXPR:
1254 1.1 mrg case UNLT_EXPR:
1255 1.1 mrg case UNGE_EXPR:
1256 1.1 mrg case UNLE_EXPR:
1257 1.1 mrg case LTGT_EXPR:
1258 1.1 mrg case ORDERED_EXPR:
1259 1.1 mrg case UNORDERED_EXPR:
1260 1.1 mrg {
1261 1.1 mrg tree rhs1 = gimple_assign_rhs1 (assign);
1262 1.1 mrg tree rhs2 = gimple_assign_rhs2 (assign);
1263 1.1 mrg
1264 1.1 mrg return expand_vector_comparison (gsi, type, rhs1, rhs2, code,
1265 1.1 mrg dce_ssa_names);
1266 1.1 mrg }
1267 1.1 mrg
1268 1.1 mrg case TRUNC_DIV_EXPR:
1269 1.1 mrg case TRUNC_MOD_EXPR:
1270 1.1 mrg {
1271 1.1 mrg tree rhs1 = gimple_assign_rhs1 (assign);
1272 1.1 mrg tree rhs2 = gimple_assign_rhs2 (assign);
1273 1.1 mrg tree ret;
1274 1.1 mrg
1275 1.1 mrg if (!optimize
1276 1.1 mrg || !VECTOR_INTEGER_TYPE_P (type)
1277 1.1 mrg || TREE_CODE (rhs2) != VECTOR_CST
1278 1.1 mrg || !VECTOR_MODE_P (TYPE_MODE (type)))
1279 1.1 mrg break;
1280 1.1 mrg
1281 1.1 mrg ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1282 1.1 mrg if (ret != NULL_TREE)
1283 1.1 mrg return ret;
1284 1.1 mrg break;
1285 1.1 mrg }
1286 1.1 mrg
1287 1.1 mrg default:
1288 1.1 mrg break;
1289 1.1 mrg }
1290 1.1 mrg
1291 1.1 mrg if (TREE_CODE_CLASS (code) == tcc_unary)
1292 1.1 mrg return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1293 1.1 mrg gimple_assign_rhs1 (assign),
1294 1.1 mrg NULL_TREE, code, false);
1295 1.1 mrg else
1296 1.1 mrg return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1297 1.1 mrg gimple_assign_rhs1 (assign),
1298 1.1 mrg gimple_assign_rhs2 (assign), code, false);
1299 1.1 mrg }
1300 1.1 mrg
1301 1.1 mrg /* Try to optimize
1302 1.1 mrg a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1303 1.1 mrg style stmts into:
1304 1.1 mrg _9 = { b_7, b_7, b_7, b_7 };
1305 1.1 mrg a_5 = _9 + { 0, 3, 6, 9 };
1306 1.1 mrg because vector splat operation is usually more efficient
1307 1.1 mrg than piecewise initialization of the vector. */
1308 1.1 mrg
1309 1.1 mrg static void
1310 1.1 mrg optimize_vector_constructor (gimple_stmt_iterator *gsi)
1311 1.1 mrg {
1312 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1313 1.1 mrg tree lhs = gimple_assign_lhs (stmt);
1314 1.1 mrg tree rhs = gimple_assign_rhs1 (stmt);
1315 1.1 mrg tree type = TREE_TYPE (rhs);
1316 1.1 mrg unsigned int i, j;
1317 1.1 mrg unsigned HOST_WIDE_INT nelts;
1318 1.1 mrg bool all_same = true;
1319 1.1 mrg constructor_elt *elt;
1320 1.1 mrg gimple *g;
1321 1.1 mrg tree base = NULL_TREE;
1322 1.1 mrg optab op;
1323 1.1 mrg
1324 1.1 mrg if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1325 1.1 mrg || nelts <= 2
1326 1.1 mrg || CONSTRUCTOR_NELTS (rhs) != nelts)
1327 1.1 mrg return;
1328 1.1 mrg op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1329 1.1 mrg if (op == unknown_optab
1330 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1331 1.1 mrg return;
1332 1.1 mrg FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1333 1.1 mrg if (TREE_CODE (elt->value) != SSA_NAME
1334 1.1 mrg || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1335 1.1 mrg return;
1336 1.1 mrg else
1337 1.1 mrg {
1338 1.1 mrg tree this_base = elt->value;
1339 1.1 mrg if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1340 1.1 mrg all_same = false;
1341 1.1 mrg for (j = 0; j < nelts + 1; j++)
1342 1.1 mrg {
1343 1.1 mrg g = SSA_NAME_DEF_STMT (this_base);
1344 1.1 mrg if (is_gimple_assign (g)
1345 1.1 mrg && gimple_assign_rhs_code (g) == PLUS_EXPR
1346 1.1 mrg && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1347 1.1 mrg && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1348 1.1 mrg && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1349 1.1 mrg this_base = gimple_assign_rhs1 (g);
1350 1.1 mrg else
1351 1.1 mrg break;
1352 1.1 mrg }
1353 1.1 mrg if (i == 0)
1354 1.1 mrg base = this_base;
1355 1.1 mrg else if (this_base != base)
1356 1.1 mrg return;
1357 1.1 mrg }
1358 1.1 mrg if (all_same)
1359 1.1 mrg return;
1360 1.1 mrg tree_vector_builder cst (type, nelts, 1);
1361 1.1 mrg for (i = 0; i < nelts; i++)
1362 1.1 mrg {
1363 1.1 mrg tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1364 1.1 mrg tree elt = build_zero_cst (TREE_TYPE (base));
1365 1.1 mrg while (this_base != base)
1366 1.1 mrg {
1367 1.1 mrg g = SSA_NAME_DEF_STMT (this_base);
1368 1.1 mrg elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1369 1.1 mrg elt, gimple_assign_rhs2 (g));
1370 1.1 mrg if (elt == NULL_TREE
1371 1.1 mrg || TREE_CODE (elt) != INTEGER_CST
1372 1.1 mrg || TREE_OVERFLOW (elt))
1373 1.1 mrg return;
1374 1.1 mrg this_base = gimple_assign_rhs1 (g);
1375 1.1 mrg }
1376 1.1 mrg cst.quick_push (elt);
1377 1.1 mrg }
1378 1.1 mrg for (i = 0; i < nelts; i++)
1379 1.1 mrg CONSTRUCTOR_ELT (rhs, i)->value = base;
1380 1.1 mrg g = gimple_build_assign (make_ssa_name (type), rhs);
1381 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT);
1382 1.1 mrg g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1383 1.1 mrg cst.build ());
1384 1.1 mrg gsi_replace (gsi, g, false);
1385 1.1 mrg }
1386 1.1 mrg
1387 1.1 mrg /* Return a type for the widest vector mode with the same element type as
1389 1.1 mrg type ORIGINAL_VECTOR_TYPE, with at most the same number of elements as type
1390 1.1 mrg ORIGINAL_VECTOR_TYPE and that is supported by the target for an operation
1391 1.1 mrg with optab OP, or return NULL_TREE if none is found. */
1392 1.1 mrg
1393 1.1 mrg static tree
1394 1.1 mrg type_for_widest_vector_mode (tree original_vector_type, optab op)
1395 1.1 mrg {
1396 1.1 mrg gcc_assert (VECTOR_TYPE_P (original_vector_type));
1397 1.1 mrg tree type = TREE_TYPE (original_vector_type);
1398 1.1 mrg machine_mode inner_mode = TYPE_MODE (type);
1399 1.1 mrg machine_mode best_mode = VOIDmode, mode;
1400 1.1 mrg poly_int64 best_nunits = 0;
1401 1.1 mrg
1402 1.1 mrg if (SCALAR_FLOAT_MODE_P (inner_mode))
1403 1.1 mrg mode = MIN_MODE_VECTOR_FLOAT;
1404 1.1 mrg else if (SCALAR_FRACT_MODE_P (inner_mode))
1405 1.1 mrg mode = MIN_MODE_VECTOR_FRACT;
1406 1.1 mrg else if (SCALAR_UFRACT_MODE_P (inner_mode))
1407 1.1 mrg mode = MIN_MODE_VECTOR_UFRACT;
1408 1.1 mrg else if (SCALAR_ACCUM_MODE_P (inner_mode))
1409 1.1 mrg mode = MIN_MODE_VECTOR_ACCUM;
1410 1.1 mrg else if (SCALAR_UACCUM_MODE_P (inner_mode))
1411 1.1 mrg mode = MIN_MODE_VECTOR_UACCUM;
1412 1.1 mrg else if (inner_mode == BImode)
1413 1.1 mrg mode = MIN_MODE_VECTOR_BOOL;
1414 1.1 mrg else
1415 1.1 mrg mode = MIN_MODE_VECTOR_INT;
1416 1.1 mrg
1417 1.1 mrg FOR_EACH_MODE_FROM (mode, mode)
1418 1.1 mrg if (GET_MODE_INNER (mode) == inner_mode
1419 1.1 mrg && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1420 1.1 mrg && optab_handler (op, mode) != CODE_FOR_nothing
1421 1.1 mrg && known_le (GET_MODE_NUNITS (mode),
1422 1.1 mrg TYPE_VECTOR_SUBPARTS (original_vector_type)))
1423 1.1 mrg best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1424 1.1 mrg
1425 1.1 mrg if (best_mode == VOIDmode)
1426 1.1 mrg return NULL_TREE;
1427 1.1 mrg else
1428 1.1 mrg return build_vector_type_for_mode (type, best_mode);
1429 1.1 mrg }
1430 1.1 mrg
1431 1.1 mrg
1432 1.1 mrg /* Build a reference to the element of the vector VECT. Function
1433 1.1 mrg returns either the element itself, either BIT_FIELD_REF, or an
1434 1.1 mrg ARRAY_REF expression.
1435 1.1 mrg
1436 1.1 mrg GSI is required to insert temporary variables while building a
1437 1.1 mrg refernece to the element of the vector VECT.
1438 1.1 mrg
1439 1.1 mrg PTMPVEC is a pointer to the temporary variable for caching
1440 1.1 mrg purposes. In case when PTMPVEC is NULL new temporary variable
1441 1.1 mrg will be created. */
1442 1.1 mrg static tree
1443 1.1 mrg vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1444 1.1 mrg {
1445 1.1 mrg tree vect_type, vect_elt_type;
1446 1.1 mrg gimple *asgn;
1447 1.1 mrg tree tmpvec;
1448 1.1 mrg tree arraytype;
1449 1.1 mrg bool need_asgn = true;
1450 1.1 mrg unsigned int elements;
1451 1.1 mrg
1452 1.1 mrg vect_type = TREE_TYPE (vect);
1453 1.1 mrg vect_elt_type = TREE_TYPE (vect_type);
1454 1.1 mrg elements = nunits_for_known_piecewise_op (vect_type);
1455 1.1 mrg
1456 1.1 mrg if (TREE_CODE (idx) == INTEGER_CST)
1457 1.1 mrg {
1458 1.1 mrg unsigned HOST_WIDE_INT index;
1459 1.1 mrg
1460 1.1 mrg /* Given that we're about to compute a binary modulus,
1461 1.1 mrg we don't care about the high bits of the value. */
1462 1.1 mrg index = TREE_INT_CST_LOW (idx);
1463 1.1 mrg if (!tree_fits_uhwi_p (idx) || index >= elements)
1464 1.1 mrg {
1465 1.1 mrg index &= elements - 1;
1466 1.1 mrg idx = build_int_cst (TREE_TYPE (idx), index);
1467 1.1 mrg }
1468 1.1 mrg
1469 1.1 mrg /* When lowering a vector statement sequence do some easy
1470 1.1 mrg simplification by looking through intermediate vector results. */
1471 1.1 mrg if (TREE_CODE (vect) == SSA_NAME)
1472 1.1 mrg {
1473 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1474 1.1 mrg if (is_gimple_assign (def_stmt)
1475 1.1 mrg && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1476 1.1 mrg || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1477 1.1 mrg vect = gimple_assign_rhs1 (def_stmt);
1478 1.1 mrg }
1479 1.1 mrg
1480 1.1 mrg if (TREE_CODE (vect) == VECTOR_CST)
1481 1.1 mrg return VECTOR_CST_ELT (vect, index);
1482 1.1 mrg else if (TREE_CODE (vect) == CONSTRUCTOR
1483 1.1 mrg && (CONSTRUCTOR_NELTS (vect) == 0
1484 1.1 mrg || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1485 1.1 mrg != VECTOR_TYPE))
1486 1.1 mrg {
1487 1.1 mrg if (index < CONSTRUCTOR_NELTS (vect))
1488 1.1 mrg return CONSTRUCTOR_ELT (vect, index)->value;
1489 1.1 mrg return build_zero_cst (vect_elt_type);
1490 1.1 mrg }
1491 1.1 mrg else
1492 1.1 mrg {
1493 1.1 mrg tree size = vector_element_bits_tree (vect_type);
1494 1.1 mrg tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1495 1.1 mrg size);
1496 1.1 mrg return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1497 1.1 mrg }
1498 1.1 mrg }
1499 1.1 mrg
1500 1.1 mrg if (!ptmpvec)
1501 1.1 mrg tmpvec = create_tmp_var (vect_type, "vectmp");
1502 1.1 mrg else if (!*ptmpvec)
1503 1.1 mrg tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1504 1.1 mrg else
1505 1.1 mrg {
1506 1.1 mrg tmpvec = *ptmpvec;
1507 1.1 mrg need_asgn = false;
1508 1.1 mrg }
1509 1.1 mrg
1510 1.1 mrg if (need_asgn)
1511 1.1 mrg {
1512 1.1 mrg TREE_ADDRESSABLE (tmpvec) = 1;
1513 1.1 mrg asgn = gimple_build_assign (tmpvec, vect);
1514 1.1 mrg gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1515 1.1 mrg }
1516 1.1 mrg
1517 1.1 mrg arraytype = build_array_type_nelts (vect_elt_type, elements);
1518 1.1 mrg return build4 (ARRAY_REF, vect_elt_type,
1519 1.1 mrg build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1520 1.1 mrg idx, NULL_TREE, NULL_TREE);
1521 1.1 mrg }
1522 1.1 mrg
1523 1.1 mrg /* Check if VEC_PERM_EXPR within the given setting is supported
1524 1.1 mrg by hardware, or lower it piecewise.
1525 1.1 mrg
1526 1.1 mrg When VEC_PERM_EXPR has the same first and second operands:
1527 1.1 mrg VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1528 1.1 mrg {v0[mask[0]], v0[mask[1]], ...}
1529 1.1 mrg MASK and V0 must have the same number of elements.
1530 1.1 mrg
1531 1.1 mrg Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1532 1.1 mrg {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1533 1.1 mrg V0 and V1 must have the same type. MASK, V0, V1 must have the
1534 1.1 mrg same number of arguments. */
1535 1.1 mrg
1536 1.1 mrg static void
1537 1.1 mrg lower_vec_perm (gimple_stmt_iterator *gsi)
1538 1.1 mrg {
1539 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1540 1.1 mrg tree mask = gimple_assign_rhs3 (stmt);
1541 1.1 mrg tree vec0 = gimple_assign_rhs1 (stmt);
1542 1.1 mrg tree vec1 = gimple_assign_rhs2 (stmt);
1543 1.1 mrg tree vect_type = TREE_TYPE (vec0);
1544 1.1 mrg tree mask_type = TREE_TYPE (mask);
1545 1.1 mrg tree vect_elt_type = TREE_TYPE (vect_type);
1546 1.1 mrg tree mask_elt_type = TREE_TYPE (mask_type);
1547 1.1 mrg unsigned HOST_WIDE_INT elements;
1548 1.1 mrg vec<constructor_elt, va_gc> *v;
1549 1.1 mrg tree constr, t, si, i_val;
1550 1.1 mrg tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1551 1.1 mrg bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1552 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
1553 1.1 mrg unsigned i;
1554 1.1 mrg
1555 1.1 mrg if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1556 1.1 mrg return;
1557 1.1 mrg
1558 1.1 mrg if (TREE_CODE (mask) == SSA_NAME)
1559 1.1 mrg {
1560 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1561 1.1 mrg if (is_gimple_assign (def_stmt)
1562 1.1 mrg && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1563 1.1 mrg mask = gimple_assign_rhs1 (def_stmt);
1564 1.1 mrg }
1565 1.1 mrg
1566 1.1 mrg vec_perm_builder sel_int;
1567 1.1 mrg
1568 1.1 mrg if (TREE_CODE (mask) == VECTOR_CST
1569 1.1 mrg && tree_to_vec_perm_builder (&sel_int, mask))
1570 1.1 mrg {
1571 1.1 mrg vec_perm_indices indices (sel_int, 2, elements);
1572 1.1 mrg if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices))
1573 1.1 mrg {
1574 1.1 mrg gimple_assign_set_rhs3 (stmt, mask);
1575 1.1 mrg update_stmt (stmt);
1576 1.1 mrg return;
1577 1.1 mrg }
1578 1.1 mrg /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1579 1.1 mrg vector as VEC1 and a right element shift MASK. */
1580 1.1 mrg if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1581 1.1 mrg != CODE_FOR_nothing
1582 1.1 mrg && TREE_CODE (vec1) == VECTOR_CST
1583 1.1 mrg && initializer_zerop (vec1)
1584 1.1 mrg && maybe_ne (indices[0], 0)
1585 1.1 mrg && known_lt (poly_uint64 (indices[0]), elements))
1586 1.1 mrg {
1587 1.1 mrg bool ok_p = indices.series_p (0, 1, indices[0], 1);
1588 1.1 mrg if (!ok_p)
1589 1.1 mrg {
1590 1.1 mrg for (i = 1; i < elements; ++i)
1591 1.1 mrg {
1592 1.1 mrg poly_uint64 actual = indices[i];
1593 1.1 mrg poly_uint64 expected = i + indices[0];
1594 1.1 mrg /* Indices into the second vector are all equivalent. */
1595 1.1 mrg if (maybe_lt (actual, elements)
1596 1.1 mrg ? maybe_ne (actual, expected)
1597 1.1 mrg : maybe_lt (expected, elements))
1598 1.1 mrg break;
1599 1.1 mrg }
1600 1.1 mrg ok_p = i == elements;
1601 1.1 mrg }
1602 1.1 mrg if (ok_p)
1603 1.1 mrg {
1604 1.1 mrg gimple_assign_set_rhs3 (stmt, mask);
1605 1.1 mrg update_stmt (stmt);
1606 1.1 mrg return;
1607 1.1 mrg }
1608 1.1 mrg }
1609 1.1 mrg /* And similarly vec_shl pattern. */
1610 1.1 mrg if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
1611 1.1 mrg != CODE_FOR_nothing
1612 1.1 mrg && TREE_CODE (vec0) == VECTOR_CST
1613 1.1 mrg && initializer_zerop (vec0))
1614 1.1 mrg {
1615 1.1 mrg unsigned int first = 0;
1616 1.1 mrg for (i = 0; i < elements; ++i)
1617 1.1 mrg if (known_eq (poly_uint64 (indices[i]), elements))
1618 1.1 mrg {
1619 1.1 mrg if (i == 0 || first)
1620 1.1 mrg break;
1621 1.1 mrg first = i;
1622 1.1 mrg }
1623 1.1 mrg else if (first
1624 1.1 mrg ? maybe_ne (poly_uint64 (indices[i]),
1625 1.1 mrg elements + i - first)
1626 1.1 mrg : maybe_ge (poly_uint64 (indices[i]), elements))
1627 1.1 mrg break;
1628 1.1 mrg if (first && i == elements)
1629 1.1 mrg {
1630 1.1 mrg gimple_assign_set_rhs3 (stmt, mask);
1631 1.1 mrg update_stmt (stmt);
1632 1.1 mrg return;
1633 1.1 mrg }
1634 1.1 mrg }
1635 1.1 mrg }
1636 1.1 mrg else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1637 1.1 mrg return;
1638 1.1 mrg
1639 1.1 mrg if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1640 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
1641 1.1 mrg "vector shuffling operation will be expanded piecewise");
1642 1.1 mrg
1643 1.1 mrg vec_alloc (v, elements);
1644 1.1 mrg bool constant_p = true;
1645 1.1 mrg for (i = 0; i < elements; i++)
1646 1.1 mrg {
1647 1.1 mrg si = size_int (i);
1648 1.1 mrg i_val = vector_element (gsi, mask, si, &masktmp);
1649 1.1 mrg
1650 1.1 mrg if (TREE_CODE (i_val) == INTEGER_CST)
1651 1.1 mrg {
1652 1.1 mrg unsigned HOST_WIDE_INT index;
1653 1.1 mrg
1654 1.1 mrg index = TREE_INT_CST_LOW (i_val);
1655 1.1 mrg if (!tree_fits_uhwi_p (i_val) || index >= elements)
1656 1.1 mrg i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1657 1.1 mrg
1658 1.1 mrg if (two_operand_p && (index & elements) != 0)
1659 1.1 mrg t = vector_element (gsi, vec1, i_val, &vec1tmp);
1660 1.1 mrg else
1661 1.1 mrg t = vector_element (gsi, vec0, i_val, &vec0tmp);
1662 1.1 mrg
1663 1.1 mrg t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1664 1.1 mrg true, GSI_SAME_STMT);
1665 1.1 mrg }
1666 1.1 mrg else
1667 1.1 mrg {
1668 1.1 mrg tree cond = NULL_TREE, v0_val;
1669 1.1 mrg
1670 1.1 mrg if (two_operand_p)
1671 1.1 mrg {
1672 1.1 mrg cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1673 1.1 mrg build_int_cst (mask_elt_type, elements));
1674 1.1 mrg cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1675 1.1 mrg true, GSI_SAME_STMT);
1676 1.1 mrg }
1677 1.1 mrg
1678 1.1 mrg i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1679 1.1 mrg build_int_cst (mask_elt_type, elements - 1));
1680 1.1 mrg i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1681 1.1 mrg true, GSI_SAME_STMT);
1682 1.1 mrg
1683 1.1 mrg v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1684 1.1 mrg v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1685 1.1 mrg true, GSI_SAME_STMT);
1686 1.1 mrg
1687 1.1 mrg if (two_operand_p)
1688 1.1 mrg {
1689 1.1 mrg tree v1_val;
1690 1.1 mrg
1691 1.1 mrg v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1692 1.1 mrg v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1693 1.1 mrg true, GSI_SAME_STMT);
1694 1.1 mrg
1695 1.1 mrg cond = fold_build2 (EQ_EXPR, boolean_type_node,
1696 1.1 mrg cond, build_zero_cst (mask_elt_type));
1697 1.1 mrg cond = fold_build3 (COND_EXPR, vect_elt_type,
1698 1.1 mrg cond, v0_val, v1_val);
1699 1.1 mrg t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1700 1.1 mrg true, GSI_SAME_STMT);
1701 1.1 mrg }
1702 1.1 mrg else
1703 1.1 mrg t = v0_val;
1704 1.1 mrg }
1705 1.1 mrg
1706 1.1 mrg if (!CONSTANT_CLASS_P (t))
1707 1.1 mrg constant_p = false;
1708 1.1 mrg CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1709 1.1 mrg }
1710 1.1 mrg
1711 1.1 mrg if (constant_p)
1712 1.1 mrg constr = build_vector_from_ctor (vect_type, v);
1713 1.1 mrg else
1714 1.1 mrg constr = build_constructor (vect_type, v);
1715 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, constr);
1716 1.1 mrg update_stmt (gsi_stmt (*gsi));
1717 1.1 mrg }
1718 1.1 mrg
1719 1.1 mrg /* If OP is a uniform vector return the element it is a splat from. */
1720 1.1 mrg
1721 1.1 mrg static tree
1722 1.1 mrg ssa_uniform_vector_p (tree op)
1723 1.1 mrg {
1724 1.1 mrg if (TREE_CODE (op) == VECTOR_CST
1725 1.1 mrg || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1726 1.1 mrg || TREE_CODE (op) == CONSTRUCTOR)
1727 1.1 mrg return uniform_vector_p (op);
1728 1.1 mrg if (TREE_CODE (op) == SSA_NAME)
1729 1.1 mrg {
1730 1.1 mrg gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1731 1.1 mrg if (gimple_assign_single_p (def_stmt))
1732 1.1 mrg return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1733 1.1 mrg }
1734 1.1 mrg return NULL_TREE;
1735 1.1 mrg }
1736 1.1 mrg
1737 1.1 mrg /* Return type in which CODE operation with optab OP can be
1738 1.1 mrg computed. */
1739 1.1 mrg
1740 1.1 mrg static tree
1741 1.1 mrg get_compute_type (enum tree_code code, optab op, tree type)
1742 1.1 mrg {
1743 1.1 mrg /* For very wide vectors, try using a smaller vector mode. */
1744 1.1 mrg tree compute_type = type;
1745 1.1 mrg if (op
1746 1.1 mrg && (!VECTOR_MODE_P (TYPE_MODE (type))
1747 1.1 mrg || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1748 1.1 mrg {
1749 1.1 mrg tree vector_compute_type
1750 1.1 mrg = type_for_widest_vector_mode (type, op);
1751 1.1 mrg if (vector_compute_type != NULL_TREE
1752 1.1 mrg && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1753 1.1 mrg && (optab_handler (op, TYPE_MODE (vector_compute_type))
1754 1.1 mrg != CODE_FOR_nothing))
1755 1.1 mrg compute_type = vector_compute_type;
1756 1.1 mrg }
1757 1.1 mrg
1758 1.1 mrg /* If we are breaking a BLKmode vector into smaller pieces,
1759 1.1 mrg type_for_widest_vector_mode has already looked into the optab,
1760 1.1 mrg so skip these checks. */
1761 1.1 mrg if (compute_type == type)
1762 1.1 mrg {
1763 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type);
1764 1.1 mrg if (VECTOR_MODE_P (compute_mode))
1765 1.1 mrg {
1766 1.1 mrg if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1767 1.1 mrg return compute_type;
1768 1.1 mrg if (code == MULT_HIGHPART_EXPR
1769 1.1 mrg && can_mult_highpart_p (compute_mode,
1770 1.1 mrg TYPE_UNSIGNED (compute_type)))
1771 1.1 mrg return compute_type;
1772 1.1 mrg }
1773 1.1 mrg /* There is no operation in hardware, so fall back to scalars. */
1774 1.1 mrg compute_type = TREE_TYPE (type);
1775 1.1 mrg }
1776 1.1 mrg
1777 1.1 mrg return compute_type;
1778 1.1 mrg }
1779 1.1 mrg
1780 1.1 mrg static tree
1781 1.1 mrg do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1782 1.1 mrg tree bitpos, tree bitsize, enum tree_code code,
1783 1.1 mrg tree type ATTRIBUTE_UNUSED)
1784 1.1 mrg {
1785 1.1 mrg if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1786 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1787 1.1 mrg if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1788 1.1 mrg b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1789 1.1 mrg tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1790 1.1 mrg return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1791 1.1 mrg }
1792 1.1 mrg
1793 1.1 mrg /* Expand a vector COND_EXPR to scalars, piecewise. */
1794 1.1 mrg static void
1795 1.1 mrg expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1796 1.1 mrg {
1797 1.1 mrg gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1798 1.1 mrg tree lhs = gimple_assign_lhs (stmt);
1799 1.1 mrg tree type = TREE_TYPE (lhs);
1800 1.1 mrg tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1801 1.1 mrg machine_mode compute_mode = TYPE_MODE (compute_type);
1802 1.1 mrg gcc_assert (compute_mode != BLKmode);
1803 1.1 mrg tree rhs2 = gimple_assign_rhs2 (stmt);
1804 1.1 mrg tree rhs3 = gimple_assign_rhs3 (stmt);
1805 1.1 mrg tree new_rhs;
1806 1.1 mrg
1807 1.1 mrg /* If the compute mode is not a vector mode (hence we are not decomposing
1808 1.1 mrg a BLKmode vector to smaller, hardware-supported vectors), we may want
1809 1.1 mrg to expand the operations in parallel. */
1810 1.1 mrg if (!VECTOR_MODE_P (compute_mode))
1811 1.1 mrg new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1812 1.1 mrg COND_EXPR);
1813 1.1 mrg else
1814 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1815 1.1 mrg rhs2, rhs3, COND_EXPR, false);
1816 1.1 mrg if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1817 1.1 mrg new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1818 1.1 mrg new_rhs);
1819 1.1 mrg
1820 1.1 mrg /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1821 1.1 mrg way to do it is change expand_vector_operation and its callees to
1822 1.1 mrg return a tree_code, RHS1 and RHS2 instead of a tree. */
1823 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1824 1.1 mrg update_stmt (gsi_stmt (*gsi));
1825 1.1 mrg }
1826 1.1 mrg
1827 1.1 mrg /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1828 1.1 mrg lowering. If INNER_TYPE is not a vector type, this is a scalar
1829 1.1 mrg fallback. */
1830 1.1 mrg
1831 1.1 mrg static tree
1832 1.1 mrg do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1833 1.1 mrg tree decl, tree bitpos, tree bitsize,
1834 1.1 mrg enum tree_code code, tree type)
1835 1.1 mrg {
1836 1.1 mrg a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1837 1.1 mrg if (!VECTOR_TYPE_P (inner_type))
1838 1.1 mrg return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1839 1.1 mrg if (code == CALL_EXPR)
1840 1.1 mrg {
1841 1.1 mrg gimple *g = gimple_build_call (decl, 1, a);
1842 1.1 mrg tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1843 1.1 mrg gimple_call_set_lhs (g, lhs);
1844 1.1 mrg gsi_insert_before (gsi, g, GSI_SAME_STMT);
1845 1.1 mrg return lhs;
1846 1.1 mrg }
1847 1.1 mrg else
1848 1.1 mrg {
1849 1.1 mrg tree outer_type = build_vector_type (TREE_TYPE (type),
1850 1.1 mrg TYPE_VECTOR_SUBPARTS (inner_type));
1851 1.1 mrg return gimplify_build1 (gsi, code, outer_type, a);
1852 1.1 mrg }
1853 1.1 mrg }
1854 1.1 mrg
1855 1.1 mrg /* Similarly, but for narrowing conversion. */
1856 1.1 mrg
1857 1.1 mrg static tree
1858 1.1 mrg do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1859 1.1 mrg tree, tree bitpos, tree, enum tree_code code,
1860 1.1 mrg tree type)
1861 1.1 mrg {
1862 1.1 mrg tree itype = build_vector_type (TREE_TYPE (inner_type),
1863 1.1 mrg exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1864 1.1 mrg 2));
1865 1.1 mrg tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1866 1.1 mrg tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1867 1.1 mrg int_const_binop (PLUS_EXPR, bitpos,
1868 1.1 mrg TYPE_SIZE (itype)));
1869 1.1 mrg tree outer_type = build_vector_type (TREE_TYPE (type),
1870 1.1 mrg TYPE_VECTOR_SUBPARTS (inner_type));
1871 1.1 mrg return gimplify_build2 (gsi, code, outer_type, b, c);
1872 1.1 mrg }
1873 1.1 mrg
1874 1.1 mrg /* Expand VEC_CONVERT ifn call. */
1875 1.1 mrg
1876 1.1 mrg static void
1877 1.1 mrg expand_vector_conversion (gimple_stmt_iterator *gsi)
1878 1.1 mrg {
1879 1.1 mrg gimple *stmt = gsi_stmt (*gsi);
1880 1.1 mrg gimple *g;
1881 1.1 mrg tree lhs = gimple_call_lhs (stmt);
1882 1.1 mrg if (lhs == NULL_TREE)
1883 1.1 mrg {
1884 1.1 mrg g = gimple_build_nop ();
1885 1.1 mrg gsi_replace (gsi, g, false);
1886 1.1 mrg return;
1887 1.1 mrg }
1888 1.1 mrg tree arg = gimple_call_arg (stmt, 0);
1889 1.1 mrg tree ret_type = TREE_TYPE (lhs);
1890 1.1 mrg tree arg_type = TREE_TYPE (arg);
1891 1.1 mrg tree new_rhs, compute_type = TREE_TYPE (arg_type);
1892 1.1 mrg enum tree_code code = NOP_EXPR;
1893 1.1 mrg enum tree_code code1 = ERROR_MARK;
1894 1.1 mrg enum { NARROW, NONE, WIDEN } modifier = NONE;
1895 1.1 mrg optab optab1 = unknown_optab;
1896 1.1 mrg
1897 1.1 mrg gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1898 1.1 mrg if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1899 1.1 mrg && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1900 1.1 mrg code = FIX_TRUNC_EXPR;
1901 1.1 mrg else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1902 1.1 mrg && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1903 1.1 mrg code = FLOAT_EXPR;
1904 1.1 mrg unsigned int ret_elt_bits = vector_element_bits (ret_type);
1905 1.1 mrg unsigned int arg_elt_bits = vector_element_bits (arg_type);
1906 1.1 mrg if (ret_elt_bits < arg_elt_bits)
1907 1.1 mrg modifier = NARROW;
1908 1.1 mrg else if (ret_elt_bits > arg_elt_bits)
1909 1.1 mrg modifier = WIDEN;
1910 1.1 mrg
1911 1.1 mrg if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1912 1.1 mrg {
1913 1.1 mrg if (supportable_convert_operation (code, ret_type, arg_type, &code1))
1914 1.1 mrg {
1915 1.1 mrg g = gimple_build_assign (lhs, code1, arg);
1916 1.1 mrg gsi_replace (gsi, g, false);
1917 1.1 mrg return;
1918 1.1 mrg }
1919 1.1 mrg /* Can't use get_compute_type here, as supportable_convert_operation
1920 1.1 mrg doesn't necessarily use an optab and needs two arguments. */
1921 1.1 mrg tree vec_compute_type
1922 1.1 mrg = type_for_widest_vector_mode (arg_type, mov_optab);
1923 1.1 mrg if (vec_compute_type
1924 1.1 mrg && VECTOR_MODE_P (TYPE_MODE (vec_compute_type)))
1925 1.1 mrg {
1926 1.1 mrg unsigned HOST_WIDE_INT nelts
1927 1.1 mrg = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1928 1.1 mrg while (nelts > 1)
1929 1.1 mrg {
1930 1.1 mrg tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1931 1.1 mrg tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1932 1.1 mrg if (supportable_convert_operation (code, ret1_type, arg1_type,
1933 1.1 mrg &code1))
1934 1.1 mrg {
1935 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1936 1.1 mrg ret_type, arg1_type, arg,
1937 1.1 mrg NULL_TREE, code1, false);
1938 1.1 mrg g = gimple_build_assign (lhs, new_rhs);
1939 1.1 mrg gsi_replace (gsi, g, false);
1940 1.1 mrg return;
1941 1.1 mrg }
1942 1.1 mrg nelts = nelts / 2;
1943 1.1 mrg }
1944 1.1 mrg }
1945 1.1 mrg }
1946 1.1 mrg else if (modifier == NARROW)
1947 1.1 mrg {
1948 1.1 mrg switch (code)
1949 1.1 mrg {
1950 1.1 mrg CASE_CONVERT:
1951 1.1 mrg code1 = VEC_PACK_TRUNC_EXPR;
1952 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1953 1.1 mrg break;
1954 1.1 mrg case FIX_TRUNC_EXPR:
1955 1.1 mrg code1 = VEC_PACK_FIX_TRUNC_EXPR;
1956 1.1 mrg /* The signedness is determined from output operand. */
1957 1.1 mrg optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1958 1.1 mrg break;
1959 1.1 mrg case FLOAT_EXPR:
1960 1.1 mrg code1 = VEC_PACK_FLOAT_EXPR;
1961 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1962 1.1 mrg break;
1963 1.1 mrg default:
1964 1.1 mrg gcc_unreachable ();
1965 1.1 mrg }
1966 1.1 mrg
1967 1.1 mrg if (optab1)
1968 1.1 mrg compute_type = get_compute_type (code1, optab1, arg_type);
1969 1.1 mrg enum insn_code icode1;
1970 1.1 mrg if (VECTOR_TYPE_P (compute_type)
1971 1.1 mrg && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1972 1.1 mrg != CODE_FOR_nothing)
1973 1.1 mrg && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1974 1.1 mrg {
1975 1.1 mrg tree cretd_type
1976 1.1 mrg = build_vector_type (TREE_TYPE (ret_type),
1977 1.1 mrg TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1978 1.1 mrg if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1979 1.1 mrg {
1980 1.1 mrg if (compute_type == arg_type)
1981 1.1 mrg {
1982 1.1 mrg new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1983 1.1 mrg arg, build_zero_cst (arg_type));
1984 1.1 mrg new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1985 1.1 mrg TYPE_SIZE (ret_type),
1986 1.1 mrg bitsize_int (0));
1987 1.1 mrg g = gimple_build_assign (lhs, new_rhs);
1988 1.1 mrg gsi_replace (gsi, g, false);
1989 1.1 mrg return;
1990 1.1 mrg }
1991 1.1 mrg tree dcompute_type
1992 1.1 mrg = build_vector_type (TREE_TYPE (compute_type),
1993 1.1 mrg TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1994 1.1 mrg if (TYPE_MAIN_VARIANT (dcompute_type)
1995 1.1 mrg == TYPE_MAIN_VARIANT (arg_type))
1996 1.1 mrg new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1997 1.1 mrg NULL_TREE, bitsize_int (0),
1998 1.1 mrg NULL_TREE, code1,
1999 1.1 mrg ret_type);
2000 1.1 mrg else
2001 1.1 mrg new_rhs = expand_vector_piecewise (gsi,
2002 1.1 mrg do_vec_narrow_conversion,
2003 1.1 mrg arg_type, dcompute_type,
2004 1.1 mrg arg, NULL_TREE, code1,
2005 1.1 mrg false, ret_type);
2006 1.1 mrg g = gimple_build_assign (lhs, new_rhs);
2007 1.1 mrg gsi_replace (gsi, g, false);
2008 1.1 mrg return;
2009 1.1 mrg }
2010 1.1 mrg }
2011 1.1 mrg }
2012 1.1 mrg else if (modifier == WIDEN)
2013 1.1 mrg {
2014 1.1 mrg enum tree_code code2 = ERROR_MARK;
2015 1.1 mrg optab optab2 = unknown_optab;
2016 1.1 mrg switch (code)
2017 1.1 mrg {
2018 1.1 mrg CASE_CONVERT:
2019 1.1 mrg code1 = VEC_UNPACK_LO_EXPR;
2020 1.1 mrg code2 = VEC_UNPACK_HI_EXPR;
2021 1.1 mrg break;
2022 1.1 mrg case FIX_TRUNC_EXPR:
2023 1.1 mrg code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
2024 1.1 mrg code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
2025 1.1 mrg break;
2026 1.1 mrg case FLOAT_EXPR:
2027 1.1 mrg code1 = VEC_UNPACK_FLOAT_LO_EXPR;
2028 1.1 mrg code2 = VEC_UNPACK_FLOAT_HI_EXPR;
2029 1.1 mrg break;
2030 1.1 mrg default:
2031 1.1 mrg gcc_unreachable ();
2032 1.1 mrg }
2033 1.1 mrg if (BYTES_BIG_ENDIAN)
2034 1.1 mrg std::swap (code1, code2);
2035 1.1 mrg
2036 1.1 mrg if (code == FIX_TRUNC_EXPR)
2037 1.1 mrg {
2038 1.1 mrg /* The signedness is determined from output operand. */
2039 1.1 mrg optab1 = optab_for_tree_code (code1, ret_type, optab_default);
2040 1.1 mrg optab2 = optab_for_tree_code (code2, ret_type, optab_default);
2041 1.1 mrg }
2042 1.1 mrg else
2043 1.1 mrg {
2044 1.1 mrg optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2045 1.1 mrg optab2 = optab_for_tree_code (code2, arg_type, optab_default);
2046 1.1 mrg }
2047 1.1 mrg
2048 1.1 mrg if (optab1 && optab2)
2049 1.1 mrg compute_type = get_compute_type (code1, optab1, arg_type);
2050 1.1 mrg
2051 1.1 mrg enum insn_code icode1, icode2;
2052 1.1 mrg if (VECTOR_TYPE_P (compute_type)
2053 1.1 mrg && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2054 1.1 mrg != CODE_FOR_nothing)
2055 1.1 mrg && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
2056 1.1 mrg != CODE_FOR_nothing)
2057 1.1 mrg && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
2058 1.1 mrg && (insn_data[icode1].operand[0].mode
2059 1.1 mrg == insn_data[icode2].operand[0].mode))
2060 1.1 mrg {
2061 1.1 mrg poly_uint64 nunits
2062 1.1 mrg = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
2063 1.1 mrg tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
2064 1.1 mrg if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2065 1.1 mrg {
2066 1.1 mrg vec<constructor_elt, va_gc> *v;
2067 1.1 mrg tree part_width = TYPE_SIZE (compute_type);
2068 1.1 mrg tree index = bitsize_int (0);
2069 1.1 mrg int nunits = nunits_for_known_piecewise_op (arg_type);
2070 1.1 mrg int delta = tree_to_uhwi (part_width) / arg_elt_bits;
2071 1.1 mrg int i;
2072 1.1 mrg location_t loc = gimple_location (gsi_stmt (*gsi));
2073 1.1 mrg
2074 1.1 mrg if (compute_type != arg_type)
2075 1.1 mrg {
2076 1.1 mrg if (!warning_suppressed_p (gsi_stmt (*gsi),
2077 1.1 mrg OPT_Wvector_operation_performance))
2078 1.1 mrg warning_at (loc, OPT_Wvector_operation_performance,
2079 1.1 mrg "vector operation will be expanded piecewise");
2080 1.1 mrg }
2081 1.1 mrg else
2082 1.1 mrg {
2083 1.1 mrg nunits = 1;
2084 1.1 mrg delta = 1;
2085 1.1 mrg }
2086 1.1 mrg
2087 1.1 mrg vec_alloc (v, (nunits + delta - 1) / delta * 2);
2088 1.1 mrg bool constant_p = true;
2089 1.1 mrg for (i = 0; i < nunits;
2090 1.1 mrg i += delta, index = int_const_binop (PLUS_EXPR, index,
2091 1.1 mrg part_width))
2092 1.1 mrg {
2093 1.1 mrg tree a = arg;
2094 1.1 mrg if (compute_type != arg_type)
2095 1.1 mrg a = tree_vec_extract (gsi, compute_type, a, part_width,
2096 1.1 mrg index);
2097 1.1 mrg tree result = gimplify_build1 (gsi, code1, cretd_type, a);
2098 1.1 mrg constructor_elt ce = { NULL_TREE, result };
2099 1.1 mrg if (!CONSTANT_CLASS_P (ce.value))
2100 1.1 mrg constant_p = false;
2101 1.1 mrg v->quick_push (ce);
2102 1.1 mrg ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
2103 1.1 mrg if (!CONSTANT_CLASS_P (ce.value))
2104 1.1 mrg constant_p = false;
2105 1.1 mrg v->quick_push (ce);
2106 1.1 mrg }
2107 1.1 mrg
2108 1.1 mrg if (constant_p)
2109 1.1 mrg new_rhs = build_vector_from_ctor (ret_type, v);
2110 1.1 mrg else
2111 1.1 mrg new_rhs = build_constructor (ret_type, v);
2112 1.1 mrg g = gimple_build_assign (lhs, new_rhs);
2113 1.1 mrg gsi_replace (gsi, g, false);
2114 1.1 mrg return;
2115 1.1 mrg }
2116 1.1 mrg }
2117 1.1 mrg }
2118 1.1 mrg
2119 1.1 mrg new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
2120 1.1 mrg TREE_TYPE (arg_type), arg,
2121 1.1 mrg NULL_TREE, code, false, ret_type);
2122 1.1 mrg g = gimple_build_assign (lhs, new_rhs);
2123 1.1 mrg gsi_replace (gsi, g, false);
2124 1.1 mrg }
2125 1.1 mrg
2126 1.1 mrg /* Process one statement. If we identify a vector operation, expand it. */
2127 1.1 mrg
2128 1.1 mrg static void
2129 1.1 mrg expand_vector_operations_1 (gimple_stmt_iterator *gsi,
2130 1.1 mrg bitmap dce_ssa_names)
2131 1.1 mrg {
2132 1.1 mrg tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
2133 1.1 mrg enum tree_code code;
2134 1.1 mrg optab op = unknown_optab;
2135 1.1 mrg enum gimple_rhs_class rhs_class;
2136 1.1 mrg tree new_rhs;
2137 1.1 mrg
2138 1.1 mrg /* Only consider code == GIMPLE_ASSIGN. */
2139 1.1 mrg gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
2140 1.1 mrg if (!stmt)
2141 1.1 mrg {
2142 1.1 mrg if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
2143 1.1 mrg expand_vector_conversion (gsi);
2144 1.1 mrg return;
2145 1.1 mrg }
2146 1.1 mrg
2147 1.1 mrg code = gimple_assign_rhs_code (stmt);
2148 1.1 mrg rhs_class = get_gimple_rhs_class (code);
2149 1.1 mrg lhs = gimple_assign_lhs (stmt);
2150 1.1 mrg
2151 1.1 mrg if (code == VEC_PERM_EXPR)
2152 1.1 mrg {
2153 1.1 mrg lower_vec_perm (gsi);
2154 1.1 mrg return;
2155 1.1 mrg }
2156 1.1 mrg
2157 1.1 mrg if (code == VEC_COND_EXPR)
2158 1.1 mrg {
2159 1.1 mrg expand_vector_condition (gsi, dce_ssa_names);
2160 1.1 mrg return;
2161 1.1 mrg }
2162 1.1 mrg
2163 1.1 mrg if (code == COND_EXPR
2164 1.1 mrg && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
2165 1.1 mrg && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
2166 1.1 mrg {
2167 1.1 mrg expand_vector_scalar_condition (gsi);
2168 1.1 mrg return;
2169 1.1 mrg }
2170 1.1 mrg
2171 1.1 mrg if (code == CONSTRUCTOR
2172 1.1 mrg && TREE_CODE (lhs) == SSA_NAME
2173 1.1 mrg && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
2174 1.1 mrg && !gimple_clobber_p (stmt)
2175 1.1 mrg && optimize)
2176 1.1 mrg {
2177 1.1 mrg optimize_vector_constructor (gsi);
2178 1.1 mrg return;
2179 1.1 mrg }
2180 1.1 mrg
2181 1.1 mrg if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2182 1.1 mrg return;
2183 1.1 mrg
2184 1.1 mrg rhs1 = gimple_assign_rhs1 (stmt);
2185 1.1 mrg if (rhs_class == GIMPLE_BINARY_RHS)
2186 1.1 mrg rhs2 = gimple_assign_rhs2 (stmt);
2187 1.1 mrg
2188 1.1 mrg type = TREE_TYPE (lhs);
2189 1.1 mrg if (!VECTOR_TYPE_P (type)
2190 1.1 mrg || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2191 1.1 mrg return;
2192 1.1 mrg
2193 1.1 mrg /* A scalar operation pretending to be a vector one. */
2194 1.1 mrg if (VECTOR_BOOLEAN_TYPE_P (type)
2195 1.1 mrg && !VECTOR_MODE_P (TYPE_MODE (type))
2196 1.1 mrg && TYPE_MODE (type) != BLKmode
2197 1.1 mrg && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2198 1.1 mrg || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2199 1.1 mrg && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2200 1.1 mrg && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2201 1.1 mrg return;
2202 1.1 mrg
2203 1.1 mrg /* If the vector operation is operating on all same vector elements
2204 1.1 mrg implement it with a scalar operation and a splat if the target
2205 1.1 mrg supports the scalar operation. */
2206 1.1 mrg tree srhs1, srhs2 = NULL_TREE;
2207 1.1 mrg if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2208 1.1 mrg && (rhs2 == NULL_TREE
2209 1.1 mrg || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2210 1.1 mrg && (srhs2 = rhs2))
2211 1.1 mrg || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2212 1.1 mrg /* As we query direct optabs restrict to non-convert operations. */
2213 1.1 mrg && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2214 1.1 mrg {
2215 1.1 mrg op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2216 1.1 mrg if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2217 1.1 mrg && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
2218 1.1 mrg {
2219 1.1 mrg tree stype = TREE_TYPE (TREE_TYPE (lhs));
2220 1.1 mrg tree slhs = (rhs2 != NULL_TREE)
2221 1.1 mrg ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
2222 1.1 mrg : gimplify_build1 (gsi, code, stype, srhs1);
2223 1.1 mrg gimple_assign_set_rhs_from_tree (gsi,
2224 1.1 mrg build_vector_from_val (type, slhs));
2225 1.1 mrg update_stmt (stmt);
2226 1.1 mrg return;
2227 1.1 mrg }
2228 1.1 mrg }
2229 1.1 mrg
2230 1.1 mrg if (CONVERT_EXPR_CODE_P (code)
2231 1.1 mrg || code == FLOAT_EXPR
2232 1.1 mrg || code == FIX_TRUNC_EXPR
2233 1.1 mrg || code == VIEW_CONVERT_EXPR)
2234 1.1 mrg return;
2235 1.1 mrg
2236 1.1 mrg /* The signedness is determined from input argument. */
2237 1.1 mrg if (code == VEC_UNPACK_FLOAT_HI_EXPR
2238 1.1 mrg || code == VEC_UNPACK_FLOAT_LO_EXPR
2239 1.1 mrg || code == VEC_PACK_FLOAT_EXPR)
2240 1.1 mrg {
2241 1.1 mrg /* We do not know how to scalarize those. */
2242 1.1 mrg return;
2243 1.1 mrg }
2244 1.1 mrg
2245 1.1 mrg /* For widening/narrowing vector operations, the relevant type is of the
2246 1.1 mrg arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2247 1.1 mrg calculated in the same way above. */
2248 1.1 mrg if (code == WIDEN_SUM_EXPR
2249 1.1 mrg || code == VEC_WIDEN_PLUS_HI_EXPR
2250 1.1 mrg || code == VEC_WIDEN_PLUS_LO_EXPR
2251 1.1 mrg || code == VEC_WIDEN_MINUS_HI_EXPR
2252 1.1 mrg || code == VEC_WIDEN_MINUS_LO_EXPR
2253 1.1 mrg || code == VEC_WIDEN_MULT_HI_EXPR
2254 1.1 mrg || code == VEC_WIDEN_MULT_LO_EXPR
2255 1.1 mrg || code == VEC_WIDEN_MULT_EVEN_EXPR
2256 1.1 mrg || code == VEC_WIDEN_MULT_ODD_EXPR
2257 1.1 mrg || code == VEC_UNPACK_HI_EXPR
2258 1.1 mrg || code == VEC_UNPACK_LO_EXPR
2259 1.1 mrg || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2260 1.1 mrg || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2261 1.1 mrg || code == VEC_PACK_TRUNC_EXPR
2262 1.1 mrg || code == VEC_PACK_SAT_EXPR
2263 1.1 mrg || code == VEC_PACK_FIX_TRUNC_EXPR
2264 1.1 mrg || code == VEC_WIDEN_LSHIFT_HI_EXPR
2265 1.1 mrg || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2266 1.1 mrg {
2267 1.1 mrg /* We do not know how to scalarize those. */
2268 1.1 mrg return;
2269 1.1 mrg }
2270 1.1 mrg
2271 1.1 mrg /* Choose between vector shift/rotate by vector and vector shift/rotate by
2272 1.1 mrg scalar */
2273 1.1 mrg if (code == LSHIFT_EXPR
2274 1.1 mrg || code == RSHIFT_EXPR
2275 1.1 mrg || code == LROTATE_EXPR
2276 1.1 mrg || code == RROTATE_EXPR)
2277 1.1 mrg {
2278 1.1 mrg optab opv;
2279 1.1 mrg
2280 1.1 mrg /* Check whether we have vector <op> {x,x,x,x} where x
2281 1.1 mrg could be a scalar variable or a constant. Transform
2282 1.1 mrg vector <op> {x,x,x,x} ==> vector <op> scalar. */
2283 1.1 mrg if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2284 1.1 mrg {
2285 1.1 mrg tree first;
2286 1.1 mrg
2287 1.1 mrg if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2288 1.1 mrg {
2289 1.1 mrg gimple_assign_set_rhs2 (stmt, first);
2290 1.1 mrg update_stmt (stmt);
2291 1.1 mrg rhs2 = first;
2292 1.1 mrg }
2293 1.1 mrg }
2294 1.1 mrg
2295 1.1 mrg opv = optab_for_tree_code (code, type, optab_vector);
2296 1.1 mrg if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2297 1.1 mrg op = opv;
2298 1.1 mrg else
2299 1.1 mrg {
2300 1.1 mrg op = optab_for_tree_code (code, type, optab_scalar);
2301 1.1 mrg
2302 1.1 mrg compute_type = get_compute_type (code, op, type);
2303 1.1 mrg if (compute_type == type)
2304 1.1 mrg return;
2305 1.1 mrg /* The rtl expander will expand vector/scalar as vector/vector
2306 1.1 mrg if necessary. Pick one with wider vector type. */
2307 1.1 mrg tree compute_vtype = get_compute_type (code, opv, type);
2308 1.1 mrg if (subparts_gt (compute_vtype, compute_type))
2309 1.1 mrg {
2310 1.1 mrg compute_type = compute_vtype;
2311 1.1 mrg op = opv;
2312 1.1 mrg }
2313 1.1 mrg }
2314 1.1 mrg
2315 1.1 mrg if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2316 1.1 mrg {
2317 1.1 mrg if (compute_type == NULL_TREE)
2318 1.1 mrg compute_type = get_compute_type (code, op, type);
2319 1.1 mrg if (compute_type == type)
2320 1.1 mrg return;
2321 1.1 mrg /* Before splitting vector rotates into scalar rotates,
2322 1.1 mrg see if we can't use vector shifts and BIT_IOR_EXPR
2323 1.1 mrg instead. For vector by vector rotates we'd also
2324 1.1 mrg need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2325 1.1 mrg for now, fold doesn't seem to create such rotates anyway. */
2326 1.1 mrg if (compute_type == TREE_TYPE (type)
2327 1.1 mrg && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2328 1.1 mrg {
2329 1.1 mrg optab oplv = vashl_optab, opl = ashl_optab;
2330 1.1 mrg optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2331 1.1 mrg tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2332 1.1 mrg tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2333 1.1 mrg tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2334 1.1 mrg tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2335 1.1 mrg tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2336 1.1 mrg /* The rtl expander will expand vector/scalar as vector/vector
2337 1.1 mrg if necessary. Pick one with wider vector type. */
2338 1.1 mrg if (subparts_gt (compute_lvtype, compute_ltype))
2339 1.1 mrg {
2340 1.1 mrg compute_ltype = compute_lvtype;
2341 1.1 mrg opl = oplv;
2342 1.1 mrg }
2343 1.1 mrg if (subparts_gt (compute_rvtype, compute_rtype))
2344 1.1 mrg {
2345 1.1 mrg compute_rtype = compute_rvtype;
2346 1.1 mrg opr = oprv;
2347 1.1 mrg }
2348 1.1 mrg /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2349 1.1 mrg BIT_IOR_EXPR. */
2350 1.1 mrg compute_type = compute_ltype;
2351 1.1 mrg if (subparts_gt (compute_type, compute_rtype))
2352 1.1 mrg compute_type = compute_rtype;
2353 1.1 mrg if (subparts_gt (compute_type, compute_otype))
2354 1.1 mrg compute_type = compute_otype;
2355 1.1 mrg /* Verify all 3 operations can be performed in that type. */
2356 1.1 mrg if (compute_type != TREE_TYPE (type))
2357 1.1 mrg {
2358 1.1 mrg if (optab_handler (opl, TYPE_MODE (compute_type))
2359 1.1 mrg == CODE_FOR_nothing
2360 1.1 mrg || optab_handler (opr, TYPE_MODE (compute_type))
2361 1.1 mrg == CODE_FOR_nothing
2362 1.1 mrg || optab_handler (opo, TYPE_MODE (compute_type))
2363 1.1 mrg == CODE_FOR_nothing)
2364 1.1 mrg compute_type = TREE_TYPE (type);
2365 1.1 mrg }
2366 1.1 mrg }
2367 1.1 mrg }
2368 1.1 mrg }
2369 1.1 mrg else
2370 1.1 mrg op = optab_for_tree_code (code, type, optab_default);
2371 1.1 mrg
2372 1.1 mrg /* Optabs will try converting a negation into a subtraction, so
2373 1.1 mrg look for it as well. TODO: negation of floating-point vectors
2374 1.1 mrg might be turned into an exclusive OR toggling the sign bit. */
2375 1.1 mrg if (op == unknown_optab
2376 1.1 mrg && code == NEGATE_EXPR
2377 1.1 mrg && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2378 1.1 mrg op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2379 1.1 mrg
2380 1.1 mrg if (compute_type == NULL_TREE)
2381 1.1 mrg compute_type = get_compute_type (code, op, type);
2382 1.1 mrg if (compute_type == type)
2383 1.1 mrg return;
2384 1.1 mrg
2385 1.1 mrg new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code,
2386 1.1 mrg dce_ssa_names);
2387 1.1 mrg
2388 1.1 mrg /* Leave expression untouched for later expansion. */
2389 1.1 mrg if (new_rhs == NULL_TREE)
2390 1.1 mrg return;
2391 1.1 mrg
2392 1.1 mrg if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2393 1.1 mrg new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2394 1.1 mrg new_rhs);
2395 1.1 mrg
2396 1.1 mrg /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2397 1.1 mrg way to do it is change expand_vector_operation and its callees to
2398 1.1 mrg return a tree_code, RHS1 and RHS2 instead of a tree. */
2399 1.1 mrg gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2400 1.1 mrg update_stmt (gsi_stmt (*gsi));
2401 1.1 mrg }
2402 1.1 mrg
2403 1.1 mrg /* Use this to lower vector operations introduced by the vectorizer,
2405 1.1 mrg if it may need the bit-twiddling tricks implemented in this file. */
2406 1.1 mrg
2407 1.1 mrg static unsigned int
2408 1.1 mrg expand_vector_operations (void)
2409 1.1 mrg {
2410 1.1 mrg gimple_stmt_iterator gsi;
2411 1.1 mrg basic_block bb;
2412 1.1 mrg bool cfg_changed = false;
2413 1.1 mrg
2414 1.1 mrg auto_bitmap dce_ssa_names;
2415 1.1 mrg
2416 1.1 mrg FOR_EACH_BB_FN (bb, cfun)
2417 1.1 mrg {
2418 1.1 mrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2419 1.1 mrg {
2420 1.1 mrg expand_vector_operations_1 (&gsi, dce_ssa_names);
2421 1.1 mrg /* ??? If we do not cleanup EH then we will ICE in
2422 1.1 mrg verification. But in reality we have created wrong-code
2423 1.1 mrg as we did not properly transition EH info and edges to
2424 1.1 mrg the piecewise computations. */
2425 1.1 mrg if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2426 1.1 mrg && gimple_purge_dead_eh_edges (bb))
2427 1.1 mrg cfg_changed = true;
2428 1.1 mrg }
2429 1.1 mrg }
2430 1.1 mrg
2431 1.1 mrg simple_dce_from_worklist (dce_ssa_names);
2432 1.1 mrg
2433 1.1 mrg return cfg_changed ? TODO_cleanup_cfg : 0;
2434 1.1 mrg }
2435 1.1 mrg
2436 1.1 mrg namespace {
2437 1.1 mrg
2438 1.1 mrg const pass_data pass_data_lower_vector =
2439 1.1 mrg {
2440 1.1 mrg GIMPLE_PASS, /* type */
2441 1.1 mrg "veclower", /* name */
2442 1.1 mrg OPTGROUP_VEC, /* optinfo_flags */
2443 1.1 mrg TV_NONE, /* tv_id */
2444 1.1 mrg PROP_cfg, /* properties_required */
2445 1.1 mrg PROP_gimple_lvec, /* properties_provided */
2446 1.1 mrg 0, /* properties_destroyed */
2447 1.1 mrg 0, /* todo_flags_start */
2448 1.1 mrg TODO_update_ssa, /* todo_flags_finish */
2449 1.1 mrg };
2450 1.1 mrg
2451 1.1 mrg class pass_lower_vector : public gimple_opt_pass
2452 1.1 mrg {
2453 1.1 mrg public:
2454 1.1 mrg pass_lower_vector (gcc::context *ctxt)
2455 1.1 mrg : gimple_opt_pass (pass_data_lower_vector, ctxt)
2456 1.1 mrg {}
2457 1.1 mrg
2458 1.1 mrg /* opt_pass methods: */
2459 1.1 mrg virtual bool gate (function *fun)
2460 1.1 mrg {
2461 1.1 mrg return !(fun->curr_properties & PROP_gimple_lvec);
2462 1.1 mrg }
2463 1.1 mrg
2464 1.1 mrg virtual unsigned int execute (function *)
2465 1.1 mrg {
2466 1.1 mrg return expand_vector_operations ();
2467 1.1 mrg }
2468 1.1 mrg
2469 1.1 mrg }; // class pass_lower_vector
2470 1.1 mrg
2471 1.1 mrg } // anon namespace
2472 1.1 mrg
2473 1.1 mrg gimple_opt_pass *
2474 1.1 mrg make_pass_lower_vector (gcc::context *ctxt)
2475 1.1 mrg {
2476 1.1 mrg return new pass_lower_vector (ctxt);
2477 1.1 mrg }
2478 1.1 mrg
2479 1.1 mrg namespace {
2480 1.1 mrg
2481 1.1 mrg const pass_data pass_data_lower_vector_ssa =
2482 1.1 mrg {
2483 1.1 mrg GIMPLE_PASS, /* type */
2484 1.1 mrg "veclower2", /* name */
2485 1.1 mrg OPTGROUP_VEC, /* optinfo_flags */
2486 1.1 mrg TV_NONE, /* tv_id */
2487 1.1 mrg PROP_cfg, /* properties_required */
2488 1.1 mrg PROP_gimple_lvec, /* properties_provided */
2489 1.1 mrg 0, /* properties_destroyed */
2490 1.1 mrg 0, /* todo_flags_start */
2491 1.1 mrg ( TODO_update_ssa
2492 1.1 mrg | TODO_cleanup_cfg ), /* todo_flags_finish */
2493 1.1 mrg };
2494 1.1 mrg
2495 1.1 mrg class pass_lower_vector_ssa : public gimple_opt_pass
2496 1.1 mrg {
2497 1.1 mrg public:
2498 1.1 mrg pass_lower_vector_ssa (gcc::context *ctxt)
2499 1.1 mrg : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2500 1.1 mrg {}
2501 1.1 mrg
2502 1.1 mrg /* opt_pass methods: */
2503 1.1 mrg opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
2504 1.1 mrg virtual unsigned int execute (function *)
2505 1.1 mrg {
2506 1.1 mrg return expand_vector_operations ();
2507 1.1 mrg }
2508 1.1 mrg
2509 1.1 mrg }; // class pass_lower_vector_ssa
2510 1.1 mrg
2511 1.1 mrg } // anon namespace
2512 1.1 mrg
2513 1.1 mrg gimple_opt_pass *
2514 1.1 mrg make_pass_lower_vector_ssa (gcc::context *ctxt)
2515 1.1 mrg {
2516 1.1 mrg return new pass_lower_vector_ssa (ctxt);
2517 1.1 mrg }
2518
2519 #include "gt-tree-vect-generic.h"
2520