Suppress -fstack-protector warning on hppa.
[official-gcc.git] / gcc / tree-vect-generic.cc
blob6ad6372c55eef94a742a8fa35e79d66aa24e2f3b
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 /* Check if the target was going to handle it through the special
1241 division callback hook. */
1242 tree cst = uniform_integer_cst_p (rhs2);
1243 if (cst &&
1244 targetm.vectorize.can_special_div_by_const (code, type,
1245 wi::to_wide (cst),
1246 NULL,
1247 NULL_RTX, NULL_RTX))
1248 return NULL_TREE;
1251 if (!optimize
1252 || !VECTOR_INTEGER_TYPE_P (type)
1253 || TREE_CODE (rhs2) != VECTOR_CST
1254 || !VECTOR_MODE_P (TYPE_MODE (type)))
1255 break;
1257 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1258 if (ret != NULL_TREE)
1259 return ret;
1260 break;
1263 default:
1264 break;
1267 if (TREE_CODE_CLASS (code) == tcc_unary)
1268 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1269 gimple_assign_rhs1 (assign),
1270 NULL_TREE, code, false);
1271 else
1272 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1273 gimple_assign_rhs1 (assign),
1274 gimple_assign_rhs2 (assign), code, false);
1277 /* Try to optimize
1278 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1279 style stmts into:
1280 _9 = { b_7, b_7, b_7, b_7 };
1281 a_5 = _9 + { 0, 3, 6, 9 };
1282 because vector splat operation is usually more efficient
1283 than piecewise initialization of the vector. */
1285 static void
1286 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1288 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1289 tree lhs = gimple_assign_lhs (stmt);
1290 tree rhs = gimple_assign_rhs1 (stmt);
1291 tree type = TREE_TYPE (rhs);
1292 unsigned int i, j;
1293 unsigned HOST_WIDE_INT nelts;
1294 bool all_same = true;
1295 constructor_elt *elt;
1296 gimple *g;
1297 tree base = NULL_TREE;
1298 optab op;
1300 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1301 || nelts <= 2
1302 || CONSTRUCTOR_NELTS (rhs) != nelts)
1303 return;
1304 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1305 if (op == unknown_optab
1306 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1307 return;
1308 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1309 if (TREE_CODE (elt->value) != SSA_NAME
1310 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1311 return;
1312 else
1314 tree this_base = elt->value;
1315 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1316 all_same = false;
1317 for (j = 0; j < nelts + 1; j++)
1319 g = SSA_NAME_DEF_STMT (this_base);
1320 if (is_gimple_assign (g)
1321 && gimple_assign_rhs_code (g) == PLUS_EXPR
1322 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1323 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1324 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1325 this_base = gimple_assign_rhs1 (g);
1326 else
1327 break;
1329 if (i == 0)
1330 base = this_base;
1331 else if (this_base != base)
1332 return;
1334 if (all_same)
1335 return;
1336 tree_vector_builder cst (type, nelts, 1);
1337 for (i = 0; i < nelts; i++)
1339 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1340 tree elt = build_zero_cst (TREE_TYPE (base));
1341 while (this_base != base)
1343 g = SSA_NAME_DEF_STMT (this_base);
1344 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1345 elt, gimple_assign_rhs2 (g));
1346 if (elt == NULL_TREE
1347 || TREE_CODE (elt) != INTEGER_CST
1348 || TREE_OVERFLOW (elt))
1349 return;
1350 this_base = gimple_assign_rhs1 (g);
1352 cst.quick_push (elt);
1354 for (i = 0; i < nelts; i++)
1355 CONSTRUCTOR_ELT (rhs, i)->value = base;
1356 g = gimple_build_assign (make_ssa_name (type), rhs);
1357 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1358 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1359 cst.build ());
1360 gsi_replace (gsi, g, false);
1363 /* Return a type for the widest vector mode whose components are of type
1364 TYPE, or NULL_TREE if none is found. */
1366 static tree
1367 type_for_widest_vector_mode (tree type, optab op)
1369 machine_mode inner_mode = TYPE_MODE (type);
1370 machine_mode best_mode = VOIDmode, mode;
1371 poly_int64 best_nunits = 0;
1373 if (SCALAR_FLOAT_MODE_P (inner_mode))
1374 mode = MIN_MODE_VECTOR_FLOAT;
1375 else if (SCALAR_FRACT_MODE_P (inner_mode))
1376 mode = MIN_MODE_VECTOR_FRACT;
1377 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1378 mode = MIN_MODE_VECTOR_UFRACT;
1379 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1380 mode = MIN_MODE_VECTOR_ACCUM;
1381 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1382 mode = MIN_MODE_VECTOR_UACCUM;
1383 else if (inner_mode == BImode)
1384 mode = MIN_MODE_VECTOR_BOOL;
1385 else
1386 mode = MIN_MODE_VECTOR_INT;
1388 FOR_EACH_MODE_FROM (mode, mode)
1389 if (GET_MODE_INNER (mode) == inner_mode
1390 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1391 && optab_handler (op, mode) != CODE_FOR_nothing)
1392 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1394 if (best_mode == VOIDmode)
1395 return NULL_TREE;
1396 else
1397 return build_vector_type_for_mode (type, best_mode);
1401 /* Build a reference to the element of the vector VECT. Function
1402 returns either the element itself, either BIT_FIELD_REF, or an
1403 ARRAY_REF expression.
1405 GSI is required to insert temporary variables while building a
1406 refernece to the element of the vector VECT.
1408 PTMPVEC is a pointer to the temporary variable for caching
1409 purposes. In case when PTMPVEC is NULL new temporary variable
1410 will be created. */
1411 static tree
1412 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1414 tree vect_type, vect_elt_type;
1415 gimple *asgn;
1416 tree tmpvec;
1417 tree arraytype;
1418 bool need_asgn = true;
1419 unsigned int elements;
1421 vect_type = TREE_TYPE (vect);
1422 vect_elt_type = TREE_TYPE (vect_type);
1423 elements = nunits_for_known_piecewise_op (vect_type);
1425 if (TREE_CODE (idx) == INTEGER_CST)
1427 unsigned HOST_WIDE_INT index;
1429 /* Given that we're about to compute a binary modulus,
1430 we don't care about the high bits of the value. */
1431 index = TREE_INT_CST_LOW (idx);
1432 if (!tree_fits_uhwi_p (idx) || index >= elements)
1434 index &= elements - 1;
1435 idx = build_int_cst (TREE_TYPE (idx), index);
1438 /* When lowering a vector statement sequence do some easy
1439 simplification by looking through intermediate vector results. */
1440 if (TREE_CODE (vect) == SSA_NAME)
1442 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1443 if (is_gimple_assign (def_stmt)
1444 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1445 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1446 vect = gimple_assign_rhs1 (def_stmt);
1449 if (TREE_CODE (vect) == VECTOR_CST)
1450 return VECTOR_CST_ELT (vect, index);
1451 else if (TREE_CODE (vect) == CONSTRUCTOR
1452 && (CONSTRUCTOR_NELTS (vect) == 0
1453 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1454 != VECTOR_TYPE))
1456 if (index < CONSTRUCTOR_NELTS (vect))
1457 return CONSTRUCTOR_ELT (vect, index)->value;
1458 return build_zero_cst (vect_elt_type);
1460 else
1462 tree size = vector_element_bits_tree (vect_type);
1463 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1464 size);
1465 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1469 if (!ptmpvec)
1470 tmpvec = create_tmp_var (vect_type, "vectmp");
1471 else if (!*ptmpvec)
1472 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1473 else
1475 tmpvec = *ptmpvec;
1476 need_asgn = false;
1479 if (need_asgn)
1481 TREE_ADDRESSABLE (tmpvec) = 1;
1482 asgn = gimple_build_assign (tmpvec, vect);
1483 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1486 arraytype = build_array_type_nelts (vect_elt_type, elements);
1487 return build4 (ARRAY_REF, vect_elt_type,
1488 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1489 idx, NULL_TREE, NULL_TREE);
1492 /* Check if VEC_PERM_EXPR within the given setting is supported
1493 by hardware, or lower it piecewise.
1495 When VEC_PERM_EXPR has the same first and second operands:
1496 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1497 {v0[mask[0]], v0[mask[1]], ...}
1498 MASK and V0 must have the same number of elements.
1500 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1501 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1502 V0 and V1 must have the same type. MASK, V0, V1 must have the
1503 same number of arguments. */
1505 static void
1506 lower_vec_perm (gimple_stmt_iterator *gsi)
1508 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1509 tree mask = gimple_assign_rhs3 (stmt);
1510 tree vec0 = gimple_assign_rhs1 (stmt);
1511 tree vec1 = gimple_assign_rhs2 (stmt);
1512 tree vect_type = TREE_TYPE (vec0);
1513 tree mask_type = TREE_TYPE (mask);
1514 tree vect_elt_type = TREE_TYPE (vect_type);
1515 tree mask_elt_type = TREE_TYPE (mask_type);
1516 unsigned HOST_WIDE_INT elements;
1517 vec<constructor_elt, va_gc> *v;
1518 tree constr, t, si, i_val;
1519 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1520 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1521 location_t loc = gimple_location (gsi_stmt (*gsi));
1522 unsigned i;
1524 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1525 return;
1527 if (TREE_CODE (mask) == SSA_NAME)
1529 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1530 if (is_gimple_assign (def_stmt)
1531 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1532 mask = gimple_assign_rhs1 (def_stmt);
1535 vec_perm_builder sel_int;
1537 if (TREE_CODE (mask) == VECTOR_CST
1538 && tree_to_vec_perm_builder (&sel_int, mask))
1540 vec_perm_indices indices (sel_int, 2, elements);
1541 machine_mode vmode = TYPE_MODE (vect_type);
1542 tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
1543 machine_mode lhs_mode = TYPE_MODE (lhs_type);
1544 if (can_vec_perm_const_p (lhs_mode, vmode, indices))
1546 gimple_assign_set_rhs3 (stmt, mask);
1547 update_stmt (stmt);
1548 return;
1550 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1551 vector as VEC1 and a right element shift MASK. */
1552 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1553 != CODE_FOR_nothing
1554 && TREE_CODE (vec1) == VECTOR_CST
1555 && initializer_zerop (vec1)
1556 && maybe_ne (indices[0], 0)
1557 && known_lt (poly_uint64 (indices[0]), elements))
1559 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1560 if (!ok_p)
1562 for (i = 1; i < elements; ++i)
1564 poly_uint64 actual = indices[i];
1565 poly_uint64 expected = i + indices[0];
1566 /* Indices into the second vector are all equivalent. */
1567 if (maybe_lt (actual, elements)
1568 ? maybe_ne (actual, expected)
1569 : maybe_lt (expected, elements))
1570 break;
1572 ok_p = i == elements;
1574 if (ok_p)
1576 gimple_assign_set_rhs3 (stmt, mask);
1577 update_stmt (stmt);
1578 return;
1581 /* And similarly vec_shl pattern. */
1582 if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
1583 != CODE_FOR_nothing
1584 && TREE_CODE (vec0) == VECTOR_CST
1585 && initializer_zerop (vec0))
1587 unsigned int first = 0;
1588 for (i = 0; i < elements; ++i)
1589 if (known_eq (poly_uint64 (indices[i]), elements))
1591 if (i == 0 || first)
1592 break;
1593 first = i;
1595 else if (first
1596 ? maybe_ne (poly_uint64 (indices[i]),
1597 elements + i - first)
1598 : maybe_ge (poly_uint64 (indices[i]), elements))
1599 break;
1600 if (first && i == elements)
1602 gimple_assign_set_rhs3 (stmt, mask);
1603 update_stmt (stmt);
1604 return;
1608 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1609 return;
1611 if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1612 warning_at (loc, OPT_Wvector_operation_performance,
1613 "vector shuffling operation will be expanded piecewise");
1615 vec_alloc (v, elements);
1616 bool constant_p = true;
1617 for (i = 0; i < elements; i++)
1619 si = size_int (i);
1620 i_val = vector_element (gsi, mask, si, &masktmp);
1622 if (TREE_CODE (i_val) == INTEGER_CST)
1624 unsigned HOST_WIDE_INT index;
1626 index = TREE_INT_CST_LOW (i_val);
1627 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1628 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1630 if (two_operand_p && (index & elements) != 0)
1631 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1632 else
1633 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1635 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1636 true, GSI_SAME_STMT);
1638 else
1640 tree cond = NULL_TREE, v0_val;
1642 if (two_operand_p)
1644 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1645 build_int_cst (mask_elt_type, elements));
1646 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1647 true, GSI_SAME_STMT);
1650 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1651 build_int_cst (mask_elt_type, elements - 1));
1652 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1653 true, GSI_SAME_STMT);
1655 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1656 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1657 true, GSI_SAME_STMT);
1659 if (two_operand_p)
1661 tree v1_val;
1663 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1664 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1665 true, GSI_SAME_STMT);
1667 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1668 cond, build_zero_cst (mask_elt_type));
1669 cond = fold_build3 (COND_EXPR, vect_elt_type,
1670 cond, v0_val, v1_val);
1671 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1672 true, GSI_SAME_STMT);
1674 else
1675 t = v0_val;
1678 if (!CONSTANT_CLASS_P (t))
1679 constant_p = false;
1680 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1683 if (constant_p)
1684 constr = build_vector_from_ctor (vect_type, v);
1685 else
1686 constr = build_constructor (vect_type, v);
1687 gimple_assign_set_rhs_from_tree (gsi, constr);
1688 update_stmt (gsi_stmt (*gsi));
1691 /* If OP is a uniform vector return the element it is a splat from. */
1693 static tree
1694 ssa_uniform_vector_p (tree op)
1696 if (TREE_CODE (op) == VECTOR_CST
1697 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1698 || TREE_CODE (op) == CONSTRUCTOR)
1699 return uniform_vector_p (op);
1700 if (TREE_CODE (op) == SSA_NAME)
1702 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1703 if (gimple_assign_single_p (def_stmt))
1704 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1706 return NULL_TREE;
1709 /* Return type in which CODE operation with optab OP can be
1710 computed. */
1712 static tree
1713 get_compute_type (enum tree_code code, optab op, tree type)
1715 /* For very wide vectors, try using a smaller vector mode. */
1716 tree compute_type = type;
1717 if (op
1718 && (!VECTOR_MODE_P (TYPE_MODE (type))
1719 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1721 tree vector_compute_type
1722 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1723 if (vector_compute_type != NULL_TREE
1724 && subparts_gt (compute_type, vector_compute_type)
1725 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1726 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1727 != CODE_FOR_nothing))
1728 compute_type = vector_compute_type;
1731 /* If we are breaking a BLKmode vector into smaller pieces,
1732 type_for_widest_vector_mode has already looked into the optab,
1733 so skip these checks. */
1734 if (compute_type == type)
1736 machine_mode compute_mode = TYPE_MODE (compute_type);
1737 if (VECTOR_MODE_P (compute_mode))
1739 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1740 return compute_type;
1741 if (code == MULT_HIGHPART_EXPR
1742 && can_mult_highpart_p (compute_mode,
1743 TYPE_UNSIGNED (compute_type)))
1744 return compute_type;
1746 /* There is no operation in hardware, so fall back to scalars. */
1747 compute_type = TREE_TYPE (type);
1750 return compute_type;
1753 static tree
1754 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1755 tree bitpos, tree bitsize, enum tree_code code,
1756 tree type ATTRIBUTE_UNUSED)
1758 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1759 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1760 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1761 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1762 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1763 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1766 /* Expand a vector COND_EXPR to scalars, piecewise. */
1767 static void
1768 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1770 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1771 tree lhs = gimple_assign_lhs (stmt);
1772 tree type = TREE_TYPE (lhs);
1773 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1774 machine_mode compute_mode = TYPE_MODE (compute_type);
1775 gcc_assert (compute_mode != BLKmode);
1776 tree rhs2 = gimple_assign_rhs2 (stmt);
1777 tree rhs3 = gimple_assign_rhs3 (stmt);
1778 tree new_rhs;
1780 /* If the compute mode is not a vector mode (hence we are not decomposing
1781 a BLKmode vector to smaller, hardware-supported vectors), we may want
1782 to expand the operations in parallel. */
1783 if (!VECTOR_MODE_P (compute_mode))
1784 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1785 COND_EXPR);
1786 else
1787 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1788 rhs2, rhs3, COND_EXPR, false);
1789 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1790 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1791 new_rhs);
1793 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1794 way to do it is change expand_vector_operation and its callees to
1795 return a tree_code, RHS1 and RHS2 instead of a tree. */
1796 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1797 update_stmt (gsi_stmt (*gsi));
1800 /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1801 lowering. If INNER_TYPE is not a vector type, this is a scalar
1802 fallback. */
1804 static tree
1805 do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1806 tree decl, tree bitpos, tree bitsize,
1807 enum tree_code code, tree type)
1809 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1810 if (!VECTOR_TYPE_P (inner_type))
1811 return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1812 if (code == CALL_EXPR)
1814 gimple *g = gimple_build_call (decl, 1, a);
1815 tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1816 gimple_call_set_lhs (g, lhs);
1817 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1818 return lhs;
1820 else
1822 tree outer_type = build_vector_type (TREE_TYPE (type),
1823 TYPE_VECTOR_SUBPARTS (inner_type));
1824 return gimplify_build1 (gsi, code, outer_type, a);
1828 /* Similarly, but for narrowing conversion. */
1830 static tree
1831 do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1832 tree, tree bitpos, tree, enum tree_code code,
1833 tree type)
1835 tree itype = build_vector_type (TREE_TYPE (inner_type),
1836 exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1837 2));
1838 tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1839 tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1840 int_const_binop (PLUS_EXPR, bitpos,
1841 TYPE_SIZE (itype)));
1842 tree outer_type = build_vector_type (TREE_TYPE (type),
1843 TYPE_VECTOR_SUBPARTS (inner_type));
1844 return gimplify_build2 (gsi, code, outer_type, b, c);
1847 /* Expand VEC_CONVERT ifn call. */
1849 static void
1850 expand_vector_conversion (gimple_stmt_iterator *gsi)
1852 gimple *stmt = gsi_stmt (*gsi);
1853 gimple *g;
1854 tree lhs = gimple_call_lhs (stmt);
1855 if (lhs == NULL_TREE)
1857 g = gimple_build_nop ();
1858 gsi_replace (gsi, g, false);
1859 return;
1861 tree arg = gimple_call_arg (stmt, 0);
1862 tree ret_type = TREE_TYPE (lhs);
1863 tree arg_type = TREE_TYPE (arg);
1864 tree new_rhs, compute_type = TREE_TYPE (arg_type);
1865 enum tree_code code = NOP_EXPR;
1866 enum tree_code code1 = ERROR_MARK;
1867 enum { NARROW, NONE, WIDEN } modifier = NONE;
1868 optab optab1 = unknown_optab;
1870 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1871 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1872 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1873 code = FIX_TRUNC_EXPR;
1874 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1875 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1876 code = FLOAT_EXPR;
1877 unsigned int ret_elt_bits = vector_element_bits (ret_type);
1878 unsigned int arg_elt_bits = vector_element_bits (arg_type);
1879 if (ret_elt_bits < arg_elt_bits)
1880 modifier = NARROW;
1881 else if (ret_elt_bits > arg_elt_bits)
1882 modifier = WIDEN;
1884 if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1886 if (supportable_convert_operation (code, ret_type, arg_type, &code1))
1888 g = gimple_build_assign (lhs, code1, arg);
1889 gsi_replace (gsi, g, false);
1890 return;
1892 /* Can't use get_compute_type here, as supportable_convert_operation
1893 doesn't necessarily use an optab and needs two arguments. */
1894 tree vec_compute_type
1895 = type_for_widest_vector_mode (TREE_TYPE (arg_type), mov_optab);
1896 if (vec_compute_type
1897 && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))
1898 && subparts_gt (arg_type, vec_compute_type))
1900 unsigned HOST_WIDE_INT nelts
1901 = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1902 while (nelts > 1)
1904 tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1905 tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1906 if (supportable_convert_operation (code, ret1_type, arg1_type,
1907 &code1))
1909 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1910 ret_type, arg1_type, arg,
1911 NULL_TREE, code1, false);
1912 g = gimple_build_assign (lhs, new_rhs);
1913 gsi_replace (gsi, g, false);
1914 return;
1916 nelts = nelts / 2;
1920 else if (modifier == NARROW)
1922 switch (code)
1924 CASE_CONVERT:
1925 code1 = VEC_PACK_TRUNC_EXPR;
1926 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1927 break;
1928 case FIX_TRUNC_EXPR:
1929 code1 = VEC_PACK_FIX_TRUNC_EXPR;
1930 /* The signedness is determined from output operand. */
1931 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1932 break;
1933 case FLOAT_EXPR:
1934 code1 = VEC_PACK_FLOAT_EXPR;
1935 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1936 break;
1937 default:
1938 gcc_unreachable ();
1941 if (optab1)
1942 compute_type = get_compute_type (code1, optab1, arg_type);
1943 enum insn_code icode1;
1944 if (VECTOR_TYPE_P (compute_type)
1945 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1946 != CODE_FOR_nothing)
1947 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1949 tree cretd_type
1950 = build_vector_type (TREE_TYPE (ret_type),
1951 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1952 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1954 if (compute_type == arg_type)
1956 new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1957 arg, build_zero_cst (arg_type));
1958 new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1959 TYPE_SIZE (ret_type),
1960 bitsize_int (0));
1961 g = gimple_build_assign (lhs, new_rhs);
1962 gsi_replace (gsi, g, false);
1963 return;
1965 tree dcompute_type
1966 = build_vector_type (TREE_TYPE (compute_type),
1967 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1968 if (TYPE_MAIN_VARIANT (dcompute_type)
1969 == TYPE_MAIN_VARIANT (arg_type))
1970 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1971 NULL_TREE, bitsize_int (0),
1972 NULL_TREE, code1,
1973 ret_type);
1974 else
1975 new_rhs = expand_vector_piecewise (gsi,
1976 do_vec_narrow_conversion,
1977 arg_type, dcompute_type,
1978 arg, NULL_TREE, code1,
1979 false, ret_type);
1980 g = gimple_build_assign (lhs, new_rhs);
1981 gsi_replace (gsi, g, false);
1982 return;
1986 else if (modifier == WIDEN)
1988 enum tree_code code2 = ERROR_MARK;
1989 optab optab2 = unknown_optab;
1990 switch (code)
1992 CASE_CONVERT:
1993 code1 = VEC_UNPACK_LO_EXPR;
1994 code2 = VEC_UNPACK_HI_EXPR;
1995 break;
1996 case FIX_TRUNC_EXPR:
1997 code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
1998 code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
1999 break;
2000 case FLOAT_EXPR:
2001 code1 = VEC_UNPACK_FLOAT_LO_EXPR;
2002 code2 = VEC_UNPACK_FLOAT_HI_EXPR;
2003 break;
2004 default:
2005 gcc_unreachable ();
2007 if (BYTES_BIG_ENDIAN)
2008 std::swap (code1, code2);
2010 if (code == FIX_TRUNC_EXPR)
2012 /* The signedness is determined from output operand. */
2013 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
2014 optab2 = optab_for_tree_code (code2, ret_type, optab_default);
2016 else
2018 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2019 optab2 = optab_for_tree_code (code2, arg_type, optab_default);
2022 if (optab1 && optab2)
2023 compute_type = get_compute_type (code1, optab1, arg_type);
2025 enum insn_code icode1, icode2;
2026 if (VECTOR_TYPE_P (compute_type)
2027 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2028 != CODE_FOR_nothing)
2029 && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
2030 != CODE_FOR_nothing)
2031 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
2032 && (insn_data[icode1].operand[0].mode
2033 == insn_data[icode2].operand[0].mode))
2035 poly_uint64 nunits
2036 = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
2037 tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
2038 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2040 vec<constructor_elt, va_gc> *v;
2041 tree part_width = TYPE_SIZE (compute_type);
2042 tree index = bitsize_int (0);
2043 int nunits = nunits_for_known_piecewise_op (arg_type);
2044 int delta = tree_to_uhwi (part_width) / arg_elt_bits;
2045 int i;
2046 location_t loc = gimple_location (gsi_stmt (*gsi));
2048 if (compute_type != arg_type)
2050 if (!warning_suppressed_p (gsi_stmt (*gsi),
2051 OPT_Wvector_operation_performance))
2052 warning_at (loc, OPT_Wvector_operation_performance,
2053 "vector operation will be expanded piecewise");
2055 else
2057 nunits = 1;
2058 delta = 1;
2061 vec_alloc (v, (nunits + delta - 1) / delta * 2);
2062 bool constant_p = true;
2063 for (i = 0; i < nunits;
2064 i += delta, index = int_const_binop (PLUS_EXPR, index,
2065 part_width))
2067 tree a = arg;
2068 if (compute_type != arg_type)
2069 a = tree_vec_extract (gsi, compute_type, a, part_width,
2070 index);
2071 tree result = gimplify_build1 (gsi, code1, cretd_type, a);
2072 constructor_elt ce = { NULL_TREE, result };
2073 if (!CONSTANT_CLASS_P (ce.value))
2074 constant_p = false;
2075 v->quick_push (ce);
2076 ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
2077 if (!CONSTANT_CLASS_P (ce.value))
2078 constant_p = false;
2079 v->quick_push (ce);
2082 if (constant_p)
2083 new_rhs = build_vector_from_ctor (ret_type, v);
2084 else
2085 new_rhs = build_constructor (ret_type, v);
2086 g = gimple_build_assign (lhs, new_rhs);
2087 gsi_replace (gsi, g, false);
2088 return;
2093 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
2094 TREE_TYPE (arg_type), arg,
2095 NULL_TREE, code, false, ret_type);
2096 g = gimple_build_assign (lhs, new_rhs);
2097 gsi_replace (gsi, g, false);
2100 /* Process one statement. If we identify a vector operation, expand it. */
2102 static void
2103 expand_vector_operations_1 (gimple_stmt_iterator *gsi,
2104 bitmap dce_ssa_names)
2106 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
2107 enum tree_code code;
2108 optab op = unknown_optab;
2109 enum gimple_rhs_class rhs_class;
2110 tree new_rhs;
2112 /* Only consider code == GIMPLE_ASSIGN. */
2113 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
2114 if (!stmt)
2116 if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
2117 expand_vector_conversion (gsi);
2118 return;
2121 code = gimple_assign_rhs_code (stmt);
2122 rhs_class = get_gimple_rhs_class (code);
2123 lhs = gimple_assign_lhs (stmt);
2125 if (code == VEC_PERM_EXPR)
2127 lower_vec_perm (gsi);
2128 return;
2131 if (code == VEC_COND_EXPR)
2133 expand_vector_condition (gsi, dce_ssa_names);
2134 return;
2137 if (code == COND_EXPR
2138 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
2139 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
2141 expand_vector_scalar_condition (gsi);
2142 return;
2145 if (code == CONSTRUCTOR
2146 && TREE_CODE (lhs) == SSA_NAME
2147 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
2148 && !gimple_clobber_p (stmt)
2149 && optimize)
2151 optimize_vector_constructor (gsi);
2152 return;
2155 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2156 return;
2158 rhs1 = gimple_assign_rhs1 (stmt);
2159 if (rhs_class == GIMPLE_BINARY_RHS)
2160 rhs2 = gimple_assign_rhs2 (stmt);
2162 type = TREE_TYPE (lhs);
2163 if (!VECTOR_TYPE_P (type)
2164 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2165 return;
2167 /* A scalar operation pretending to be a vector one. */
2168 if (VECTOR_BOOLEAN_TYPE_P (type)
2169 && !VECTOR_MODE_P (TYPE_MODE (type))
2170 && TYPE_MODE (type) != BLKmode
2171 && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2172 || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2173 && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2174 && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2175 return;
2177 /* If the vector operation is operating on all same vector elements
2178 implement it with a scalar operation and a splat if the target
2179 supports the scalar operation. */
2180 tree srhs1, srhs2 = NULL_TREE;
2181 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2182 && (rhs2 == NULL_TREE
2183 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2184 && (srhs2 = rhs2))
2185 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2186 /* As we query direct optabs restrict to non-convert operations. */
2187 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2189 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2190 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2191 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
2193 tree stype = TREE_TYPE (TREE_TYPE (lhs));
2194 tree slhs = (rhs2 != NULL_TREE)
2195 ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
2196 : gimplify_build1 (gsi, code, stype, srhs1);
2197 gimple_assign_set_rhs_from_tree (gsi,
2198 build_vector_from_val (type, slhs));
2199 update_stmt (stmt);
2200 return;
2204 if (CONVERT_EXPR_CODE_P (code)
2205 || code == FLOAT_EXPR
2206 || code == FIX_TRUNC_EXPR
2207 || code == VIEW_CONVERT_EXPR)
2208 return;
2210 /* The signedness is determined from input argument. */
2211 if (code == VEC_UNPACK_FLOAT_HI_EXPR
2212 || code == VEC_UNPACK_FLOAT_LO_EXPR
2213 || code == VEC_PACK_FLOAT_EXPR)
2215 /* We do not know how to scalarize those. */
2216 return;
2219 /* For widening/narrowing vector operations, the relevant type is of the
2220 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2221 calculated in the same way above. */
2222 if (code == WIDEN_SUM_EXPR
2223 || code == VEC_WIDEN_PLUS_HI_EXPR
2224 || code == VEC_WIDEN_PLUS_LO_EXPR
2225 || code == VEC_WIDEN_MINUS_HI_EXPR
2226 || code == VEC_WIDEN_MINUS_LO_EXPR
2227 || code == VEC_WIDEN_MULT_HI_EXPR
2228 || code == VEC_WIDEN_MULT_LO_EXPR
2229 || code == VEC_WIDEN_MULT_EVEN_EXPR
2230 || code == VEC_WIDEN_MULT_ODD_EXPR
2231 || code == VEC_UNPACK_HI_EXPR
2232 || code == VEC_UNPACK_LO_EXPR
2233 || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2234 || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2235 || code == VEC_PACK_TRUNC_EXPR
2236 || code == VEC_PACK_SAT_EXPR
2237 || code == VEC_PACK_FIX_TRUNC_EXPR
2238 || code == VEC_WIDEN_LSHIFT_HI_EXPR
2239 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2241 /* We do not know how to scalarize those. */
2242 return;
2245 /* Choose between vector shift/rotate by vector and vector shift/rotate by
2246 scalar */
2247 if (code == LSHIFT_EXPR
2248 || code == RSHIFT_EXPR
2249 || code == LROTATE_EXPR
2250 || code == RROTATE_EXPR)
2252 optab opv;
2254 /* Check whether we have vector <op> {x,x,x,x} where x
2255 could be a scalar variable or a constant. Transform
2256 vector <op> {x,x,x,x} ==> vector <op> scalar. */
2257 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2259 tree first;
2261 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2263 gimple_assign_set_rhs2 (stmt, first);
2264 update_stmt (stmt);
2265 rhs2 = first;
2269 opv = optab_for_tree_code (code, type, optab_vector);
2270 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2271 op = opv;
2272 else
2274 op = optab_for_tree_code (code, type, optab_scalar);
2276 compute_type = get_compute_type (code, op, type);
2277 if (compute_type == type)
2278 return;
2279 /* The rtl expander will expand vector/scalar as vector/vector
2280 if necessary. Pick one with wider vector type. */
2281 tree compute_vtype = get_compute_type (code, opv, type);
2282 if (subparts_gt (compute_vtype, compute_type))
2284 compute_type = compute_vtype;
2285 op = opv;
2289 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2291 if (compute_type == NULL_TREE)
2292 compute_type = get_compute_type (code, op, type);
2293 if (compute_type == type)
2294 return;
2295 /* Before splitting vector rotates into scalar rotates,
2296 see if we can't use vector shifts and BIT_IOR_EXPR
2297 instead. For vector by vector rotates we'd also
2298 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2299 for now, fold doesn't seem to create such rotates anyway. */
2300 if (compute_type == TREE_TYPE (type)
2301 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2303 optab oplv = vashl_optab, opl = ashl_optab;
2304 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2305 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2306 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2307 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2308 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2309 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2310 /* The rtl expander will expand vector/scalar as vector/vector
2311 if necessary. Pick one with wider vector type. */
2312 if (subparts_gt (compute_lvtype, compute_ltype))
2314 compute_ltype = compute_lvtype;
2315 opl = oplv;
2317 if (subparts_gt (compute_rvtype, compute_rtype))
2319 compute_rtype = compute_rvtype;
2320 opr = oprv;
2322 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2323 BIT_IOR_EXPR. */
2324 compute_type = compute_ltype;
2325 if (subparts_gt (compute_type, compute_rtype))
2326 compute_type = compute_rtype;
2327 if (subparts_gt (compute_type, compute_otype))
2328 compute_type = compute_otype;
2329 /* Verify all 3 operations can be performed in that type. */
2330 if (compute_type != TREE_TYPE (type))
2332 if (optab_handler (opl, TYPE_MODE (compute_type))
2333 == CODE_FOR_nothing
2334 || optab_handler (opr, TYPE_MODE (compute_type))
2335 == CODE_FOR_nothing
2336 || optab_handler (opo, TYPE_MODE (compute_type))
2337 == CODE_FOR_nothing)
2338 compute_type = TREE_TYPE (type);
2343 else
2344 op = optab_for_tree_code (code, type, optab_default);
2346 /* Optabs will try converting a negation into a subtraction, so
2347 look for it as well. TODO: negation of floating-point vectors
2348 might be turned into an exclusive OR toggling the sign bit. */
2349 if (op == unknown_optab
2350 && code == NEGATE_EXPR
2351 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2352 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2354 if (compute_type == NULL_TREE)
2355 compute_type = get_compute_type (code, op, type);
2356 if (compute_type == type)
2357 return;
2359 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code,
2360 dce_ssa_names);
2362 /* Leave expression untouched for later expansion. */
2363 if (new_rhs == NULL_TREE)
2364 return;
2366 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2367 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2368 new_rhs);
2370 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2371 way to do it is change expand_vector_operation and its callees to
2372 return a tree_code, RHS1 and RHS2 instead of a tree. */
2373 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2374 update_stmt (gsi_stmt (*gsi));
2377 /* Use this to lower vector operations introduced by the vectorizer,
2378 if it may need the bit-twiddling tricks implemented in this file. */
2380 static unsigned int
2381 expand_vector_operations (void)
2383 gimple_stmt_iterator gsi;
2384 basic_block bb;
2385 bool cfg_changed = false;
2387 auto_bitmap dce_ssa_names;
2389 FOR_EACH_BB_FN (bb, cfun)
2391 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2393 expand_vector_operations_1 (&gsi, dce_ssa_names);
2394 /* ??? If we do not cleanup EH then we will ICE in
2395 verification. But in reality we have created wrong-code
2396 as we did not properly transition EH info and edges to
2397 the piecewise computations. */
2398 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2399 && gimple_purge_dead_eh_edges (bb))
2400 cfg_changed = true;
2404 simple_dce_from_worklist (dce_ssa_names);
2406 return cfg_changed ? TODO_cleanup_cfg : 0;
2409 namespace {
2411 const pass_data pass_data_lower_vector =
2413 GIMPLE_PASS, /* type */
2414 "veclower", /* name */
2415 OPTGROUP_VEC, /* optinfo_flags */
2416 TV_NONE, /* tv_id */
2417 PROP_cfg, /* properties_required */
2418 PROP_gimple_lvec, /* properties_provided */
2419 0, /* properties_destroyed */
2420 0, /* todo_flags_start */
2421 TODO_update_ssa, /* todo_flags_finish */
2424 class pass_lower_vector : public gimple_opt_pass
2426 public:
2427 pass_lower_vector (gcc::context *ctxt)
2428 : gimple_opt_pass (pass_data_lower_vector, ctxt)
2431 /* opt_pass methods: */
2432 bool gate (function *fun) final override
2434 return !(fun->curr_properties & PROP_gimple_lvec);
2437 unsigned int execute (function *) final override
2439 return expand_vector_operations ();
2442 }; // class pass_lower_vector
2444 } // anon namespace
2446 gimple_opt_pass *
2447 make_pass_lower_vector (gcc::context *ctxt)
2449 return new pass_lower_vector (ctxt);
2452 namespace {
2454 const pass_data pass_data_lower_vector_ssa =
2456 GIMPLE_PASS, /* type */
2457 "veclower2", /* name */
2458 OPTGROUP_VEC, /* optinfo_flags */
2459 TV_NONE, /* tv_id */
2460 PROP_cfg, /* properties_required */
2461 PROP_gimple_lvec, /* properties_provided */
2462 0, /* properties_destroyed */
2463 0, /* todo_flags_start */
2464 ( TODO_update_ssa
2465 | TODO_cleanup_cfg ), /* todo_flags_finish */
2468 class pass_lower_vector_ssa : public gimple_opt_pass
2470 public:
2471 pass_lower_vector_ssa (gcc::context *ctxt)
2472 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2475 /* opt_pass methods: */
2476 opt_pass * clone () final override
2478 return new pass_lower_vector_ssa (m_ctxt);
2480 unsigned int execute (function *) final override
2482 return expand_vector_operations ();
2485 }; // class pass_lower_vector_ssa
2487 } // anon namespace
2489 gimple_opt_pass *
2490 make_pass_lower_vector_ssa (gcc::context *ctxt)
2492 return new pass_lower_vector_ssa (ctxt);
2495 #include "gt-tree-vect-generic.h"