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