1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2013 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
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
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/>. */
22 #include "coretypes.h"
25 #include "langhooks.h"
27 #include "gimple-iterator.h"
28 #include "gimple-ssa.h"
30 #include "tree-ssanames.h"
31 #include "tree-iterator.h"
32 #include "tree-pass.h"
35 #include "diagnostic.h"
38 /* Need to include rtl.h, expr.h, etc. for optabs. */
43 static void expand_vector_operations_1 (gimple_stmt_iterator *);
46 /* Build a constant of type TYPE, made of VALUE's bits replicated
47 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
49 build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
51 int width = tree_low_cst (TYPE_SIZE (inner_type), 1);
52 int n = HOST_BITS_PER_WIDE_INT / width;
53 unsigned HOST_WIDE_INT low, high, mask;
58 if (width == HOST_BITS_PER_WIDE_INT)
62 mask = ((HOST_WIDE_INT)1 << width) - 1;
63 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
66 if (TYPE_PRECISION (type) < HOST_BITS_PER_WIDE_INT)
67 low &= ((HOST_WIDE_INT)1 << TYPE_PRECISION (type)) - 1, high = 0;
68 else if (TYPE_PRECISION (type) == HOST_BITS_PER_WIDE_INT)
70 else if (TYPE_PRECISION (type) == HOST_BITS_PER_DOUBLE_INT)
75 ret = build_int_cst_wide (type, low, high);
79 static GTY(()) tree vector_inner_type;
80 static GTY(()) tree vector_last_type;
81 static GTY(()) int vector_last_nunits;
83 /* Return a suitable vector types made of SUBPARTS units each of mode
84 "word_mode" (the global variable). */
86 build_word_mode_vector_type (int nunits)
88 if (!vector_inner_type)
89 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
90 else if (vector_last_nunits == nunits)
92 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
93 return vector_last_type;
96 /* We build a new type, but we canonicalize it nevertheless,
97 because it still saves some memory. */
98 vector_last_nunits = nunits;
99 vector_last_type = type_hash_canon (nunits,
100 build_vector_type (vector_inner_type,
102 return vector_last_type;
105 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
106 tree, tree, tree, tree, tree, enum tree_code);
109 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
110 tree t, tree bitsize, tree bitpos)
113 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
115 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
119 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
120 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
123 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
124 return gimplify_build1 (gsi, code, inner_type, a);
128 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
129 tree bitpos, tree bitsize, enum tree_code code)
131 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
132 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
133 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
134 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
135 return gimplify_build2 (gsi, code, inner_type, a, b);
138 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
140 INNER_TYPE is the type of A and B elements
142 returned expression is of signed integer type with the
143 size equal to the size of INNER_TYPE. */
145 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
146 tree bitpos, tree bitsize, enum tree_code code)
150 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
151 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
153 comp_type = build_nonstandard_integer_type
154 (GET_MODE_BITSIZE (TYPE_MODE (inner_type)), 0);
156 return gimplify_build3 (gsi, COND_EXPR, comp_type,
157 fold_build2 (code, boolean_type_node, a, b),
158 build_int_cst (comp_type, -1),
159 build_int_cst (comp_type, 0));
162 /* Expand vector addition to scalars. This does bit twiddling
163 in order to increase parallelism:
165 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
168 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
169 (a ^ ~b) & 0x80808080
171 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
173 This optimization should be done only if 4 vector items or more
176 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
177 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
180 tree inner_type = TREE_TYPE (TREE_TYPE (a));
181 unsigned HOST_WIDE_INT max;
182 tree low_bits, high_bits, a_low, b_low, result_low, signs;
184 max = GET_MODE_MASK (TYPE_MODE (inner_type));
185 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
186 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
188 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
189 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
191 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
192 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
193 if (code == PLUS_EXPR)
194 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
197 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
198 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
201 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
202 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
203 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
207 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
208 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
209 tree bitsize ATTRIBUTE_UNUSED,
210 enum tree_code code ATTRIBUTE_UNUSED)
212 tree inner_type = TREE_TYPE (TREE_TYPE (b));
214 tree low_bits, high_bits, b_low, result_low, signs;
216 max = GET_MODE_MASK (TYPE_MODE (inner_type));
217 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
218 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
220 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
222 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
223 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
224 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
225 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
226 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
229 /* Expand a vector operation to scalars, by using many operations
230 whose type is the vector type's inner type. */
232 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
233 tree type, tree inner_type,
234 tree a, tree b, enum tree_code code)
236 vec<constructor_elt, va_gc> *v;
237 tree part_width = TYPE_SIZE (inner_type);
238 tree index = bitsize_int (0);
239 int nunits = TYPE_VECTOR_SUBPARTS (type);
240 int delta = tree_low_cst (part_width, 1)
241 / tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
243 location_t loc = gimple_location (gsi_stmt (*gsi));
245 if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
246 warning_at (loc, OPT_Wvector_operation_performance,
247 "vector operation will be expanded piecewise");
249 warning_at (loc, OPT_Wvector_operation_performance,
250 "vector operation will be expanded in parallel");
252 vec_alloc (v, (nunits + delta - 1) / delta);
253 for (i = 0; i < nunits;
254 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
256 tree result = f (gsi, inner_type, a, b, index, part_width, code);
257 constructor_elt ce = {NULL_TREE, result};
261 return build_constructor (type, v);
264 /* Expand a vector operation to scalars with the freedom to use
265 a scalar integer type, or to use a different size for the items
266 in the vector type. */
268 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
272 tree result, compute_type;
273 enum machine_mode mode;
274 int n_words = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
275 location_t loc = gimple_location (gsi_stmt (*gsi));
277 /* We have three strategies. If the type is already correct, just do
278 the operation an element at a time. Else, if the vector is wider than
279 one word, do it a word at a time; finally, if the vector is smaller
280 than one word, do it as a scalar. */
281 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
282 return expand_vector_piecewise (gsi, f,
283 type, TREE_TYPE (type),
285 else if (n_words > 1)
287 tree word_type = build_word_mode_vector_type (n_words);
288 result = expand_vector_piecewise (gsi, f,
289 word_type, TREE_TYPE (word_type),
291 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
296 /* Use a single scalar operation with a mode no wider than word_mode. */
297 mode = mode_for_size (tree_low_cst (TYPE_SIZE (type), 1), MODE_INT, 0);
298 compute_type = lang_hooks.types.type_for_mode (mode, 1);
299 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
300 warning_at (loc, OPT_Wvector_operation_performance,
301 "vector operation will be expanded with a "
302 "single scalar operation");
308 /* Expand a vector operation to scalars; for integer types we can use
309 special bit twiddling tricks to do the sums a word at a time, using
310 function F_PARALLEL instead of F. These tricks are done only if
311 they can process at least four items, that is, only if the vector
312 holds at least four items and if a word can hold four items. */
314 expand_vector_addition (gimple_stmt_iterator *gsi,
315 elem_op_func f, elem_op_func f_parallel,
316 tree type, tree a, tree b, enum tree_code code)
318 int parts_per_word = UNITS_PER_WORD
319 / tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
321 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
322 && parts_per_word >= 4
323 && TYPE_VECTOR_SUBPARTS (type) >= 4)
324 return expand_vector_parallel (gsi, f_parallel,
327 return expand_vector_piecewise (gsi, f,
328 type, TREE_TYPE (type),
332 /* Try to expand vector comparison expression OP0 CODE OP1 by
333 querying optab if the following expression:
334 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
337 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
338 tree op1, enum tree_code code)
341 if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
342 t = expand_vector_piecewise (gsi, do_compare, type,
343 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
350 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
351 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
352 the result if successful, otherwise return NULL_TREE. */
354 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
357 unsigned int i, nunits = TYPE_VECTOR_SUBPARTS (type);
358 bool scalar_shift = true;
360 for (i = 1; i < nunits; i++)
362 if (shiftcnts[i] != shiftcnts[0])
363 scalar_shift = false;
366 if (scalar_shift && shiftcnts[0] == 0)
371 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
372 if (op != unknown_optab
373 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
374 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
375 build_int_cst (NULL_TREE, shiftcnts[0]));
378 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
379 if (op != unknown_optab
380 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
382 tree *vec = XALLOCAVEC (tree, nunits);
383 for (i = 0; i < nunits; i++)
384 vec[i] = build_int_cst (TREE_TYPE (type), shiftcnts[i]);
385 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
386 build_vector (type, vec));
392 /* Try to expand integer vector division by constant using
393 widening multiply, shifts and additions. */
395 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
396 tree op1, enum tree_code code)
398 bool use_pow2 = true;
399 bool has_vector_shift = true;
400 int mode = -1, this_mode;
401 int pre_shift = -1, post_shift;
402 unsigned int nunits = TYPE_VECTOR_SUBPARTS (type);
403 int *shifts = XALLOCAVEC (int, nunits * 4);
404 int *pre_shifts = shifts + nunits;
405 int *post_shifts = pre_shifts + nunits;
406 int *shift_temps = post_shifts + nunits;
407 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
408 int prec = TYPE_PRECISION (TREE_TYPE (type));
410 unsigned int i, unsignedp = TYPE_UNSIGNED (TREE_TYPE (type));
411 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
413 tree cur_op, mulcst, tem;
416 if (prec > HOST_BITS_PER_WIDE_INT)
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)
422 has_vector_shift = false;
424 /* Analysis phase. Determine if all op1 elements are either power
425 of two and it is possible to expand it using shifts (or for remainder
426 using masking). Additionally compute the multiplicative constants
427 and pre and post shifts if the division is to be expanded using
428 widening or high part multiplication plus shifts. */
429 for (i = 0; i < nunits; i++)
431 tree cst = VECTOR_CST_ELT (op1, i);
432 unsigned HOST_WIDE_INT ml;
434 if (!host_integerp (cst, unsignedp) || integer_zerop (cst))
440 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
444 shifts[i] = tree_log2 (cst);
445 if (shifts[i] != shifts[0]
446 && code == TRUNC_DIV_EXPR
447 && !has_vector_shift)
454 unsigned HOST_WIDE_INT mh;
455 unsigned HOST_WIDE_INT d = tree_low_cst (cst, 1) & mask;
457 if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
458 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
467 /* Find a suitable multiplier and right shift count
468 instead of multiplying with D. */
469 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
471 /* If the suggested multiplier is more than SIZE bits, we can
472 do better for even divisors, using an initial right shift. */
473 if ((mh != 0 && (d & 1) == 0)
474 || (!has_vector_shift && pre_shift != -1))
476 if (has_vector_shift)
477 pre_shift = floor_log2 (d & -d);
478 else if (pre_shift == -1)
481 for (j = 0; j < nunits; j++)
483 tree cst2 = VECTOR_CST_ELT (op1, j);
484 unsigned HOST_WIDE_INT d2;
487 if (!host_integerp (cst2, 1))
489 d2 = tree_low_cst (cst2, 1) & mask;
492 this_pre_shift = floor_log2 (d2 & -d2);
493 if (pre_shift == -1 || this_pre_shift < pre_shift)
494 pre_shift = this_pre_shift;
496 if (i != 0 && pre_shift != 0)
506 if ((d >> pre_shift) <= 1)
511 mh = choose_multiplier (d >> pre_shift, prec,
513 &ml, &post_shift, &dummy_int);
515 pre_shifts[i] = pre_shift;
525 HOST_WIDE_INT d = tree_low_cst (cst, 0);
526 unsigned HOST_WIDE_INT abs_d;
531 /* Since d might be INT_MIN, we have to cast to
532 unsigned HOST_WIDE_INT before negating to avoid
533 undefined signed overflow. */
535 ? (unsigned HOST_WIDE_INT) d
536 : - (unsigned HOST_WIDE_INT) d);
538 /* n rem d = n rem -d */
539 if (code == TRUNC_MOD_EXPR && d < 0)
541 else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (prec - 1))
543 /* This case is not handled correctly below. */
553 choose_multiplier (abs_d, prec, prec - 1, &ml,
554 &post_shift, &dummy_int);
555 if (ml >= (unsigned HOST_WIDE_INT) 1 << (prec - 1))
557 this_mode = 4 + (d < 0);
558 ml |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
561 this_mode = 2 + (d < 0);
564 post_shifts[i] = post_shift;
565 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
566 || post_shift >= prec
567 || pre_shifts[i] >= prec)
572 else if (mode != this_mode)
576 vec = XALLOCAVEC (tree, nunits);
580 tree addend = NULL_TREE;
585 /* Both division and remainder sequences need
586 op0 < 0 ? mask : 0 computed. It can be either computed as
587 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
588 if none of the shifts is 0, or as the conditional. */
589 for (i = 0; i < nunits; i++)
593 = build_vector_type (build_nonstandard_integer_type (prec, 1),
595 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
597 for (i = 0; i < nunits; i++)
598 shift_temps[i] = prec - 1;
599 cur_op = add_rshift (gsi, type, op0, shift_temps);
600 if (cur_op != NULL_TREE)
602 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
604 for (i = 0; i < nunits; i++)
605 shift_temps[i] = prec - shifts[i];
606 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
607 if (cur_op != NULL_TREE)
608 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
612 if (addend == NULL_TREE
613 && expand_vec_cond_expr_p (type, type))
615 tree zero, cst, cond;
618 zero = build_zero_cst (type);
619 cond = build2 (LT_EXPR, type, op0, zero);
620 for (i = 0; i < nunits; i++)
621 vec[i] = build_int_cst (TREE_TYPE (type),
622 ((unsigned HOST_WIDE_INT) 1
624 cst = build_vector (type, vec);
625 addend = make_ssa_name (type, NULL);
626 stmt = gimple_build_assign_with_ops (VEC_COND_EXPR, addend,
628 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
631 if (code == TRUNC_DIV_EXPR)
635 /* q = op0 >> shift; */
636 cur_op = add_rshift (gsi, type, op0, shifts);
637 if (cur_op != NULL_TREE)
640 else if (addend != NULL_TREE)
642 /* t1 = op0 + addend;
644 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
645 if (op != unknown_optab
646 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
648 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
649 cur_op = add_rshift (gsi, type, cur_op, shifts);
650 if (cur_op != NULL_TREE)
658 for (i = 0; i < nunits; i++)
659 vec[i] = build_int_cst (TREE_TYPE (type),
660 ((unsigned HOST_WIDE_INT) 1
662 mask = build_vector (type, vec);
663 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
664 if (op != unknown_optab
665 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
668 /* r = op0 & mask; */
669 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
670 else if (addend != NULL_TREE)
672 /* t1 = op0 + addend;
675 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
676 if (op != unknown_optab
677 && optab_handler (op, TYPE_MODE (type))
680 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
682 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
684 op = optab_for_tree_code (MINUS_EXPR, type,
686 if (op != unknown_optab
687 && optab_handler (op, TYPE_MODE (type))
689 return gimplify_build2 (gsi, MINUS_EXPR, type,
697 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
700 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
708 gcc_assert (unsignedp);
709 /* t1 = oprnd0 >> pre_shift;
711 q = t2 >> post_shift; */
712 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
713 if (cur_op == NULL_TREE)
717 gcc_assert (unsignedp);
718 for (i = 0; i < nunits; i++)
728 gcc_assert (!unsignedp);
729 for (i = 0; i < nunits; i++)
730 shift_temps[i] = prec - 1;
736 for (i = 0; i < nunits; i++)
737 vec[i] = build_int_cst (TREE_TYPE (type), mulc[i]);
738 mulcst = build_vector (type, vec);
740 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
745 /* t1 = oprnd0 >> pre_shift;
747 q = t2 >> post_shift; */
748 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
751 /* t1 = oprnd0 h* ml;
755 q = t4 >> (post_shift - 1); */
756 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
757 if (op == unknown_optab
758 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
760 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
761 tem = add_rshift (gsi, type, tem, shift_temps);
762 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
763 if (op == unknown_optab
764 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
766 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
767 cur_op = add_rshift (gsi, type, tem, post_shifts);
768 if (cur_op == NULL_TREE)
775 /* t1 = oprnd0 h* ml;
776 t2 = t1; [ iff (mode & 2) != 0 ]
777 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
778 t3 = t2 >> post_shift;
779 t4 = oprnd0 >> (prec - 1);
780 q = t3 - t4; [ iff (mode & 1) == 0 ]
781 q = t4 - t3; [ iff (mode & 1) != 0 ] */
784 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
785 if (op == unknown_optab
786 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
788 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
790 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
791 if (cur_op == NULL_TREE)
793 tem = add_rshift (gsi, type, op0, shift_temps);
794 if (tem == NULL_TREE)
796 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
797 if (op == unknown_optab
798 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
801 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
803 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
809 if (code == TRUNC_DIV_EXPR)
812 /* We divided. Now finish by:
815 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
816 if (op == unknown_optab
817 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
819 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
820 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
821 if (op == unknown_optab
822 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
824 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
827 /* Expand a vector condition to scalars, by using many conditions
828 on the vector's elements. */
830 expand_vector_condition (gimple_stmt_iterator *gsi)
832 gimple stmt = gsi_stmt (*gsi);
833 tree type = gimple_expr_type (stmt);
834 tree a = gimple_assign_rhs1 (stmt);
837 bool a_is_comparison = false;
838 tree b = gimple_assign_rhs2 (stmt);
839 tree c = gimple_assign_rhs3 (stmt);
840 vec<constructor_elt, va_gc> *v;
842 tree inner_type = TREE_TYPE (type);
843 tree cond_type = TREE_TYPE (TREE_TYPE (a));
844 tree comp_inner_type = cond_type;
845 tree width = TYPE_SIZE (inner_type);
846 tree index = bitsize_int (0);
847 int nunits = TYPE_VECTOR_SUBPARTS (type);
849 location_t loc = gimple_location (gsi_stmt (*gsi));
851 if (!is_gimple_val (a))
853 gcc_assert (COMPARISON_CLASS_P (a));
854 a_is_comparison = true;
855 a1 = TREE_OPERAND (a, 0);
856 a2 = TREE_OPERAND (a, 1);
857 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
860 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1)))
863 /* TODO: try and find a smaller vector type. */
865 warning_at (loc, OPT_Wvector_operation_performance,
866 "vector condition will be expanded piecewise");
868 vec_alloc (v, nunits);
869 for (i = 0; i < nunits;
870 i++, index = int_const_binop (PLUS_EXPR, index, width))
873 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
874 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
877 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index);
878 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index);
879 aa = build2 (TREE_CODE (a), cond_type, aa1, aa2);
882 aa = tree_vec_extract (gsi, cond_type, a, width, index);
883 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
884 constructor_elt ce = {NULL_TREE, result};
888 constr = build_constructor (type, v);
889 gimple_assign_set_rhs_from_tree (gsi, constr);
890 update_stmt (gsi_stmt (*gsi));
894 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
895 gimple assign, enum tree_code code)
897 enum machine_mode compute_mode = TYPE_MODE (compute_type);
899 /* If the compute mode is not a vector mode (hence we are not decomposing
900 a BLKmode vector to smaller, hardware-supported vectors), we may want
901 to expand the operations in parallel. */
902 if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
903 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
904 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
905 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
906 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
907 && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
912 if (!TYPE_OVERFLOW_TRAPS (type))
913 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
914 gimple_assign_rhs1 (assign),
915 gimple_assign_rhs2 (assign), code);
919 if (!TYPE_OVERFLOW_TRAPS (type))
920 return expand_vector_addition (gsi, do_unop, do_negate, type,
921 gimple_assign_rhs1 (assign),
928 return expand_vector_parallel (gsi, do_binop, type,
929 gimple_assign_rhs1 (assign),
930 gimple_assign_rhs2 (assign), code);
933 return expand_vector_parallel (gsi, do_unop, type,
934 gimple_assign_rhs1 (assign),
951 tree rhs1 = gimple_assign_rhs1 (assign);
952 tree rhs2 = gimple_assign_rhs2 (assign);
954 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
960 tree rhs1 = gimple_assign_rhs1 (assign);
961 tree rhs2 = gimple_assign_rhs2 (assign);
965 || !VECTOR_INTEGER_TYPE_P (type)
966 || TREE_CODE (rhs2) != VECTOR_CST)
969 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
970 if (ret != NULL_TREE)
979 if (TREE_CODE_CLASS (code) == tcc_unary)
980 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
981 gimple_assign_rhs1 (assign),
984 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
985 gimple_assign_rhs1 (assign),
986 gimple_assign_rhs2 (assign), code);
989 /* Return a type for the widest vector mode whose components are of type
990 TYPE, or NULL_TREE if none is found. */
993 type_for_widest_vector_mode (tree type, optab op)
995 enum machine_mode inner_mode = TYPE_MODE (type);
996 enum machine_mode best_mode = VOIDmode, mode;
999 if (SCALAR_FLOAT_MODE_P (inner_mode))
1000 mode = MIN_MODE_VECTOR_FLOAT;
1001 else if (SCALAR_FRACT_MODE_P (inner_mode))
1002 mode = MIN_MODE_VECTOR_FRACT;
1003 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1004 mode = MIN_MODE_VECTOR_UFRACT;
1005 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1006 mode = MIN_MODE_VECTOR_ACCUM;
1007 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1008 mode = MIN_MODE_VECTOR_UACCUM;
1010 mode = MIN_MODE_VECTOR_INT;
1012 for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
1013 if (GET_MODE_INNER (mode) == inner_mode
1014 && GET_MODE_NUNITS (mode) > best_nunits
1015 && optab_handler (op, mode) != CODE_FOR_nothing)
1016 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1018 if (best_mode == VOIDmode)
1021 return build_vector_type_for_mode (type, best_mode);
1025 /* Build a reference to the element of the vector VECT. Function
1026 returns either the element itself, either BIT_FIELD_REF, or an
1027 ARRAY_REF expression.
1029 GSI is required to insert temporary variables while building a
1030 refernece to the element of the vector VECT.
1032 PTMPVEC is a pointer to the temporary variable for caching
1033 purposes. In case when PTMPVEC is NULL new temporary variable
1036 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1038 tree vect_type, vect_elt_type;
1042 bool need_asgn = true;
1043 unsigned int elements;
1045 vect_type = TREE_TYPE (vect);
1046 vect_elt_type = TREE_TYPE (vect_type);
1047 elements = TYPE_VECTOR_SUBPARTS (vect_type);
1049 if (TREE_CODE (idx) == INTEGER_CST)
1051 unsigned HOST_WIDE_INT index;
1053 /* Given that we're about to compute a binary modulus,
1054 we don't care about the high bits of the value. */
1055 index = TREE_INT_CST_LOW (idx);
1056 if (!host_integerp (idx, 1) || index >= elements)
1058 index &= elements - 1;
1059 idx = build_int_cst (TREE_TYPE (idx), index);
1062 /* When lowering a vector statement sequence do some easy
1063 simplification by looking through intermediate vector results. */
1064 if (TREE_CODE (vect) == SSA_NAME)
1066 gimple def_stmt = SSA_NAME_DEF_STMT (vect);
1067 if (is_gimple_assign (def_stmt)
1068 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1069 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1070 vect = gimple_assign_rhs1 (def_stmt);
1073 if (TREE_CODE (vect) == VECTOR_CST)
1074 return VECTOR_CST_ELT (vect, index);
1075 else if (TREE_CODE (vect) == CONSTRUCTOR
1076 && (CONSTRUCTOR_NELTS (vect) == 0
1077 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1080 if (index < CONSTRUCTOR_NELTS (vect))
1081 return CONSTRUCTOR_ELT (vect, index)->value;
1082 return build_zero_cst (vect_elt_type);
1086 tree size = TYPE_SIZE (vect_elt_type);
1087 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1089 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1094 tmpvec = create_tmp_var (vect_type, "vectmp");
1096 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1105 TREE_ADDRESSABLE (tmpvec) = 1;
1106 asgn = gimple_build_assign (tmpvec, vect);
1107 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1110 arraytype = build_array_type_nelts (vect_elt_type, elements);
1111 return build4 (ARRAY_REF, vect_elt_type,
1112 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1113 idx, NULL_TREE, NULL_TREE);
1116 /* Check if VEC_PERM_EXPR within the given setting is supported
1117 by hardware, or lower it piecewise.
1119 When VEC_PERM_EXPR has the same first and second operands:
1120 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1121 {v0[mask[0]], v0[mask[1]], ...}
1122 MASK and V0 must have the same number of elements.
1124 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1125 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1126 V0 and V1 must have the same type. MASK, V0, V1 must have the
1127 same number of arguments. */
1130 lower_vec_perm (gimple_stmt_iterator *gsi)
1132 gimple stmt = gsi_stmt (*gsi);
1133 tree mask = gimple_assign_rhs3 (stmt);
1134 tree vec0 = gimple_assign_rhs1 (stmt);
1135 tree vec1 = gimple_assign_rhs2 (stmt);
1136 tree vect_type = TREE_TYPE (vec0);
1137 tree mask_type = TREE_TYPE (mask);
1138 tree vect_elt_type = TREE_TYPE (vect_type);
1139 tree mask_elt_type = TREE_TYPE (mask_type);
1140 unsigned int elements = TYPE_VECTOR_SUBPARTS (vect_type);
1141 vec<constructor_elt, va_gc> *v;
1142 tree constr, t, si, i_val;
1143 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1144 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1145 location_t loc = gimple_location (gsi_stmt (*gsi));
1148 if (TREE_CODE (mask) == SSA_NAME)
1150 gimple def_stmt = SSA_NAME_DEF_STMT (mask);
1151 if (is_gimple_assign (def_stmt)
1152 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1153 mask = gimple_assign_rhs1 (def_stmt);
1156 if (TREE_CODE (mask) == VECTOR_CST)
1158 unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
1160 for (i = 0; i < elements; ++i)
1161 sel_int[i] = (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
1162 & (2 * elements - 1));
1164 if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
1166 gimple_assign_set_rhs3 (stmt, mask);
1171 else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
1174 warning_at (loc, OPT_Wvector_operation_performance,
1175 "vector shuffling operation will be expanded piecewise");
1177 vec_alloc (v, elements);
1178 for (i = 0; i < elements; i++)
1181 i_val = vector_element (gsi, mask, si, &masktmp);
1183 if (TREE_CODE (i_val) == INTEGER_CST)
1185 unsigned HOST_WIDE_INT index;
1187 index = TREE_INT_CST_LOW (i_val);
1188 if (!host_integerp (i_val, 1) || index >= elements)
1189 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1191 if (two_operand_p && (index & elements) != 0)
1192 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1194 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1196 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1197 true, GSI_SAME_STMT);
1201 tree cond = NULL_TREE, v0_val;
1205 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1206 build_int_cst (mask_elt_type, elements));
1207 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1208 true, GSI_SAME_STMT);
1211 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1212 build_int_cst (mask_elt_type, elements - 1));
1213 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1214 true, GSI_SAME_STMT);
1216 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1217 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1218 true, GSI_SAME_STMT);
1224 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1225 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1226 true, GSI_SAME_STMT);
1228 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1229 cond, build_zero_cst (mask_elt_type));
1230 cond = fold_build3 (COND_EXPR, vect_elt_type,
1231 cond, v0_val, v1_val);
1232 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1233 true, GSI_SAME_STMT);
1239 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1242 constr = build_constructor (vect_type, v);
1243 gimple_assign_set_rhs_from_tree (gsi, constr);
1244 update_stmt (gsi_stmt (*gsi));
1247 /* Process one statement. If we identify a vector operation, expand it. */
1250 expand_vector_operations_1 (gimple_stmt_iterator *gsi)
1252 gimple stmt = gsi_stmt (*gsi);
1253 tree lhs, rhs1, rhs2 = NULL, type, compute_type;
1254 enum tree_code code;
1255 enum machine_mode compute_mode;
1256 optab op = unknown_optab;
1257 enum gimple_rhs_class rhs_class;
1260 if (gimple_code (stmt) != GIMPLE_ASSIGN)
1263 code = gimple_assign_rhs_code (stmt);
1264 rhs_class = get_gimple_rhs_class (code);
1265 lhs = gimple_assign_lhs (stmt);
1267 if (code == VEC_PERM_EXPR)
1269 lower_vec_perm (gsi);
1273 if (code == VEC_COND_EXPR)
1275 expand_vector_condition (gsi);
1278 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1281 rhs1 = gimple_assign_rhs1 (stmt);
1282 type = gimple_expr_type (stmt);
1283 if (rhs_class == GIMPLE_BINARY_RHS)
1284 rhs2 = gimple_assign_rhs2 (stmt);
1286 if (TREE_CODE (type) != VECTOR_TYPE)
1289 if (code == NOP_EXPR
1290 || code == FLOAT_EXPR
1291 || code == FIX_TRUNC_EXPR
1292 || code == VIEW_CONVERT_EXPR)
1295 gcc_assert (code != CONVERT_EXPR);
1297 /* The signedness is determined from input argument. */
1298 if (code == VEC_UNPACK_FLOAT_HI_EXPR
1299 || code == VEC_UNPACK_FLOAT_LO_EXPR)
1300 type = TREE_TYPE (rhs1);
1302 /* For widening/narrowing vector operations, the relevant type is of the
1303 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
1304 calculated in the same way above. */
1305 if (code == WIDEN_SUM_EXPR
1306 || code == VEC_WIDEN_MULT_HI_EXPR
1307 || code == VEC_WIDEN_MULT_LO_EXPR
1308 || code == VEC_WIDEN_MULT_EVEN_EXPR
1309 || code == VEC_WIDEN_MULT_ODD_EXPR
1310 || code == VEC_UNPACK_HI_EXPR
1311 || code == VEC_UNPACK_LO_EXPR
1312 || code == VEC_PACK_TRUNC_EXPR
1313 || code == VEC_PACK_SAT_EXPR
1314 || code == VEC_PACK_FIX_TRUNC_EXPR
1315 || code == VEC_WIDEN_LSHIFT_HI_EXPR
1316 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
1317 type = TREE_TYPE (rhs1);
1319 /* Choose between vector shift/rotate by vector and vector shift/rotate by
1321 if (code == LSHIFT_EXPR
1322 || code == RSHIFT_EXPR
1323 || code == LROTATE_EXPR
1324 || code == RROTATE_EXPR)
1328 /* Check whether we have vector <op> {x,x,x,x} where x
1329 could be a scalar variable or a constant. Transform
1330 vector <op> {x,x,x,x} ==> vector <op> scalar. */
1331 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1336 if ((TREE_CODE (rhs2) == VECTOR_CST
1337 && (first = uniform_vector_p (rhs2)) != NULL_TREE)
1338 || (TREE_CODE (rhs2) == SSA_NAME
1339 && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
1340 && gimple_assign_single_p (def_stmt)
1341 && (first = uniform_vector_p
1342 (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))
1344 gimple_assign_set_rhs2 (stmt, first);
1350 opv = optab_for_tree_code (code, type, optab_vector);
1351 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1355 op = optab_for_tree_code (code, type, optab_scalar);
1357 /* The rtl expander will expand vector/scalar as vector/vector
1358 if necessary. Don't bother converting the stmt here. */
1359 if (optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing
1360 && optab_handler (opv, TYPE_MODE (type)) != CODE_FOR_nothing)
1365 op = optab_for_tree_code (code, type, optab_default);
1367 /* Optabs will try converting a negation into a subtraction, so
1368 look for it as well. TODO: negation of floating-point vectors
1369 might be turned into an exclusive OR toggling the sign bit. */
1370 if (op == unknown_optab
1371 && code == NEGATE_EXPR
1372 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
1373 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1375 /* For very wide vectors, try using a smaller vector mode. */
1376 compute_type = type;
1377 if (!VECTOR_MODE_P (TYPE_MODE (type)) && op)
1379 tree vector_compute_type
1380 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1381 if (vector_compute_type != NULL_TREE
1382 && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
1383 < TYPE_VECTOR_SUBPARTS (compute_type))
1384 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1385 != CODE_FOR_nothing))
1386 compute_type = vector_compute_type;
1389 /* If we are breaking a BLKmode vector into smaller pieces,
1390 type_for_widest_vector_mode has already looked into the optab,
1391 so skip these checks. */
1392 if (compute_type == type)
1394 compute_mode = TYPE_MODE (compute_type);
1395 if (VECTOR_MODE_P (compute_mode))
1397 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1399 if (code == MULT_HIGHPART_EXPR
1400 && can_mult_highpart_p (compute_mode,
1401 TYPE_UNSIGNED (compute_type)))
1404 /* There is no operation in hardware, so fall back to scalars. */
1405 compute_type = TREE_TYPE (type);
1408 gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
1409 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
1411 /* Leave expression untouched for later expansion. */
1412 if (new_rhs == NULL_TREE)
1415 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1416 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1419 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1420 way to do it is change expand_vector_operation and its callees to
1421 return a tree_code, RHS1 and RHS2 instead of a tree. */
1422 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1423 update_stmt (gsi_stmt (*gsi));
1426 /* Use this to lower vector operations introduced by the vectorizer,
1427 if it may need the bit-twiddling tricks implemented in this file. */
1430 gate_expand_vector_operations_ssa (void)
1432 return !(cfun->curr_properties & PROP_gimple_lvec);
1436 expand_vector_operations (void)
1438 gimple_stmt_iterator gsi;
1440 bool cfg_changed = false;
1444 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1446 expand_vector_operations_1 (&gsi);
1447 /* ??? If we do not cleanup EH then we will ICE in
1448 verification. But in reality we have created wrong-code
1449 as we did not properly transition EH info and edges to
1450 the piecewise computations. */
1451 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
1452 && gimple_purge_dead_eh_edges (bb))
1457 return cfg_changed ? TODO_cleanup_cfg : 0;
1462 const pass_data pass_data_lower_vector =
1464 GIMPLE_PASS, /* type */
1465 "veclower", /* name */
1466 OPTGROUP_VEC, /* optinfo_flags */
1467 true, /* has_gate */
1468 true, /* has_execute */
1469 TV_NONE, /* tv_id */
1470 PROP_cfg, /* properties_required */
1471 PROP_gimple_lvec, /* properties_provided */
1472 0, /* properties_destroyed */
1473 0, /* todo_flags_start */
1474 ( TODO_update_ssa | TODO_verify_ssa
1477 | TODO_cleanup_cfg ), /* todo_flags_finish */
1480 class pass_lower_vector : public gimple_opt_pass
1483 pass_lower_vector (gcc::context *ctxt)
1484 : gimple_opt_pass (pass_data_lower_vector, ctxt)
1487 /* opt_pass methods: */
1488 bool gate () { return gate_expand_vector_operations_ssa (); }
1489 unsigned int execute () { return expand_vector_operations (); }
1491 }; // class pass_lower_vector
1496 make_pass_lower_vector (gcc::context *ctxt)
1498 return new pass_lower_vector (ctxt);
1503 const pass_data pass_data_lower_vector_ssa =
1505 GIMPLE_PASS, /* type */
1506 "veclower2", /* name */
1507 OPTGROUP_VEC, /* optinfo_flags */
1508 false, /* has_gate */
1509 true, /* has_execute */
1510 TV_NONE, /* tv_id */
1511 PROP_cfg, /* properties_required */
1512 PROP_gimple_lvec, /* properties_provided */
1513 0, /* properties_destroyed */
1514 0, /* todo_flags_start */
1515 ( TODO_update_ssa | TODO_verify_ssa
1518 | TODO_cleanup_cfg ), /* todo_flags_finish */
1521 class pass_lower_vector_ssa : public gimple_opt_pass
1524 pass_lower_vector_ssa (gcc::context *ctxt)
1525 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
1528 /* opt_pass methods: */
1529 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
1530 unsigned int execute () { return expand_vector_operations (); }
1532 }; // class pass_lower_vector_ssa
1537 make_pass_lower_vector_ssa (gcc::context *ctxt)
1539 return new pass_lower_vector_ssa (ctxt);
1542 #include "gt-tree-vect-generic.h"