ada: Fix renaming of predefined equality operator for unchecked union types
[official-gcc.git] / gcc / tree-vect-generic.cc
blobdf04a0db68da3222f43dd938f8e7adb186cd93c9
1 /* Lower vector operations to scalar operations.
2 Copyright (C) 2004-2023 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 */
47 #include "optabs-libfuncs.h"
50 /* Build a ternary operation and gimplify it. Emit code before GSI.
51 Return the gimple_val holding the result. */
53 static tree
54 gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
55 tree type, tree a, tree b, tree c)
57 location_t loc = gimple_location (gsi_stmt (*gsi));
58 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b, c);
61 /* Build a binary operation and gimplify it. Emit code before GSI.
62 Return the gimple_val holding the result. */
64 static tree
65 gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
66 tree type, tree a, tree b)
68 location_t loc = gimple_location (gsi_stmt (*gsi));
69 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a, b);
72 /* Build a unary operation and gimplify it. Emit code before GSI.
73 Return the gimple_val holding the result. */
75 static tree
76 gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
77 tree a)
79 location_t loc = gimple_location (gsi_stmt (*gsi));
80 return gimple_build (gsi, true, GSI_SAME_STMT, loc, code, type, a);
84 static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap);
86 /* Return the number of elements in a vector type TYPE that we have
87 already decided needs to be expanded piecewise. We don't support
88 this kind of expansion for variable-length vectors, since we should
89 always check for target support before introducing uses of those. */
90 static unsigned int
91 nunits_for_known_piecewise_op (const_tree type)
93 return TYPE_VECTOR_SUBPARTS (type).to_constant ();
96 /* Return true if TYPE1 has more elements than TYPE2, where either
97 type may be a vector or a scalar. */
99 static inline bool
100 subparts_gt (tree type1, tree type2)
102 poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
103 poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
104 return known_gt (n1, n2);
107 static GTY(()) tree vector_inner_type;
108 static GTY(()) tree vector_last_type;
109 static GTY(()) int vector_last_nunits;
111 /* Return a suitable vector types made of SUBPARTS units each of mode
112 "word_mode" (the global variable). */
113 static tree
114 build_word_mode_vector_type (int nunits)
116 if (!vector_inner_type)
117 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
118 else if (vector_last_nunits == nunits)
120 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
121 return vector_last_type;
124 vector_last_nunits = nunits;
125 vector_last_type = build_vector_type (vector_inner_type, nunits);
126 return vector_last_type;
129 typedef tree (*elem_op_func) (gimple_stmt_iterator *,
130 tree, tree, tree, tree, tree, enum tree_code,
131 tree);
133 /* Extract the vector element of type TYPE at BITPOS with BITSIZE from T
134 and return it. */
136 tree
137 tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
138 tree t, tree bitsize, tree bitpos)
140 /* We're using the resimplify API and maybe_push_res_to_seq to
141 simplify the BIT_FIELD_REF but restrict the simplification to
142 a single stmt while at the same time following SSA edges for
143 simplification with already emitted CTORs. */
144 gimple_match_op opr;
145 opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
146 opr.resimplify (NULL, follow_all_ssa_edges);
147 gimple_seq stmts = NULL;
148 tree res = maybe_push_res_to_seq (&opr, &stmts);
149 if (!res)
151 /* This can happen if SSA_NAME_OCCURS_IN_ABNORMAL_PHI are
152 used. Build BIT_FIELD_REF manually otherwise. */
153 t = build3 (BIT_FIELD_REF, type, t, bitsize, bitpos);
154 res = make_ssa_name (type);
155 gimple *g = gimple_build_assign (res, t);
156 gsi_insert_before (gsi, g, GSI_SAME_STMT);
157 return res;
159 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
160 return res;
163 static tree
164 do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
165 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
166 enum tree_code code, tree type ATTRIBUTE_UNUSED)
168 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
169 return gimplify_build1 (gsi, code, inner_type, a);
172 static tree
173 do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
174 tree bitpos, tree bitsize, enum tree_code code,
175 tree type ATTRIBUTE_UNUSED)
177 if (VECTOR_TYPE_P (TREE_TYPE (a)))
178 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
179 if (VECTOR_TYPE_P (TREE_TYPE (b)))
180 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
181 return gimplify_build2 (gsi, code, inner_type, a, b);
184 /* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
186 INNER_TYPE is the type of A and B elements
188 returned expression is of signed integer type with the
189 size equal to the size of INNER_TYPE. */
190 static tree
191 do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
192 tree bitpos, tree bitsize, enum tree_code code, tree type)
194 tree stype = TREE_TYPE (type);
195 tree cst_false = build_zero_cst (stype);
196 tree cst_true = build_all_ones_cst (stype);
197 tree cmp;
199 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
200 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
202 cmp = build2 (code, boolean_type_node, a, b);
203 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
206 /* Expand vector addition to scalars. This does bit twiddling
207 in order to increase parallelism:
209 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
210 (a ^ b) & 0x80808080
212 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
213 (a ^ ~b) & 0x80808080
215 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
217 This optimization should be done only if 4 vector items or more
218 fit into a word. */
219 static tree
220 do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
221 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
222 enum tree_code code, tree type ATTRIBUTE_UNUSED)
224 unsigned int width = vector_element_bits (TREE_TYPE (a));
225 tree inner_type = TREE_TYPE (TREE_TYPE (a));
226 unsigned HOST_WIDE_INT max;
227 tree low_bits, high_bits, a_low, b_low, result_low, signs;
229 max = GET_MODE_MASK (TYPE_MODE (inner_type));
230 low_bits = build_replicated_int_cst (word_type, width, max >> 1);
231 high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
233 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
234 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
236 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
237 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
238 if (code == PLUS_EXPR)
239 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
240 else
242 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
243 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
246 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
247 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
248 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
251 static tree
252 do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
253 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
254 tree bitsize ATTRIBUTE_UNUSED,
255 enum tree_code code ATTRIBUTE_UNUSED,
256 tree type ATTRIBUTE_UNUSED)
258 unsigned int width = vector_element_bits (TREE_TYPE (b));
259 tree inner_type = TREE_TYPE (TREE_TYPE (b));
260 HOST_WIDE_INT max;
261 tree low_bits, high_bits, b_low, result_low, signs;
263 max = GET_MODE_MASK (TYPE_MODE (inner_type));
264 low_bits = build_replicated_int_cst (word_type, width, max >> 1);
265 high_bits = build_replicated_int_cst (word_type, width, max & ~(max >> 1));
267 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
269 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
270 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
271 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
272 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
273 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
276 /* Expand a vector operation to scalars, by using many operations
277 whose type is the vector type's inner type. */
278 static tree
279 expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
280 tree type, tree inner_type,
281 tree a, tree b, enum tree_code code,
282 bool parallel_p, tree ret_type = NULL_TREE)
284 vec<constructor_elt, va_gc> *v;
285 tree part_width = TYPE_SIZE (inner_type);
286 tree index = bitsize_int (0);
287 int nunits = nunits_for_known_piecewise_op (type);
288 int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
289 int i;
290 location_t loc = gimple_location (gsi_stmt (*gsi));
292 if (nunits == 1
293 || warning_suppressed_p (gsi_stmt (*gsi),
294 OPT_Wvector_operation_performance))
295 /* Do not diagnose decomposing single element vectors or when
296 decomposing vectorizer produced operations. */
298 else if (ret_type || !parallel_p)
299 warning_at (loc, OPT_Wvector_operation_performance,
300 "vector operation will be expanded piecewise");
301 else
302 warning_at (loc, OPT_Wvector_operation_performance,
303 "vector operation will be expanded in parallel");
305 if (!ret_type)
306 ret_type = type;
307 vec_alloc (v, (nunits + delta - 1) / delta);
308 bool constant_p = true;
309 for (i = 0; i < nunits;
310 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
312 tree result = f (gsi, inner_type, a, b, index, part_width, code,
313 ret_type);
314 if (!CONSTANT_CLASS_P (result))
315 constant_p = false;
316 constructor_elt ce = {NULL_TREE, result};
317 v->quick_push (ce);
320 if (constant_p)
321 return build_vector_from_ctor (ret_type, v);
322 else
323 return build_constructor (ret_type, v);
326 /* Expand a vector operation to scalars with the freedom to use
327 a scalar integer type, or to use a different size for the items
328 in the vector type. */
329 static tree
330 expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
331 tree a, tree b, enum tree_code code)
333 tree result, compute_type;
334 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
335 location_t loc = gimple_location (gsi_stmt (*gsi));
337 /* We have three strategies. If the type is already correct, just do
338 the operation an element at a time. Else, if the vector is wider than
339 one word, do it a word at a time; finally, if the vector is smaller
340 than one word, do it as a scalar. */
341 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
342 return expand_vector_piecewise (gsi, f,
343 type, TREE_TYPE (type),
344 a, b, code, true);
345 else if (n_words > 1)
347 tree word_type = build_word_mode_vector_type (n_words);
348 result = expand_vector_piecewise (gsi, f,
349 word_type, TREE_TYPE (word_type),
350 a, b, code, true);
351 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
352 GSI_SAME_STMT);
354 else
356 /* Use a single scalar operation with a mode no wider than word_mode. */
357 if (!warning_suppressed_p (gsi_stmt (*gsi),
358 OPT_Wvector_operation_performance))
359 warning_at (loc, OPT_Wvector_operation_performance,
360 "vector operation will be expanded with a "
361 "single scalar operation");
362 scalar_int_mode mode
363 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
364 compute_type = lang_hooks.types.type_for_mode (mode, 1);
365 result = f (gsi, compute_type, a, b, bitsize_zero_node,
366 TYPE_SIZE (compute_type), code, type);
369 return result;
372 /* Expand a vector operation to scalars; for integer types we can use
373 special bit twiddling tricks to do the sums a word at a time, using
374 function F_PARALLEL instead of F. These tricks are done only if
375 they can process at least four items, that is, only if the vector
376 holds at least four items and if a word can hold four items. */
377 static tree
378 expand_vector_addition (gimple_stmt_iterator *gsi,
379 elem_op_func f, elem_op_func f_parallel,
380 tree type, tree a, tree b, enum tree_code code)
382 int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
384 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
385 && parts_per_word >= 4
386 && nunits_for_known_piecewise_op (type) >= 4)
387 return expand_vector_parallel (gsi, f_parallel,
388 type, a, b, code);
389 else
390 return expand_vector_piecewise (gsi, f,
391 type, TREE_TYPE (type),
392 a, b, code, false);
395 static bool
396 expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names);
398 /* Try to expand vector comparison expression OP0 CODE OP1 by
399 querying optab if the following expression:
400 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
401 can be expanded. */
402 static tree
403 expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
404 tree op1, enum tree_code code,
405 bitmap dce_ssa_names)
407 tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
408 use_operand_p use_p;
409 imm_use_iterator iterator;
410 bool vec_cond_expr_only = true;
412 /* As seen in PR95830, we should not expand comparisons that are only
413 feeding a VEC_COND_EXPR statement. */
414 auto_vec<gimple *> uses;
415 FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs)
417 gimple *use = USE_STMT (use_p);
418 if (is_gimple_debug (use))
419 continue;
420 if (is_gimple_assign (use)
421 && gimple_assign_rhs_code (use) == VEC_COND_EXPR
422 && gimple_assign_rhs1 (use) == lhs
423 && gimple_assign_rhs2 (use) != lhs
424 && gimple_assign_rhs3 (use) != lhs)
425 uses.safe_push (use);
426 else
427 vec_cond_expr_only = false;
430 if (vec_cond_expr_only)
431 for (gimple *use : uses)
433 gimple_stmt_iterator it = gsi_for_stmt (use);
434 if (!expand_vector_condition (&it, dce_ssa_names))
436 vec_cond_expr_only = false;
437 break;
441 if (!uses.is_empty () && vec_cond_expr_only)
442 return NULL_TREE;
444 tree t;
445 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
447 if (VECTOR_BOOLEAN_TYPE_P (type)
448 && SCALAR_INT_MODE_P (TYPE_MODE (type))
449 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
450 TYPE_VECTOR_SUBPARTS (type)
451 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
452 (TREE_TYPE (type)))))
454 tree inner_type = TREE_TYPE (TREE_TYPE (op0));
455 tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
456 tree index = bitsize_int (0);
457 int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
458 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
459 tree ret_type = build_nonstandard_integer_type (prec, 1);
460 tree ret_inner_type = boolean_type_node;
461 int i;
462 location_t loc = gimple_location (gsi_stmt (*gsi));
463 t = build_zero_cst (ret_type);
465 if (TYPE_PRECISION (ret_inner_type) != 1)
466 ret_inner_type = build_nonstandard_integer_type (1, 1);
467 if (!warning_suppressed_p (gsi_stmt (*gsi),
468 OPT_Wvector_operation_performance))
469 warning_at (loc, OPT_Wvector_operation_performance,
470 "vector operation will be expanded piecewise");
471 for (i = 0; i < nunits;
472 i++, index = int_const_binop (PLUS_EXPR, index, part_width))
474 tree a = tree_vec_extract (gsi, inner_type, op0, part_width,
475 index);
476 tree b = tree_vec_extract (gsi, inner_type, op1, part_width,
477 index);
478 tree result = gimplify_build2 (gsi, code, ret_inner_type, a, b);
479 t = gimplify_build3 (gsi, BIT_INSERT_EXPR, ret_type, t, result,
480 bitsize_int (i));
482 t = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
484 else
485 t = expand_vector_piecewise (gsi, do_compare, type,
486 TREE_TYPE (TREE_TYPE (op0)), op0, op1,
487 code, false);
489 else
490 t = NULL_TREE;
492 return t;
495 /* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
496 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
497 the result if successful, otherwise return NULL_TREE. */
498 static tree
499 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
501 optab op;
502 unsigned int i, nunits = nunits_for_known_piecewise_op (type);
503 bool scalar_shift = true;
505 for (i = 1; i < nunits; i++)
507 if (shiftcnts[i] != shiftcnts[0])
508 scalar_shift = false;
511 if (scalar_shift && shiftcnts[0] == 0)
512 return op0;
514 if (scalar_shift)
516 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
517 if (op != unknown_optab
518 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
519 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
520 build_int_cst (NULL_TREE, shiftcnts[0]));
523 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
524 if (op != unknown_optab
525 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
527 tree_vector_builder vec (type, nunits, 1);
528 for (i = 0; i < nunits; i++)
529 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
530 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
533 return NULL_TREE;
536 /* Try to expand integer vector division by constant using
537 widening multiply, shifts and additions. */
538 static tree
539 expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
540 tree op1, enum tree_code code)
542 bool use_pow2 = true;
543 bool has_vector_shift = true;
544 bool use_abs_op1 = false;
545 int mode = -1, this_mode;
546 int pre_shift = -1, post_shift;
547 unsigned int nunits = nunits_for_known_piecewise_op (type);
548 int *shifts = XALLOCAVEC (int, nunits * 4);
549 int *pre_shifts = shifts + nunits;
550 int *post_shifts = pre_shifts + nunits;
551 int *shift_temps = post_shifts + nunits;
552 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
553 int prec = TYPE_PRECISION (TREE_TYPE (type));
554 int dummy_int;
555 unsigned int i;
556 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
557 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
558 tree cur_op, mulcst, tem;
559 optab op;
561 if (prec > HOST_BITS_PER_WIDE_INT)
562 return NULL_TREE;
564 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
565 if (op == unknown_optab
566 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
567 has_vector_shift = false;
569 /* Analysis phase. Determine if all op1 elements are either power
570 of two and it is possible to expand it using shifts (or for remainder
571 using masking). Additionally compute the multiplicative constants
572 and pre and post shifts if the division is to be expanded using
573 widening or high part multiplication plus shifts. */
574 for (i = 0; i < nunits; i++)
576 tree cst = VECTOR_CST_ELT (op1, i);
577 unsigned HOST_WIDE_INT ml;
579 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
580 return NULL_TREE;
581 pre_shifts[i] = 0;
582 post_shifts[i] = 0;
583 mulc[i] = 0;
584 if (use_pow2
585 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
586 use_pow2 = false;
587 if (use_pow2)
589 shifts[i] = tree_log2 (cst);
590 if (shifts[i] != shifts[0]
591 && code == TRUNC_DIV_EXPR
592 && !has_vector_shift)
593 use_pow2 = false;
595 if (mode == -2)
596 continue;
597 if (sign_p == UNSIGNED)
599 unsigned HOST_WIDE_INT mh;
600 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
602 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
603 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
604 return NULL_TREE;
606 if (d <= 1)
608 mode = -2;
609 continue;
612 /* Find a suitable multiplier and right shift count
613 instead of multiplying with D. */
614 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
616 /* If the suggested multiplier is more than SIZE bits, we can
617 do better for even divisors, using an initial right shift. */
618 if ((mh != 0 && (d & 1) == 0)
619 || (!has_vector_shift && pre_shift != -1))
621 if (has_vector_shift)
622 pre_shift = ctz_or_zero (d);
623 else if (pre_shift == -1)
625 unsigned int j;
626 for (j = 0; j < nunits; j++)
628 tree cst2 = VECTOR_CST_ELT (op1, j);
629 unsigned HOST_WIDE_INT d2;
630 int this_pre_shift;
632 if (!tree_fits_uhwi_p (cst2))
633 return NULL_TREE;
634 d2 = tree_to_uhwi (cst2) & mask;
635 if (d2 == 0)
636 return NULL_TREE;
637 this_pre_shift = floor_log2 (d2 & -d2);
638 if (pre_shift == -1 || this_pre_shift < pre_shift)
639 pre_shift = this_pre_shift;
641 if (i != 0 && pre_shift != 0)
643 /* Restart. */
644 i = -1U;
645 mode = -1;
646 continue;
649 if (pre_shift != 0)
651 if ((d >> pre_shift) <= 1)
653 mode = -2;
654 continue;
656 mh = choose_multiplier (d >> pre_shift, prec,
657 prec - pre_shift,
658 &ml, &post_shift, &dummy_int);
659 gcc_assert (!mh);
660 pre_shifts[i] = pre_shift;
663 if (!mh)
664 this_mode = 0;
665 else
666 this_mode = 1;
668 else
670 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
671 unsigned HOST_WIDE_INT abs_d;
673 if (d == -1)
674 return NULL_TREE;
676 /* Since d might be INT_MIN, we have to cast to
677 unsigned HOST_WIDE_INT before negating to avoid
678 undefined signed overflow. */
679 abs_d = (d >= 0
680 ? (unsigned HOST_WIDE_INT) d
681 : - (unsigned HOST_WIDE_INT) d);
683 /* n rem d = n rem -d */
684 if (code == TRUNC_MOD_EXPR && d < 0)
686 d = abs_d;
687 use_abs_op1 = true;
689 if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
691 /* This case is not handled correctly below. */
692 mode = -2;
693 continue;
695 if (abs_d <= 1)
697 mode = -2;
698 continue;
701 choose_multiplier (abs_d, prec, prec - 1, &ml,
702 &post_shift, &dummy_int);
703 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
705 this_mode = 4 + (d < 0);
706 ml |= HOST_WIDE_INT_M1U << (prec - 1);
708 else
709 this_mode = 2 + (d < 0);
711 mulc[i] = ml;
712 post_shifts[i] = post_shift;
713 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
714 || post_shift >= prec
715 || pre_shifts[i] >= prec)
716 this_mode = -2;
718 if (i == 0)
719 mode = this_mode;
720 else if (mode != this_mode)
721 mode = -2;
724 if (use_pow2)
726 tree addend = NULL_TREE;
727 if (sign_p == SIGNED)
729 tree uns_type;
731 /* Both division and remainder sequences need
732 op0 < 0 ? mask : 0 computed. It can be either computed as
733 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
734 if none of the shifts is 0, or as the conditional. */
735 for (i = 0; i < nunits; i++)
736 if (shifts[i] == 0)
737 break;
738 uns_type
739 = build_vector_type (build_nonstandard_integer_type (prec, 1),
740 nunits);
741 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
743 for (i = 0; i < nunits; i++)
744 shift_temps[i] = prec - 1;
745 cur_op = add_rshift (gsi, type, op0, shift_temps);
746 if (cur_op != NULL_TREE)
748 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
749 uns_type, cur_op);
750 for (i = 0; i < nunits; i++)
751 shift_temps[i] = prec - shifts[i];
752 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
753 if (cur_op != NULL_TREE)
754 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
755 type, cur_op);
758 if (addend == NULL_TREE
759 && expand_vec_cond_expr_p (type, type, LT_EXPR))
761 tree zero, cst, mask_type, mask;
762 gimple *stmt, *cond;
764 mask_type = truth_type_for (type);
765 zero = build_zero_cst (type);
766 mask = make_ssa_name (mask_type);
767 cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
768 gsi_insert_before (gsi, cond, GSI_SAME_STMT);
769 tree_vector_builder vec (type, nunits, 1);
770 for (i = 0; i < nunits; i++)
771 vec.quick_push (build_int_cst (TREE_TYPE (type),
772 (HOST_WIDE_INT_1U
773 << shifts[i]) - 1));
774 cst = vec.build ();
775 addend = make_ssa_name (type);
776 stmt
777 = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
778 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
781 if (code == TRUNC_DIV_EXPR)
783 if (sign_p == UNSIGNED)
785 /* q = op0 >> shift; */
786 cur_op = add_rshift (gsi, type, op0, shifts);
787 if (cur_op != NULL_TREE)
788 return cur_op;
790 else if (addend != NULL_TREE)
792 /* t1 = op0 + addend;
793 q = t1 >> shift; */
794 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
795 if (op != unknown_optab
796 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
798 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
799 cur_op = add_rshift (gsi, type, cur_op, shifts);
800 if (cur_op != NULL_TREE)
801 return cur_op;
805 else
807 tree mask;
808 tree_vector_builder vec (type, nunits, 1);
809 for (i = 0; i < nunits; i++)
810 vec.quick_push (build_int_cst (TREE_TYPE (type),
811 (HOST_WIDE_INT_1U
812 << shifts[i]) - 1));
813 mask = vec.build ();
814 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
815 if (op != unknown_optab
816 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
818 if (sign_p == UNSIGNED)
819 /* r = op0 & mask; */
820 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
821 else if (addend != NULL_TREE)
823 /* t1 = op0 + addend;
824 t2 = t1 & mask;
825 r = t2 - addend; */
826 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
827 if (op != unknown_optab
828 && optab_handler (op, TYPE_MODE (type))
829 != CODE_FOR_nothing)
831 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
832 addend);
833 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
834 cur_op, mask);
835 op = optab_for_tree_code (MINUS_EXPR, type,
836 optab_default);
837 if (op != unknown_optab
838 && optab_handler (op, TYPE_MODE (type))
839 != CODE_FOR_nothing)
840 return gimplify_build2 (gsi, MINUS_EXPR, type,
841 cur_op, addend);
848 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
849 return NULL_TREE;
851 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
852 return NULL_TREE;
854 cur_op = op0;
856 switch (mode)
858 case 0:
859 gcc_assert (sign_p == UNSIGNED);
860 /* t1 = oprnd0 >> pre_shift;
861 t2 = t1 h* ml;
862 q = t2 >> post_shift; */
863 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
864 if (cur_op == NULL_TREE)
865 return NULL_TREE;
866 break;
867 case 1:
868 gcc_assert (sign_p == UNSIGNED);
869 for (i = 0; i < nunits; i++)
871 shift_temps[i] = 1;
872 post_shifts[i]--;
874 break;
875 case 2:
876 case 3:
877 case 4:
878 case 5:
879 gcc_assert (sign_p == SIGNED);
880 for (i = 0; i < nunits; i++)
881 shift_temps[i] = prec - 1;
882 break;
883 default:
884 return NULL_TREE;
887 tree_vector_builder vec (type, nunits, 1);
888 for (i = 0; i < nunits; i++)
889 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
890 mulcst = vec.build ();
892 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
894 switch (mode)
896 case 0:
897 /* t1 = oprnd0 >> pre_shift;
898 t2 = t1 h* ml;
899 q = t2 >> post_shift; */
900 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
901 break;
902 case 1:
903 /* t1 = oprnd0 h* ml;
904 t2 = oprnd0 - t1;
905 t3 = t2 >> 1;
906 t4 = t1 + t3;
907 q = t4 >> (post_shift - 1); */
908 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
909 if (op == unknown_optab
910 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
911 return NULL_TREE;
912 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
913 tem = add_rshift (gsi, type, tem, shift_temps);
914 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
915 if (op == unknown_optab
916 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
917 return NULL_TREE;
918 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
919 cur_op = add_rshift (gsi, type, tem, post_shifts);
920 if (cur_op == NULL_TREE)
921 return NULL_TREE;
922 break;
923 case 2:
924 case 3:
925 case 4:
926 case 5:
927 /* t1 = oprnd0 h* ml;
928 t2 = t1; [ iff (mode & 2) != 0 ]
929 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
930 t3 = t2 >> post_shift;
931 t4 = oprnd0 >> (prec - 1);
932 q = t3 - t4; [ iff (mode & 1) == 0 ]
933 q = t4 - t3; [ iff (mode & 1) != 0 ] */
934 if ((mode & 2) == 0)
936 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
937 if (op == unknown_optab
938 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
939 return NULL_TREE;
940 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
942 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
943 if (cur_op == NULL_TREE)
944 return NULL_TREE;
945 tem = add_rshift (gsi, type, op0, shift_temps);
946 if (tem == NULL_TREE)
947 return NULL_TREE;
948 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
949 if (op == unknown_optab
950 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
951 return NULL_TREE;
952 if ((mode & 1) == 0)
953 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
954 else
955 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
956 break;
957 default:
958 gcc_unreachable ();
961 if (code == TRUNC_DIV_EXPR)
962 return cur_op;
964 /* We divided. Now finish by:
965 t1 = q * oprnd1;
966 r = oprnd0 - t1; */
967 op = optab_for_tree_code (MULT_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 (use_abs_op1)
973 tree_vector_builder elts;
974 if (!elts.new_unary_operation (type, op1, false))
975 return NULL_TREE;
976 unsigned int count = elts.encoded_nelts ();
977 for (unsigned int i = 0; i < count; ++i)
979 tree elem1 = VECTOR_CST_ELT (op1, i);
981 tree elt = const_unop (ABS_EXPR, TREE_TYPE (elem1), elem1);
982 if (elt == NULL_TREE)
983 return NULL_TREE;
984 elts.quick_push (elt);
986 op1 = elts.build ();
988 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
989 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
990 if (op == unknown_optab
991 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
992 return NULL_TREE;
993 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
996 /* Expand a vector condition to scalars, by using many conditions
997 on the vector's elements. */
999 static bool
1000 expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
1002 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1003 tree type = TREE_TYPE (gimple_assign_lhs (stmt));
1004 tree a = gimple_assign_rhs1 (stmt);
1005 tree a1 = a;
1006 tree a2 = NULL_TREE;
1007 bool a_is_comparison = false;
1008 bool a_is_scalar_bitmask = false;
1009 tree b = gimple_assign_rhs2 (stmt);
1010 tree c = gimple_assign_rhs3 (stmt);
1011 vec<constructor_elt, va_gc> *v;
1012 tree constr;
1013 tree inner_type = TREE_TYPE (type);
1014 tree width = vector_element_bits_tree (type);
1015 tree cond_type = TREE_TYPE (TREE_TYPE (a));
1016 tree comp_inner_type = cond_type;
1017 tree index = bitsize_int (0);
1018 tree comp_width = width;
1019 tree comp_index = index;
1020 location_t loc = gimple_location (gsi_stmt (*gsi));
1021 tree_code code = TREE_CODE (a);
1022 gassign *assign = NULL;
1024 if (code == SSA_NAME)
1026 assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a));
1027 if (assign != NULL
1028 && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison)
1030 a_is_comparison = true;
1031 a1 = gimple_assign_rhs1 (assign);
1032 a2 = gimple_assign_rhs2 (assign);
1033 code = gimple_assign_rhs_code (assign);
1034 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
1035 comp_width = vector_element_bits_tree (TREE_TYPE (a1));
1039 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code)
1040 || (integer_all_onesp (b) && integer_zerop (c)
1041 && expand_vec_cmp_expr_p (type, TREE_TYPE (a1), code)))
1043 gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST);
1044 return true;
1047 /* If a has vector boolean type and is a comparison, above
1048 expand_vec_cond_expr_p might fail, even if both the comparison and
1049 VEC_COND_EXPR could be supported individually. See PR109176. */
1050 if (a_is_comparison
1051 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1052 && expand_vec_cond_expr_p (type, TREE_TYPE (a), SSA_NAME)
1053 && expand_vec_cmp_expr_p (TREE_TYPE (a1), TREE_TYPE (a), code))
1054 return true;
1056 /* Handle vector boolean types with bitmasks. If there is a comparison
1057 and we can expand the comparison into the vector boolean bitmask,
1058 or otherwise if it is compatible with type, we can transform
1059 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
1060 into
1061 tmp_6 = x_2 < y_3;
1062 tmp_7 = tmp_6 & vbfld_4;
1063 tmp_8 = ~tmp_6;
1064 tmp_9 = tmp_8 & vbfld_5;
1065 vbfld_1 = tmp_7 | tmp_9;
1066 Similarly for vbfld_10 instead of x_2 < y_3. */
1067 if (VECTOR_BOOLEAN_TYPE_P (type)
1068 && SCALAR_INT_MODE_P (TYPE_MODE (type))
1069 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
1070 TYPE_VECTOR_SUBPARTS (type)
1071 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
1072 && (a_is_comparison
1073 ? useless_type_conversion_p (type, TREE_TYPE (a))
1074 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
1076 if (a_is_comparison)
1077 a = gimplify_build2 (gsi, code, type, a1, a2);
1078 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
1079 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
1080 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
1081 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
1082 gimple_assign_set_rhs_from_tree (gsi, a);
1083 update_stmt (gsi_stmt (*gsi));
1084 return true;
1087 /* TODO: try and find a smaller vector type. */
1089 if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1090 warning_at (loc, OPT_Wvector_operation_performance,
1091 "vector condition will be expanded piecewise");
1093 if (!a_is_comparison
1094 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a))
1095 && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (a)))
1096 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (a))),
1097 TYPE_VECTOR_SUBPARTS (TREE_TYPE (a))
1098 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE
1099 (TREE_TYPE (TREE_TYPE (a))))))
1101 a_is_scalar_bitmask = true;
1102 int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (TREE_TYPE (a)));
1103 tree atype = build_nonstandard_integer_type (prec, 1);
1104 a = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, atype, a);
1106 else if (!a_is_comparison
1107 && VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (a)))
1108 comp_width = vector_element_bits_tree (TREE_TYPE (a));
1110 int nunits = nunits_for_known_piecewise_op (type);
1111 vec_alloc (v, nunits);
1112 bool constant_p = true;
1113 for (int i = 0; i < nunits; i++)
1115 tree aa, result;
1116 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
1117 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
1118 if (a_is_comparison)
1120 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
1121 comp_width, comp_index);
1122 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
1123 comp_width, comp_index);
1124 aa = gimplify_build2 (gsi, code, cond_type, aa1, aa2);
1126 else if (a_is_scalar_bitmask)
1128 wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
1129 result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
1130 a, wide_int_to_tree (TREE_TYPE (a), w));
1131 aa = gimplify_build2 (gsi, NE_EXPR, boolean_type_node, result,
1132 build_zero_cst (TREE_TYPE (a)));
1134 else
1135 aa = tree_vec_extract (gsi, cond_type, a, comp_width, comp_index);
1136 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
1137 if (!CONSTANT_CLASS_P (result))
1138 constant_p = false;
1139 constructor_elt ce = {NULL_TREE, result};
1140 v->quick_push (ce);
1141 index = int_const_binop (PLUS_EXPR, index, width);
1142 if (width == comp_width)
1143 comp_index = index;
1144 else
1145 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
1148 if (constant_p)
1149 constr = build_vector_from_ctor (type, v);
1150 else
1151 constr = build_constructor (type, v);
1152 gimple_assign_set_rhs_from_tree (gsi, constr);
1153 update_stmt (gsi_stmt (*gsi));
1155 if (a_is_comparison)
1156 bitmap_set_bit (dce_ssa_names,
1157 SSA_NAME_VERSION (gimple_assign_lhs (assign)));
1159 return false;
1162 static tree
1163 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1164 gassign *assign, enum tree_code code,
1165 bitmap dce_ssa_names)
1167 machine_mode compute_mode = TYPE_MODE (compute_type);
1169 /* If the compute mode is not a vector mode (hence we are not decomposing
1170 a BLKmode vector to smaller, hardware-supported vectors), we may want
1171 to expand the operations in parallel. */
1172 if (!VECTOR_MODE_P (compute_mode))
1173 switch (code)
1175 case PLUS_EXPR:
1176 case MINUS_EXPR:
1177 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1178 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
1179 gimple_assign_rhs1 (assign),
1180 gimple_assign_rhs2 (assign), code);
1181 break;
1183 case NEGATE_EXPR:
1184 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
1185 return expand_vector_addition (gsi, do_unop, do_negate, type,
1186 gimple_assign_rhs1 (assign),
1187 NULL_TREE, code);
1188 break;
1190 case BIT_AND_EXPR:
1191 case BIT_IOR_EXPR:
1192 case BIT_XOR_EXPR:
1193 return expand_vector_parallel (gsi, do_binop, type,
1194 gimple_assign_rhs1 (assign),
1195 gimple_assign_rhs2 (assign), code);
1197 case BIT_NOT_EXPR:
1198 return expand_vector_parallel (gsi, do_unop, type,
1199 gimple_assign_rhs1 (assign),
1200 NULL_TREE, code);
1201 case EQ_EXPR:
1202 case NE_EXPR:
1203 case GT_EXPR:
1204 case LT_EXPR:
1205 case GE_EXPR:
1206 case LE_EXPR:
1207 case UNEQ_EXPR:
1208 case UNGT_EXPR:
1209 case UNLT_EXPR:
1210 case UNGE_EXPR:
1211 case UNLE_EXPR:
1212 case LTGT_EXPR:
1213 case ORDERED_EXPR:
1214 case UNORDERED_EXPR:
1216 tree rhs1 = gimple_assign_rhs1 (assign);
1217 tree rhs2 = gimple_assign_rhs2 (assign);
1219 return expand_vector_comparison (gsi, type, rhs1, rhs2, code,
1220 dce_ssa_names);
1223 case TRUNC_DIV_EXPR:
1224 case TRUNC_MOD_EXPR:
1226 tree rhs1 = gimple_assign_rhs1 (assign);
1227 tree rhs2 = gimple_assign_rhs2 (assign);
1228 tree ret;
1230 if (!optimize
1231 || !VECTOR_INTEGER_TYPE_P (type)
1232 || TREE_CODE (rhs2) != VECTOR_CST
1233 || !VECTOR_MODE_P (TYPE_MODE (type)))
1234 break;
1236 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1237 if (ret != NULL_TREE)
1238 return ret;
1239 break;
1242 default:
1243 break;
1246 if (TREE_CODE_CLASS (code) == tcc_unary)
1247 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1248 gimple_assign_rhs1 (assign),
1249 NULL_TREE, code, false);
1250 else
1251 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1252 gimple_assign_rhs1 (assign),
1253 gimple_assign_rhs2 (assign), code, false);
1256 /* Try to optimize
1257 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1258 style stmts into:
1259 _9 = { b_7, b_7, b_7, b_7 };
1260 a_5 = _9 + { 0, 3, 6, 9 };
1261 because vector splat operation is usually more efficient
1262 than piecewise initialization of the vector. */
1264 static void
1265 optimize_vector_constructor (gimple_stmt_iterator *gsi)
1267 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1268 tree lhs = gimple_assign_lhs (stmt);
1269 tree rhs = gimple_assign_rhs1 (stmt);
1270 tree type = TREE_TYPE (rhs);
1271 unsigned int i, j;
1272 unsigned HOST_WIDE_INT nelts;
1273 bool all_same = true;
1274 constructor_elt *elt;
1275 gimple *g;
1276 tree base = NULL_TREE;
1277 optab op;
1279 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1280 || nelts <= 2
1281 || CONSTRUCTOR_NELTS (rhs) != nelts)
1282 return;
1283 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1284 if (op == unknown_optab
1285 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1286 return;
1287 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1288 if (TREE_CODE (elt->value) != SSA_NAME
1289 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1290 return;
1291 else
1293 tree this_base = elt->value;
1294 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1295 all_same = false;
1296 for (j = 0; j < nelts + 1; j++)
1298 g = SSA_NAME_DEF_STMT (this_base);
1299 if (is_gimple_assign (g)
1300 && gimple_assign_rhs_code (g) == PLUS_EXPR
1301 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1302 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1303 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1304 this_base = gimple_assign_rhs1 (g);
1305 else
1306 break;
1308 if (i == 0)
1309 base = this_base;
1310 else if (this_base != base)
1311 return;
1313 if (all_same)
1314 return;
1315 tree_vector_builder cst (type, nelts, 1);
1316 for (i = 0; i < nelts; i++)
1318 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1319 tree elt = build_zero_cst (TREE_TYPE (base));
1320 while (this_base != base)
1322 g = SSA_NAME_DEF_STMT (this_base);
1323 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1324 elt, gimple_assign_rhs2 (g));
1325 if (elt == NULL_TREE
1326 || TREE_CODE (elt) != INTEGER_CST
1327 || TREE_OVERFLOW (elt))
1328 return;
1329 this_base = gimple_assign_rhs1 (g);
1331 cst.quick_push (elt);
1333 for (i = 0; i < nelts; i++)
1334 CONSTRUCTOR_ELT (rhs, i)->value = base;
1335 g = gimple_build_assign (make_ssa_name (type), rhs);
1336 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1337 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1338 cst.build ());
1339 gsi_replace (gsi, g, false);
1342 /* Return a type for the widest vector mode whose components are of type
1343 TYPE, or NULL_TREE if none is found. */
1345 static tree
1346 type_for_widest_vector_mode (tree type, optab op)
1348 machine_mode inner_mode = TYPE_MODE (type);
1349 machine_mode best_mode = VOIDmode, mode;
1350 poly_int64 best_nunits = 0;
1352 if (SCALAR_FLOAT_MODE_P (inner_mode))
1353 mode = MIN_MODE_VECTOR_FLOAT;
1354 else if (SCALAR_FRACT_MODE_P (inner_mode))
1355 mode = MIN_MODE_VECTOR_FRACT;
1356 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1357 mode = MIN_MODE_VECTOR_UFRACT;
1358 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1359 mode = MIN_MODE_VECTOR_ACCUM;
1360 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1361 mode = MIN_MODE_VECTOR_UACCUM;
1362 else if (inner_mode == BImode)
1363 mode = MIN_MODE_VECTOR_BOOL;
1364 else
1365 mode = MIN_MODE_VECTOR_INT;
1367 FOR_EACH_MODE_FROM (mode, mode)
1368 if (GET_MODE_INNER (mode) == inner_mode
1369 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
1370 && optab_handler (op, mode) != CODE_FOR_nothing)
1371 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1373 if (best_mode == VOIDmode)
1374 return NULL_TREE;
1375 else
1376 return build_vector_type_for_mode (type, best_mode);
1380 /* Build a reference to the element of the vector VECT. Function
1381 returns either the element itself, either BIT_FIELD_REF, or an
1382 ARRAY_REF expression.
1384 GSI is required to insert temporary variables while building a
1385 refernece to the element of the vector VECT.
1387 PTMPVEC is a pointer to the temporary variable for caching
1388 purposes. In case when PTMPVEC is NULL new temporary variable
1389 will be created. */
1390 static tree
1391 vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1393 tree vect_type, vect_elt_type;
1394 gimple *asgn;
1395 tree tmpvec;
1396 tree arraytype;
1397 bool need_asgn = true;
1398 unsigned int elements;
1400 vect_type = TREE_TYPE (vect);
1401 vect_elt_type = TREE_TYPE (vect_type);
1402 elements = nunits_for_known_piecewise_op (vect_type);
1404 if (TREE_CODE (idx) == INTEGER_CST)
1406 unsigned HOST_WIDE_INT index;
1408 /* Given that we're about to compute a binary modulus,
1409 we don't care about the high bits of the value. */
1410 index = TREE_INT_CST_LOW (idx);
1411 if (!tree_fits_uhwi_p (idx) || index >= elements)
1413 index &= elements - 1;
1414 idx = build_int_cst (TREE_TYPE (idx), index);
1417 /* When lowering a vector statement sequence do some easy
1418 simplification by looking through intermediate vector results. */
1419 if (TREE_CODE (vect) == SSA_NAME)
1421 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
1422 if (is_gimple_assign (def_stmt)
1423 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1424 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1425 vect = gimple_assign_rhs1 (def_stmt);
1428 if (TREE_CODE (vect) == VECTOR_CST)
1429 return VECTOR_CST_ELT (vect, index);
1430 else if (TREE_CODE (vect) == CONSTRUCTOR
1431 && (CONSTRUCTOR_NELTS (vect) == 0
1432 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1433 != VECTOR_TYPE))
1435 if (index < CONSTRUCTOR_NELTS (vect))
1436 return CONSTRUCTOR_ELT (vect, index)->value;
1437 return build_zero_cst (vect_elt_type);
1439 else
1441 tree size = vector_element_bits_tree (vect_type);
1442 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1443 size);
1444 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1448 if (!ptmpvec)
1449 tmpvec = create_tmp_var (vect_type, "vectmp");
1450 else if (!*ptmpvec)
1451 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1452 else
1454 tmpvec = *ptmpvec;
1455 need_asgn = false;
1458 if (need_asgn)
1460 TREE_ADDRESSABLE (tmpvec) = 1;
1461 asgn = gimple_build_assign (tmpvec, vect);
1462 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1465 arraytype = build_array_type_nelts (vect_elt_type, elements);
1466 return build4 (ARRAY_REF, vect_elt_type,
1467 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1468 idx, NULL_TREE, NULL_TREE);
1471 /* Check if VEC_PERM_EXPR within the given setting is supported
1472 by hardware, or lower it piecewise.
1474 When VEC_PERM_EXPR has the same first and second operands:
1475 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1476 {v0[mask[0]], v0[mask[1]], ...}
1477 MASK and V0 must have the same number of elements.
1479 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1480 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1481 V0 and V1 must have the same type. MASK, V0, V1 must have the
1482 same number of arguments. */
1484 static void
1485 lower_vec_perm (gimple_stmt_iterator *gsi)
1487 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1488 tree mask = gimple_assign_rhs3 (stmt);
1489 tree vec0 = gimple_assign_rhs1 (stmt);
1490 tree vec1 = gimple_assign_rhs2 (stmt);
1491 tree vect_type = TREE_TYPE (vec0);
1492 tree mask_type = TREE_TYPE (mask);
1493 tree vect_elt_type = TREE_TYPE (vect_type);
1494 tree mask_elt_type = TREE_TYPE (mask_type);
1495 unsigned HOST_WIDE_INT elements;
1496 vec<constructor_elt, va_gc> *v;
1497 tree constr, t, si, i_val;
1498 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1499 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1500 location_t loc = gimple_location (gsi_stmt (*gsi));
1501 unsigned i;
1503 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1504 return;
1506 if (TREE_CODE (mask) == SSA_NAME)
1508 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
1509 if (is_gimple_assign (def_stmt)
1510 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1511 mask = gimple_assign_rhs1 (def_stmt);
1514 vec_perm_builder sel_int;
1516 if (TREE_CODE (mask) == VECTOR_CST
1517 && tree_to_vec_perm_builder (&sel_int, mask))
1519 vec_perm_indices indices (sel_int, 2, elements);
1520 machine_mode vmode = TYPE_MODE (vect_type);
1521 tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt));
1522 machine_mode lhs_mode = TYPE_MODE (lhs_type);
1523 if (can_vec_perm_const_p (lhs_mode, vmode, indices))
1525 gimple_assign_set_rhs3 (stmt, mask);
1526 update_stmt (stmt);
1527 return;
1529 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1530 vector as VEC1 and a right element shift MASK. */
1531 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1532 != CODE_FOR_nothing
1533 && TREE_CODE (vec1) == VECTOR_CST
1534 && initializer_zerop (vec1)
1535 && maybe_ne (indices[0], 0)
1536 && known_lt (poly_uint64 (indices[0]), elements))
1538 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1539 if (!ok_p)
1541 for (i = 1; i < elements; ++i)
1543 poly_uint64 actual = indices[i];
1544 poly_uint64 expected = i + indices[0];
1545 /* Indices into the second vector are all equivalent. */
1546 if (maybe_lt (actual, elements)
1547 ? maybe_ne (actual, expected)
1548 : maybe_lt (expected, elements))
1549 break;
1551 ok_p = i == elements;
1553 if (ok_p)
1555 gimple_assign_set_rhs3 (stmt, mask);
1556 update_stmt (stmt);
1557 return;
1560 /* And similarly vec_shl pattern. */
1561 if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
1562 != CODE_FOR_nothing
1563 && TREE_CODE (vec0) == VECTOR_CST
1564 && initializer_zerop (vec0))
1566 unsigned int first = 0;
1567 for (i = 0; i < elements; ++i)
1568 if (known_eq (poly_uint64 (indices[i]), elements))
1570 if (i == 0 || first)
1571 break;
1572 first = i;
1574 else if (first
1575 ? maybe_ne (poly_uint64 (indices[i]),
1576 elements + i - first)
1577 : maybe_ge (poly_uint64 (indices[i]), elements))
1578 break;
1579 if (first && i == elements)
1581 gimple_assign_set_rhs3 (stmt, mask);
1582 update_stmt (stmt);
1583 return;
1587 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
1588 return;
1590 if (!warning_suppressed_p (stmt, OPT_Wvector_operation_performance))
1591 warning_at (loc, OPT_Wvector_operation_performance,
1592 "vector shuffling operation will be expanded piecewise");
1594 vec_alloc (v, elements);
1595 bool constant_p = true;
1596 for (i = 0; i < elements; i++)
1598 si = size_int (i);
1599 i_val = vector_element (gsi, mask, si, &masktmp);
1601 if (TREE_CODE (i_val) == INTEGER_CST)
1603 unsigned HOST_WIDE_INT index;
1605 index = TREE_INT_CST_LOW (i_val);
1606 if (!tree_fits_uhwi_p (i_val) || index >= elements)
1607 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1609 if (two_operand_p && (index & elements) != 0)
1610 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1611 else
1612 t = vector_element (gsi, vec0, i_val, &vec0tmp);
1614 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1615 true, GSI_SAME_STMT);
1617 else
1619 tree cond = NULL_TREE, v0_val;
1621 if (two_operand_p)
1623 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1624 build_int_cst (mask_elt_type, elements));
1625 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1626 true, GSI_SAME_STMT);
1629 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1630 build_int_cst (mask_elt_type, elements - 1));
1631 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1632 true, GSI_SAME_STMT);
1634 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1635 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1636 true, GSI_SAME_STMT);
1638 if (two_operand_p)
1640 tree v1_val;
1642 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1643 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1644 true, GSI_SAME_STMT);
1646 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1647 cond, build_zero_cst (mask_elt_type));
1648 cond = fold_build3 (COND_EXPR, vect_elt_type,
1649 cond, v0_val, v1_val);
1650 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1651 true, GSI_SAME_STMT);
1653 else
1654 t = v0_val;
1657 if (!CONSTANT_CLASS_P (t))
1658 constant_p = false;
1659 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1662 if (constant_p)
1663 constr = build_vector_from_ctor (vect_type, v);
1664 else
1665 constr = build_constructor (vect_type, v);
1666 gimple_assign_set_rhs_from_tree (gsi, constr);
1667 update_stmt (gsi_stmt (*gsi));
1670 /* If OP is a uniform vector return the element it is a splat from. */
1672 static tree
1673 ssa_uniform_vector_p (tree op)
1675 if (TREE_CODE (op) == VECTOR_CST
1676 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
1677 || TREE_CODE (op) == CONSTRUCTOR)
1678 return uniform_vector_p (op);
1679 if (TREE_CODE (op) == SSA_NAME)
1681 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1682 if (gimple_assign_single_p (def_stmt))
1683 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1685 return NULL_TREE;
1688 /* Return type in which CODE operation with optab OP can be
1689 computed. */
1691 static tree
1692 get_compute_type (enum tree_code code, optab op, tree type)
1694 /* For very wide vectors, try using a smaller vector mode. */
1695 tree compute_type = type;
1696 if (op
1697 && (!VECTOR_MODE_P (TYPE_MODE (type))
1698 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1700 tree vector_compute_type
1701 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1702 if (vector_compute_type != NULL_TREE
1703 && subparts_gt (compute_type, vector_compute_type)
1704 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
1705 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1706 != CODE_FOR_nothing))
1707 compute_type = vector_compute_type;
1710 /* If we are breaking a BLKmode vector into smaller pieces,
1711 type_for_widest_vector_mode has already looked into the optab,
1712 so skip these checks. */
1713 if (compute_type == type)
1715 machine_mode compute_mode = TYPE_MODE (compute_type);
1716 if (VECTOR_MODE_P (compute_mode))
1718 if (op
1719 && (optab_handler (op, compute_mode) != CODE_FOR_nothing
1720 || optab_libfunc (op, compute_mode)))
1721 return compute_type;
1722 if (code == MULT_HIGHPART_EXPR
1723 && can_mult_highpart_p (compute_mode,
1724 TYPE_UNSIGNED (compute_type)))
1725 return compute_type;
1727 /* There is no operation in hardware, so fall back to scalars. */
1728 compute_type = TREE_TYPE (type);
1731 return compute_type;
1734 static tree
1735 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1736 tree bitpos, tree bitsize, enum tree_code code,
1737 tree type ATTRIBUTE_UNUSED)
1739 if (VECTOR_TYPE_P (TREE_TYPE (a)))
1740 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1741 if (VECTOR_TYPE_P (TREE_TYPE (b)))
1742 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1743 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1744 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
1747 /* Expand a vector COND_EXPR to scalars, piecewise. */
1748 static void
1749 expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1751 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1752 tree lhs = gimple_assign_lhs (stmt);
1753 tree type = TREE_TYPE (lhs);
1754 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1755 machine_mode compute_mode = TYPE_MODE (compute_type);
1756 gcc_assert (compute_mode != BLKmode);
1757 tree rhs2 = gimple_assign_rhs2 (stmt);
1758 tree rhs3 = gimple_assign_rhs3 (stmt);
1759 tree new_rhs;
1761 /* If the compute mode is not a vector mode (hence we are not decomposing
1762 a BLKmode vector to smaller, hardware-supported vectors), we may want
1763 to expand the operations in parallel. */
1764 if (!VECTOR_MODE_P (compute_mode))
1765 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1766 COND_EXPR);
1767 else
1768 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1769 rhs2, rhs3, COND_EXPR, false);
1770 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1771 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1772 new_rhs);
1774 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1775 way to do it is change expand_vector_operation and its callees to
1776 return a tree_code, RHS1 and RHS2 instead of a tree. */
1777 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1778 update_stmt (gsi_stmt (*gsi));
1781 /* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1782 lowering. If INNER_TYPE is not a vector type, this is a scalar
1783 fallback. */
1785 static tree
1786 do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1787 tree decl, tree bitpos, tree bitsize,
1788 enum tree_code code, tree type)
1790 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1791 if (!VECTOR_TYPE_P (inner_type))
1792 return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1793 if (code == CALL_EXPR)
1795 gimple *g = gimple_build_call (decl, 1, a);
1796 tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1797 gimple_call_set_lhs (g, lhs);
1798 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1799 return lhs;
1801 else
1803 tree outer_type = build_vector_type (TREE_TYPE (type),
1804 TYPE_VECTOR_SUBPARTS (inner_type));
1805 return gimplify_build1 (gsi, code, outer_type, a);
1809 /* Similarly, but for narrowing conversion. */
1811 static tree
1812 do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1813 tree, tree bitpos, tree, enum tree_code code,
1814 tree type)
1816 tree itype = build_vector_type (TREE_TYPE (inner_type),
1817 exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1818 2));
1819 tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1820 tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1821 int_const_binop (PLUS_EXPR, bitpos,
1822 TYPE_SIZE (itype)));
1823 tree outer_type = build_vector_type (TREE_TYPE (type),
1824 TYPE_VECTOR_SUBPARTS (inner_type));
1825 return gimplify_build2 (gsi, code, outer_type, b, c);
1828 /* Expand VEC_CONVERT ifn call. */
1830 static void
1831 expand_vector_conversion (gimple_stmt_iterator *gsi)
1833 gimple *stmt = gsi_stmt (*gsi);
1834 gimple *g;
1835 tree lhs = gimple_call_lhs (stmt);
1836 if (lhs == NULL_TREE)
1838 g = gimple_build_nop ();
1839 gsi_replace (gsi, g, false);
1840 return;
1842 tree arg = gimple_call_arg (stmt, 0);
1843 tree ret_type = TREE_TYPE (lhs);
1844 tree arg_type = TREE_TYPE (arg);
1845 tree new_rhs, compute_type = TREE_TYPE (arg_type);
1846 enum tree_code code = NOP_EXPR;
1847 enum tree_code code1 = ERROR_MARK;
1848 enum { NARROW, NONE, WIDEN } modifier = NONE;
1849 optab optab1 = unknown_optab;
1851 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1852 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1853 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1854 code = FIX_TRUNC_EXPR;
1855 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1856 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1857 code = FLOAT_EXPR;
1858 unsigned int ret_elt_bits = vector_element_bits (ret_type);
1859 unsigned int arg_elt_bits = vector_element_bits (arg_type);
1860 if (ret_elt_bits < arg_elt_bits)
1861 modifier = NARROW;
1862 else if (ret_elt_bits > arg_elt_bits)
1863 modifier = WIDEN;
1865 if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1867 if (supportable_convert_operation (code, ret_type, arg_type, &code1))
1869 g = gimple_build_assign (lhs, code1, arg);
1870 gsi_replace (gsi, g, false);
1871 return;
1873 /* Can't use get_compute_type here, as supportable_convert_operation
1874 doesn't necessarily use an optab and needs two arguments. */
1875 tree vec_compute_type
1876 = type_for_widest_vector_mode (TREE_TYPE (arg_type), mov_optab);
1877 if (vec_compute_type
1878 && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))
1879 && subparts_gt (arg_type, vec_compute_type))
1881 unsigned HOST_WIDE_INT nelts
1882 = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1883 while (nelts > 1)
1885 tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1886 tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1887 if (supportable_convert_operation (code, ret1_type, arg1_type,
1888 &code1))
1890 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1891 ret_type, arg1_type, arg,
1892 NULL_TREE, code1, false);
1893 g = gimple_build_assign (lhs, new_rhs);
1894 gsi_replace (gsi, g, false);
1895 return;
1897 nelts = nelts / 2;
1901 else if (modifier == NARROW)
1903 switch (code)
1905 CASE_CONVERT:
1906 code1 = VEC_PACK_TRUNC_EXPR;
1907 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1908 break;
1909 case FIX_TRUNC_EXPR:
1910 code1 = VEC_PACK_FIX_TRUNC_EXPR;
1911 /* The signedness is determined from output operand. */
1912 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1913 break;
1914 case FLOAT_EXPR:
1915 code1 = VEC_PACK_FLOAT_EXPR;
1916 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1917 break;
1918 default:
1919 gcc_unreachable ();
1922 if (optab1)
1923 compute_type = get_compute_type (code1, optab1, arg_type);
1924 enum insn_code icode1;
1925 if (VECTOR_TYPE_P (compute_type)
1926 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1927 != CODE_FOR_nothing)
1928 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1930 tree cretd_type
1931 = build_vector_type (TREE_TYPE (ret_type),
1932 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1933 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1935 if (compute_type == arg_type)
1937 new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1938 arg, build_zero_cst (arg_type));
1939 new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1940 TYPE_SIZE (ret_type),
1941 bitsize_int (0));
1942 g = gimple_build_assign (lhs, new_rhs);
1943 gsi_replace (gsi, g, false);
1944 return;
1946 tree dcompute_type
1947 = build_vector_type (TREE_TYPE (compute_type),
1948 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1949 if (TYPE_MAIN_VARIANT (dcompute_type)
1950 == TYPE_MAIN_VARIANT (arg_type))
1951 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1952 NULL_TREE, bitsize_int (0),
1953 NULL_TREE, code1,
1954 ret_type);
1955 else
1956 new_rhs = expand_vector_piecewise (gsi,
1957 do_vec_narrow_conversion,
1958 arg_type, dcompute_type,
1959 arg, NULL_TREE, code1,
1960 false, ret_type);
1961 g = gimple_build_assign (lhs, new_rhs);
1962 gsi_replace (gsi, g, false);
1963 return;
1967 else if (modifier == WIDEN)
1969 enum tree_code code2 = ERROR_MARK;
1970 optab optab2 = unknown_optab;
1971 switch (code)
1973 CASE_CONVERT:
1974 code1 = VEC_UNPACK_LO_EXPR;
1975 code2 = VEC_UNPACK_HI_EXPR;
1976 break;
1977 case FIX_TRUNC_EXPR:
1978 code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
1979 code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
1980 break;
1981 case FLOAT_EXPR:
1982 code1 = VEC_UNPACK_FLOAT_LO_EXPR;
1983 code2 = VEC_UNPACK_FLOAT_HI_EXPR;
1984 break;
1985 default:
1986 gcc_unreachable ();
1988 if (BYTES_BIG_ENDIAN)
1989 std::swap (code1, code2);
1991 if (code == FIX_TRUNC_EXPR)
1993 /* The signedness is determined from output operand. */
1994 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1995 optab2 = optab_for_tree_code (code2, ret_type, optab_default);
1997 else
1999 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
2000 optab2 = optab_for_tree_code (code2, arg_type, optab_default);
2003 if (optab1 && optab2)
2004 compute_type = get_compute_type (code1, optab1, arg_type);
2006 enum insn_code icode1, icode2;
2007 if (VECTOR_TYPE_P (compute_type)
2008 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
2009 != CODE_FOR_nothing)
2010 && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
2011 != CODE_FOR_nothing)
2012 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
2013 && (insn_data[icode1].operand[0].mode
2014 == insn_data[icode2].operand[0].mode))
2016 poly_uint64 nunits
2017 = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
2018 tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
2019 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
2021 vec<constructor_elt, va_gc> *v;
2022 tree part_width = TYPE_SIZE (compute_type);
2023 tree index = bitsize_int (0);
2024 int nunits = nunits_for_known_piecewise_op (arg_type);
2025 int delta = tree_to_uhwi (part_width) / arg_elt_bits;
2026 int i;
2027 location_t loc = gimple_location (gsi_stmt (*gsi));
2029 if (compute_type != arg_type)
2031 if (!warning_suppressed_p (gsi_stmt (*gsi),
2032 OPT_Wvector_operation_performance))
2033 warning_at (loc, OPT_Wvector_operation_performance,
2034 "vector operation will be expanded piecewise");
2036 else
2038 nunits = 1;
2039 delta = 1;
2042 vec_alloc (v, (nunits + delta - 1) / delta * 2);
2043 bool constant_p = true;
2044 for (i = 0; i < nunits;
2045 i += delta, index = int_const_binop (PLUS_EXPR, index,
2046 part_width))
2048 tree a = arg;
2049 if (compute_type != arg_type)
2050 a = tree_vec_extract (gsi, compute_type, a, part_width,
2051 index);
2052 tree result = gimplify_build1 (gsi, code1, cretd_type, a);
2053 constructor_elt ce = { NULL_TREE, result };
2054 if (!CONSTANT_CLASS_P (ce.value))
2055 constant_p = false;
2056 v->quick_push (ce);
2057 ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
2058 if (!CONSTANT_CLASS_P (ce.value))
2059 constant_p = false;
2060 v->quick_push (ce);
2063 if (constant_p)
2064 new_rhs = build_vector_from_ctor (ret_type, v);
2065 else
2066 new_rhs = build_constructor (ret_type, v);
2067 g = gimple_build_assign (lhs, new_rhs);
2068 gsi_replace (gsi, g, false);
2069 return;
2074 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
2075 TREE_TYPE (arg_type), arg,
2076 NULL_TREE, code, false, ret_type);
2077 g = gimple_build_assign (lhs, new_rhs);
2078 gsi_replace (gsi, g, false);
2081 /* Process one statement. If we identify a vector operation, expand it. */
2083 static void
2084 expand_vector_operations_1 (gimple_stmt_iterator *gsi,
2085 bitmap dce_ssa_names)
2087 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
2088 enum tree_code code;
2089 optab op = unknown_optab;
2090 enum gimple_rhs_class rhs_class;
2091 tree new_rhs;
2093 /* Only consider code == GIMPLE_ASSIGN. */
2094 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
2095 if (!stmt)
2097 if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
2098 expand_vector_conversion (gsi);
2099 return;
2102 code = gimple_assign_rhs_code (stmt);
2103 rhs_class = get_gimple_rhs_class (code);
2104 lhs = gimple_assign_lhs (stmt);
2106 if (code == VEC_PERM_EXPR)
2108 lower_vec_perm (gsi);
2109 return;
2112 if (code == VEC_COND_EXPR)
2114 expand_vector_condition (gsi, dce_ssa_names);
2115 return;
2118 if (code == COND_EXPR
2119 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
2120 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
2122 expand_vector_scalar_condition (gsi);
2123 return;
2126 if (code == CONSTRUCTOR
2127 && TREE_CODE (lhs) == SSA_NAME
2128 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
2129 && !gimple_clobber_p (stmt)
2130 && optimize)
2132 optimize_vector_constructor (gsi);
2133 return;
2136 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
2137 return;
2139 rhs1 = gimple_assign_rhs1 (stmt);
2140 if (rhs_class == GIMPLE_BINARY_RHS)
2141 rhs2 = gimple_assign_rhs2 (stmt);
2143 type = TREE_TYPE (lhs);
2144 if (!VECTOR_TYPE_P (type)
2145 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
2146 return;
2148 /* A scalar operation pretending to be a vector one. */
2149 if (VECTOR_BOOLEAN_TYPE_P (type)
2150 && !VECTOR_MODE_P (TYPE_MODE (type))
2151 && TYPE_MODE (type) != BLKmode
2152 && (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) != tcc_comparison
2153 || (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1))
2154 && !VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs1)))
2155 && TYPE_MODE (TREE_TYPE (rhs1)) != BLKmode)))
2156 return;
2158 /* If the vector operation is operating on all same vector elements
2159 implement it with a scalar operation and a splat if the target
2160 supports the scalar operation. */
2161 tree srhs1, srhs2 = NULL_TREE;
2162 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
2163 && (rhs2 == NULL_TREE
2164 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
2165 && (srhs2 = rhs2))
2166 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2167 /* As we query direct optabs restrict to non-convert operations. */
2168 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
2170 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
2171 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
2172 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
2174 tree stype = TREE_TYPE (TREE_TYPE (lhs));
2175 tree slhs = (rhs2 != NULL_TREE)
2176 ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
2177 : gimplify_build1 (gsi, code, stype, srhs1);
2178 gimple_assign_set_rhs_from_tree (gsi,
2179 build_vector_from_val (type, slhs));
2180 update_stmt (stmt);
2181 return;
2185 if (CONVERT_EXPR_CODE_P (code)
2186 || code == FLOAT_EXPR
2187 || code == FIX_TRUNC_EXPR
2188 || code == VIEW_CONVERT_EXPR)
2189 return;
2191 /* The signedness is determined from input argument. */
2192 if (code == VEC_UNPACK_FLOAT_HI_EXPR
2193 || code == VEC_UNPACK_FLOAT_LO_EXPR
2194 || code == VEC_PACK_FLOAT_EXPR)
2196 /* We do not know how to scalarize those. */
2197 return;
2200 /* For widening/narrowing vector operations, the relevant type is of the
2201 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
2202 calculated in the same way above. */
2203 if (code == WIDEN_SUM_EXPR
2204 || code == VEC_WIDEN_MULT_HI_EXPR
2205 || code == VEC_WIDEN_MULT_LO_EXPR
2206 || code == VEC_WIDEN_MULT_EVEN_EXPR
2207 || code == VEC_WIDEN_MULT_ODD_EXPR
2208 || code == VEC_UNPACK_HI_EXPR
2209 || code == VEC_UNPACK_LO_EXPR
2210 || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
2211 || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
2212 || code == VEC_PACK_TRUNC_EXPR
2213 || code == VEC_PACK_SAT_EXPR
2214 || code == VEC_PACK_FIX_TRUNC_EXPR
2215 || code == VEC_WIDEN_LSHIFT_HI_EXPR
2216 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
2218 /* We do not know how to scalarize those. */
2219 return;
2222 /* Choose between vector shift/rotate by vector and vector shift/rotate by
2223 scalar */
2224 if (code == LSHIFT_EXPR
2225 || code == RSHIFT_EXPR
2226 || code == LROTATE_EXPR
2227 || code == RROTATE_EXPR)
2229 optab opv;
2231 /* Check whether we have vector <op> {x,x,x,x} where x
2232 could be a scalar variable or a constant. Transform
2233 vector <op> {x,x,x,x} ==> vector <op> scalar. */
2234 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2236 tree first;
2238 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2240 gimple_assign_set_rhs2 (stmt, first);
2241 update_stmt (stmt);
2242 rhs2 = first;
2246 opv = optab_for_tree_code (code, type, optab_vector);
2247 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2248 op = opv;
2249 else
2251 op = optab_for_tree_code (code, type, optab_scalar);
2253 compute_type = get_compute_type (code, op, type);
2254 if (compute_type == type)
2255 return;
2256 /* The rtl expander will expand vector/scalar as vector/vector
2257 if necessary. Pick one with wider vector type. */
2258 tree compute_vtype = get_compute_type (code, opv, type);
2259 if (subparts_gt (compute_vtype, compute_type))
2261 compute_type = compute_vtype;
2262 op = opv;
2266 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2268 if (compute_type == NULL_TREE)
2269 compute_type = get_compute_type (code, op, type);
2270 if (compute_type == type)
2271 return;
2272 /* Before splitting vector rotates into scalar rotates,
2273 see if we can't use vector shifts and BIT_IOR_EXPR
2274 instead. For vector by vector rotates we'd also
2275 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2276 for now, fold doesn't seem to create such rotates anyway. */
2277 if (compute_type == TREE_TYPE (type)
2278 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2280 optab oplv = vashl_optab, opl = ashl_optab;
2281 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2282 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2283 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2284 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2285 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2286 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2287 /* The rtl expander will expand vector/scalar as vector/vector
2288 if necessary. Pick one with wider vector type. */
2289 if (subparts_gt (compute_lvtype, compute_ltype))
2291 compute_ltype = compute_lvtype;
2292 opl = oplv;
2294 if (subparts_gt (compute_rvtype, compute_rtype))
2296 compute_rtype = compute_rvtype;
2297 opr = oprv;
2299 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2300 BIT_IOR_EXPR. */
2301 compute_type = compute_ltype;
2302 if (subparts_gt (compute_type, compute_rtype))
2303 compute_type = compute_rtype;
2304 if (subparts_gt (compute_type, compute_otype))
2305 compute_type = compute_otype;
2306 /* Verify all 3 operations can be performed in that type. */
2307 if (compute_type != TREE_TYPE (type))
2309 if (optab_handler (opl, TYPE_MODE (compute_type))
2310 == CODE_FOR_nothing
2311 || optab_handler (opr, TYPE_MODE (compute_type))
2312 == CODE_FOR_nothing
2313 || optab_handler (opo, TYPE_MODE (compute_type))
2314 == CODE_FOR_nothing)
2315 compute_type = TREE_TYPE (type);
2320 else
2321 op = optab_for_tree_code (code, type, optab_default);
2323 /* Optabs will try converting a negation into a subtraction, so
2324 look for it as well. TODO: negation of floating-point vectors
2325 might be turned into an exclusive OR toggling the sign bit. */
2326 if (op == unknown_optab
2327 && code == NEGATE_EXPR
2328 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
2329 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
2331 if (compute_type == NULL_TREE)
2332 compute_type = get_compute_type (code, op, type);
2333 if (compute_type == type)
2334 return;
2336 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code,
2337 dce_ssa_names);
2339 /* Leave expression untouched for later expansion. */
2340 if (new_rhs == NULL_TREE)
2341 return;
2343 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2344 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2345 new_rhs);
2347 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2348 way to do it is change expand_vector_operation and its callees to
2349 return a tree_code, RHS1 and RHS2 instead of a tree. */
2350 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
2351 update_stmt (gsi_stmt (*gsi));
2354 /* Use this to lower vector operations introduced by the vectorizer,
2355 if it may need the bit-twiddling tricks implemented in this file. */
2357 static unsigned int
2358 expand_vector_operations (void)
2360 gimple_stmt_iterator gsi;
2361 basic_block bb;
2362 bool cfg_changed = false;
2364 auto_bitmap dce_ssa_names;
2366 FOR_EACH_BB_FN (bb, cfun)
2368 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2370 expand_vector_operations_1 (&gsi, dce_ssa_names);
2371 /* ??? If we do not cleanup EH then we will ICE in
2372 verification. But in reality we have created wrong-code
2373 as we did not properly transition EH info and edges to
2374 the piecewise computations. */
2375 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2376 && gimple_purge_dead_eh_edges (bb))
2377 cfg_changed = true;
2378 /* If a .LOOP_DIST_ALIAS call prevailed loops got elided
2379 before vectorization got a chance to get at them. Simply
2380 fold as if loop distribution wasn't performed. */
2381 if (gimple_call_internal_p (gsi_stmt (gsi), IFN_LOOP_DIST_ALIAS))
2383 fold_loop_internal_call (gsi_stmt (gsi), boolean_false_node);
2384 cfg_changed = true;
2389 simple_dce_from_worklist (dce_ssa_names);
2391 return cfg_changed ? TODO_cleanup_cfg : 0;
2394 namespace {
2396 const pass_data pass_data_lower_vector =
2398 GIMPLE_PASS, /* type */
2399 "veclower", /* name */
2400 OPTGROUP_VEC, /* optinfo_flags */
2401 TV_NONE, /* tv_id */
2402 PROP_cfg, /* properties_required */
2403 PROP_gimple_lvec, /* properties_provided */
2404 0, /* properties_destroyed */
2405 0, /* todo_flags_start */
2406 TODO_update_ssa, /* todo_flags_finish */
2409 class pass_lower_vector : public gimple_opt_pass
2411 public:
2412 pass_lower_vector (gcc::context *ctxt)
2413 : gimple_opt_pass (pass_data_lower_vector, ctxt)
2416 /* opt_pass methods: */
2417 bool gate (function *fun) final override
2419 return !(fun->curr_properties & PROP_gimple_lvec);
2422 unsigned int execute (function *) final override
2424 return expand_vector_operations ();
2427 }; // class pass_lower_vector
2429 } // anon namespace
2431 gimple_opt_pass *
2432 make_pass_lower_vector (gcc::context *ctxt)
2434 return new pass_lower_vector (ctxt);
2437 namespace {
2439 const pass_data pass_data_lower_vector_ssa =
2441 GIMPLE_PASS, /* type */
2442 "veclower2", /* name */
2443 OPTGROUP_VEC, /* optinfo_flags */
2444 TV_NONE, /* tv_id */
2445 PROP_cfg, /* properties_required */
2446 PROP_gimple_lvec, /* properties_provided */
2447 0, /* properties_destroyed */
2448 0, /* todo_flags_start */
2449 ( TODO_update_ssa
2450 | TODO_cleanup_cfg ), /* todo_flags_finish */
2453 class pass_lower_vector_ssa : public gimple_opt_pass
2455 public:
2456 pass_lower_vector_ssa (gcc::context *ctxt)
2457 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
2460 /* opt_pass methods: */
2461 opt_pass * clone () final override
2463 return new pass_lower_vector_ssa (m_ctxt);
2465 unsigned int execute (function *) final override
2467 return expand_vector_operations ();
2470 }; // class pass_lower_vector_ssa
2472 } // anon namespace
2474 gimple_opt_pass *
2475 make_pass_lower_vector_ssa (gcc::context *ctxt)
2477 return new pass_lower_vector_ssa (ctxt);
2480 #include "gt-tree-vect-generic.h"