]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-vect-generic.c
2019-04-15 Richard Biener <rguenther@suse.de>
[thirdparty/gcc.git] / gcc / tree-vect-generic.c
CommitLineData
0501cacc 1/* Lower vector operations to scalar operations.
fbd26352 2 Copyright (C) 2004-2019 Free Software Foundation, Inc.
0501cacc 3
4This file is part of GCC.
48e1416a 5
0501cacc 6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8c4c00c1 8Free Software Foundation; either version 3, or (at your option) any
0501cacc 9later version.
48e1416a 10
0501cacc 11GCC is distributed in the hope that it will be useful, but WITHOUT
12ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
48e1416a 15
0501cacc 16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
0501cacc 19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
9ef16211 23#include "backend.h"
7c29e30e 24#include "rtl.h"
0501cacc 25#include "tree.h"
9ef16211 26#include "gimple.h"
7c29e30e 27#include "tree-pass.h"
9ef16211 28#include "ssa.h"
7c29e30e 29#include "expmed.h"
30#include "optabs-tree.h"
31#include "diagnostic.h"
b20a8bb4 32#include "fold-const.h"
9ed99284 33#include "stor-layout.h"
0501cacc 34#include "langhooks.h"
bc61cadb 35#include "tree-eh.h"
dcf1a1ec 36#include "gimple-iterator.h"
e795d6e1 37#include "gimplify-me.h"
de34faa0 38#include "gimplify.h"
073c1fd5 39#include "tree-cfg.h"
6a8c2cbc 40#include "tree-vector-builder.h"
d37760c5 41#include "vec-perm-indices.h"
59409f09 42#include "insn-config.h"
43#include "recog.h" /* FIXME: for insn_data */
0501cacc 44
d7ad16c2 45
46static void expand_vector_operations_1 (gimple_stmt_iterator *);
47
5bf60cc1 48/* Return the number of elements in a vector type TYPE that we have
49 already decided needs to be expanded piecewise. We don't support
50 this kind of expansion for variable-length vectors, since we should
51 always check for target support before introducing uses of those. */
52static unsigned int
53nunits_for_known_piecewise_op (const_tree type)
54{
f08ee65f 55 return TYPE_VECTOR_SUBPARTS (type).to_constant ();
5bf60cc1 56}
57
58/* Return true if TYPE1 has more elements than TYPE2, where either
59 type may be a vector or a scalar. */
60
61static inline bool
62subparts_gt (tree type1, tree type2)
63{
64 poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
65 poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
66 return known_gt (n1, n2);
67}
d7ad16c2 68
0501cacc 69/* Build a constant of type TYPE, made of VALUE's bits replicated
70 every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
71static tree
72build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
73{
e913b5cd 74 int width = tree_to_uhwi (TYPE_SIZE (inner_type));
6c62aeae 75 int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
76 / HOST_BITS_PER_WIDE_INT;
e913b5cd 77 unsigned HOST_WIDE_INT low, mask;
78 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
79 int i;
0501cacc 80
a12aa4cc 81 gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
0501cacc 82
83 if (width == HOST_BITS_PER_WIDE_INT)
84 low = value;
85 else
86 {
87 mask = ((HOST_WIDE_INT)1 << width) - 1;
88 low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
89 }
90
e913b5cd 91 for (i = 0; i < n; i++)
92 a[i] = low;
0501cacc 93
a12aa4cc 94 gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
ddb1be65 95 return wide_int_to_tree
05363b4a 96 (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
0501cacc 97}
98
99static GTY(()) tree vector_inner_type;
100static GTY(()) tree vector_last_type;
101static GTY(()) int vector_last_nunits;
102
103/* Return a suitable vector types made of SUBPARTS units each of mode
104 "word_mode" (the global variable). */
105static tree
106build_word_mode_vector_type (int nunits)
107{
108 if (!vector_inner_type)
109 vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
110 else if (vector_last_nunits == nunits)
111 {
112 gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
113 return vector_last_type;
114 }
115
0501cacc 116 vector_last_nunits = nunits;
103cf5bb 117 vector_last_type = build_vector_type (vector_inner_type, nunits);
0501cacc 118 return vector_last_type;
119}
120
75a70cf9 121typedef tree (*elem_op_func) (gimple_stmt_iterator *,
1f137e6d 122 tree, tree, tree, tree, tree, enum tree_code,
123 tree);
0501cacc 124
3b76cef6 125tree
289cdf4a 126tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
127 tree t, tree bitsize, tree bitpos)
0501cacc 128{
de34faa0 129 if (TREE_CODE (t) == SSA_NAME)
130 {
131 gimple *def_stmt = SSA_NAME_DEF_STMT (t);
132 if (is_gimple_assign (def_stmt)
133 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
134 || (bitpos
135 && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)))
136 t = gimple_assign_rhs1 (def_stmt);
137 }
0501cacc 138 if (bitpos)
1f137e6d 139 {
140 if (TREE_CODE (type) == BOOLEAN_TYPE)
141 {
142 tree itype
143 = build_nonstandard_integer_type (tree_to_uhwi (bitsize), 0);
289cdf4a 144 tree field = gimplify_build3 (gsi, BIT_FIELD_REF, itype, t,
145 bitsize, bitpos);
146 return gimplify_build2 (gsi, NE_EXPR, type, field,
147 build_zero_cst (itype));
1f137e6d 148 }
289cdf4a 149 else
150 return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
1f137e6d 151 }
289cdf4a 152 else
153 return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
0501cacc 154}
155
156static tree
75a70cf9 157do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
0501cacc 158 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
1f137e6d 159 enum tree_code code, tree type ATTRIBUTE_UNUSED)
0501cacc 160{
289cdf4a 161 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
75a70cf9 162 return gimplify_build1 (gsi, code, inner_type, a);
0501cacc 163}
164
165static tree
75a70cf9 166do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1f137e6d 167 tree bitpos, tree bitsize, enum tree_code code,
168 tree type ATTRIBUTE_UNUSED)
0501cacc 169{
eab22dca 170 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
289cdf4a 171 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
eab22dca 172 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
289cdf4a 173 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
75a70cf9 174 return gimplify_build2 (gsi, code, inner_type, a, b);
0501cacc 175}
176
d7ad16c2 177/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
178
179 INNER_TYPE is the type of A and B elements
180
181 returned expression is of signed integer type with the
182 size equal to the size of INNER_TYPE. */
183static tree
184do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1f137e6d 185 tree bitpos, tree bitsize, enum tree_code code, tree type)
d7ad16c2 186{
097c0c82 187 tree stype = TREE_TYPE (type);
188 tree cst_false = build_zero_cst (stype);
189 tree cst_true = build_all_ones_cst (stype);
190 tree cmp;
191
289cdf4a 192 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
193 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
d7ad16c2 194
097c0c82 195 cmp = build2 (code, boolean_type_node, a, b);
196 return gimplify_build3 (gsi, COND_EXPR, stype, cmp, cst_true, cst_false);
d7ad16c2 197}
198
0501cacc 199/* Expand vector addition to scalars. This does bit twiddling
200 in order to increase parallelism:
201
202 a + b = (((int) a & 0x7f7f7f7f) + ((int) b & 0x7f7f7f7f)) ^
203 (a ^ b) & 0x80808080
204
205 a - b = (((int) a | 0x80808080) - ((int) b & 0x7f7f7f7f)) ^
206 (a ^ ~b) & 0x80808080
207
208 -b = (0x80808080 - ((int) b & 0x7f7f7f7f)) ^ (~b & 0x80808080)
209
210 This optimization should be done only if 4 vector items or more
211 fit into a word. */
212static tree
75a70cf9 213do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
0501cacc 214 tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
1f137e6d 215 enum tree_code code, tree type ATTRIBUTE_UNUSED)
0501cacc 216{
217 tree inner_type = TREE_TYPE (TREE_TYPE (a));
218 unsigned HOST_WIDE_INT max;
219 tree low_bits, high_bits, a_low, b_low, result_low, signs;
220
221 max = GET_MODE_MASK (TYPE_MODE (inner_type));
222 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
223 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
224
289cdf4a 225 a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
226 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
0501cacc 227
75a70cf9 228 signs = gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, a, b);
229 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
0501cacc 230 if (code == PLUS_EXPR)
75a70cf9 231 a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
0501cacc 232 else
233 {
75a70cf9 234 a_low = gimplify_build2 (gsi, BIT_IOR_EXPR, word_type, a, high_bits);
235 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, signs);
0501cacc 236 }
237
75a70cf9 238 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
239 result_low = gimplify_build2 (gsi, code, word_type, a_low, b_low);
240 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
0501cacc 241}
242
243static tree
75a70cf9 244do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
0501cacc 245 tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
246 tree bitsize ATTRIBUTE_UNUSED,
1f137e6d 247 enum tree_code code ATTRIBUTE_UNUSED,
248 tree type ATTRIBUTE_UNUSED)
0501cacc 249{
250 tree inner_type = TREE_TYPE (TREE_TYPE (b));
251 HOST_WIDE_INT max;
252 tree low_bits, high_bits, b_low, result_low, signs;
253
254 max = GET_MODE_MASK (TYPE_MODE (inner_type));
255 low_bits = build_replicated_const (word_type, inner_type, max >> 1);
256 high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
257
289cdf4a 258 b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
0501cacc 259
75a70cf9 260 b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
261 signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
262 signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
263 result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
264 return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
0501cacc 265}
266
267/* Expand a vector operation to scalars, by using many operations
268 whose type is the vector type's inner type. */
269static tree
75a70cf9 270expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
0501cacc 271 tree type, tree inner_type,
59409f09 272 tree a, tree b, enum tree_code code,
273 tree ret_type = NULL_TREE)
0501cacc 274{
f1f41a6c 275 vec<constructor_elt, va_gc> *v;
0501cacc 276 tree part_width = TYPE_SIZE (inner_type);
277 tree index = bitsize_int (0);
5bf60cc1 278 int nunits = nunits_for_known_piecewise_op (type);
e913b5cd 279 int delta = tree_to_uhwi (part_width)
280 / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
0501cacc 281 int i;
928efcfe 282 location_t loc = gimple_location (gsi_stmt (*gsi));
283
59409f09 284 if (ret_type
285 || types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
928efcfe 286 warning_at (loc, OPT_Wvector_operation_performance,
287 "vector operation will be expanded piecewise");
288 else
289 warning_at (loc, OPT_Wvector_operation_performance,
290 "vector operation will be expanded in parallel");
0501cacc 291
59409f09 292 if (!ret_type)
293 ret_type = type;
f1f41a6c 294 vec_alloc (v, (nunits + delta - 1) / delta);
0501cacc 295 for (i = 0; i < nunits;
317e2a67 296 i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
0501cacc 297 {
59409f09 298 tree result = f (gsi, inner_type, a, b, index, part_width, code,
299 ret_type);
e82e4eb5 300 constructor_elt ce = {NULL_TREE, result};
f1f41a6c 301 v->quick_push (ce);
0501cacc 302 }
303
59409f09 304 return build_constructor (ret_type, v);
0501cacc 305}
306
307/* Expand a vector operation to scalars with the freedom to use
308 a scalar integer type, or to use a different size for the items
309 in the vector type. */
310static tree
75a70cf9 311expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
59409f09 312 tree a, tree b, enum tree_code code)
0501cacc 313{
314 tree result, compute_type;
e913b5cd 315 int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
928efcfe 316 location_t loc = gimple_location (gsi_stmt (*gsi));
0501cacc 317
318 /* We have three strategies. If the type is already correct, just do
319 the operation an element at a time. Else, if the vector is wider than
320 one word, do it a word at a time; finally, if the vector is smaller
321 than one word, do it as a scalar. */
322 if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
75a70cf9 323 return expand_vector_piecewise (gsi, f,
0501cacc 324 type, TREE_TYPE (type),
325 a, b, code);
326 else if (n_words > 1)
327 {
328 tree word_type = build_word_mode_vector_type (n_words);
75a70cf9 329 result = expand_vector_piecewise (gsi, f,
0501cacc 330 word_type, TREE_TYPE (word_type),
331 a, b, code);
75a70cf9 332 result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
333 GSI_SAME_STMT);
0501cacc 334 }
335 else
336 {
337 /* Use a single scalar operation with a mode no wider than word_mode. */
44504d18 338 scalar_int_mode mode
339 = int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
0501cacc 340 compute_type = lang_hooks.types.type_for_mode (mode, 1);
1f137e6d 341 result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
928efcfe 342 warning_at (loc, OPT_Wvector_operation_performance,
343 "vector operation will be expanded with a "
344 "single scalar operation");
0501cacc 345 }
346
347 return result;
348}
349
350/* Expand a vector operation to scalars; for integer types we can use
351 special bit twiddling tricks to do the sums a word at a time, using
352 function F_PARALLEL instead of F. These tricks are done only if
353 they can process at least four items, that is, only if the vector
354 holds at least four items and if a word can hold four items. */
355static tree
75a70cf9 356expand_vector_addition (gimple_stmt_iterator *gsi,
0501cacc 357 elem_op_func f, elem_op_func f_parallel,
358 tree type, tree a, tree b, enum tree_code code)
359{
360 int parts_per_word = UNITS_PER_WORD
e913b5cd 361 / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
0501cacc 362
363 if (INTEGRAL_TYPE_P (TREE_TYPE (type))
364 && parts_per_word >= 4
5bf60cc1 365 && nunits_for_known_piecewise_op (type) >= 4)
75a70cf9 366 return expand_vector_parallel (gsi, f_parallel,
0501cacc 367 type, a, b, code);
368 else
75a70cf9 369 return expand_vector_piecewise (gsi, f,
0501cacc 370 type, TREE_TYPE (type),
371 a, b, code);
372}
373
d7ad16c2 374/* Try to expand vector comparison expression OP0 CODE OP1 by
375 querying optab if the following expression:
376 VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
377 can be expanded. */
378static tree
379expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
380 tree op1, enum tree_code code)
381{
382 tree t;
6a2e2a85 383 if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
384 && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
d7ad16c2 385 t = expand_vector_piecewise (gsi, do_compare, type,
386 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
387 else
388 t = NULL_TREE;
389
390 return t;
391}
392
60420e1c 393/* Helper function of expand_vector_divmod. Gimplify a RSHIFT_EXPR in type
394 of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
395 the result if successful, otherwise return NULL_TREE. */
396static tree
397add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
398{
399 optab op;
5bf60cc1 400 unsigned int i, nunits = nunits_for_known_piecewise_op (type);
60420e1c 401 bool scalar_shift = true;
402
403 for (i = 1; i < nunits; i++)
404 {
405 if (shiftcnts[i] != shiftcnts[0])
406 scalar_shift = false;
407 }
408
409 if (scalar_shift && shiftcnts[0] == 0)
410 return op0;
411
412 if (scalar_shift)
413 {
414 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
6cdd383a 415 if (op != unknown_optab
60420e1c 416 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
417 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
418 build_int_cst (NULL_TREE, shiftcnts[0]));
419 }
420
421 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
6cdd383a 422 if (op != unknown_optab
60420e1c 423 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
424 {
6a8c2cbc 425 tree_vector_builder vec (type, nunits, 1);
60420e1c 426 for (i = 0; i < nunits; i++)
eab42b58 427 vec.quick_push (build_int_cst (TREE_TYPE (type), shiftcnts[i]));
6a8c2cbc 428 return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0, vec.build ());
60420e1c 429 }
430
431 return NULL_TREE;
432}
433
434/* Try to expand integer vector division by constant using
435 widening multiply, shifts and additions. */
436static tree
437expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
438 tree op1, enum tree_code code)
439{
440 bool use_pow2 = true;
441 bool has_vector_shift = true;
442 int mode = -1, this_mode;
443 int pre_shift = -1, post_shift;
5bf60cc1 444 unsigned int nunits = nunits_for_known_piecewise_op (type);
60420e1c 445 int *shifts = XALLOCAVEC (int, nunits * 4);
446 int *pre_shifts = shifts + nunits;
447 int *post_shifts = pre_shifts + nunits;
448 int *shift_temps = post_shifts + nunits;
449 unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
450 int prec = TYPE_PRECISION (TREE_TYPE (type));
451 int dummy_int;
ddb1be65 452 unsigned int i;
e913b5cd 453 signop sign_p = TYPE_SIGN (TREE_TYPE (type));
60420e1c 454 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
ebf4f764 455 tree cur_op, mulcst, tem;
456 optab op;
60420e1c 457
458 if (prec > HOST_BITS_PER_WIDE_INT)
459 return NULL_TREE;
460
461 op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
6cdd383a 462 if (op == unknown_optab
60420e1c 463 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
464 has_vector_shift = false;
465
466 /* Analysis phase. Determine if all op1 elements are either power
467 of two and it is possible to expand it using shifts (or for remainder
468 using masking). Additionally compute the multiplicative constants
469 and pre and post shifts if the division is to be expanded using
470 widening or high part multiplication plus shifts. */
471 for (i = 0; i < nunits; i++)
472 {
473 tree cst = VECTOR_CST_ELT (op1, i);
474 unsigned HOST_WIDE_INT ml;
475
20448fd9 476 if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
60420e1c 477 return NULL_TREE;
478 pre_shifts[i] = 0;
479 post_shifts[i] = 0;
480 mulc[i] = 0;
481 if (use_pow2
482 && (!integer_pow2p (cst) || tree_int_cst_sgn (cst) != 1))
483 use_pow2 = false;
484 if (use_pow2)
485 {
486 shifts[i] = tree_log2 (cst);
487 if (shifts[i] != shifts[0]
488 && code == TRUNC_DIV_EXPR
489 && !has_vector_shift)
490 use_pow2 = false;
491 }
492 if (mode == -2)
493 continue;
e913b5cd 494 if (sign_p == UNSIGNED)
60420e1c 495 {
496 unsigned HOST_WIDE_INT mh;
f9ae6f95 497 unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
60420e1c 498
edc19fd0 499 if (d >= (HOST_WIDE_INT_1U << (prec - 1)))
60420e1c 500 /* FIXME: Can transform this into op0 >= op1 ? 1 : 0. */
501 return NULL_TREE;
502
503 if (d <= 1)
504 {
505 mode = -2;
506 continue;
507 }
508
509 /* Find a suitable multiplier and right shift count
510 instead of multiplying with D. */
511 mh = choose_multiplier (d, prec, prec, &ml, &post_shift, &dummy_int);
512
513 /* If the suggested multiplier is more than SIZE bits, we can
514 do better for even divisors, using an initial right shift. */
515 if ((mh != 0 && (d & 1) == 0)
516 || (!has_vector_shift && pre_shift != -1))
517 {
518 if (has_vector_shift)
ac29ece2 519 pre_shift = ctz_or_zero (d);
60420e1c 520 else if (pre_shift == -1)
521 {
522 unsigned int j;
523 for (j = 0; j < nunits; j++)
524 {
525 tree cst2 = VECTOR_CST_ELT (op1, j);
526 unsigned HOST_WIDE_INT d2;
527 int this_pre_shift;
528
e913b5cd 529 if (!tree_fits_uhwi_p (cst2))
60420e1c 530 return NULL_TREE;
e913b5cd 531 d2 = tree_to_uhwi (cst2) & mask;
60420e1c 532 if (d2 == 0)
533 return NULL_TREE;
534 this_pre_shift = floor_log2 (d2 & -d2);
535 if (pre_shift == -1 || this_pre_shift < pre_shift)
536 pre_shift = this_pre_shift;
537 }
538 if (i != 0 && pre_shift != 0)
539 {
540 /* Restart. */
541 i = -1U;
542 mode = -1;
543 continue;
544 }
545 }
546 if (pre_shift != 0)
547 {
548 if ((d >> pre_shift) <= 1)
549 {
550 mode = -2;
551 continue;
552 }
553 mh = choose_multiplier (d >> pre_shift, prec,
554 prec - pre_shift,
555 &ml, &post_shift, &dummy_int);
556 gcc_assert (!mh);
557 pre_shifts[i] = pre_shift;
558 }
559 }
560 if (!mh)
561 this_mode = 0;
562 else
563 this_mode = 1;
564 }
565 else
566 {
f9ae6f95 567 HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
60420e1c 568 unsigned HOST_WIDE_INT abs_d;
569
570 if (d == -1)
571 return NULL_TREE;
572
573 /* Since d might be INT_MIN, we have to cast to
574 unsigned HOST_WIDE_INT before negating to avoid
575 undefined signed overflow. */
576 abs_d = (d >= 0
577 ? (unsigned HOST_WIDE_INT) d
578 : - (unsigned HOST_WIDE_INT) d);
579
580 /* n rem d = n rem -d */
581 if (code == TRUNC_MOD_EXPR && d < 0)
582 d = abs_d;
edc19fd0 583 else if (abs_d == HOST_WIDE_INT_1U << (prec - 1))
60420e1c 584 {
585 /* This case is not handled correctly below. */
586 mode = -2;
587 continue;
588 }
589 if (abs_d <= 1)
590 {
591 mode = -2;
592 continue;
593 }
594
595 choose_multiplier (abs_d, prec, prec - 1, &ml,
596 &post_shift, &dummy_int);
edc19fd0 597 if (ml >= HOST_WIDE_INT_1U << (prec - 1))
60420e1c 598 {
599 this_mode = 4 + (d < 0);
7097b942 600 ml |= HOST_WIDE_INT_M1U << (prec - 1);
60420e1c 601 }
602 else
603 this_mode = 2 + (d < 0);
604 }
605 mulc[i] = ml;
606 post_shifts[i] = post_shift;
607 if ((i && !has_vector_shift && post_shifts[0] != post_shift)
608 || post_shift >= prec
609 || pre_shifts[i] >= prec)
610 this_mode = -2;
611
612 if (i == 0)
613 mode = this_mode;
614 else if (mode != this_mode)
615 mode = -2;
616 }
617
60420e1c 618 if (use_pow2)
619 {
620 tree addend = NULL_TREE;
e913b5cd 621 if (sign_p == SIGNED)
60420e1c 622 {
623 tree uns_type;
624
625 /* Both division and remainder sequences need
626 op0 < 0 ? mask : 0 computed. It can be either computed as
627 (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
628 if none of the shifts is 0, or as the conditional. */
629 for (i = 0; i < nunits; i++)
630 if (shifts[i] == 0)
631 break;
632 uns_type
633 = build_vector_type (build_nonstandard_integer_type (prec, 1),
634 nunits);
635 if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
636 {
637 for (i = 0; i < nunits; i++)
638 shift_temps[i] = prec - 1;
639 cur_op = add_rshift (gsi, type, op0, shift_temps);
640 if (cur_op != NULL_TREE)
641 {
642 cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
643 uns_type, cur_op);
644 for (i = 0; i < nunits; i++)
645 shift_temps[i] = prec - shifts[i];
646 cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
647 if (cur_op != NULL_TREE)
648 addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
649 type, cur_op);
650 }
651 }
652 if (addend == NULL_TREE
6a2e2a85 653 && expand_vec_cond_expr_p (type, type, LT_EXPR))
60420e1c 654 {
1f137e6d 655 tree zero, cst, cond, mask_type;
42acab1c 656 gimple *stmt;
60420e1c 657
1f137e6d 658 mask_type = build_same_sized_truth_vector_type (type);
60420e1c 659 zero = build_zero_cst (type);
1f137e6d 660 cond = build2 (LT_EXPR, mask_type, op0, zero);
6a8c2cbc 661 tree_vector_builder vec (type, nunits, 1);
60420e1c 662 for (i = 0; i < nunits; i++)
eab42b58 663 vec.quick_push (build_int_cst (TREE_TYPE (type),
664 (HOST_WIDE_INT_1U
665 << shifts[i]) - 1));
6a8c2cbc 666 cst = vec.build ();
f9e245b2 667 addend = make_ssa_name (type);
e9cf809e 668 stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
669 cst, zero);
60420e1c 670 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
671 }
672 }
673 if (code == TRUNC_DIV_EXPR)
674 {
e913b5cd 675 if (sign_p == UNSIGNED)
60420e1c 676 {
677 /* q = op0 >> shift; */
678 cur_op = add_rshift (gsi, type, op0, shifts);
679 if (cur_op != NULL_TREE)
680 return cur_op;
681 }
682 else if (addend != NULL_TREE)
683 {
684 /* t1 = op0 + addend;
685 q = t1 >> shift; */
686 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
6cdd383a 687 if (op != unknown_optab
60420e1c 688 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
689 {
690 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
691 cur_op = add_rshift (gsi, type, cur_op, shifts);
692 if (cur_op != NULL_TREE)
693 return cur_op;
694 }
695 }
696 }
697 else
698 {
699 tree mask;
6a8c2cbc 700 tree_vector_builder vec (type, nunits, 1);
60420e1c 701 for (i = 0; i < nunits; i++)
eab42b58 702 vec.quick_push (build_int_cst (TREE_TYPE (type),
703 (HOST_WIDE_INT_1U
704 << shifts[i]) - 1));
6a8c2cbc 705 mask = vec.build ();
60420e1c 706 op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
6cdd383a 707 if (op != unknown_optab
60420e1c 708 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
709 {
e913b5cd 710 if (sign_p == UNSIGNED)
60420e1c 711 /* r = op0 & mask; */
712 return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
713 else if (addend != NULL_TREE)
714 {
715 /* t1 = op0 + addend;
716 t2 = t1 & mask;
717 r = t2 - addend; */
718 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
6cdd383a 719 if (op != unknown_optab
60420e1c 720 && optab_handler (op, TYPE_MODE (type))
721 != CODE_FOR_nothing)
722 {
723 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
724 addend);
725 cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
726 cur_op, mask);
727 op = optab_for_tree_code (MINUS_EXPR, type,
728 optab_default);
6cdd383a 729 if (op != unknown_optab
60420e1c 730 && optab_handler (op, TYPE_MODE (type))
731 != CODE_FOR_nothing)
732 return gimplify_build2 (gsi, MINUS_EXPR, type,
733 cur_op, addend);
734 }
735 }
736 }
737 }
738 }
739
740 if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
741 return NULL_TREE;
742
ebf4f764 743 if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
744 return NULL_TREE;
60420e1c 745
746 cur_op = op0;
747
748 switch (mode)
749 {
750 case 0:
e913b5cd 751 gcc_assert (sign_p == UNSIGNED);
60420e1c 752 /* t1 = oprnd0 >> pre_shift;
99ee4cc8 753 t2 = t1 h* ml;
60420e1c 754 q = t2 >> post_shift; */
755 cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
756 if (cur_op == NULL_TREE)
757 return NULL_TREE;
758 break;
759 case 1:
e913b5cd 760 gcc_assert (sign_p == UNSIGNED);
60420e1c 761 for (i = 0; i < nunits; i++)
762 {
763 shift_temps[i] = 1;
764 post_shifts[i]--;
765 }
766 break;
767 case 2:
768 case 3:
769 case 4:
770 case 5:
e913b5cd 771 gcc_assert (sign_p == SIGNED);
60420e1c 772 for (i = 0; i < nunits; i++)
773 shift_temps[i] = prec - 1;
774 break;
775 default:
776 return NULL_TREE;
777 }
778
6a8c2cbc 779 tree_vector_builder vec (type, nunits, 1);
60420e1c 780 for (i = 0; i < nunits; i++)
eab42b58 781 vec.quick_push (build_int_cst (TREE_TYPE (type), mulc[i]));
6a8c2cbc 782 mulcst = vec.build ();
10dd7335 783
ebf4f764 784 cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
60420e1c 785
786 switch (mode)
787 {
788 case 0:
789 /* t1 = oprnd0 >> pre_shift;
99ee4cc8 790 t2 = t1 h* ml;
60420e1c 791 q = t2 >> post_shift; */
792 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
793 break;
794 case 1:
99ee4cc8 795 /* t1 = oprnd0 h* ml;
60420e1c 796 t2 = oprnd0 - t1;
797 t3 = t2 >> 1;
798 t4 = t1 + t3;
799 q = t4 >> (post_shift - 1); */
800 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
6cdd383a 801 if (op == unknown_optab
60420e1c 802 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
803 return NULL_TREE;
804 tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
805 tem = add_rshift (gsi, type, tem, shift_temps);
806 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
6cdd383a 807 if (op == unknown_optab
60420e1c 808 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
809 return NULL_TREE;
810 tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
811 cur_op = add_rshift (gsi, type, tem, post_shifts);
812 if (cur_op == NULL_TREE)
813 return NULL_TREE;
814 break;
815 case 2:
816 case 3:
817 case 4:
818 case 5:
99ee4cc8 819 /* t1 = oprnd0 h* ml;
60420e1c 820 t2 = t1; [ iff (mode & 2) != 0 ]
821 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
822 t3 = t2 >> post_shift;
823 t4 = oprnd0 >> (prec - 1);
824 q = t3 - t4; [ iff (mode & 1) == 0 ]
825 q = t4 - t3; [ iff (mode & 1) != 0 ] */
826 if ((mode & 2) == 0)
827 {
828 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
6cdd383a 829 if (op == unknown_optab
60420e1c 830 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
831 return NULL_TREE;
832 cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
833 }
834 cur_op = add_rshift (gsi, type, cur_op, post_shifts);
835 if (cur_op == NULL_TREE)
836 return NULL_TREE;
837 tem = add_rshift (gsi, type, op0, shift_temps);
838 if (tem == NULL_TREE)
839 return NULL_TREE;
840 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
6cdd383a 841 if (op == unknown_optab
60420e1c 842 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
843 return NULL_TREE;
844 if ((mode & 1) == 0)
845 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
846 else
847 cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
848 break;
849 default:
850 gcc_unreachable ();
851 }
852
853 if (code == TRUNC_DIV_EXPR)
854 return cur_op;
855
856 /* We divided. Now finish by:
857 t1 = q * oprnd1;
858 r = oprnd0 - t1; */
859 op = optab_for_tree_code (MULT_EXPR, type, optab_default);
6cdd383a 860 if (op == unknown_optab
60420e1c 861 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
862 return NULL_TREE;
863 tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
864 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
6cdd383a 865 if (op == unknown_optab
60420e1c 866 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
867 return NULL_TREE;
868 return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
869}
870
dd8c5e6c 871/* Expand a vector condition to scalars, by using many conditions
872 on the vector's elements. */
873static void
874expand_vector_condition (gimple_stmt_iterator *gsi)
875{
1a91d914 876 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
dd8c5e6c 877 tree type = gimple_expr_type (stmt);
878 tree a = gimple_assign_rhs1 (stmt);
879 tree a1 = a;
70e262d8 880 tree a2 = NULL_TREE;
dd8c5e6c 881 bool a_is_comparison = false;
882 tree b = gimple_assign_rhs2 (stmt);
883 tree c = gimple_assign_rhs3 (stmt);
f1f41a6c 884 vec<constructor_elt, va_gc> *v;
dd8c5e6c 885 tree constr;
886 tree inner_type = TREE_TYPE (type);
887 tree cond_type = TREE_TYPE (TREE_TYPE (a));
888 tree comp_inner_type = cond_type;
889 tree width = TYPE_SIZE (inner_type);
890 tree index = bitsize_int (0);
e45b0075 891 tree comp_width = width;
892 tree comp_index = index;
dd8c5e6c 893 int i;
894 location_t loc = gimple_location (gsi_stmt (*gsi));
895
f72ca119 896 if (!is_gimple_val (a))
dd8c5e6c 897 {
898 gcc_assert (COMPARISON_CLASS_P (a));
899 a_is_comparison = true;
900 a1 = TREE_OPERAND (a, 0);
901 a2 = TREE_OPERAND (a, 1);
902 comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
e45b0075 903 comp_width = TYPE_SIZE (comp_inner_type);
dd8c5e6c 904 }
905
6a2e2a85 906 if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
dd8c5e6c 907 return;
908
e45b0075 909 /* Handle vector boolean types with bitmasks. If there is a comparison
910 and we can expand the comparison into the vector boolean bitmask,
911 or otherwise if it is compatible with type, we can transform
912 vbfld_1 = x_2 < y_3 ? vbfld_4 : vbfld_5;
913 into
914 tmp_6 = x_2 < y_3;
915 tmp_7 = tmp_6 & vbfld_4;
916 tmp_8 = ~tmp_6;
917 tmp_9 = tmp_8 & vbfld_5;
918 vbfld_1 = tmp_7 | tmp_9;
919 Similarly for vbfld_10 instead of x_2 < y_3. */
920 if (VECTOR_BOOLEAN_TYPE_P (type)
921 && SCALAR_INT_MODE_P (TYPE_MODE (type))
f08ee65f 922 && known_lt (GET_MODE_BITSIZE (TYPE_MODE (type)),
923 TYPE_VECTOR_SUBPARTS (type)
924 * GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type))))
e45b0075 925 && (a_is_comparison
926 ? useless_type_conversion_p (type, TREE_TYPE (a))
927 : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
928 {
929 if (a_is_comparison)
930 a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
931 a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
932 a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
933 a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
934 a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
935 gimple_assign_set_rhs_from_tree (gsi, a);
936 update_stmt (gsi_stmt (*gsi));
937 return;
938 }
939
dd8c5e6c 940 /* TODO: try and find a smaller vector type. */
941
942 warning_at (loc, OPT_Wvector_operation_performance,
943 "vector condition will be expanded piecewise");
944
5bf60cc1 945 int nunits = nunits_for_known_piecewise_op (type);
f1f41a6c 946 vec_alloc (v, nunits);
e45b0075 947 for (i = 0; i < nunits; i++)
dd8c5e6c 948 {
949 tree aa, result;
289cdf4a 950 tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
951 tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
dd8c5e6c 952 if (a_is_comparison)
953 {
e45b0075 954 tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1,
955 comp_width, comp_index);
956 tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
957 comp_width, comp_index);
3f2ef661 958 aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
dd8c5e6c 959 }
960 else
289cdf4a 961 aa = tree_vec_extract (gsi, cond_type, a, width, index);
dd8c5e6c 962 result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
963 constructor_elt ce = {NULL_TREE, result};
f1f41a6c 964 v->quick_push (ce);
e45b0075 965 index = int_const_binop (PLUS_EXPR, index, width);
966 if (width == comp_width)
967 comp_index = index;
968 else
969 comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
dd8c5e6c 970 }
971
972 constr = build_constructor (type, v);
973 gimple_assign_set_rhs_from_tree (gsi, constr);
974 update_stmt (gsi_stmt (*gsi));
975}
976
0501cacc 977static tree
75a70cf9 978expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
1a91d914 979 gassign *assign, enum tree_code code)
0501cacc 980{
3754d046 981 machine_mode compute_mode = TYPE_MODE (compute_type);
0501cacc 982
983 /* If the compute mode is not a vector mode (hence we are not decomposing
984 a BLKmode vector to smaller, hardware-supported vectors), we may want
985 to expand the operations in parallel. */
8464736b 986 if (!VECTOR_MODE_P (compute_mode))
0501cacc 987 switch (code)
988 {
989 case PLUS_EXPR:
990 case MINUS_EXPR:
782a35e1 991 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
928efcfe 992 return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
993 gimple_assign_rhs1 (assign),
75a70cf9 994 gimple_assign_rhs2 (assign), code);
0501cacc 995 break;
996
997 case NEGATE_EXPR:
782a35e1 998 if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
75a70cf9 999 return expand_vector_addition (gsi, do_unop, do_negate, type,
1000 gimple_assign_rhs1 (assign),
0501cacc 1001 NULL_TREE, code);
1002 break;
1003
1004 case BIT_AND_EXPR:
1005 case BIT_IOR_EXPR:
1006 case BIT_XOR_EXPR:
75a70cf9 1007 return expand_vector_parallel (gsi, do_binop, type,
1008 gimple_assign_rhs1 (assign),
1009 gimple_assign_rhs2 (assign), code);
0501cacc 1010
1011 case BIT_NOT_EXPR:
75a70cf9 1012 return expand_vector_parallel (gsi, do_unop, type,
1013 gimple_assign_rhs1 (assign),
d7ad16c2 1014 NULL_TREE, code);
1015 case EQ_EXPR:
1016 case NE_EXPR:
1017 case GT_EXPR:
1018 case LT_EXPR:
1019 case GE_EXPR:
1020 case LE_EXPR:
1021 case UNEQ_EXPR:
1022 case UNGT_EXPR:
1023 case UNLT_EXPR:
1024 case UNGE_EXPR:
1025 case UNLE_EXPR:
1026 case LTGT_EXPR:
1027 case ORDERED_EXPR:
1028 case UNORDERED_EXPR:
1029 {
1030 tree rhs1 = gimple_assign_rhs1 (assign);
1031 tree rhs2 = gimple_assign_rhs2 (assign);
0501cacc 1032
d7ad16c2 1033 return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
1034 }
60420e1c 1035
1036 case TRUNC_DIV_EXPR:
1037 case TRUNC_MOD_EXPR:
1038 {
1039 tree rhs1 = gimple_assign_rhs1 (assign);
1040 tree rhs2 = gimple_assign_rhs2 (assign);
1041 tree ret;
1042
1043 if (!optimize
1044 || !VECTOR_INTEGER_TYPE_P (type)
7ecc7511 1045 || TREE_CODE (rhs2) != VECTOR_CST
1046 || !VECTOR_MODE_P (TYPE_MODE (type)))
60420e1c 1047 break;
1048
1049 ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1050 if (ret != NULL_TREE)
1051 return ret;
1052 break;
1053 }
1054
0501cacc 1055 default:
1056 break;
1057 }
1058
1059 if (TREE_CODE_CLASS (code) == tcc_unary)
75a70cf9 1060 return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1061 gimple_assign_rhs1 (assign),
0501cacc 1062 NULL_TREE, code);
1063 else
75a70cf9 1064 return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1065 gimple_assign_rhs1 (assign),
1066 gimple_assign_rhs2 (assign), code);
0501cacc 1067}
f1c75c81 1068
1069/* Try to optimize
1070 a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1071 style stmts into:
1072 _9 = { b_7, b_7, b_7, b_7 };
1073 a_5 = _9 + { 0, 3, 6, 9 };
1074 because vector splat operation is usually more efficient
1075 than piecewise initialization of the vector. */
1076
1077static void
1078optimize_vector_constructor (gimple_stmt_iterator *gsi)
1079{
1a91d914 1080 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
f1c75c81 1081 tree lhs = gimple_assign_lhs (stmt);
1082 tree rhs = gimple_assign_rhs1 (stmt);
1083 tree type = TREE_TYPE (rhs);
f08ee65f 1084 unsigned int i, j;
1085 unsigned HOST_WIDE_INT nelts;
f1c75c81 1086 bool all_same = true;
1087 constructor_elt *elt;
42acab1c 1088 gimple *g;
f1c75c81 1089 tree base = NULL_TREE;
93a5c118 1090 optab op;
f1c75c81 1091
f08ee65f 1092 if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
1093 || nelts <= 2
1094 || CONSTRUCTOR_NELTS (rhs) != nelts)
f1c75c81 1095 return;
93a5c118 1096 op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1097 if (op == unknown_optab
1098 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1099 return;
f1c75c81 1100 FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1101 if (TREE_CODE (elt->value) != SSA_NAME
1102 || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1103 return;
1104 else
1105 {
1106 tree this_base = elt->value;
1107 if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1108 all_same = false;
1109 for (j = 0; j < nelts + 1; j++)
1110 {
1111 g = SSA_NAME_DEF_STMT (this_base);
1112 if (is_gimple_assign (g)
1113 && gimple_assign_rhs_code (g) == PLUS_EXPR
1114 && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1115 && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1116 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1117 this_base = gimple_assign_rhs1 (g);
1118 else
1119 break;
1120 }
1121 if (i == 0)
1122 base = this_base;
1123 else if (this_base != base)
1124 return;
1125 }
1126 if (all_same)
1127 return;
6a8c2cbc 1128 tree_vector_builder cst (type, nelts, 1);
f1c75c81 1129 for (i = 0; i < nelts; i++)
1130 {
eab42b58 1131 tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;
1132 tree elt = build_zero_cst (TREE_TYPE (base));
f1c75c81 1133 while (this_base != base)
1134 {
1135 g = SSA_NAME_DEF_STMT (this_base);
eab42b58 1136 elt = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1137 elt, gimple_assign_rhs2 (g));
1138 if (elt == NULL_TREE
1139 || TREE_CODE (elt) != INTEGER_CST
1140 || TREE_OVERFLOW (elt))
f1c75c81 1141 return;
1142 this_base = gimple_assign_rhs1 (g);
1143 }
eab42b58 1144 cst.quick_push (elt);
f1c75c81 1145 }
1146 for (i = 0; i < nelts; i++)
1147 CONSTRUCTOR_ELT (rhs, i)->value = base;
f9e245b2 1148 g = gimple_build_assign (make_ssa_name (type), rhs);
f1c75c81 1149 gsi_insert_before (gsi, g, GSI_SAME_STMT);
e9cf809e 1150 g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
6a8c2cbc 1151 cst.build ());
f1c75c81 1152 gsi_replace (gsi, g, false);
1153}
0501cacc 1154\f
f1690ec2 1155/* Return a type for the widest vector mode whose components are of type
1156 TYPE, or NULL_TREE if none is found. */
06f0b99c 1157
0501cacc 1158static tree
f1690ec2 1159type_for_widest_vector_mode (tree type, optab op)
0501cacc 1160{
3754d046 1161 machine_mode inner_mode = TYPE_MODE (type);
1162 machine_mode best_mode = VOIDmode, mode;
ba7efd65 1163 poly_int64 best_nunits = 0;
0501cacc 1164
cee7491d 1165 if (SCALAR_FLOAT_MODE_P (inner_mode))
0501cacc 1166 mode = MIN_MODE_VECTOR_FLOAT;
06f0b99c 1167 else if (SCALAR_FRACT_MODE_P (inner_mode))
1168 mode = MIN_MODE_VECTOR_FRACT;
1169 else if (SCALAR_UFRACT_MODE_P (inner_mode))
1170 mode = MIN_MODE_VECTOR_UFRACT;
1171 else if (SCALAR_ACCUM_MODE_P (inner_mode))
1172 mode = MIN_MODE_VECTOR_ACCUM;
1173 else if (SCALAR_UACCUM_MODE_P (inner_mode))
1174 mode = MIN_MODE_VECTOR_UACCUM;
8464736b 1175 else if (inner_mode == BImode)
1176 mode = MIN_MODE_VECTOR_BOOL;
0501cacc 1177 else
1178 mode = MIN_MODE_VECTOR_INT;
1179
19a4dce4 1180 FOR_EACH_MODE_FROM (mode, mode)
0501cacc 1181 if (GET_MODE_INNER (mode) == inner_mode
ba7efd65 1182 && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
d6bf3b14 1183 && optab_handler (op, mode) != CODE_FOR_nothing)
0501cacc 1184 best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1185
1186 if (best_mode == VOIDmode)
1187 return NULL_TREE;
1188 else
f1690ec2 1189 return build_vector_type_for_mode (type, best_mode);
0501cacc 1190}
1191
6cf89e04 1192
1193/* Build a reference to the element of the vector VECT. Function
1194 returns either the element itself, either BIT_FIELD_REF, or an
1195 ARRAY_REF expression.
1196
9d75589a 1197 GSI is required to insert temporary variables while building a
6cf89e04 1198 refernece to the element of the vector VECT.
1199
1200 PTMPVEC is a pointer to the temporary variable for caching
1201 purposes. In case when PTMPVEC is NULL new temporary variable
1202 will be created. */
1203static tree
1204vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1205{
3c425d7c 1206 tree vect_type, vect_elt_type;
42acab1c 1207 gimple *asgn;
6cf89e04 1208 tree tmpvec;
1209 tree arraytype;
1210 bool need_asgn = true;
3c425d7c 1211 unsigned int elements;
6cf89e04 1212
3c425d7c 1213 vect_type = TREE_TYPE (vect);
1214 vect_elt_type = TREE_TYPE (vect_type);
5bf60cc1 1215 elements = nunits_for_known_piecewise_op (vect_type);
6cf89e04 1216
6cf89e04 1217 if (TREE_CODE (idx) == INTEGER_CST)
1218 {
1219 unsigned HOST_WIDE_INT index;
1220
3c425d7c 1221 /* Given that we're about to compute a binary modulus,
1222 we don't care about the high bits of the value. */
f9ae6f95 1223 index = TREE_INT_CST_LOW (idx);
e913b5cd 1224 if (!tree_fits_uhwi_p (idx) || index >= elements)
3c425d7c 1225 {
1226 index &= elements - 1;
1227 idx = build_int_cst (TREE_TYPE (idx), index);
1228 }
6cf89e04 1229
649aab9e 1230 /* When lowering a vector statement sequence do some easy
1231 simplification by looking through intermediate vector results. */
1232 if (TREE_CODE (vect) == SSA_NAME)
1233 {
42acab1c 1234 gimple *def_stmt = SSA_NAME_DEF_STMT (vect);
649aab9e 1235 if (is_gimple_assign (def_stmt)
1236 && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1237 || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1238 vect = gimple_assign_rhs1 (def_stmt);
1239 }
1240
6cf89e04 1241 if (TREE_CODE (vect) == VECTOR_CST)
fadf62f4 1242 return VECTOR_CST_ELT (vect, index);
569d18a5 1243 else if (TREE_CODE (vect) == CONSTRUCTOR
1244 && (CONSTRUCTOR_NELTS (vect) == 0
1245 || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1246 != VECTOR_TYPE))
6cf89e04 1247 {
569d18a5 1248 if (index < CONSTRUCTOR_NELTS (vect))
1249 return CONSTRUCTOR_ELT (vect, index)->value;
3c425d7c 1250 return build_zero_cst (vect_elt_type);
6cf89e04 1251 }
3c425d7c 1252 else
6cf89e04 1253 {
3c425d7c 1254 tree size = TYPE_SIZE (vect_elt_type);
891f5177 1255 tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1256 size);
1257 return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
6cf89e04 1258 }
6cf89e04 1259 }
1260
1261 if (!ptmpvec)
3c425d7c 1262 tmpvec = create_tmp_var (vect_type, "vectmp");
6cf89e04 1263 else if (!*ptmpvec)
3c425d7c 1264 tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
6cf89e04 1265 else
1266 {
1267 tmpvec = *ptmpvec;
1268 need_asgn = false;
1269 }
1270
1271 if (need_asgn)
1272 {
1273 TREE_ADDRESSABLE (tmpvec) = 1;
1274 asgn = gimple_build_assign (tmpvec, vect);
1275 gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1276 }
1277
3c425d7c 1278 arraytype = build_array_type_nelts (vect_elt_type, elements);
1279 return build4 (ARRAY_REF, vect_elt_type,
6cf89e04 1280 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1281 idx, NULL_TREE, NULL_TREE);
1282}
1283
f4803722 1284/* Check if VEC_PERM_EXPR within the given setting is supported
3c425d7c 1285 by hardware, or lower it piecewise.
6cf89e04 1286
f4803722 1287 When VEC_PERM_EXPR has the same first and second operands:
1288 VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
6cf89e04 1289 {v0[mask[0]], v0[mask[1]], ...}
1290 MASK and V0 must have the same number of elements.
1291
f4803722 1292 Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
6cf89e04 1293 {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1294 V0 and V1 must have the same type. MASK, V0, V1 must have the
1295 same number of arguments. */
6cf89e04 1296
3c425d7c 1297static void
f4803722 1298lower_vec_perm (gimple_stmt_iterator *gsi)
3c425d7c 1299{
1a91d914 1300 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
6cf89e04 1301 tree mask = gimple_assign_rhs3 (stmt);
1302 tree vec0 = gimple_assign_rhs1 (stmt);
1303 tree vec1 = gimple_assign_rhs2 (stmt);
3c425d7c 1304 tree vect_type = TREE_TYPE (vec0);
1305 tree mask_type = TREE_TYPE (mask);
1306 tree vect_elt_type = TREE_TYPE (vect_type);
1307 tree mask_elt_type = TREE_TYPE (mask_type);
f08ee65f 1308 unsigned HOST_WIDE_INT elements;
f1f41a6c 1309 vec<constructor_elt, va_gc> *v;
3c425d7c 1310 tree constr, t, si, i_val;
1311 tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1312 bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
928efcfe 1313 location_t loc = gimple_location (gsi_stmt (*gsi));
3c425d7c 1314 unsigned i;
6cf89e04 1315
f08ee65f 1316 if (!TYPE_VECTOR_SUBPARTS (vect_type).is_constant (&elements))
1317 return;
1318
53d84863 1319 if (TREE_CODE (mask) == SSA_NAME)
1320 {
42acab1c 1321 gimple *def_stmt = SSA_NAME_DEF_STMT (mask);
53d84863 1322 if (is_gimple_assign (def_stmt)
1323 && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1324 mask = gimple_assign_rhs1 (def_stmt);
1325 }
1326
1957c019 1327 vec_perm_builder sel_int;
e21c468f 1328
1957c019 1329 if (TREE_CODE (mask) == VECTOR_CST
1330 && tree_to_vec_perm_builder (&sel_int, mask))
1331 {
1332 vec_perm_indices indices (sel_int, 2, elements);
1333 if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices))
53d84863 1334 {
1335 gimple_assign_set_rhs3 (stmt, mask);
1336 update_stmt (stmt);
1337 return;
1338 }
7e436644 1339 /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1340 vector as VEC1 and a right element shift MASK. */
1341 if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1342 != CODE_FOR_nothing
1343 && TREE_CODE (vec1) == VECTOR_CST
1344 && initializer_zerop (vec1)
773fdd5f 1345 && maybe_ne (indices[0], 0)
f08ee65f 1346 && known_lt (poly_uint64 (indices[0]), elements))
7e436644 1347 {
90eb8822 1348 bool ok_p = indices.series_p (0, 1, indices[0], 1);
1349 if (!ok_p)
7e436644 1350 {
90eb8822 1351 for (i = 1; i < elements; ++i)
1352 {
f08ee65f 1353 poly_uint64 actual = indices[i];
1354 poly_uint64 expected = i + indices[0];
90eb8822 1355 /* Indices into the second vector are all equivalent. */
f08ee65f 1356 if (maybe_lt (actual, elements)
1357 ? maybe_ne (actual, expected)
773fdd5f 1358 : maybe_lt (expected, elements))
90eb8822 1359 break;
1360 }
1361 ok_p = i == elements;
7e436644 1362 }
90eb8822 1363 if (ok_p)
7e436644 1364 {
1365 gimple_assign_set_rhs3 (stmt, mask);
1366 update_stmt (stmt);
1367 return;
1368 }
1369 }
e21c468f 1370 }
97f7d65e 1371 else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
3c425d7c 1372 return;
928efcfe 1373
1374 warning_at (loc, OPT_Wvector_operation_performance,
1375 "vector shuffling operation will be expanded piecewise");
1376
f1f41a6c 1377 vec_alloc (v, elements);
3c425d7c 1378 for (i = 0; i < elements; i++)
6cf89e04 1379 {
3c425d7c 1380 si = size_int (i);
1381 i_val = vector_element (gsi, mask, si, &masktmp);
6cf89e04 1382
3c425d7c 1383 if (TREE_CODE (i_val) == INTEGER_CST)
6cf89e04 1384 {
3c425d7c 1385 unsigned HOST_WIDE_INT index;
6cf89e04 1386
f9ae6f95 1387 index = TREE_INT_CST_LOW (i_val);
e913b5cd 1388 if (!tree_fits_uhwi_p (i_val) || index >= elements)
3c425d7c 1389 i_val = build_int_cst (mask_elt_type, index & (elements - 1));
6cf89e04 1390
3c425d7c 1391 if (two_operand_p && (index & elements) != 0)
1392 t = vector_element (gsi, vec1, i_val, &vec1tmp);
1393 else
1394 t = vector_element (gsi, vec0, i_val, &vec0tmp);
6cf89e04 1395
3c425d7c 1396 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1397 true, GSI_SAME_STMT);
6cf89e04 1398 }
3c425d7c 1399 else
6cf89e04 1400 {
3c425d7c 1401 tree cond = NULL_TREE, v0_val;
1402
1403 if (two_operand_p)
1404 {
1405 cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1406 build_int_cst (mask_elt_type, elements));
1407 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1408 true, GSI_SAME_STMT);
1409 }
1410
1411 i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1412 build_int_cst (mask_elt_type, elements - 1));
1413 i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1414 true, GSI_SAME_STMT);
1415
1416 v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1417 v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1418 true, GSI_SAME_STMT);
1419
1420 if (two_operand_p)
1421 {
1422 tree v1_val;
1423
1424 v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1425 v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1426 true, GSI_SAME_STMT);
1427
1428 cond = fold_build2 (EQ_EXPR, boolean_type_node,
1429 cond, build_zero_cst (mask_elt_type));
1430 cond = fold_build3 (COND_EXPR, vect_elt_type,
1431 cond, v0_val, v1_val);
1432 t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1433 true, GSI_SAME_STMT);
6cf89e04 1434 }
3c425d7c 1435 else
1436 t = v0_val;
6cf89e04 1437 }
3c425d7c 1438
569d18a5 1439 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
6cf89e04 1440 }
1441
3c425d7c 1442 constr = build_constructor (vect_type, v);
6cf89e04 1443 gimple_assign_set_rhs_from_tree (gsi, constr);
3c425d7c 1444 update_stmt (gsi_stmt (*gsi));
6cf89e04 1445}
1446
ba257f0b 1447/* If OP is a uniform vector return the element it is a splat from. */
1448
1449static tree
1450ssa_uniform_vector_p (tree op)
1451{
1452 if (TREE_CODE (op) == VECTOR_CST
a308fcf8 1453 || TREE_CODE (op) == VEC_DUPLICATE_EXPR
ba257f0b 1454 || TREE_CODE (op) == CONSTRUCTOR)
1455 return uniform_vector_p (op);
1456 if (TREE_CODE (op) == SSA_NAME)
1457 {
1458 gimple *def_stmt = SSA_NAME_DEF_STMT (op);
1459 if (gimple_assign_single_p (def_stmt))
1460 return uniform_vector_p (gimple_assign_rhs1 (def_stmt));
1461 }
1462 return NULL_TREE;
1463}
1464
c10b4d55 1465/* Return type in which CODE operation with optab OP can be
1466 computed. */
1467
1468static tree
1469get_compute_type (enum tree_code code, optab op, tree type)
1470{
1471 /* For very wide vectors, try using a smaller vector mode. */
1472 tree compute_type = type;
1473 if (op
1474 && (!VECTOR_MODE_P (TYPE_MODE (type))
1475 || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1476 {
1477 tree vector_compute_type
1478 = type_for_widest_vector_mode (TREE_TYPE (type), op);
1479 if (vector_compute_type != NULL_TREE
5bf60cc1 1480 && subparts_gt (compute_type, vector_compute_type)
f08ee65f 1481 && maybe_ne (TYPE_VECTOR_SUBPARTS (vector_compute_type), 1U)
c10b4d55 1482 && (optab_handler (op, TYPE_MODE (vector_compute_type))
1483 != CODE_FOR_nothing))
1484 compute_type = vector_compute_type;
1485 }
1486
1487 /* If we are breaking a BLKmode vector into smaller pieces,
1488 type_for_widest_vector_mode has already looked into the optab,
1489 so skip these checks. */
1490 if (compute_type == type)
1491 {
3754d046 1492 machine_mode compute_mode = TYPE_MODE (compute_type);
c10b4d55 1493 if (VECTOR_MODE_P (compute_mode))
1494 {
1495 if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1496 return compute_type;
1497 if (code == MULT_HIGHPART_EXPR
1498 && can_mult_highpart_p (compute_mode,
1499 TYPE_UNSIGNED (compute_type)))
1500 return compute_type;
1501 }
1502 /* There is no operation in hardware, so fall back to scalars. */
1503 compute_type = TREE_TYPE (type);
1504 }
1505
1506 return compute_type;
1507}
1508
7e64a875 1509static tree
1510do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1f137e6d 1511 tree bitpos, tree bitsize, enum tree_code code,
1512 tree type ATTRIBUTE_UNUSED)
7e64a875 1513{
1514 if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
289cdf4a 1515 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
7e64a875 1516 if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
289cdf4a 1517 b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
7e64a875 1518 tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
de34faa0 1519 return gimplify_build3 (gsi, code, inner_type, unshare_expr (cond), a, b);
7e64a875 1520}
1521
1522/* Expand a vector COND_EXPR to scalars, piecewise. */
1523static void
1524expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1525{
1526 gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1527 tree type = gimple_expr_type (stmt);
1528 tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1529 machine_mode compute_mode = TYPE_MODE (compute_type);
1530 gcc_assert (compute_mode != BLKmode);
1531 tree lhs = gimple_assign_lhs (stmt);
1532 tree rhs2 = gimple_assign_rhs2 (stmt);
1533 tree rhs3 = gimple_assign_rhs3 (stmt);
1534 tree new_rhs;
1535
1536 /* If the compute mode is not a vector mode (hence we are not decomposing
1537 a BLKmode vector to smaller, hardware-supported vectors), we may want
1538 to expand the operations in parallel. */
8464736b 1539 if (!VECTOR_MODE_P (compute_mode))
7e64a875 1540 new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1541 COND_EXPR);
1542 else
1543 new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1544 rhs2, rhs3, COND_EXPR);
1545 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1546 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1547 new_rhs);
1548
1549 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
1550 way to do it is change expand_vector_operation and its callees to
1551 return a tree_code, RHS1 and RHS2 instead of a tree. */
1552 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1553 update_stmt (gsi_stmt (*gsi));
1554}
1555
59409f09 1556/* Callback for expand_vector_piecewise to do VEC_CONVERT ifn call
1557 lowering. If INNER_TYPE is not a vector type, this is a scalar
1558 fallback. */
1559
1560static tree
1561do_vec_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1562 tree decl, tree bitpos, tree bitsize,
1563 enum tree_code code, tree type)
1564{
1565 a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1566 if (!VECTOR_TYPE_P (inner_type))
1567 return gimplify_build1 (gsi, code, TREE_TYPE (type), a);
1568 if (code == CALL_EXPR)
1569 {
1570 gimple *g = gimple_build_call (decl, 1, a);
1571 tree lhs = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)));
1572 gimple_call_set_lhs (g, lhs);
1573 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1574 return lhs;
1575 }
1576 else
1577 {
1578 tree outer_type = build_vector_type (TREE_TYPE (type),
1579 TYPE_VECTOR_SUBPARTS (inner_type));
1580 return gimplify_build1 (gsi, code, outer_type, a);
1581 }
1582}
1583
1584/* Similarly, but for narrowing conversion. */
1585
1586static tree
1587do_vec_narrow_conversion (gimple_stmt_iterator *gsi, tree inner_type, tree a,
1588 tree, tree bitpos, tree, enum tree_code code,
1589 tree type)
1590{
1591 tree itype = build_vector_type (TREE_TYPE (inner_type),
1592 exact_div (TYPE_VECTOR_SUBPARTS (inner_type),
1593 2));
1594 tree b = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype), bitpos);
1595 tree c = tree_vec_extract (gsi, itype, a, TYPE_SIZE (itype),
1596 int_const_binop (PLUS_EXPR, bitpos,
1597 TYPE_SIZE (itype)));
1598 tree outer_type = build_vector_type (TREE_TYPE (type),
1599 TYPE_VECTOR_SUBPARTS (inner_type));
1600 return gimplify_build2 (gsi, code, outer_type, b, c);
1601}
1602
1603/* Expand VEC_CONVERT ifn call. */
1604
1605static void
1606expand_vector_conversion (gimple_stmt_iterator *gsi)
1607{
1608 gimple *stmt = gsi_stmt (*gsi);
1609 gimple *g;
1610 tree lhs = gimple_call_lhs (stmt);
1611 tree arg = gimple_call_arg (stmt, 0);
1612 tree decl = NULL_TREE;
1613 tree ret_type = TREE_TYPE (lhs);
1614 tree arg_type = TREE_TYPE (arg);
1615 tree new_rhs, compute_type = TREE_TYPE (arg_type);
1616 enum tree_code code = NOP_EXPR;
1617 enum tree_code code1 = ERROR_MARK;
1618 enum { NARROW, NONE, WIDEN } modifier = NONE;
1619 optab optab1 = unknown_optab;
1620
1621 gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
1622 gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (ret_type))));
1623 gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type))));
1624 if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
1625 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
1626 code = FIX_TRUNC_EXPR;
1627 else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
1628 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
1629 code = FLOAT_EXPR;
1630 if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
1631 < tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
1632 modifier = NARROW;
1633 else if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
1634 > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
1635 modifier = WIDEN;
1636
1637 if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
1638 {
1639 if (supportable_convert_operation (code, ret_type, arg_type, &decl,
1640 &code1))
1641 {
1642 if (code1 == CALL_EXPR)
1643 {
1644 g = gimple_build_call (decl, 1, arg);
1645 gimple_call_set_lhs (g, lhs);
1646 }
1647 else
1648 g = gimple_build_assign (lhs, code1, arg);
1649 gsi_replace (gsi, g, false);
1650 return;
1651 }
1652 /* Can't use get_compute_type here, as supportable_convert_operation
1653 doesn't necessarily use an optab and needs two arguments. */
1654 tree vec_compute_type
1655 = type_for_widest_vector_mode (TREE_TYPE (arg_type), mov_optab);
1656 if (vec_compute_type
1657 && VECTOR_MODE_P (TYPE_MODE (vec_compute_type))
1658 && subparts_gt (arg_type, vec_compute_type))
1659 {
1660 unsigned HOST_WIDE_INT nelts
1661 = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vec_compute_type));
1662 while (nelts > 1)
1663 {
1664 tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
1665 tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
1666 if (supportable_convert_operation (code, ret1_type, arg1_type,
1667 &decl, &code1))
1668 {
1669 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
1670 ret_type, arg1_type, arg,
1671 decl, code1);
1672 g = gimple_build_assign (lhs, new_rhs);
1673 gsi_replace (gsi, g, false);
1674 return;
1675 }
1676 nelts = nelts / 2;
1677 }
1678 }
1679 }
1680 else if (modifier == NARROW)
1681 {
1682 switch (code)
1683 {
1684 CASE_CONVERT:
1685 code1 = VEC_PACK_TRUNC_EXPR;
1686 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1687 break;
1688 case FIX_TRUNC_EXPR:
1689 code1 = VEC_PACK_FIX_TRUNC_EXPR;
1690 /* The signedness is determined from output operand. */
1691 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1692 break;
1693 case FLOAT_EXPR:
1694 code1 = VEC_PACK_FLOAT_EXPR;
1695 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1696 break;
1697 default:
1698 gcc_unreachable ();
1699 }
1700
1701 if (optab1)
1702 compute_type = get_compute_type (code1, optab1, arg_type);
1703 enum insn_code icode1;
1704 if (VECTOR_TYPE_P (compute_type)
1705 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1706 != CODE_FOR_nothing)
1707 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode))
1708 {
1709 tree cretd_type
1710 = build_vector_type (TREE_TYPE (ret_type),
1711 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1712 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1713 {
1714 if (compute_type == arg_type)
1715 {
1716 new_rhs = gimplify_build2 (gsi, code1, cretd_type,
1717 arg, build_zero_cst (arg_type));
1718 new_rhs = tree_vec_extract (gsi, ret_type, new_rhs,
1719 TYPE_SIZE (ret_type),
1720 bitsize_int (0));
1721 g = gimple_build_assign (lhs, new_rhs);
1722 gsi_replace (gsi, g, false);
1723 return;
1724 }
1725 tree dcompute_type
1726 = build_vector_type (TREE_TYPE (compute_type),
1727 TYPE_VECTOR_SUBPARTS (compute_type) * 2);
1728 if (TYPE_MAIN_VARIANT (dcompute_type)
1729 == TYPE_MAIN_VARIANT (arg_type))
1730 new_rhs = do_vec_narrow_conversion (gsi, dcompute_type, arg,
1731 NULL_TREE, bitsize_int (0),
1732 NULL_TREE, code1,
1733 ret_type);
1734 else
1735 new_rhs = expand_vector_piecewise (gsi,
1736 do_vec_narrow_conversion,
1737 arg_type, dcompute_type,
1738 arg, NULL_TREE, code1,
1739 ret_type);
1740 g = gimple_build_assign (lhs, new_rhs);
1741 gsi_replace (gsi, g, false);
1742 return;
1743 }
1744 }
1745 }
1746 else if (modifier == WIDEN)
1747 {
1748 enum tree_code code2 = ERROR_MARK;
1749 optab optab2 = unknown_optab;
1750 switch (code)
1751 {
1752 CASE_CONVERT:
1753 code1 = VEC_UNPACK_LO_EXPR;
1754 code2 = VEC_UNPACK_HI_EXPR;
1755 break;
1756 case FIX_TRUNC_EXPR:
1757 code1 = VEC_UNPACK_FIX_TRUNC_LO_EXPR;
1758 code2 = VEC_UNPACK_FIX_TRUNC_HI_EXPR;
1759 break;
1760 case FLOAT_EXPR:
1761 code1 = VEC_UNPACK_FLOAT_LO_EXPR;
1762 code2 = VEC_UNPACK_FLOAT_HI_EXPR;
1763 break;
1764 default:
1765 gcc_unreachable ();
1766 }
1767 if (BYTES_BIG_ENDIAN)
1768 std::swap (code1, code2);
1769
1770 if (code == FIX_TRUNC_EXPR)
1771 {
1772 /* The signedness is determined from output operand. */
1773 optab1 = optab_for_tree_code (code1, ret_type, optab_default);
1774 optab2 = optab_for_tree_code (code2, ret_type, optab_default);
1775 }
1776 else
1777 {
1778 optab1 = optab_for_tree_code (code1, arg_type, optab_default);
1779 optab2 = optab_for_tree_code (code2, arg_type, optab_default);
1780 }
1781
1782 if (optab1 && optab2)
1783 compute_type = get_compute_type (code1, optab1, arg_type);
1784
1785 enum insn_code icode1, icode2;
1786 if (VECTOR_TYPE_P (compute_type)
1787 && ((icode1 = optab_handler (optab1, TYPE_MODE (compute_type)))
1788 != CODE_FOR_nothing)
1789 && ((icode2 = optab_handler (optab2, TYPE_MODE (compute_type)))
1790 != CODE_FOR_nothing)
1791 && VECTOR_MODE_P (insn_data[icode1].operand[0].mode)
1792 && (insn_data[icode1].operand[0].mode
1793 == insn_data[icode2].operand[0].mode))
1794 {
1795 poly_uint64 nunits
1796 = exact_div (TYPE_VECTOR_SUBPARTS (compute_type), 2);
1797 tree cretd_type = build_vector_type (TREE_TYPE (ret_type), nunits);
1798 if (insn_data[icode1].operand[0].mode == TYPE_MODE (cretd_type))
1799 {
1800 vec<constructor_elt, va_gc> *v;
1801 tree part_width = TYPE_SIZE (compute_type);
1802 tree index = bitsize_int (0);
1803 int nunits = nunits_for_known_piecewise_op (arg_type);
1804 int delta = tree_to_uhwi (part_width)
1805 / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)));
1806 int i;
1807 location_t loc = gimple_location (gsi_stmt (*gsi));
1808
1809 if (compute_type != arg_type)
1810 warning_at (loc, OPT_Wvector_operation_performance,
1811 "vector operation will be expanded piecewise");
1812 else
1813 {
1814 nunits = 1;
1815 delta = 1;
1816 }
1817
1818 vec_alloc (v, (nunits + delta - 1) / delta * 2);
1819 for (i = 0; i < nunits;
1820 i += delta, index = int_const_binop (PLUS_EXPR, index,
1821 part_width))
1822 {
1823 tree a = arg;
1824 if (compute_type != arg_type)
1825 a = tree_vec_extract (gsi, compute_type, a, part_width,
1826 index);
1827 tree result = gimplify_build1 (gsi, code1, cretd_type, a);
1828 constructor_elt ce = { NULL_TREE, result };
1829 v->quick_push (ce);
1830 ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
1831 v->quick_push (ce);
1832 }
1833
1834 new_rhs = build_constructor (ret_type, v);
1835 g = gimple_build_assign (lhs, new_rhs);
1836 gsi_replace (gsi, g, false);
1837 return;
1838 }
1839 }
1840 }
1841
1842 new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
1843 TREE_TYPE (arg_type), arg,
1844 NULL_TREE, code, ret_type);
1845 g = gimple_build_assign (lhs, new_rhs);
1846 gsi_replace (gsi, g, false);
1847}
1848
0501cacc 1849/* Process one statement. If we identify a vector operation, expand it. */
1850
1851static void
75a70cf9 1852expand_vector_operations_1 (gimple_stmt_iterator *gsi)
0501cacc 1853{
c10b4d55 1854 tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
0501cacc 1855 enum tree_code code;
6cdd383a 1856 optab op = unknown_optab;
75a70cf9 1857 enum gimple_rhs_class rhs_class;
1858 tree new_rhs;
0501cacc 1859
1a91d914 1860 /* Only consider code == GIMPLE_ASSIGN. */
1861 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
1862 if (!stmt)
59409f09 1863 {
1864 if (gimple_call_internal_p (gsi_stmt (*gsi), IFN_VEC_CONVERT))
1865 expand_vector_conversion (gsi);
1866 return;
1867 }
0501cacc 1868
75a70cf9 1869 code = gimple_assign_rhs_code (stmt);
1870 rhs_class = get_gimple_rhs_class (code);
d7ad16c2 1871 lhs = gimple_assign_lhs (stmt);
0501cacc 1872
f4803722 1873 if (code == VEC_PERM_EXPR)
6cf89e04 1874 {
f4803722 1875 lower_vec_perm (gsi);
3c425d7c 1876 return;
6cf89e04 1877 }
1878
dd8c5e6c 1879 if (code == VEC_COND_EXPR)
1880 {
1881 expand_vector_condition (gsi);
1882 return;
1883 }
f1c75c81 1884
7e64a875 1885 if (code == COND_EXPR
1886 && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
1887 && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
1888 {
1889 expand_vector_scalar_condition (gsi);
1890 return;
1891 }
1892
f1c75c81 1893 if (code == CONSTRUCTOR
1894 && TREE_CODE (lhs) == SSA_NAME
1895 && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
1896 && !gimple_clobber_p (stmt)
1897 && optimize)
1898 {
1899 optimize_vector_constructor (gsi);
1900 return;
1901 }
1902
75a70cf9 1903 if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1904 return;
0501cacc 1905
75a70cf9 1906 rhs1 = gimple_assign_rhs1 (stmt);
1907 type = gimple_expr_type (stmt);
1908 if (rhs_class == GIMPLE_BINARY_RHS)
1909 rhs2 = gimple_assign_rhs2 (stmt);
0501cacc 1910
7ed29fa2 1911 if (!VECTOR_TYPE_P (type)
1912 || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
0501cacc 1913 return;
9a10d5a8 1914
1915 /* A scalar operation pretending to be a vector one. */
1916 if (VECTOR_BOOLEAN_TYPE_P (type)
1917 && !VECTOR_MODE_P (TYPE_MODE (type))
1918 && TYPE_MODE (type) != BLKmode)
1919 return;
0501cacc 1920
ba257f0b 1921 /* If the vector operation is operating on all same vector elements
1922 implement it with a scalar operation and a splat if the target
1923 supports the scalar operation. */
1924 tree srhs1, srhs2 = NULL_TREE;
1925 if ((srhs1 = ssa_uniform_vector_p (rhs1)) != NULL_TREE
1926 && (rhs2 == NULL_TREE
abad1993 1927 || (! VECTOR_TYPE_P (TREE_TYPE (rhs2))
1928 && (srhs2 = rhs2))
ba257f0b 1929 || (srhs2 = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
1930 /* As we query direct optabs restrict to non-convert operations. */
1931 && TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (TREE_TYPE (srhs1)))
1932 {
1933 op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
5cf8b9ea 1934 if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
158d21fb 1935 && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
ba257f0b 1936 {
1937 tree slhs = make_ssa_name (TREE_TYPE (srhs1));
1938 gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
1939 gsi_insert_before (gsi, repl, GSI_SAME_STMT);
1940 gimple_assign_set_rhs_from_tree (gsi,
1941 build_vector_from_val (type, slhs));
1942 update_stmt (stmt);
1943 return;
1944 }
1945 }
1f137e6d 1946
d09ef31a 1947 if (CONVERT_EXPR_CODE_P (code)
9d8bf4aa 1948 || code == FLOAT_EXPR
1949 || code == FIX_TRUNC_EXPR
1950 || code == VIEW_CONVERT_EXPR)
0501cacc 1951 return;
48e1416a 1952
bb6c9541 1953 /* The signedness is determined from input argument. */
1954 if (code == VEC_UNPACK_FLOAT_HI_EXPR
0efcdf5a 1955 || code == VEC_UNPACK_FLOAT_LO_EXPR
1956 || code == VEC_PACK_FLOAT_EXPR)
ad0cb942 1957 {
1958 type = TREE_TYPE (rhs1);
1959 /* We do not know how to scalarize those. */
1960 return;
1961 }
bb6c9541 1962
79a78f7f 1963 /* For widening/narrowing vector operations, the relevant type is of the
1964 arguments, not the widened result. VEC_UNPACK_FLOAT_*_EXPR is
1965 calculated in the same way above. */
1966 if (code == WIDEN_SUM_EXPR
1967 || code == VEC_WIDEN_MULT_HI_EXPR
1968 || code == VEC_WIDEN_MULT_LO_EXPR
1969 || code == VEC_WIDEN_MULT_EVEN_EXPR
1970 || code == VEC_WIDEN_MULT_ODD_EXPR
1971 || code == VEC_UNPACK_HI_EXPR
1972 || code == VEC_UNPACK_LO_EXPR
0efcdf5a 1973 || code == VEC_UNPACK_FIX_TRUNC_HI_EXPR
1974 || code == VEC_UNPACK_FIX_TRUNC_LO_EXPR
79a78f7f 1975 || code == VEC_PACK_TRUNC_EXPR
1976 || code == VEC_PACK_SAT_EXPR
1977 || code == VEC_PACK_FIX_TRUNC_EXPR
1978 || code == VEC_WIDEN_LSHIFT_HI_EXPR
1979 || code == VEC_WIDEN_LSHIFT_LO_EXPR)
ad0cb942 1980 {
1981 type = TREE_TYPE (rhs1);
1982 /* We do not know how to scalarize those. */
1983 return;
1984 }
79a78f7f 1985
4d54df85 1986 /* Choose between vector shift/rotate by vector and vector shift/rotate by
1987 scalar */
48e1416a 1988 if (code == LSHIFT_EXPR
1989 || code == RSHIFT_EXPR
75a70cf9 1990 || code == LROTATE_EXPR
4d54df85 1991 || code == RROTATE_EXPR)
1992 {
64791788 1993 optab opv;
1994
83a28c11 1995 /* Check whether we have vector <op> {x,x,x,x} where x
1996 could be a scalar variable or a constant. Transform
1997 vector <op> {x,x,x,x} ==> vector <op> scalar. */
64791788 1998 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2fee2038 1999 {
2000 tree first;
ba257f0b 2001
2002 if ((first = ssa_uniform_vector_p (rhs2)) != NULL_TREE)
2fee2038 2003 {
2004 gimple_assign_set_rhs2 (stmt, first);
2005 update_stmt (stmt);
2006 rhs2 = first;
2007 }
2fee2038 2008 }
6cf89e04 2009
64791788 2010 opv = optab_for_tree_code (code, type, optab_vector);
2011 if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2012 op = opv;
83a28c11 2013 else
4d5b2207 2014 {
83a28c11 2015 op = optab_for_tree_code (code, type, optab_scalar);
4d5b2207 2016
c10b4d55 2017 compute_type = get_compute_type (code, op, type);
2018 if (compute_type == type)
2019 return;
83a28c11 2020 /* The rtl expander will expand vector/scalar as vector/vector
c10b4d55 2021 if necessary. Pick one with wider vector type. */
2022 tree compute_vtype = get_compute_type (code, opv, type);
5bf60cc1 2023 if (subparts_gt (compute_vtype, compute_type))
c10b4d55 2024 {
2025 compute_type = compute_vtype;
2026 op = opv;
2027 }
2028 }
2029
2030 if (code == LROTATE_EXPR || code == RROTATE_EXPR)
2031 {
2032 if (compute_type == NULL_TREE)
2033 compute_type = get_compute_type (code, op, type);
2034 if (compute_type == type)
64791788 2035 return;
c10b4d55 2036 /* Before splitting vector rotates into scalar rotates,
2037 see if we can't use vector shifts and BIT_IOR_EXPR
2038 instead. For vector by vector rotates we'd also
2039 need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
2040 for now, fold doesn't seem to create such rotates anyway. */
2041 if (compute_type == TREE_TYPE (type)
2042 && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
2043 {
2044 optab oplv = vashl_optab, opl = ashl_optab;
2045 optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
2046 tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
2047 tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
2048 tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
2049 tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
2050 tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
2051 /* The rtl expander will expand vector/scalar as vector/vector
2052 if necessary. Pick one with wider vector type. */
5bf60cc1 2053 if (subparts_gt (compute_lvtype, compute_ltype))
c10b4d55 2054 {
2055 compute_ltype = compute_lvtype;
2056 opl = oplv;
2057 }
5bf60cc1 2058 if (subparts_gt (compute_rvtype, compute_rtype))
c10b4d55 2059 {
2060 compute_rtype = compute_rvtype;
2061 opr = oprv;
2062 }
2063 /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
2064 BIT_IOR_EXPR. */
2065 compute_type = compute_ltype;
5bf60cc1 2066 if (subparts_gt (compute_type, compute_rtype))
c10b4d55 2067 compute_type = compute_rtype;
5bf60cc1 2068 if (subparts_gt (compute_type, compute_otype))
c10b4d55 2069 compute_type = compute_otype;
2070 /* Verify all 3 operations can be performed in that type. */
2071 if (compute_type != TREE_TYPE (type))
2072 {
2073 if (optab_handler (opl, TYPE_MODE (compute_type))
2074 == CODE_FOR_nothing
2075 || optab_handler (opr, TYPE_MODE (compute_type))
2076 == CODE_FOR_nothing
2077 || optab_handler (opo, TYPE_MODE (compute_type))
2078 == CODE_FOR_nothing)
2079 compute_type = TREE_TYPE (type);
2080 }
2081 }
4d5b2207 2082 }
4d54df85 2083 }
2084 else
2085 op = optab_for_tree_code (code, type, optab_default);
0501cacc 2086
2087 /* Optabs will try converting a negation into a subtraction, so
2088 look for it as well. TODO: negation of floating-point vectors
2089 might be turned into an exclusive OR toggling the sign bit. */
6cdd383a 2090 if (op == unknown_optab
0501cacc 2091 && code == NEGATE_EXPR
2092 && INTEGRAL_TYPE_P (TREE_TYPE (type)))
4d54df85 2093 op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
0501cacc 2094
c10b4d55 2095 if (compute_type == NULL_TREE)
2096 compute_type = get_compute_type (code, op, type);
0501cacc 2097 if (compute_type == type)
c10b4d55 2098 return;
0501cacc 2099
75a70cf9 2100 new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
d7ad16c2 2101
2102 /* Leave expression untouched for later expansion. */
2103 if (new_rhs == NULL_TREE)
2104 return;
2105
75a70cf9 2106 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
2107 new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
2108 new_rhs);
2109
2110 /* NOTE: We should avoid using gimple_assign_set_rhs_from_tree. One
2111 way to do it is change expand_vector_operation and its callees to
2112 return a tree_code, RHS1 and RHS2 instead of a tree. */
2113 gimple_assign_set_rhs_from_tree (gsi, new_rhs);
82f9a36f 2114 update_stmt (gsi_stmt (*gsi));
0501cacc 2115}
2116\f
2117/* Use this to lower vector operations introduced by the vectorizer,
2118 if it may need the bit-twiddling tricks implemented in this file. */
2119
2a1990e9 2120static unsigned int
0501cacc 2121expand_vector_operations (void)
2122{
75a70cf9 2123 gimple_stmt_iterator gsi;
0501cacc 2124 basic_block bb;
82f9a36f 2125 bool cfg_changed = false;
0501cacc 2126
fc00614f 2127 FOR_EACH_BB_FN (bb, cfun)
0501cacc 2128 {
75a70cf9 2129 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
0501cacc 2130 {
75a70cf9 2131 expand_vector_operations_1 (&gsi);
82f9a36f 2132 /* ??? If we do not cleanup EH then we will ICE in
2133 verification. But in reality we have created wrong-code
2134 as we did not properly transition EH info and edges to
2135 the piecewise computations. */
2136 if (maybe_clean_eh_stmt (gsi_stmt (gsi))
2137 && gimple_purge_dead_eh_edges (bb))
2138 cfg_changed = true;
0501cacc 2139 }
2140 }
82f9a36f 2141
2142 return cfg_changed ? TODO_cleanup_cfg : 0;
0501cacc 2143}
2144
7620bc82 2145namespace {
2146
2147const pass_data pass_data_lower_vector =
0501cacc 2148{
cbe8bda8 2149 GIMPLE_PASS, /* type */
2150 "veclower", /* name */
2151 OPTGROUP_VEC, /* optinfo_flags */
cbe8bda8 2152 TV_NONE, /* tv_id */
2153 PROP_cfg, /* properties_required */
2154 PROP_gimple_lvec, /* properties_provided */
2155 0, /* properties_destroyed */
2156 0, /* todo_flags_start */
051d7389 2157 TODO_update_ssa, /* todo_flags_finish */
0501cacc 2158};
2159
7620bc82 2160class pass_lower_vector : public gimple_opt_pass
cbe8bda8 2161{
2162public:
9af5ce0c 2163 pass_lower_vector (gcc::context *ctxt)
2164 : gimple_opt_pass (pass_data_lower_vector, ctxt)
cbe8bda8 2165 {}
2166
2167 /* opt_pass methods: */
31315c24 2168 virtual bool gate (function *fun)
2169 {
2170 return !(fun->curr_properties & PROP_gimple_lvec);
2171 }
2172
65b0537f 2173 virtual unsigned int execute (function *)
2174 {
2175 return expand_vector_operations ();
2176 }
cbe8bda8 2177
2178}; // class pass_lower_vector
2179
7620bc82 2180} // anon namespace
2181
cbe8bda8 2182gimple_opt_pass *
2183make_pass_lower_vector (gcc::context *ctxt)
2184{
2185 return new pass_lower_vector (ctxt);
2186}
2187
7620bc82 2188namespace {
2189
2190const pass_data pass_data_lower_vector_ssa =
0501cacc 2191{
cbe8bda8 2192 GIMPLE_PASS, /* type */
2193 "veclower2", /* name */
2194 OPTGROUP_VEC, /* optinfo_flags */
cbe8bda8 2195 TV_NONE, /* tv_id */
2196 PROP_cfg, /* properties_required */
2197 PROP_gimple_lvec, /* properties_provided */
2198 0, /* properties_destroyed */
2199 0, /* todo_flags_start */
8b88439e 2200 ( TODO_update_ssa
cbe8bda8 2201 | TODO_cleanup_cfg ), /* todo_flags_finish */
0501cacc 2202};
2203
7620bc82 2204class pass_lower_vector_ssa : public gimple_opt_pass
cbe8bda8 2205{
2206public:
9af5ce0c 2207 pass_lower_vector_ssa (gcc::context *ctxt)
2208 : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
cbe8bda8 2209 {}
2210
2211 /* opt_pass methods: */
ae84f584 2212 opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
65b0537f 2213 virtual unsigned int execute (function *)
2214 {
2215 return expand_vector_operations ();
2216 }
cbe8bda8 2217
2218}; // class pass_lower_vector_ssa
2219
7620bc82 2220} // anon namespace
2221
cbe8bda8 2222gimple_opt_pass *
2223make_pass_lower_vector_ssa (gcc::context *ctxt)
2224{
2225 return new pass_lower_vector_ssa (ctxt);
2226}
2227
0501cacc 2228#include "gt-tree-vect-generic.h"