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