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