poly_int: TYPE_VECTOR_SUBPARTS
[official-gcc.git] / gcc / tree-vect-generic.c
blobd7e77b6ace37fdd647a28897853fad3ff065272d
1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2018 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
44 static void expand_vector_operations_1 (gimple_stmt_iterator *);
46 /* Return the number of elements in a vector type TYPE that we have
47 already decided needs to be expanded piecewise. We don't support
48 this kind of expansion for variable-length vectors, since we should
49 always check for target support before introducing uses of those. */
50 static unsigned int
51 nunits_for_known_piecewise_op (const_tree type)
53 return TYPE_VECTOR_SUBPARTS (type).to_constant ();
56 /* Return true if TYPE1 has more elements than TYPE2, where either
57 type may be a vector or a scalar. */
59 static inline bool
60 subparts_gt (tree type1, tree type2)
62 poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
63 poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
64 return known_gt (n1, n2);
67 /* Build a constant of type TYPE, made of VALUE's bits replicated
68 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
69 static tree
70 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
72 int width = tree_to_uhwi (TYPE_SIZE (inner_type));
73 int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
74 / HOST_BITS_PER_WIDE_INT;
75 unsigned HOST_WIDE_INT low, mask;
76 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
77 int i;
79 gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
81 if (width == HOST_BITS_PER_WIDE_INT)
82 low = value;
83 else
85 mask = ((HOST_WIDE_INT)1 << width) - 1;
86 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
89 for (i = 0; i < n; i++)
90 a[i] = low;
92 gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
93 return wide_int_to_tree
94 (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
97 static GTY(()) tree vector_inner_type;
98 static GTY(()) tree vector_last_type;
99 static GTY(()) int vector_last_nunits;
101 /* Return a suitable vector types made of SUBPARTS units each of mode
102 "word_mode" (the global variable). */
103 static tree
104 build_word_mode_vector_type (int nunits)
106 if (!vector_inner_type)
107 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
108 else if (vector_last_nunits == nunits)
110 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
111 return vector_last_type;
114 /* We build a new type, but we canonicalize it nevertheless,
115 because it still saves some memory. */
116 vector_last_nunits = nunits;
117 vector_last_type = type_hash_canon (nunits,
118 build_vector_type (vector_inner_type,
119 nunits));
120 return vector_last_type;
123 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
124 tree, tree, tree, tree, tree, enum tree_code,
125 tree);
127 static inline tree
128 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
129 tree t, tree bitsize, tree bitpos)
131 if (TREE_CODE (t) == SSA_NAME)
133 gimple *def_stmt = SSA_NAME_DEF_STMT (t);
134 if (is_gimple_assign (def_stmt)
135 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
136 || (bitpos
137 && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)))
138 t = gimple_assign_rhs1 (def_stmt);
140 if (bitpos)
142 if (TREE_CODE (type) == BOOLEAN_TYPE)
144 tree itype
145 = build_nonstandard_integer_type (tree_to_uhwi (bitsize), 0);
146 tree field = gimplify_build3 (gsi, BIT_FIELD_REF, itype, t,
147 bitsize, bitpos);
148 return gimplify_build2 (gsi, NE_EXPR, type, field,
149 build_zero_cst (itype));
151 else
152 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
154 else
155 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
158 static tree
159 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
160 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
161 enum tree_code code, tree type ATTRIBUTE_UNUSED)
163 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
164 return gimplify_build1 (gsi, code, inner_type, a);
167 static tree
168 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
169 tree bitpos, tree bitsize, enum tree_code code,
170 tree type ATTRIBUTE_UNUSED)
172 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
173 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
174 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
175 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
176 return gimplify_build2 (gsi, code, inner_type, a, b);
179 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
181 INNER_TYPE is the type of A and B elements
183 returned expression is of signed integer type with the
184 size equal to the size of INNER_TYPE. */
185 static tree
186 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
187 tree bitpos, tree bitsize, enum tree_code code, tree type)
189 tree stype = TREE_TYPE (type);
190 tree cst_false = build_zero_cst (stype);
191 tree cst_true = build_all_ones_cst (stype);
192 tree cmp;
194 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
195 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
197 cmp = build2 (code, boolean_type_node, a, b);
198 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
201 /* Expand vector addition to scalars. This does bit twiddling
202 in order to increase parallelism:
204 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
205 (a ^ b) & 0x80808080
207 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
208 (a ^ ~b) & 0x80808080
210 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
212 This optimization should be done only if 4 vector items or more
213 fit into a word. */
214 static tree
215 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
216 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
217 enum tree_code code, tree type ATTRIBUTE_UNUSED)
219 tree inner_type = TREE_TYPE (TREE_TYPE (a));
220 unsigned HOST_WIDE_INT max;
221 tree low_bits, high_bits, a_low, b_low, result_low, signs;
223 max = GET_MODE_MASK (TYPE_MODE (inner_type));
224 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
225 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
227 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
228 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
230 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
231 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
232 if (code == PLUS_EXPR)
233 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
234 else
236 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
237 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
240 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
241 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
242 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
245 static tree
246 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
247 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
248 tree bitsize ATTRIBUTE_UNUSED,
249 enum tree_code code ATTRIBUTE_UNUSED,
250 tree type ATTRIBUTE_UNUSED)
252 tree inner_type = TREE_TYPE (TREE_TYPE (b));
253 HOST_WIDE_INT max;
254 tree low_bits, high_bits, b_low, result_low, signs;
256 max = GET_MODE_MASK (TYPE_MODE (inner_type));
257 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
258 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
260 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
262 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
263 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
264 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
265 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
266 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
269 /* Expand a vector operation to scalars, by using many operations
270 whose type is the vector type's inner type. */
271 static tree
272 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
273 tree type, tree inner_type,
274 tree a, tree b, enum tree_code code)
276 vec<constructor_elt, va_gc> *v;
277 tree part_width = TYPE_SIZE (inner_type);
278 tree index = bitsize_int (0);
279 int nunits = nunits_for_known_piecewise_op (type);
280 int delta = tree_to_uhwi (part_width)
281 / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
282 int i;
283 location_t loc = gimple_location (gsi_stmt (*gsi));
285 if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
286 warning_at (loc, OPT_Wvector_operation_performance,
287 "vector operation will be expanded piecewise");
288 else
289 warning_at (loc, OPT_Wvector_operation_performance,
290 "vector operation will be expanded in parallel");
292 vec_alloc (v, (nunits + delta - 1) / delta);
293 for (i = 0; i < nunits;
294 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
296 tree result = f (gsi, inner_type, a, b, index, part_width, code, type);
297 constructor_elt ce = {NULL_TREE, result};
298 v->quick_push (ce);
301 return build_constructor (type, v);
304 /* Expand a vector operation to scalars with the freedom to use
305 a scalar integer type, or to use a different size for the items
306 in the vector type. */
307 static tree
308 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
309 tree a, tree b,
310 enum tree_code code)
312 tree result, compute_type;
313 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
314 location_t loc = gimple_location (gsi_stmt (*gsi));
316 /* We have three strategies. If the type is already correct, just do
317 the operation an element at a time. Else, if the vector is wider than
318 one word, do it a word at a time; finally, if the vector is smaller
319 than one word, do it as a scalar. */
320 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
321 return expand_vector_piecewise (gsi, f,
322 type, TREE_TYPE (type),
323 a, b, code);
324 else if (n_words > 1)
326 tree word_type = build_word_mode_vector_type (n_words);
327 result = expand_vector_piecewise (gsi, f,
328 word_type, TREE_TYPE (word_type),
329 a, b, code);
330 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
331 GSI_SAME_STMT);
333 else
335 /* Use a single scalar operation with a mode no wider than word_mode. */
336 scalar_int_mode mode
337 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
338 compute_type = lang_hooks.types.type_for_mode (mode, 1);
339 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
340 warning_at (loc, OPT_Wvector_operation_performance,
341 "vector operation will be expanded with a "
342 "single scalar operation");
345 return result;
348 /* Expand a vector operation to scalars; for integer types we can use
349 special bit twiddling tricks to do the sums a word at a time, using
350 function F_PARALLEL instead of F. These tricks are done only if
351 they can process at least four items, that is, only if the vector
352 holds at least four items and if a word can hold four items. */
353 static tree
354 expand_vector_addition (gimple_stmt_iterator *gsi,
355 elem_op_func f, elem_op_func f_parallel,
356 tree type, tree a, tree b, enum tree_code code)
358 int parts_per_word = UNITS_PER_WORD
359 / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
361 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
362 && parts_per_word >= 4
363 && nunits_for_known_piecewise_op (type) >= 4)
364 return expand_vector_parallel (gsi, f_parallel,
365 type, a, b, code);
366 else
367 return expand_vector_piecewise (gsi, f,
368 type, TREE_TYPE (type),
369 a, b, code);
372 /* Try to expand vector comparison expression OP0 CODE OP1 by
373 querying optab if the following expression:
374 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
375 can be expanded. */
376 static tree
377 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
378 tree op1, enum tree_code code)
380 tree t;
381 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
382 && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
383 t = expand_vector_piecewise (gsi, do_compare, type,
384 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
385 else
386 t = NULL_TREE;
388 return t;
391 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
392 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
393 the result if successful, otherwise return NULL_TREE. */
394 static tree
395 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
397 optab op;
398 unsigned int i, nunits = nunits_for_known_piecewise_op (type);
399 bool scalar_shift = true;
401 for (i = 1; i < nunits; i++)
403 if (shiftcnts[i] != shiftcnts[0])
404 scalar_shift = false;
407 if (scalar_shift && shiftcnts[0] == 0)
408 return op0;
410 if (scalar_shift)
412 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
413 if (op != unknown_optab
414 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
415 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
416 build_int_cst (NULL_TREE, shiftcnts[0]));
419 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
420 if (op != unknown_optab
421 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
423 tree_vector_builder vec (type, nunits, 1);
424 for (i = 0; i < nunits; i++)
425 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
426 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
429 return NULL_TREE;
432 /* Try to expand integer vector division by constant using
433 widening multiply, shifts and additions. */
434 static tree
435 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
436 tree op1, enum tree_code code)
438 bool use_pow2 = true;
439 bool has_vector_shift = true;
440 int mode = -1, this_mode;
441 int pre_shift = -1, post_shift;
442 unsigned int nunits = nunits_for_known_piecewise_op (type);
443 int *shifts = XALLOCAVEC (int, nunits * 4);
444 int *pre_shifts = shifts + nunits;
445 int *post_shifts = pre_shifts + nunits;
446 int *shift_temps = post_shifts + nunits;
447 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
448 int prec = TYPE_PRECISION (TREE_TYPE (type));
449 int dummy_int;
450 unsigned int i;
451 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
452 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
453 tree cur_op, mulcst, tem;
454 optab op;
456 if (prec > HOST_BITS_PER_WIDE_INT)
457 return NULL_TREE;
459 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
460 if (op == unknown_optab
461 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
462 has_vector_shift = false;
464 /* Analysis phase. Determine if all op1 elements are either power
465 of two and it is possible to expand it using shifts (or for remainder
466 using masking). Additionally compute the multiplicative constants
467 and pre and post shifts if the division is to be expanded using
468 widening or high part multiplication plus shifts. */
469 for (i = 0; i < nunits; i++)
471 tree cst = VECTOR_CST_ELT (op1, i);
472 unsigned HOST_WIDE_INT ml;
474 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
475 return NULL_TREE;
476 pre_shifts[i] = 0;
477 post_shifts[i] = 0;
478 mulc[i] = 0;
479 if (use_pow2
480 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
481 use_pow2 = false;
482 if (use_pow2)
484 shifts[i] = tree_log2 (cst);
485 if (shifts[i] != shifts[0]
486 && code == TRUNC_DIV_EXPR
487 && !has_vector_shift)
488 use_pow2 = false;
490 if (mode == -2)
491 continue;
492 if (sign_p == UNSIGNED)
494 unsigned HOST_WIDE_INT mh;
495 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
497 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
498 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
499 return NULL_TREE;
501 if (d <= 1)
503 mode = -2;
504 continue;
507 /* Find a suitable multiplier and right shift count
508 instead of multiplying with D. */
509 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
511 /* If the suggested multiplier is more than SIZE bits, we can
512 do better for even divisors, using an initial right shift. */
513 if ((mh != 0 && (d & 1) == 0)
514 || (!has_vector_shift && pre_shift != -1))
516 if (has_vector_shift)
517 pre_shift = ctz_or_zero (d);
518 else if (pre_shift == -1)
520 unsigned int j;
521 for (j = 0; j < nunits; j++)
523 tree cst2 = VECTOR_CST_ELT (op1, j);
524 unsigned HOST_WIDE_INT d2;
525 int this_pre_shift;
527 if (!tree_fits_uhwi_p (cst2))
528 return NULL_TREE;
529 d2 = tree_to_uhwi (cst2) & mask;
530 if (d2 == 0)
531 return NULL_TREE;
532 this_pre_shift = floor_log2 (d2 & -d2);
533 if (pre_shift == -1 || this_pre_shift < pre_shift)
534 pre_shift = this_pre_shift;
536 if (i != 0 && pre_shift != 0)
538 /* Restart. */
539 i = -1U;
540 mode = -1;
541 continue;
544 if (pre_shift != 0)
546 if ((d >> pre_shift) <= 1)
548 mode = -2;
549 continue;
551 mh = choose_multiplier (d >> pre_shift, prec,
552 prec - pre_shift,
553 &ml, &post_shift, &dummy_int);
554 gcc_assert (!mh);
555 pre_shifts[i] = pre_shift;
558 if (!mh)
559 this_mode = 0;
560 else
561 this_mode = 1;
563 else
565 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
566 unsigned HOST_WIDE_INT abs_d;
568 if (d == -1)
569 return NULL_TREE;
571 /* Since d might be INT_MIN, we have to cast to
572 unsigned HOST_WIDE_INT before negating to avoid
573 undefined signed overflow. */
574 abs_d = (d >= 0
575 ? (unsigned HOST_WIDE_INT) d
576 : - (unsigned HOST_WIDE_INT) d);
578 /* n rem d = n rem -d */
579 if (code == TRUNC_MOD_EXPR && d < 0)
580 d = abs_d;
581 else if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
583 /* This case is not handled correctly below. */
584 mode = -2;
585 continue;
587 if (abs_d <= 1)
589 mode = -2;
590 continue;
593 choose_multiplier (abs_d, prec, prec - 1, &ml,
594 &post_shift, &dummy_int);
595 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
597 this_mode = 4 + (d < 0);
598 ml |= HOST_WIDE_INT_M1U << (prec - 1);
600 else
601 this_mode = 2 + (d < 0);
603 mulc[i] = ml;
604 post_shifts[i] = post_shift;
605 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
606 || post_shift >= prec
607 || pre_shifts[i] >= prec)
608 this_mode = -2;
610 if (i == 0)
611 mode = this_mode;
612 else if (mode != this_mode)
613 mode = -2;
616 if (use_pow2)
618 tree addend = NULL_TREE;
619 if (sign_p == SIGNED)
621 tree uns_type;
623 /* Both division and remainder sequences need
624 op0 < 0 ? mask : 0 computed. It can be either computed as
625 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
626 if none of the shifts is 0, or as the conditional. */
627 for (i = 0; i < nunits; i++)
628 if (shifts[i] == 0)
629 break;
630 uns_type
631 = build_vector_type (build_nonstandard_integer_type (prec, 1),
632 nunits);
633 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
635 for (i = 0; i < nunits; i++)
636 shift_temps[i] = prec - 1;
637 cur_op = add_rshift (gsi, type, op0, shift_temps);
638 if (cur_op != NULL_TREE)
640 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
641 uns_type, cur_op);
642 for (i = 0; i < nunits; i++)
643 shift_temps[i] = prec - shifts[i];
644 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
645 if (cur_op != NULL_TREE)
646 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
647 type, cur_op);
650 if (addend == NULL_TREE
651 && expand_vec_cond_expr_p (type, type, LT_EXPR))
653 tree zero, cst, cond, mask_type;
654 gimple *stmt;
656 mask_type = build_same_sized_truth_vector_type (type);
657 zero = build_zero_cst (type);
658 cond = build2 (LT_EXPR, mask_type, op0, zero);
659 tree_vector_builder vec (type, nunits, 1);
660 for (i = 0; i < nunits; i++)
661 vec.quick_push (build_int_cst (TREE_TYPE (type),
662 (HOST_WIDE_INT_1U
663 << shifts[i]) - 1));
664 cst = vec.build ();
665 addend = make_ssa_name (type);
666 stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
667 cst, zero);
668 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
671 if (code == TRUNC_DIV_EXPR)
673 if (sign_p == UNSIGNED)
675 /* q = op0 >> shift; */
676 cur_op = add_rshift (gsi, type, op0, shifts);
677 if (cur_op != NULL_TREE)
678 return cur_op;
680 else if (addend != NULL_TREE)
682 /* t1 = op0 + addend;
683 q = t1 >> shift; */
684 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
685 if (op != unknown_optab
686 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
688 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
689 cur_op = add_rshift (gsi, type, cur_op, shifts);
690 if (cur_op != NULL_TREE)
691 return cur_op;
695 else
697 tree mask;
698 tree_vector_builder vec (type, nunits, 1);
699 for (i = 0; i < nunits; i++)
700 vec.quick_push (build_int_cst (TREE_TYPE (type),
701 (HOST_WIDE_INT_1U
702 << shifts[i]) - 1));
703 mask = vec.build ();
704 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
705 if (op != unknown_optab
706 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
708 if (sign_p == UNSIGNED)
709 /* r = op0 & mask; */
710 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
711 else if (addend != NULL_TREE)
713 /* t1 = op0 + addend;
714 t2 = t1 & mask;
715 r = t2 - addend; */
716 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
717 if (op != unknown_optab
718 && optab_handler (op, TYPE_MODE (type))
719 != CODE_FOR_nothing)
721 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
722 addend);
723 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
724 cur_op, mask);
725 op = optab_for_tree_code (MINUS_EXPR, type,
726 optab_default);
727 if (op != unknown_optab
728 && optab_handler (op, TYPE_MODE (type))
729 != CODE_FOR_nothing)
730 return gimplify_build2 (gsi, MINUS_EXPR, type,
731 cur_op, addend);
738 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
739 return NULL_TREE;
741 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
742 return NULL_TREE;
744 cur_op = op0;
746 switch (mode)
748 case 0:
749 gcc_assert (sign_p == UNSIGNED);
750 /* t1 = oprnd0 >> pre_shift;
751 t2 = t1 h* ml;
752 q = t2 >> post_shift; */
753 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
754 if (cur_op == NULL_TREE)
755 return NULL_TREE;
756 break;
757 case 1:
758 gcc_assert (sign_p == UNSIGNED);
759 for (i = 0; i < nunits; i++)
761 shift_temps[i] = 1;
762 post_shifts[i]--;
764 break;
765 case 2:
766 case 3:
767 case 4:
768 case 5:
769 gcc_assert (sign_p == SIGNED);
770 for (i = 0; i < nunits; i++)
771 shift_temps[i] = prec - 1;
772 break;
773 default:
774 return NULL_TREE;
777 tree_vector_builder vec (type, nunits, 1);
778 for (i = 0; i < nunits; i++)
779 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
780 mulcst = vec.build ();
782 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
784 switch (mode)
786 case 0:
787 /* t1 = oprnd0 >> pre_shift;
788 t2 = t1 h* ml;
789 q = t2 >> post_shift; */
790 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
791 break;
792 case 1:
793 /* t1 = oprnd0 h* ml;
794 t2 = oprnd0 - t1;
795 t3 = t2 >> 1;
796 t4 = t1 + t3;
797 q = t4 >> (post_shift - 1); */
798 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
799 if (op == unknown_optab
800 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
801 return NULL_TREE;
802 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
803 tem = add_rshift (gsi, type, tem, shift_temps);
804 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
805 if (op == unknown_optab
806 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
807 return NULL_TREE;
808 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
809 cur_op = add_rshift (gsi, type, tem, post_shifts);
810 if (cur_op == NULL_TREE)
811 return NULL_TREE;
812 break;
813 case 2:
814 case 3:
815 case 4:
816 case 5:
817 /* t1 = oprnd0 h* ml;
818 t2 = t1; [ iff (mode & 2) != 0 ]
819 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
820 t3 = t2 >> post_shift;
821 t4 = oprnd0 >> (prec - 1);
822 q = t3 - t4; [ iff (mode & 1) == 0 ]
823 q = t4 - t3; [ iff (mode & 1) != 0 ] */
824 if ((mode & 2) == 0)
826 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
827 if (op == unknown_optab
828 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
829 return NULL_TREE;
830 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
832 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
833 if (cur_op == NULL_TREE)
834 return NULL_TREE;
835 tem = add_rshift (gsi, type, op0, shift_temps);
836 if (tem == NULL_TREE)
837 return NULL_TREE;
838 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
839 if (op == unknown_optab
840 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
841 return NULL_TREE;
842 if ((mode & 1) == 0)
843 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
844 else
845 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
846 break;
847 default:
848 gcc_unreachable ();
851 if (code == TRUNC_DIV_EXPR)
852 return cur_op;
854 /* We divided. Now finish by:
855 t1 = q * oprnd1;
856 r = oprnd0 - t1; */
857 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
858 if (op == unknown_optab
859 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
860 return NULL_TREE;
861 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
862 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
863 if (op == unknown_optab
864 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
865 return NULL_TREE;
866 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
869 /* Expand a vector condition to scalars, by using many conditions
870 on the vector's elements. */
871 static void
872 expand_vector_condition (gimple_stmt_iterator *gsi)
874 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
875 tree type = gimple_expr_type (stmt);
876 tree a = gimple_assign_rhs1 (stmt);
877 tree a1 = a;
878 tree a2 = NULL_TREE;
879 bool a_is_comparison = false;
880 tree b = gimple_assign_rhs2 (stmt);
881 tree c = gimple_assign_rhs3 (stmt);
882 vec<constructor_elt, va_gc> *v;
883 tree constr;
884 tree inner_type = TREE_TYPE (type);
885 tree cond_type = TREE_TYPE (TREE_TYPE (a));
886 tree comp_inner_type = cond_type;
887 tree width = TYPE_SIZE (inner_type);
888 tree index = bitsize_int (0);
889 tree comp_width = width;
890 tree comp_index = index;
891 int i;
892 location_t loc = gimple_location (gsi_stmt (*gsi));
894 if (!is_gimple_val (a))
896 gcc_assert (COMPARISON_CLASS_P (a));
897 a_is_comparison = true;
898 a1 = TREE_OPERAND (a, 0);
899 a2 = TREE_OPERAND (a, 1);
900 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
901 comp_width = TYPE_SIZE (comp_inner_type);
904 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
905 return;
907 /* Handle vector boolean types with bitmasks. If there is a comparison
908 and we can expand the comparison into the vector boolean bitmask,
909 or otherwise if it is compatible with type, we can transform
910 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
911 into
912 tmp_6 = x_2 < y_3;
913 tmp_7 = tmp_6 & vbfld_4;
914 tmp_8 = ~tmp_6;
915 tmp_9 = tmp_8 & vbfld_5;
916 vbfld_1 = tmp_7 | tmp_9;
917 Similarly for vbfld_10 instead of x_2 < y_3. */
918 if (VECTOR_BOOLEAN_TYPE_P (type)
919 && SCALAR_INT_MODE_P (TYPE_MODE (type))
920 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
921 TYPE_VECTOR_SUBPARTS (type)
922 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
923 && (a_is_comparison
924 ? useless_type_conversion_p (type, TREE_TYPE (a))
925 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
927 if (a_is_comparison)
928 a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
929 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
930 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
931 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
932 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
933 gimple_assign_set_rhs_from_tree (gsi, a);
934 update_stmt (gsi_stmt (*gsi));
935 return;
938 /* TODO: try and find a smaller vector type. */
940 warning_at (loc, OPT_Wvector_operation_performance,
941 "vector condition will be expanded piecewise");
943 int nunits = nunits_for_known_piecewise_op (type);
944 vec_alloc (v, nunits);
945 for (i = 0; i < nunits; i++)
947 tree aa, result;
948 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
949 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
950 if (a_is_comparison)
952 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
953 comp_width, comp_index);
954 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
955 comp_width, comp_index);
956 aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
958 else
959 aa = tree_vec_extract (gsi, cond_type, a, width, index);
960 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
961 constructor_elt ce = {NULL_TREE, result};
962 v->quick_push (ce);
963 index = int_const_binop (PLUS_EXPR, index, width);
964 if (width == comp_width)
965 comp_index = index;
966 else
967 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
970 constr = build_constructor (type, v);
971 gimple_assign_set_rhs_from_tree (gsi, constr);
972 update_stmt (gsi_stmt (*gsi));
975 static tree
976 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
977 gassign *assign, enum tree_code code)
979 machine_mode compute_mode = TYPE_MODE (compute_type);
981 /* If the compute mode is not a vector mode (hence we are not decomposing
982 a BLKmode vector to smaller, hardware-supported vectors), we may want
983 to expand the operations in parallel. */
984 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
985 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
986 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
987 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
988 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
989 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
990 switch (code)
992 case PLUS_EXPR:
993 case MINUS_EXPR:
994 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
995 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
996 gimple_assign_rhs1 (assign),
997 gimple_assign_rhs2 (assign), code);
998 break;
1000 case NEGATE_EXPR:
1001 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1002 return expand_vector_addition (gsi, do_unop, do_negate, type,
1003 gimple_assign_rhs1 (assign),
1004 NULL_TREE, code);
1005 break;
1007 case BIT_AND_EXPR:
1008 case BIT_IOR_EXPR:
1009 case BIT_XOR_EXPR:
1010 return expand_vector_parallel (gsi, do_binop, type,
1011 gimple_assign_rhs1 (assign),
1012 gimple_assign_rhs2 (assign), code);
1014 case BIT_NOT_EXPR:
1015 return expand_vector_parallel (gsi, do_unop, type,
1016 gimple_assign_rhs1 (assign),
1017 NULL_TREE, code);
1018 case EQ_EXPR:
1019 case NE_EXPR:
1020 case GT_EXPR:
1021 case LT_EXPR:
1022 case GE_EXPR:
1023 case LE_EXPR:
1024 case UNEQ_EXPR:
1025 case UNGT_EXPR:
1026 case UNLT_EXPR:
1027 case UNGE_EXPR:
1028 case UNLE_EXPR:
1029 case LTGT_EXPR:
1030 case ORDERED_EXPR:
1031 case UNORDERED_EXPR:
1033 tree rhs1 = gimple_assign_rhs1 (assign);
1034 tree rhs2 = gimple_assign_rhs2 (assign);
1036 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
1039 case TRUNC_DIV_EXPR:
1040 case TRUNC_MOD_EXPR:
1042 tree rhs1 = gimple_assign_rhs1 (assign);
1043 tree rhs2 = gimple_assign_rhs2 (assign);
1044 tree ret;
1046 if (!optimize
1047 || !VECTOR_INTEGER_TYPE_P (type)
1048 || TREE_CODE (rhs2) != VECTOR_CST
1049 || !VECTOR_MODE_P (TYPE_MODE (type)))
1050 break;
1052 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1053 if (ret != NULL_TREE)
1054 return ret;
1055 break;
1058 default:
1059 break;
1062 if (TREE_CODE_CLASS (code) == tcc_unary)
1063 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1064 gimple_assign_rhs1 (assign),
1065 NULL_TREE, code);
1066 else
1067 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1068 gimple_assign_rhs1 (assign),
1069 gimple_assign_rhs2 (assign), code);
1072 /* Try to optimize
1073 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1074 style stmts into:
1075 _9 = { b_7, b_7, b_7, b_7 };
1076 a_5 = _9 + { 0, 3, 6, 9 };
1077 because vector splat operation is usually more efficient
1078 than piecewise initialization of the vector. */
1080 static void
1081 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1083 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1084 tree lhs = gimple_assign_lhs (stmt);
1085 tree rhs = gimple_assign_rhs1 (stmt);
1086 tree type = TREE_TYPE (rhs);
1087 unsigned int i, j;
1088 unsigned HOST_WIDE_INT nelts;
1089 bool all_same = true;
1090 constructor_elt *elt;
1091 gimple *g;
1092 tree base = NULL_TREE;
1093 optab op;
1095 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1096 || nelts <= 2
1097 || CONSTRUCTOR_NELTS (rhs) != nelts)
1098 return;
1099 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1100 if (op == unknown_optab
1101 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1102 return;
1103 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1104 if (TREE_CODE (elt->value) != SSA_NAME
1105 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1106 return;
1107 else
1109 tree this_base = elt->value;
1110 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1111 all_same = false;
1112 for (j = 0; j < nelts + 1; j++)
1114 g = SSA_NAME_DEF_STMT (this_base);
1115 if (is_gimple_assign (g)
1116 && gimple_assign_rhs_code (g) == PLUS_EXPR
1117 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1118 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1119 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1120 this_base = gimple_assign_rhs1 (g);
1121 else
1122 break;
1124 if (i == 0)
1125 base = this_base;
1126 else if (this_base != base)
1127 return;
1129 if (all_same)
1130 return;
1131 tree_vector_builder cst (type, nelts, 1);
1132 for (i = 0; i < nelts; i++)
1134 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1135 tree elt = build_zero_cst (TREE_TYPE (base));
1136 while (this_base != base)
1138 g = SSA_NAME_DEF_STMT (this_base);
1139 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1140 elt, gimple_assign_rhs2 (g));
1141 if (elt == NULL_TREE
1142 || TREE_CODE (elt) != INTEGER_CST
1143 || TREE_OVERFLOW (elt))
1144 return;
1145 this_base = gimple_assign_rhs1 (g);
1147 cst.quick_push (elt);
1149 for (i = 0; i < nelts; i++)
1150 CONSTRUCTOR_ELT (rhs, i)->value = base;
1151 g = gimple_build_assign (make_ssa_name (type), rhs);
1152 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1153 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1154 cst.build ());
1155 gsi_replace (gsi, g, false);
1158 /* Return a type for the widest vector mode whose components are of type
1159 TYPE, or NULL_TREE if none is found. */
1161 static tree
1162 type_for_widest_vector_mode (tree type, optab op)
1164 machine_mode inner_mode = TYPE_MODE (type);
1165 machine_mode best_mode = VOIDmode, mode;
1166 poly_int64 best_nunits = 0;
1168 if (SCALAR_FLOAT_MODE_P (inner_mode))
1169 mode = MIN_MODE_VECTOR_FLOAT;
1170 else if (SCALAR_FRACT_MODE_P (inner_mode))
1171 mode = MIN_MODE_VECTOR_FRACT;
1172 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1173 mode = MIN_MODE_VECTOR_UFRACT;
1174 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1175 mode = MIN_MODE_VECTOR_ACCUM;
1176 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1177 mode = MIN_MODE_VECTOR_UACCUM;
1178 else
1179 mode = MIN_MODE_VECTOR_INT;
1181 FOR_EACH_MODE_FROM (mode, mode)
1182 if (GET_MODE_INNER (mode) == inner_mode
1183 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1184 && optab_handler (op, mode) != CODE_FOR_nothing)
1185 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1187 if (best_mode == VOIDmode)
1188 return NULL_TREE;
1189 else
1190 return build_vector_type_for_mode (type, best_mode);
1194 /* Build a reference to the element of the vector VECT. Function
1195 returns either the element itself, either BIT_FIELD_REF, or an
1196 ARRAY_REF expression.
1198 GSI is required to insert temporary variables while building a
1199 refernece to the element of the vector VECT.
1201 PTMPVEC is a pointer to the temporary variable for caching
1202 purposes. In case when PTMPVEC is NULL new temporary variable
1203 will be created. */
1204 static tree
1205 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1207 tree vect_type, vect_elt_type;
1208 gimple *asgn;
1209 tree tmpvec;
1210 tree arraytype;
1211 bool need_asgn = true;
1212 unsigned int elements;
1214 vect_type = TREE_TYPE (vect);
1215 vect_elt_type = TREE_TYPE (vect_type);
1216 elements = nunits_for_known_piecewise_op (vect_type);
1218 if (TREE_CODE (idx) == INTEGER_CST)
1220 unsigned HOST_WIDE_INT index;
1222 /* Given that we're about to compute a binary modulus,
1223 we don't care about the high bits of the value. */
1224 index = TREE_INT_CST_LOW (idx);
1225 if (!tree_fits_uhwi_p (idx) || index >= elements)
1227 index &= elements - 1;
1228 idx = build_int_cst (TREE_TYPE (idx), index);
1231 /* When lowering a vector statement sequence do some easy
1232 simplification by looking through intermediate vector results. */
1233 if (TREE_CODE (vect) == SSA_NAME)
1235 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1236 if (is_gimple_assign (def_stmt)
1237 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1238 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1239 vect = gimple_assign_rhs1 (def_stmt);
1242 if (TREE_CODE (vect) == VECTOR_CST)
1243 return VECTOR_CST_ELT (vect, index);
1244 else if (TREE_CODE (vect) == CONSTRUCTOR
1245 && (CONSTRUCTOR_NELTS (vect) == 0
1246 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1247 != VECTOR_TYPE))
1249 if (index < CONSTRUCTOR_NELTS (vect))
1250 return CONSTRUCTOR_ELT (vect, index)->value;
1251 return build_zero_cst (vect_elt_type);
1253 else
1255 tree size = TYPE_SIZE (vect_elt_type);
1256 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1257 size);
1258 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1262 if (!ptmpvec)
1263 tmpvec = create_tmp_var (vect_type, "vectmp");
1264 else if (!*ptmpvec)
1265 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1266 else
1268 tmpvec = *ptmpvec;
1269 need_asgn = false;
1272 if (need_asgn)
1274 TREE_ADDRESSABLE (tmpvec) = 1;
1275 asgn = gimple_build_assign (tmpvec, vect);
1276 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1279 arraytype = build_array_type_nelts (vect_elt_type, elements);
1280 return build4 (ARRAY_REF, vect_elt_type,
1281 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1282 idx, NULL_TREE, NULL_TREE);
1285 /* Check if VEC_PERM_EXPR within the given setting is supported
1286 by hardware, or lower it piecewise.
1288 When VEC_PERM_EXPR has the same first and second operands:
1289 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1290 {v0[mask[0]], v0[mask[1]], ...}
1291 MASK and V0 must have the same number of elements.
1293 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1294 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1295 V0 and V1 must have the same type. MASK, V0, V1 must have the
1296 same number of arguments. */
1298 static void
1299 lower_vec_perm (gimple_stmt_iterator *gsi)
1301 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1302 tree mask = gimple_assign_rhs3 (stmt);
1303 tree vec0 = gimple_assign_rhs1 (stmt);
1304 tree vec1 = gimple_assign_rhs2 (stmt);
1305 tree vect_type = TREE_TYPE (vec0);
1306 tree mask_type = TREE_TYPE (mask);
1307 tree vect_elt_type = TREE_TYPE (vect_type);
1308 tree mask_elt_type = TREE_TYPE (mask_type);
1309 unsigned HOST_WIDE_INT elements;
1310 vec<constructor_elt, va_gc> *v;
1311 tree constr, t, si, i_val;
1312 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1313 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1314 location_t loc = gimple_location (gsi_stmt (*gsi));
1315 unsigned i;
1317 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1318 return;
1320 if (TREE_CODE (mask) == SSA_NAME)
1322 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1323 if (is_gimple_assign (def_stmt)
1324 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1325 mask = gimple_assign_rhs1 (def_stmt);
1328 vec_perm_builder sel_int;
1330 if (TREE_CODE (mask) == VECTOR_CST
1331 && tree_to_vec_perm_builder (&sel_int, mask))
1333 vec_perm_indices indices (sel_int, 2, elements);
1334 if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices))
1336 gimple_assign_set_rhs3 (stmt, mask);
1337 update_stmt (stmt);
1338 return;
1340 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1341 vector as VEC1 and a right element shift MASK. */
1342 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1343 != CODE_FOR_nothing
1344 && TREE_CODE (vec1) == VECTOR_CST
1345 && initializer_zerop (vec1)
1346 && maybe_ne (indices[0], 0)
1347 && known_lt (poly_uint64 (indices[0]), elements))
1349 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1350 if (!ok_p)
1352 for (i = 1; i < elements; ++i)
1354 poly_uint64 actual = indices[i];
1355 poly_uint64 expected = i + indices[0];
1356 /* Indices into the second vector are all equivalent. */
1357 if (maybe_lt (actual, elements)
1358 ? maybe_ne (actual, expected)
1359 : maybe_lt (expected, elements))
1360 break;
1362 ok_p = i == elements;
1364 if (ok_p)
1366 gimple_assign_set_rhs3 (stmt, mask);
1367 update_stmt (stmt);
1368 return;
1372 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1373 return;
1375 warning_at (loc, OPT_Wvector_operation_performance,
1376 "vector shuffling operation will be expanded piecewise");
1378 vec_alloc (v, elements);
1379 for (i = 0; i < elements; i++)
1381 si = size_int (i);
1382 i_val = vector_element (gsi, mask, si, &masktmp);
1384 if (TREE_CODE (i_val) == INTEGER_CST)
1386 unsigned HOST_WIDE_INT index;
1388 index = TREE_INT_CST_LOW (i_val);
1389 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1390 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1392 if (two_operand_p && (index & elements) != 0)
1393 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1394 else
1395 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1397 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1398 true, GSI_SAME_STMT);
1400 else
1402 tree cond = NULL_TREE, v0_val;
1404 if (two_operand_p)
1406 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1407 build_int_cst (mask_elt_type, elements));
1408 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1409 true, GSI_SAME_STMT);
1412 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1413 build_int_cst (mask_elt_type, elements - 1));
1414 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1415 true, GSI_SAME_STMT);
1417 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1418 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1419 true, GSI_SAME_STMT);
1421 if (two_operand_p)
1423 tree v1_val;
1425 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1426 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1427 true, GSI_SAME_STMT);
1429 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1430 cond, build_zero_cst (mask_elt_type));
1431 cond = fold_build3 (COND_EXPR, vect_elt_type,
1432 cond, v0_val, v1_val);
1433 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1434 true, GSI_SAME_STMT);
1436 else
1437 t = v0_val;
1440 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1443 constr = build_constructor (vect_type, v);
1444 gimple_assign_set_rhs_from_tree (gsi, constr);
1445 update_stmt (gsi_stmt (*gsi));
1448 /* If OP is a uniform vector return the element it is a splat from. */
1450 static tree
1451 ssa_uniform_vector_p (tree op)
1453 if (TREE_CODE (op) == VECTOR_CST
1454 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1455 || TREE_CODE (op) == CONSTRUCTOR)
1456 return uniform_vector_p (op);
1457 if (TREE_CODE (op) == SSA_NAME)
1459 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1460 if (gimple_assign_single_p (def_stmt))
1461 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1463 return NULL_TREE;
1466 /* Return type in which CODE operation with optab OP can be
1467 computed. */
1469 static tree
1470 get_compute_type (enum tree_code code, optab op, tree type)
1472 /* For very wide vectors, try using a smaller vector mode. */
1473 tree compute_type = type;
1474 if (op
1475 && (!VECTOR_MODE_P (TYPE_MODE (type))
1476 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1478 tree vector_compute_type
1479 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1480 if (vector_compute_type != NULL_TREE
1481 && subparts_gt (compute_type, vector_compute_type)
1482 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1483 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1484 != CODE_FOR_nothing))
1485 compute_type = vector_compute_type;
1488 /* If we are breaking a BLKmode vector into smaller pieces,
1489 type_for_widest_vector_mode has already looked into the optab,
1490 so skip these checks. */
1491 if (compute_type == type)
1493 machine_mode compute_mode = TYPE_MODE (compute_type);
1494 if (VECTOR_MODE_P (compute_mode))
1496 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1497 return compute_type;
1498 if (code == MULT_HIGHPART_EXPR
1499 && can_mult_highpart_p (compute_mode,
1500 TYPE_UNSIGNED (compute_type)))
1501 return compute_type;
1503 /* There is no operation in hardware, so fall back to scalars. */
1504 compute_type = TREE_TYPE (type);
1507 return compute_type;
1510 static tree
1511 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1512 tree bitpos, tree bitsize, enum tree_code code,
1513 tree type ATTRIBUTE_UNUSED)
1515 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1516 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1517 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1518 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1519 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1520 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1523 /* Expand a vector COND_EXPR to scalars, piecewise. */
1524 static void
1525 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1527 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1528 tree type = gimple_expr_type (stmt);
1529 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1530 machine_mode compute_mode = TYPE_MODE (compute_type);
1531 gcc_assert (compute_mode != BLKmode);
1532 tree lhs = gimple_assign_lhs (stmt);
1533 tree rhs2 = gimple_assign_rhs2 (stmt);
1534 tree rhs3 = gimple_assign_rhs3 (stmt);
1535 tree new_rhs;
1537 /* If the compute mode is not a vector mode (hence we are not decomposing
1538 a BLKmode vector to smaller, hardware-supported vectors), we may want
1539 to expand the operations in parallel. */
1540 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
1541 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
1542 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
1543 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
1544 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
1545 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
1546 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1547 COND_EXPR);
1548 else
1549 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1550 rhs2, rhs3, COND_EXPR);
1551 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1552 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1553 new_rhs);
1555 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1556 way to do it is change expand_vector_operation and its callees to
1557 return a tree_code, RHS1 and RHS2 instead of a tree. */
1558 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1559 update_stmt (gsi_stmt (*gsi));
1562 /* Process one statement. If we identify a vector operation, expand it. */
1564 static void
1565 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
1567 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
1568 enum tree_code code;
1569 optab op = unknown_optab;
1570 enum gimple_rhs_class rhs_class;
1571 tree new_rhs;
1573 /* Only consider code == GIMPLE_ASSIGN. */
1574 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
1575 if (!stmt)
1576 return;
1578 code = gimple_assign_rhs_code (stmt);
1579 rhs_class = get_gimple_rhs_class (code);
1580 lhs = gimple_assign_lhs (stmt);
1582 if (code == VEC_PERM_EXPR)
1584 lower_vec_perm (gsi);
1585 return;
1588 if (code == VEC_COND_EXPR)
1590 expand_vector_condition (gsi);
1591 return;
1594 if (code == COND_EXPR
1595 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
1596 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
1598 expand_vector_scalar_condition (gsi);
1599 return;
1602 if (code == CONSTRUCTOR
1603 && TREE_CODE (lhs) == SSA_NAME
1604 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
1605 && !gimple_clobber_p (stmt)
1606 && optimize)
1608 optimize_vector_constructor (gsi);
1609 return;
1612 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1613 return;
1615 rhs1 = gimple_assign_rhs1 (stmt);
1616 type = gimple_expr_type (stmt);
1617 if (rhs_class == GIMPLE_BINARY_RHS)
1618 rhs2 = gimple_assign_rhs2 (stmt);
1620 if (!VECTOR_TYPE_P (type)
1621 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
1622 return;
1624 /* If the vector operation is operating on all same vector elements
1625 implement it with a scalar operation and a splat if the target
1626 supports the scalar operation. */
1627 tree srhs1, srhs2 = NULL_TREE;
1628 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
1629 && (rhs2 == NULL_TREE
1630 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
1631 && (srhs2 = rhs2))
1632 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
1633 /* As we query direct optabs restrict to non-convert operations. */
1634 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
1636 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
1637 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
1638 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
1640 tree slhs = make_ssa_name (TREE_TYPE (srhs1));
1641 gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
1642 gsi_insert_before (gsi, repl, GSI_SAME_STMT);
1643 gimple_assign_set_rhs_from_tree (gsi,
1644 build_vector_from_val (type, slhs));
1645 update_stmt (stmt);
1646 return;
1650 /* A scalar operation pretending to be a vector one. */
1651 if (VECTOR_BOOLEAN_TYPE_P (type)
1652 && !VECTOR_MODE_P (TYPE_MODE (type))
1653 && TYPE_MODE (type) != BLKmode)
1654 return;
1656 if (CONVERT_EXPR_CODE_P (code)
1657 || code == FLOAT_EXPR
1658 || code == FIX_TRUNC_EXPR
1659 || code == VIEW_CONVERT_EXPR)
1660 return;
1662 /* The signedness is determined from input argument. */
1663 if (code == VEC_UNPACK_FLOAT_HI_EXPR
1664 || code == VEC_UNPACK_FLOAT_LO_EXPR)
1666 type = TREE_TYPE (rhs1);
1667 /* We do not know how to scalarize those. */
1668 return;
1671 /* For widening/narrowing vector operations, the relevant type is of the
1672 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
1673 calculated in the same way above. */
1674 if (code == WIDEN_SUM_EXPR
1675 || code == VEC_WIDEN_MULT_HI_EXPR
1676 || code == VEC_WIDEN_MULT_LO_EXPR
1677 || code == VEC_WIDEN_MULT_EVEN_EXPR
1678 || code == VEC_WIDEN_MULT_ODD_EXPR
1679 || code == VEC_UNPACK_HI_EXPR
1680 || code == VEC_UNPACK_LO_EXPR
1681 || code == VEC_PACK_TRUNC_EXPR
1682 || code == VEC_PACK_SAT_EXPR
1683 || code == VEC_PACK_FIX_TRUNC_EXPR
1684 || code == VEC_WIDEN_LSHIFT_HI_EXPR
1685 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
1687 type = TREE_TYPE (rhs1);
1688 /* We do not know how to scalarize those. */
1689 return;
1692 /* Choose between vector shift/rotate by vector and vector shift/rotate by
1693 scalar */
1694 if (code == LSHIFT_EXPR
1695 || code == RSHIFT_EXPR
1696 || code == LROTATE_EXPR
1697 || code == RROTATE_EXPR)
1699 optab opv;
1701 /* Check whether we have vector <op> {x,x,x,x} where x
1702 could be a scalar variable or a constant. Transform
1703 vector <op> {x,x,x,x} ==> vector <op> scalar. */
1704 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1706 tree first;
1708 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
1710 gimple_assign_set_rhs2 (stmt, first);
1711 update_stmt (stmt);
1712 rhs2 = first;
1716 opv = optab_for_tree_code (code, type, optab_vector);
1717 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1718 op = opv;
1719 else
1721 op = optab_for_tree_code (code, type, optab_scalar);
1723 compute_type = get_compute_type (code, op, type);
1724 if (compute_type == type)
1725 return;
1726 /* The rtl expander will expand vector/scalar as vector/vector
1727 if necessary. Pick one with wider vector type. */
1728 tree compute_vtype = get_compute_type (code, opv, type);
1729 if (subparts_gt (compute_vtype, compute_type))
1731 compute_type = compute_vtype;
1732 op = opv;
1736 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
1738 if (compute_type == NULL_TREE)
1739 compute_type = get_compute_type (code, op, type);
1740 if (compute_type == type)
1741 return;
1742 /* Before splitting vector rotates into scalar rotates,
1743 see if we can't use vector shifts and BIT_IOR_EXPR
1744 instead. For vector by vector rotates we'd also
1745 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
1746 for now, fold doesn't seem to create such rotates anyway. */
1747 if (compute_type == TREE_TYPE (type)
1748 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1750 optab oplv = vashl_optab, opl = ashl_optab;
1751 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
1752 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
1753 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
1754 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
1755 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
1756 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
1757 /* The rtl expander will expand vector/scalar as vector/vector
1758 if necessary. Pick one with wider vector type. */
1759 if (subparts_gt (compute_lvtype, compute_ltype))
1761 compute_ltype = compute_lvtype;
1762 opl = oplv;
1764 if (subparts_gt (compute_rvtype, compute_rtype))
1766 compute_rtype = compute_rvtype;
1767 opr = oprv;
1769 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
1770 BIT_IOR_EXPR. */
1771 compute_type = compute_ltype;
1772 if (subparts_gt (compute_type, compute_rtype))
1773 compute_type = compute_rtype;
1774 if (subparts_gt (compute_type, compute_otype))
1775 compute_type = compute_otype;
1776 /* Verify all 3 operations can be performed in that type. */
1777 if (compute_type != TREE_TYPE (type))
1779 if (optab_handler (opl, TYPE_MODE (compute_type))
1780 == CODE_FOR_nothing
1781 || optab_handler (opr, TYPE_MODE (compute_type))
1782 == CODE_FOR_nothing
1783 || optab_handler (opo, TYPE_MODE (compute_type))
1784 == CODE_FOR_nothing)
1785 compute_type = TREE_TYPE (type);
1790 else
1791 op = optab_for_tree_code (code, type, optab_default);
1793 /* Optabs will try converting a negation into a subtraction, so
1794 look for it as well. TODO: negation of floating-point vectors
1795 might be turned into an exclusive OR toggling the sign bit. */
1796 if (op == unknown_optab
1797 && code == NEGATE_EXPR
1798 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
1799 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1801 if (compute_type == NULL_TREE)
1802 compute_type = get_compute_type (code, op, type);
1803 if (compute_type == type)
1804 return;
1806 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
1808 /* Leave expression untouched for later expansion. */
1809 if (new_rhs == NULL_TREE)
1810 return;
1812 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1813 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1814 new_rhs);
1816 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1817 way to do it is change expand_vector_operation and its callees to
1818 return a tree_code, RHS1 and RHS2 instead of a tree. */
1819 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1820 update_stmt (gsi_stmt (*gsi));
1823 /* Use this to lower vector operations introduced by the vectorizer,
1824 if it may need the bit-twiddling tricks implemented in this file. */
1826 static unsigned int
1827 expand_vector_operations (void)
1829 gimple_stmt_iterator gsi;
1830 basic_block bb;
1831 bool cfg_changed = false;
1833 FOR_EACH_BB_FN (bb, cfun)
1835 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1837 expand_vector_operations_1 (&gsi);
1838 /* ??? If we do not cleanup EH then we will ICE in
1839 verification. But in reality we have created wrong-code
1840 as we did not properly transition EH info and edges to
1841 the piecewise computations. */
1842 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
1843 && gimple_purge_dead_eh_edges (bb))
1844 cfg_changed = true;
1848 return cfg_changed ? TODO_cleanup_cfg : 0;
1851 namespace {
1853 const pass_data pass_data_lower_vector =
1855 GIMPLE_PASS, /* type */
1856 "veclower", /* name */
1857 OPTGROUP_VEC, /* optinfo_flags */
1858 TV_NONE, /* tv_id */
1859 PROP_cfg, /* properties_required */
1860 PROP_gimple_lvec, /* properties_provided */
1861 0, /* properties_destroyed */
1862 0, /* todo_flags_start */
1863 TODO_update_ssa, /* todo_flags_finish */
1866 class pass_lower_vector : public gimple_opt_pass
1868 public:
1869 pass_lower_vector (gcc::context *ctxt)
1870 : gimple_opt_pass (pass_data_lower_vector, ctxt)
1873 /* opt_pass methods: */
1874 virtual bool gate (function *fun)
1876 return !(fun->curr_properties & PROP_gimple_lvec);
1879 virtual unsigned int execute (function *)
1881 return expand_vector_operations ();
1884 }; // class pass_lower_vector
1886 } // anon namespace
1888 gimple_opt_pass *
1889 make_pass_lower_vector (gcc::context *ctxt)
1891 return new pass_lower_vector (ctxt);
1894 namespace {
1896 const pass_data pass_data_lower_vector_ssa =
1898 GIMPLE_PASS, /* type */
1899 "veclower2", /* name */
1900 OPTGROUP_VEC, /* optinfo_flags */
1901 TV_NONE, /* tv_id */
1902 PROP_cfg, /* properties_required */
1903 PROP_gimple_lvec, /* properties_provided */
1904 0, /* properties_destroyed */
1905 0, /* todo_flags_start */
1906 ( TODO_update_ssa
1907 | TODO_cleanup_cfg ), /* todo_flags_finish */
1910 class pass_lower_vector_ssa : public gimple_opt_pass
1912 public:
1913 pass_lower_vector_ssa (gcc::context *ctxt)
1914 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
1917 /* opt_pass methods: */
1918 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
1919 virtual unsigned int execute (function *)
1921 return expand_vector_operations ();
1924 }; // class pass_lower_vector_ssa
1926 } // anon namespace
1928 gimple_opt_pass *
1929 make_pass_lower_vector_ssa (gcc::context *ctxt)
1931 return new pass_lower_vector_ssa (ctxt);
1934 #include "gt-tree-vect-generic.h"