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