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