1/* Lower vector operations to scalar operations.
2   Copyright (C) 2004-2015 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 "hash-set.h"
24#include "machmode.h"
25#include "vec.h"
26#include "double-int.h"
27#include "input.h"
28#include "alias.h"
29#include "symtab.h"
30#include "options.h"
31#include "wide-int.h"
32#include "inchash.h"
33#include "tree.h"
34#include "fold-const.h"
35#include "stor-layout.h"
36#include "tm.h"
37#include "langhooks.h"
38#include "predict.h"
39#include "hard-reg-set.h"
40#include "function.h"
41#include "dominance.h"
42#include "cfg.h"
43#include "basic-block.h"
44#include "tree-ssa-alias.h"
45#include "internal-fn.h"
46#include "tree-eh.h"
47#include "gimple-expr.h"
48#include "is-a.h"
49#include "gimple.h"
50#include "gimple-iterator.h"
51#include "gimplify-me.h"
52#include "gimple-ssa.h"
53#include "tree-cfg.h"
54#include "stringpool.h"
55#include "tree-ssanames.h"
56#include "tree-iterator.h"
57#include "tree-pass.h"
58#include "flags.h"
59#include "diagnostic.h"
60#include "target.h"
61
62/* Need to include rtl.h, expr.h, etc. for optabs.  */
63#include "hashtab.h"
64#include "rtl.h"
65#include "statistics.h"
66#include "real.h"
67#include "fixed-value.h"
68#include "insn-config.h"
69#include "expmed.h"
70#include "dojump.h"
71#include "explow.h"
72#include "calls.h"
73#include "emit-rtl.h"
74#include "varasm.h"
75#include "stmt.h"
76#include "expr.h"
77#include "insn-codes.h"
78#include "optabs.h"
79
80
81static void expand_vector_operations_1 (gimple_stmt_iterator *);
82
83
84/* Build a constant of type TYPE, made of VALUE's bits replicated
85   every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision.  */
86static tree
87build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
88{
89  int width = tree_to_uhwi (TYPE_SIZE (inner_type));
90  int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
91    / HOST_BITS_PER_WIDE_INT;
92  unsigned HOST_WIDE_INT low, mask;
93  HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
94  int i;
95
96  gcc_assert (n && n <= WIDE_INT_MAX_ELTS);
97
98  if (width == HOST_BITS_PER_WIDE_INT)
99    low = value;
100  else
101    {
102      mask = ((HOST_WIDE_INT)1 << width) - 1;
103      low = (unsigned HOST_WIDE_INT) ~0 / mask * (value & mask);
104    }
105
106  for (i = 0; i < n; i++)
107    a[i] = low;
108
109  gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
110  return wide_int_to_tree
111    (type, wide_int::from_array (a, n, TYPE_PRECISION (type)));
112}
113
114static GTY(()) tree vector_inner_type;
115static GTY(()) tree vector_last_type;
116static GTY(()) int vector_last_nunits;
117
118/* Return a suitable vector types made of SUBPARTS units each of mode
119   "word_mode" (the global variable).  */
120static tree
121build_word_mode_vector_type (int nunits)
122{
123  if (!vector_inner_type)
124    vector_inner_type = lang_hooks.types.type_for_mode (word_mode, 1);
125  else if (vector_last_nunits == nunits)
126    {
127      gcc_assert (TREE_CODE (vector_last_type) == VECTOR_TYPE);
128      return vector_last_type;
129    }
130
131  /* We build a new type, but we canonicalize it nevertheless,
132     because it still saves some memory.  */
133  vector_last_nunits = nunits;
134  vector_last_type = type_hash_canon (nunits,
135				      build_vector_type (vector_inner_type,
136							 nunits));
137  return vector_last_type;
138}
139
140typedef tree (*elem_op_func) (gimple_stmt_iterator *,
141			      tree, tree, tree, tree, tree, enum tree_code);
142
143static inline tree
144tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
145		  tree t, tree bitsize, tree bitpos)
146{
147  if (bitpos)
148    return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
149  else
150    return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
151}
152
153static tree
154do_unop (gimple_stmt_iterator *gsi, tree inner_type, tree a,
155	 tree b ATTRIBUTE_UNUSED, tree bitpos, tree bitsize,
156	 enum tree_code code)
157{
158  a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
159  return gimplify_build1 (gsi, code, inner_type, a);
160}
161
162static tree
163do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
164	  tree bitpos, tree bitsize, enum tree_code code)
165{
166  if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
167    a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
168  if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
169    b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
170  return gimplify_build2 (gsi, code, inner_type, a, b);
171}
172
173/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
174
175   INNER_TYPE is the type of A and B elements
176
177   returned expression is of signed integer type with the
178   size equal to the size of INNER_TYPE.  */
179static tree
180do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
181	  tree bitpos, tree bitsize, enum tree_code code)
182{
183  tree comp_type;
184
185  a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
186  b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
187
188  comp_type = build_nonstandard_integer_type
189		      (GET_MODE_BITSIZE (TYPE_MODE (inner_type)), 0);
190
191  return gimplify_build3 (gsi, COND_EXPR, comp_type,
192			  fold_build2 (code, boolean_type_node, a, b),
193			  build_int_cst (comp_type, -1),
194			  build_int_cst (comp_type, 0));
195}
196
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
211do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
212	       tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
213	       enum tree_code code)
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
223  a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
224  b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
225
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);
228  if (code == PLUS_EXPR)
229    a_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, a, low_bits);
230  else
231    {
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);
234    }
235
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);
239}
240
241static tree
242do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
243	   tree unused ATTRIBUTE_UNUSED, tree bitpos ATTRIBUTE_UNUSED,
244	   tree bitsize ATTRIBUTE_UNUSED,
245	   enum tree_code code ATTRIBUTE_UNUSED)
246{
247  tree inner_type = TREE_TYPE (TREE_TYPE (b));
248  HOST_WIDE_INT max;
249  tree low_bits, high_bits, b_low, result_low, signs;
250
251  max = GET_MODE_MASK (TYPE_MODE (inner_type));
252  low_bits = build_replicated_const (word_type, inner_type, max >> 1);
253  high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
254
255  b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
256
257  b_low = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, b, low_bits);
258  signs = gimplify_build1 (gsi, BIT_NOT_EXPR, word_type, b);
259  signs = gimplify_build2 (gsi, BIT_AND_EXPR, word_type, signs, high_bits);
260  result_low = gimplify_build2 (gsi, MINUS_EXPR, word_type, high_bits, b_low);
261  return gimplify_build2 (gsi, BIT_XOR_EXPR, word_type, result_low, signs);
262}
263
264/* Expand a vector operation to scalars, by using many operations
265   whose type is the vector type's inner type.  */
266static tree
267expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
268			 tree type, tree inner_type,
269			 tree a, tree b, enum tree_code code)
270{
271  vec<constructor_elt, va_gc> *v;
272  tree part_width = TYPE_SIZE (inner_type);
273  tree index = bitsize_int (0);
274  int nunits = TYPE_VECTOR_SUBPARTS (type);
275  int delta = tree_to_uhwi (part_width)
276	      / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
277  int i;
278  location_t loc = gimple_location (gsi_stmt (*gsi));
279
280  if (types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
281    warning_at (loc, OPT_Wvector_operation_performance,
282		"vector operation will be expanded piecewise");
283  else
284    warning_at (loc, OPT_Wvector_operation_performance,
285		"vector operation will be expanded in parallel");
286
287  vec_alloc (v, (nunits + delta - 1) / delta);
288  for (i = 0; i < nunits;
289       i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
290    {
291      tree result = f (gsi, inner_type, a, b, index, part_width, code);
292      constructor_elt ce = {NULL_TREE, result};
293      v->quick_push (ce);
294    }
295
296  return build_constructor (type, v);
297}
298
299/* Expand a vector operation to scalars with the freedom to use
300   a scalar integer type, or to use a different size for the items
301   in the vector type.  */
302static tree
303expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
304			tree a, tree b,
305			enum tree_code code)
306{
307  tree result, compute_type;
308  machine_mode mode;
309  int n_words = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD;
310  location_t loc = gimple_location (gsi_stmt (*gsi));
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)
317     return expand_vector_piecewise (gsi, f,
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);
323      result = expand_vector_piecewise (gsi, f,
324				        word_type, TREE_TYPE (word_type),
325					a, b, code);
326      result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
327                                         GSI_SAME_STMT);
328    }
329  else
330    {
331      /* Use a single scalar operation with a mode no wider than word_mode.  */
332      mode = mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), MODE_INT, 0);
333      compute_type = lang_hooks.types.type_for_mode (mode, 1);
334      result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code);
335      warning_at (loc, OPT_Wvector_operation_performance,
336	          "vector operation will be expanded with a "
337		  "single scalar operation");
338    }
339
340  return result;
341}
342
343/* Expand a vector operation to scalars; for integer types we can use
344   special bit twiddling tricks to do the sums a word at a time, using
345   function F_PARALLEL instead of F.  These tricks are done only if
346   they can process at least four items, that is, only if the vector
347   holds at least four items and if a word can hold four items.  */
348static tree
349expand_vector_addition (gimple_stmt_iterator *gsi,
350			elem_op_func f, elem_op_func f_parallel,
351			tree type, tree a, tree b, enum tree_code code)
352{
353  int parts_per_word = UNITS_PER_WORD
354	  	       / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
355
356  if (INTEGRAL_TYPE_P (TREE_TYPE (type))
357      && parts_per_word >= 4
358      && TYPE_VECTOR_SUBPARTS (type) >= 4)
359    return expand_vector_parallel (gsi, f_parallel,
360				   type, a, b, code);
361  else
362    return expand_vector_piecewise (gsi, f,
363				    type, TREE_TYPE (type),
364				    a, b, code);
365}
366
367/* Try to expand vector comparison expression OP0 CODE OP1 by
368   querying optab if the following expression:
369	VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
370   can be expanded.  */
371static tree
372expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
373                          tree op1, enum tree_code code)
374{
375  tree t;
376  if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
377    t = expand_vector_piecewise (gsi, do_compare, type,
378				 TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
379  else
380    t = NULL_TREE;
381
382  return t;
383}
384
385/* Helper function of expand_vector_divmod.  Gimplify a RSHIFT_EXPR in type
386   of OP0 with shift counts in SHIFTCNTS array and return the temporary holding
387   the result if successful, otherwise return NULL_TREE.  */
388static tree
389add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
390{
391  optab op;
392  unsigned int i, nunits = TYPE_VECTOR_SUBPARTS (type);
393  bool scalar_shift = true;
394
395  for (i = 1; i < nunits; i++)
396    {
397      if (shiftcnts[i] != shiftcnts[0])
398	scalar_shift = false;
399    }
400
401  if (scalar_shift && shiftcnts[0] == 0)
402    return op0;
403
404  if (scalar_shift)
405    {
406      op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
407      if (op != unknown_optab
408	  && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
409	return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
410				build_int_cst (NULL_TREE, shiftcnts[0]));
411    }
412
413  op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
414  if (op != unknown_optab
415      && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
416    {
417      tree *vec = XALLOCAVEC (tree, nunits);
418      for (i = 0; i < nunits; i++)
419	vec[i] = build_int_cst (TREE_TYPE (type), shiftcnts[i]);
420      return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
421			      build_vector (type, vec));
422    }
423
424  return NULL_TREE;
425}
426
427/* Try to expand integer vector division by constant using
428   widening multiply, shifts and additions.  */
429static tree
430expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
431		      tree op1, enum tree_code code)
432{
433  bool use_pow2 = true;
434  bool has_vector_shift = true;
435  int mode = -1, this_mode;
436  int pre_shift = -1, post_shift;
437  unsigned int nunits = TYPE_VECTOR_SUBPARTS (type);
438  int *shifts = XALLOCAVEC (int, nunits * 4);
439  int *pre_shifts = shifts + nunits;
440  int *post_shifts = pre_shifts + nunits;
441  int *shift_temps = post_shifts + nunits;
442  unsigned HOST_WIDE_INT *mulc = XALLOCAVEC (unsigned HOST_WIDE_INT, nunits);
443  int prec = TYPE_PRECISION (TREE_TYPE (type));
444  int dummy_int;
445  unsigned int i;
446  signop sign_p = TYPE_SIGN (TREE_TYPE (type));
447  unsigned HOST_WIDE_INT mask = GET_MODE_MASK (TYPE_MODE (TREE_TYPE (type)));
448  tree *vec;
449  tree cur_op, mulcst, tem;
450  optab op;
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);
456  if (op == unknown_optab
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
470      if (TREE_CODE (cst) != INTEGER_CST || integer_zerop (cst))
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;
488      if (sign_p == UNSIGNED)
489	{
490	  unsigned HOST_WIDE_INT mh;
491	  unsigned HOST_WIDE_INT d = TREE_INT_CST_LOW (cst) & mask;
492
493	  if (d >= ((unsigned HOST_WIDE_INT) 1 << (prec - 1)))
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)
513		pre_shift = floor_log2 (d & -d);
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
523		      if (!tree_fits_uhwi_p (cst2))
524			return NULL_TREE;
525		      d2 = tree_to_uhwi (cst2) & mask;
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	{
561	  HOST_WIDE_INT d = TREE_INT_CST_LOW (cst);
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;
577	  else if (abs_d == (unsigned HOST_WIDE_INT) 1 << (prec - 1))
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);
591	  if (ml >= (unsigned HOST_WIDE_INT) 1 << (prec - 1))
592	    {
593	      this_mode = 4 + (d < 0);
594	      ml |= (~(unsigned HOST_WIDE_INT) 0) << (prec - 1);
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
612  vec = XALLOCAVEC (tree, nunits);
613
614  if (use_pow2)
615    {
616      tree addend = NULL_TREE;
617      if (sign_p == SIGNED)
618	{
619	  tree uns_type;
620
621	  /* Both division and remainder sequences need
622	     op0 < 0 ? mask : 0 computed.  It can be either computed as
623	     (type) (((uns_type) (op0 >> (prec - 1))) >> (prec - shifts[i]))
624	     if none of the shifts is 0, or as the conditional.  */
625	  for (i = 0; i < nunits; i++)
626	    if (shifts[i] == 0)
627	      break;
628	  uns_type
629	    = build_vector_type (build_nonstandard_integer_type (prec, 1),
630				 nunits);
631	  if (i == nunits && TYPE_MODE (uns_type) == TYPE_MODE (type))
632	    {
633	      for (i = 0; i < nunits; i++)
634		shift_temps[i] = prec - 1;
635	      cur_op = add_rshift (gsi, type, op0, shift_temps);
636	      if (cur_op != NULL_TREE)
637		{
638		  cur_op = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
639					    uns_type, cur_op);
640		  for (i = 0; i < nunits; i++)
641		    shift_temps[i] = prec - shifts[i];
642		  cur_op = add_rshift (gsi, uns_type, cur_op, shift_temps);
643		  if (cur_op != NULL_TREE)
644		    addend = gimplify_build1 (gsi, VIEW_CONVERT_EXPR,
645					      type, cur_op);
646		}
647	    }
648	  if (addend == NULL_TREE
649	      && expand_vec_cond_expr_p (type, type))
650	    {
651	      tree zero, cst, cond;
652	      gimple stmt;
653
654	      zero = build_zero_cst (type);
655	      cond = build2 (LT_EXPR, type, op0, zero);
656	      for (i = 0; i < nunits; i++)
657		vec[i] = build_int_cst (TREE_TYPE (type),
658					((unsigned HOST_WIDE_INT) 1
659					 << shifts[i]) - 1);
660	      cst = build_vector (type, vec);
661	      addend = make_ssa_name (type);
662	      stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
663					  cst, zero);
664	      gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
665	    }
666	}
667      if (code == TRUNC_DIV_EXPR)
668	{
669	  if (sign_p == UNSIGNED)
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);
681	      if (op != unknown_optab
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;
694	  for (i = 0; i < nunits; i++)
695	    vec[i] = build_int_cst (TREE_TYPE (type),
696				    ((unsigned HOST_WIDE_INT) 1
697				     << shifts[i]) - 1);
698	  mask = build_vector (type, vec);
699	  op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
700	  if (op != unknown_optab
701	      && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
702	    {
703	      if (sign_p == UNSIGNED)
704		/* r = op0 & mask;  */
705		return gimplify_build2 (gsi, BIT_AND_EXPR, type, op0, mask);
706	      else if (addend != NULL_TREE)
707		{
708		  /* t1 = op0 + addend;
709		     t2 = t1 & mask;
710		     r = t2 - addend;  */
711		  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
712		  if (op != unknown_optab
713		      && optab_handler (op, TYPE_MODE (type))
714			 != CODE_FOR_nothing)
715		    {
716		      cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
717						addend);
718		      cur_op = gimplify_build2 (gsi, BIT_AND_EXPR, type,
719						cur_op, mask);
720		      op = optab_for_tree_code (MINUS_EXPR, type,
721						optab_default);
722		      if (op != unknown_optab
723			  && optab_handler (op, TYPE_MODE (type))
724			     != CODE_FOR_nothing)
725			return gimplify_build2 (gsi, MINUS_EXPR, type,
726						cur_op, addend);
727		    }
728		}
729	    }
730	}
731    }
732
733  if (mode == -2 || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
734    return NULL_TREE;
735
736  if (!can_mult_highpart_p (TYPE_MODE (type), TYPE_UNSIGNED (type)))
737    return NULL_TREE;
738
739  cur_op = op0;
740
741  switch (mode)
742    {
743    case 0:
744      gcc_assert (sign_p == UNSIGNED);
745      /* t1 = oprnd0 >> pre_shift;
746	 t2 = t1 h* ml;
747	 q = t2 >> post_shift;  */
748      cur_op = add_rshift (gsi, type, cur_op, pre_shifts);
749      if (cur_op == NULL_TREE)
750	return NULL_TREE;
751      break;
752    case 1:
753      gcc_assert (sign_p == UNSIGNED);
754      for (i = 0; i < nunits; i++)
755	{
756	  shift_temps[i] = 1;
757	  post_shifts[i]--;
758	}
759      break;
760    case 2:
761    case 3:
762    case 4:
763    case 5:
764      gcc_assert (sign_p == SIGNED);
765      for (i = 0; i < nunits; i++)
766	shift_temps[i] = prec - 1;
767      break;
768    default:
769      return NULL_TREE;
770    }
771
772  for (i = 0; i < nunits; i++)
773    vec[i] = build_int_cst (TREE_TYPE (type), mulc[i]);
774  mulcst = build_vector (type, vec);
775
776  cur_op = gimplify_build2 (gsi, MULT_HIGHPART_EXPR, type, cur_op, mulcst);
777
778  switch (mode)
779    {
780    case 0:
781      /* t1 = oprnd0 >> pre_shift;
782	 t2 = t1 h* ml;
783	 q = t2 >> post_shift;  */
784      cur_op = add_rshift (gsi, type, cur_op, post_shifts);
785      break;
786    case 1:
787      /* t1 = oprnd0 h* ml;
788	 t2 = oprnd0 - t1;
789	 t3 = t2 >> 1;
790	 t4 = t1 + t3;
791	 q = t4 >> (post_shift - 1);  */
792      op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
793      if (op == unknown_optab
794	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
795	return NULL_TREE;
796      tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
797      tem = add_rshift (gsi, type, tem, shift_temps);
798      op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
799      if (op == unknown_optab
800	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
801	return NULL_TREE;
802      tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
803      cur_op = add_rshift (gsi, type, tem, post_shifts);
804      if (cur_op == NULL_TREE)
805	return NULL_TREE;
806      break;
807    case 2:
808    case 3:
809    case 4:
810    case 5:
811      /* t1 = oprnd0 h* ml;
812	 t2 = t1; [ iff (mode & 2) != 0 ]
813	 t2 = t1 + oprnd0; [ iff (mode & 2) == 0 ]
814	 t3 = t2 >> post_shift;
815	 t4 = oprnd0 >> (prec - 1);
816	 q = t3 - t4; [ iff (mode & 1) == 0 ]
817	 q = t4 - t3; [ iff (mode & 1) != 0 ]  */
818      if ((mode & 2) == 0)
819	{
820	  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
821	  if (op == unknown_optab
822	      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
823	    return NULL_TREE;
824	  cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
825	}
826      cur_op = add_rshift (gsi, type, cur_op, post_shifts);
827      if (cur_op == NULL_TREE)
828	return NULL_TREE;
829      tem = add_rshift (gsi, type, op0, shift_temps);
830      if (tem == NULL_TREE)
831	return NULL_TREE;
832      op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
833      if (op == unknown_optab
834	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
835	return NULL_TREE;
836      if ((mode & 1) == 0)
837	cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
838      else
839	cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, tem, cur_op);
840      break;
841    default:
842      gcc_unreachable ();
843    }
844
845  if (code == TRUNC_DIV_EXPR)
846    return cur_op;
847
848  /* We divided.  Now finish by:
849     t1 = q * oprnd1;
850     r = oprnd0 - t1;  */
851  op = optab_for_tree_code (MULT_EXPR, type, optab_default);
852  if (op == unknown_optab
853      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
854    return NULL_TREE;
855  tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
856  op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
857  if (op == unknown_optab
858      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
859    return NULL_TREE;
860  return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
861}
862
863/* Expand a vector condition to scalars, by using many conditions
864   on the vector's elements.  */
865static void
866expand_vector_condition (gimple_stmt_iterator *gsi)
867{
868  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
869  tree type = gimple_expr_type (stmt);
870  tree a = gimple_assign_rhs1 (stmt);
871  tree a1 = a;
872  tree a2;
873  bool a_is_comparison = false;
874  tree b = gimple_assign_rhs2 (stmt);
875  tree c = gimple_assign_rhs3 (stmt);
876  vec<constructor_elt, va_gc> *v;
877  tree constr;
878  tree inner_type = TREE_TYPE (type);
879  tree cond_type = TREE_TYPE (TREE_TYPE (a));
880  tree comp_inner_type = cond_type;
881  tree width = TYPE_SIZE (inner_type);
882  tree index = bitsize_int (0);
883  int nunits = TYPE_VECTOR_SUBPARTS (type);
884  int i;
885  location_t loc = gimple_location (gsi_stmt (*gsi));
886
887  if (!is_gimple_val (a))
888    {
889      gcc_assert (COMPARISON_CLASS_P (a));
890      a_is_comparison = true;
891      a1 = TREE_OPERAND (a, 0);
892      a2 = TREE_OPERAND (a, 1);
893      comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
894    }
895
896  if (expand_vec_cond_expr_p (type, TREE_TYPE (a1)))
897    return;
898
899  /* TODO: try and find a smaller vector type.  */
900
901  warning_at (loc, OPT_Wvector_operation_performance,
902	      "vector condition will be expanded piecewise");
903
904  vec_alloc (v, nunits);
905  for (i = 0; i < nunits;
906       i++, index = int_const_binop (PLUS_EXPR, index, width))
907    {
908      tree aa, result;
909      tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
910      tree cc = tree_vec_extract (gsi, inner_type, c, width, index);
911      if (a_is_comparison)
912	{
913	  tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index);
914	  tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index);
915	  aa = build2 (TREE_CODE (a), cond_type, aa1, aa2);
916	}
917      else
918	aa = tree_vec_extract (gsi, cond_type, a, width, index);
919      result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
920      constructor_elt ce = {NULL_TREE, result};
921      v->quick_push (ce);
922    }
923
924  constr = build_constructor (type, v);
925  gimple_assign_set_rhs_from_tree (gsi, constr);
926  update_stmt (gsi_stmt (*gsi));
927}
928
929static tree
930expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
931			 gassign *assign, enum tree_code code)
932{
933  machine_mode compute_mode = TYPE_MODE (compute_type);
934
935  /* If the compute mode is not a vector mode (hence we are not decomposing
936     a BLKmode vector to smaller, hardware-supported vectors), we may want
937     to expand the operations in parallel.  */
938  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
939      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
940      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
941      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
942      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
943      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
944    switch (code)
945      {
946      case PLUS_EXPR:
947      case MINUS_EXPR:
948        if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
949	  return expand_vector_addition (gsi, do_binop, do_plus_minus, type,
950					 gimple_assign_rhs1 (assign),
951					 gimple_assign_rhs2 (assign), code);
952	break;
953
954      case NEGATE_EXPR:
955        if (ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_TRAPS (type))
956          return expand_vector_addition (gsi, do_unop, do_negate, type,
957		      		         gimple_assign_rhs1 (assign),
958					 NULL_TREE, code);
959	break;
960
961      case BIT_AND_EXPR:
962      case BIT_IOR_EXPR:
963      case BIT_XOR_EXPR:
964        return expand_vector_parallel (gsi, do_binop, type,
965		      		       gimple_assign_rhs1 (assign),
966				       gimple_assign_rhs2 (assign), code);
967
968      case BIT_NOT_EXPR:
969        return expand_vector_parallel (gsi, do_unop, type,
970		      		       gimple_assign_rhs1 (assign),
971        			       NULL_TREE, code);
972      case EQ_EXPR:
973      case NE_EXPR:
974      case GT_EXPR:
975      case LT_EXPR:
976      case GE_EXPR:
977      case LE_EXPR:
978      case UNEQ_EXPR:
979      case UNGT_EXPR:
980      case UNLT_EXPR:
981      case UNGE_EXPR:
982      case UNLE_EXPR:
983      case LTGT_EXPR:
984      case ORDERED_EXPR:
985      case UNORDERED_EXPR:
986	{
987	  tree rhs1 = gimple_assign_rhs1 (assign);
988	  tree rhs2 = gimple_assign_rhs2 (assign);
989
990	  return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
991	}
992
993      case TRUNC_DIV_EXPR:
994      case TRUNC_MOD_EXPR:
995	{
996	  tree rhs1 = gimple_assign_rhs1 (assign);
997	  tree rhs2 = gimple_assign_rhs2 (assign);
998	  tree ret;
999
1000	  if (!optimize
1001	      || !VECTOR_INTEGER_TYPE_P (type)
1002	      || TREE_CODE (rhs2) != VECTOR_CST
1003	      || !VECTOR_MODE_P (TYPE_MODE (type)))
1004	    break;
1005
1006	  ret = expand_vector_divmod (gsi, type, rhs1, rhs2, code);
1007	  if (ret != NULL_TREE)
1008	    return ret;
1009	  break;
1010	}
1011
1012      default:
1013	break;
1014      }
1015
1016  if (TREE_CODE_CLASS (code) == tcc_unary)
1017    return expand_vector_piecewise (gsi, do_unop, type, compute_type,
1018				    gimple_assign_rhs1 (assign),
1019				    NULL_TREE, code);
1020  else
1021    return expand_vector_piecewise (gsi, do_binop, type, compute_type,
1022				    gimple_assign_rhs1 (assign),
1023				    gimple_assign_rhs2 (assign), code);
1024}
1025
1026/* Try to optimize
1027   a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
1028   style stmts into:
1029   _9 = { b_7, b_7, b_7, b_7 };
1030   a_5 = _9 + { 0, 3, 6, 9 };
1031   because vector splat operation is usually more efficient
1032   than piecewise initialization of the vector.  */
1033
1034static void
1035optimize_vector_constructor (gimple_stmt_iterator *gsi)
1036{
1037  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1038  tree lhs = gimple_assign_lhs (stmt);
1039  tree rhs = gimple_assign_rhs1 (stmt);
1040  tree type = TREE_TYPE (rhs);
1041  unsigned int i, j, nelts = TYPE_VECTOR_SUBPARTS (type);
1042  bool all_same = true;
1043  constructor_elt *elt;
1044  tree *cst;
1045  gimple g;
1046  tree base = NULL_TREE;
1047  optab op;
1048
1049  if (nelts <= 2 || CONSTRUCTOR_NELTS (rhs) != nelts)
1050    return;
1051  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
1052  if (op == unknown_optab
1053      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
1054    return;
1055  FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
1056    if (TREE_CODE (elt->value) != SSA_NAME
1057	|| TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
1058      return;
1059    else
1060      {
1061	tree this_base = elt->value;
1062	if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
1063	  all_same = false;
1064	for (j = 0; j < nelts + 1; j++)
1065	  {
1066	    g = SSA_NAME_DEF_STMT (this_base);
1067	    if (is_gimple_assign (g)
1068		&& gimple_assign_rhs_code (g) == PLUS_EXPR
1069		&& TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
1070		&& TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
1071		&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
1072	      this_base = gimple_assign_rhs1 (g);
1073	    else
1074	      break;
1075	  }
1076	if (i == 0)
1077	  base = this_base;
1078	else if (this_base != base)
1079	  return;
1080      }
1081  if (all_same)
1082    return;
1083  cst = XALLOCAVEC (tree, nelts);
1084  for (i = 0; i < nelts; i++)
1085    {
1086      tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;;
1087      cst[i] = build_zero_cst (TREE_TYPE (base));
1088      while (this_base != base)
1089	{
1090	  g = SSA_NAME_DEF_STMT (this_base);
1091	  cst[i] = fold_binary (PLUS_EXPR, TREE_TYPE (base),
1092				cst[i], gimple_assign_rhs2 (g));
1093	  if (cst[i] == NULL_TREE
1094	      || TREE_CODE (cst[i]) != INTEGER_CST
1095	      || TREE_OVERFLOW (cst[i]))
1096	    return;
1097	  this_base = gimple_assign_rhs1 (g);
1098	}
1099    }
1100  for (i = 0; i < nelts; i++)
1101    CONSTRUCTOR_ELT (rhs, i)->value = base;
1102  g = gimple_build_assign (make_ssa_name (type), rhs);
1103  gsi_insert_before (gsi, g, GSI_SAME_STMT);
1104  g = gimple_build_assign (lhs, PLUS_EXPR, gimple_assign_lhs (g),
1105			   build_vector (type, cst));
1106  gsi_replace (gsi, g, false);
1107}
1108
1109/* Return a type for the widest vector mode whose components are of type
1110   TYPE, or NULL_TREE if none is found.  */
1111
1112static tree
1113type_for_widest_vector_mode (tree type, optab op)
1114{
1115  machine_mode inner_mode = TYPE_MODE (type);
1116  machine_mode best_mode = VOIDmode, mode;
1117  int best_nunits = 0;
1118
1119  if (SCALAR_FLOAT_MODE_P (inner_mode))
1120    mode = MIN_MODE_VECTOR_FLOAT;
1121  else if (SCALAR_FRACT_MODE_P (inner_mode))
1122    mode = MIN_MODE_VECTOR_FRACT;
1123  else if (SCALAR_UFRACT_MODE_P (inner_mode))
1124    mode = MIN_MODE_VECTOR_UFRACT;
1125  else if (SCALAR_ACCUM_MODE_P (inner_mode))
1126    mode = MIN_MODE_VECTOR_ACCUM;
1127  else if (SCALAR_UACCUM_MODE_P (inner_mode))
1128    mode = MIN_MODE_VECTOR_UACCUM;
1129  else
1130    mode = MIN_MODE_VECTOR_INT;
1131
1132  for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
1133    if (GET_MODE_INNER (mode) == inner_mode
1134        && GET_MODE_NUNITS (mode) > best_nunits
1135	&& optab_handler (op, mode) != CODE_FOR_nothing)
1136      best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
1137
1138  if (best_mode == VOIDmode)
1139    return NULL_TREE;
1140  else
1141    return build_vector_type_for_mode (type, best_mode);
1142}
1143
1144
1145/* Build a reference to the element of the vector VECT.  Function
1146   returns either the element itself, either BIT_FIELD_REF, or an
1147   ARRAY_REF expression.
1148
1149   GSI is required to insert temporary variables while building a
1150   refernece to the element of the vector VECT.
1151
1152   PTMPVEC is a pointer to the temporary variable for caching
1153   purposes.  In case when PTMPVEC is NULL new temporary variable
1154   will be created.  */
1155static tree
1156vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
1157{
1158  tree vect_type, vect_elt_type;
1159  gimple asgn;
1160  tree tmpvec;
1161  tree arraytype;
1162  bool need_asgn = true;
1163  unsigned int elements;
1164
1165  vect_type = TREE_TYPE (vect);
1166  vect_elt_type = TREE_TYPE (vect_type);
1167  elements = TYPE_VECTOR_SUBPARTS (vect_type);
1168
1169  if (TREE_CODE (idx) == INTEGER_CST)
1170    {
1171      unsigned HOST_WIDE_INT index;
1172
1173      /* Given that we're about to compute a binary modulus,
1174	 we don't care about the high bits of the value.  */
1175      index = TREE_INT_CST_LOW (idx);
1176      if (!tree_fits_uhwi_p (idx) || index >= elements)
1177	{
1178	  index &= elements - 1;
1179	  idx = build_int_cst (TREE_TYPE (idx), index);
1180	}
1181
1182      /* When lowering a vector statement sequence do some easy
1183         simplification by looking through intermediate vector results.  */
1184      if (TREE_CODE (vect) == SSA_NAME)
1185	{
1186	  gimple def_stmt = SSA_NAME_DEF_STMT (vect);
1187	  if (is_gimple_assign (def_stmt)
1188	      && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
1189		  || gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR))
1190	    vect = gimple_assign_rhs1 (def_stmt);
1191	}
1192
1193      if (TREE_CODE (vect) == VECTOR_CST)
1194	return VECTOR_CST_ELT (vect, index);
1195      else if (TREE_CODE (vect) == CONSTRUCTOR
1196	       && (CONSTRUCTOR_NELTS (vect) == 0
1197		   || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
1198		      != VECTOR_TYPE))
1199        {
1200	  if (index < CONSTRUCTOR_NELTS (vect))
1201	    return CONSTRUCTOR_ELT (vect, index)->value;
1202          return build_zero_cst (vect_elt_type);
1203        }
1204      else
1205        {
1206	  tree size = TYPE_SIZE (vect_elt_type);
1207	  tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
1208				  size);
1209	  return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
1210        }
1211    }
1212
1213  if (!ptmpvec)
1214    tmpvec = create_tmp_var (vect_type, "vectmp");
1215  else if (!*ptmpvec)
1216    tmpvec = *ptmpvec = create_tmp_var (vect_type, "vectmp");
1217  else
1218    {
1219      tmpvec = *ptmpvec;
1220      need_asgn = false;
1221    }
1222
1223  if (need_asgn)
1224    {
1225      TREE_ADDRESSABLE (tmpvec) = 1;
1226      asgn = gimple_build_assign (tmpvec, vect);
1227      gsi_insert_before (gsi, asgn, GSI_SAME_STMT);
1228    }
1229
1230  arraytype = build_array_type_nelts (vect_elt_type, elements);
1231  return build4 (ARRAY_REF, vect_elt_type,
1232                 build1 (VIEW_CONVERT_EXPR, arraytype, tmpvec),
1233                 idx, NULL_TREE, NULL_TREE);
1234}
1235
1236/* Check if VEC_PERM_EXPR within the given setting is supported
1237   by hardware, or lower it piecewise.
1238
1239   When VEC_PERM_EXPR has the same first and second operands:
1240   VEC_PERM_EXPR <v0, v0, mask> the lowered version would be
1241   {v0[mask[0]], v0[mask[1]], ...}
1242   MASK and V0 must have the same number of elements.
1243
1244   Otherwise VEC_PERM_EXPR <v0, v1, mask> is lowered to
1245   {mask[0] < len(v0) ? v0[mask[0]] : v1[mask[0]], ...}
1246   V0 and V1 must have the same type.  MASK, V0, V1 must have the
1247   same number of arguments.  */
1248
1249static void
1250lower_vec_perm (gimple_stmt_iterator *gsi)
1251{
1252  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1253  tree mask = gimple_assign_rhs3 (stmt);
1254  tree vec0 = gimple_assign_rhs1 (stmt);
1255  tree vec1 = gimple_assign_rhs2 (stmt);
1256  tree vect_type = TREE_TYPE (vec0);
1257  tree mask_type = TREE_TYPE (mask);
1258  tree vect_elt_type = TREE_TYPE (vect_type);
1259  tree mask_elt_type = TREE_TYPE (mask_type);
1260  unsigned int elements = TYPE_VECTOR_SUBPARTS (vect_type);
1261  vec<constructor_elt, va_gc> *v;
1262  tree constr, t, si, i_val;
1263  tree vec0tmp = NULL_TREE, vec1tmp = NULL_TREE, masktmp = NULL_TREE;
1264  bool two_operand_p = !operand_equal_p (vec0, vec1, 0);
1265  location_t loc = gimple_location (gsi_stmt (*gsi));
1266  unsigned i;
1267
1268  if (TREE_CODE (mask) == SSA_NAME)
1269    {
1270      gimple def_stmt = SSA_NAME_DEF_STMT (mask);
1271      if (is_gimple_assign (def_stmt)
1272	  && gimple_assign_rhs_code (def_stmt) == VECTOR_CST)
1273	mask = gimple_assign_rhs1 (def_stmt);
1274    }
1275
1276  if (TREE_CODE (mask) == VECTOR_CST)
1277    {
1278      unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
1279
1280      for (i = 0; i < elements; ++i)
1281	sel_int[i] = (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
1282		      & (2 * elements - 1));
1283
1284      if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
1285	{
1286	  gimple_assign_set_rhs3 (stmt, mask);
1287	  update_stmt (stmt);
1288	  return;
1289	}
1290      /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
1291	 vector as VEC1 and a right element shift MASK.  */
1292      if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
1293	  != CODE_FOR_nothing
1294	  && TREE_CODE (vec1) == VECTOR_CST
1295	  && initializer_zerop (vec1)
1296	  && sel_int[0]
1297	  && sel_int[0] < elements)
1298	{
1299	  for (i = 1; i < elements; ++i)
1300	    {
1301	      unsigned int expected = i + sel_int[0];
1302	      /* Indices into the second vector are all equivalent.  */
1303	      if (MIN (elements, (unsigned) sel_int[i])
1304		  != MIN (elements, expected))
1305 		break;
1306	    }
1307	  if (i == elements)
1308	    {
1309	      gimple_assign_set_rhs3 (stmt, mask);
1310	      update_stmt (stmt);
1311	      return;
1312	    }
1313	}
1314    }
1315  else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
1316    return;
1317
1318  warning_at (loc, OPT_Wvector_operation_performance,
1319              "vector shuffling operation will be expanded piecewise");
1320
1321  vec_alloc (v, elements);
1322  for (i = 0; i < elements; i++)
1323    {
1324      si = size_int (i);
1325      i_val = vector_element (gsi, mask, si, &masktmp);
1326
1327      if (TREE_CODE (i_val) == INTEGER_CST)
1328        {
1329	  unsigned HOST_WIDE_INT index;
1330
1331	  index = TREE_INT_CST_LOW (i_val);
1332	  if (!tree_fits_uhwi_p (i_val) || index >= elements)
1333	    i_val = build_int_cst (mask_elt_type, index & (elements - 1));
1334
1335          if (two_operand_p && (index & elements) != 0)
1336	    t = vector_element (gsi, vec1, i_val, &vec1tmp);
1337	  else
1338	    t = vector_element (gsi, vec0, i_val, &vec0tmp);
1339
1340          t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
1341					true, GSI_SAME_STMT);
1342        }
1343      else
1344        {
1345	  tree cond = NULL_TREE, v0_val;
1346
1347	  if (two_operand_p)
1348	    {
1349	      cond = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1350			          build_int_cst (mask_elt_type, elements));
1351	      cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1352					       true, GSI_SAME_STMT);
1353	    }
1354
1355	  i_val = fold_build2 (BIT_AND_EXPR, mask_elt_type, i_val,
1356			       build_int_cst (mask_elt_type, elements - 1));
1357	  i_val = force_gimple_operand_gsi (gsi, i_val, true, NULL_TREE,
1358					    true, GSI_SAME_STMT);
1359
1360	  v0_val = vector_element (gsi, vec0, i_val, &vec0tmp);
1361	  v0_val = force_gimple_operand_gsi (gsi, v0_val, true, NULL_TREE,
1362					     true, GSI_SAME_STMT);
1363
1364	  if (two_operand_p)
1365	    {
1366	      tree v1_val;
1367
1368	      v1_val = vector_element (gsi, vec1, i_val, &vec1tmp);
1369	      v1_val = force_gimple_operand_gsi (gsi, v1_val, true, NULL_TREE,
1370						 true, GSI_SAME_STMT);
1371
1372	      cond = fold_build2 (EQ_EXPR, boolean_type_node,
1373				  cond, build_zero_cst (mask_elt_type));
1374	      cond = fold_build3 (COND_EXPR, vect_elt_type,
1375				  cond, v0_val, v1_val);
1376              t = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE,
1377					    true, GSI_SAME_STMT);
1378            }
1379	  else
1380	    t = v0_val;
1381        }
1382
1383      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
1384    }
1385
1386  constr = build_constructor (vect_type, v);
1387  gimple_assign_set_rhs_from_tree (gsi, constr);
1388  update_stmt (gsi_stmt (*gsi));
1389}
1390
1391/* Return type in which CODE operation with optab OP can be
1392   computed.  */
1393
1394static tree
1395get_compute_type (enum tree_code code, optab op, tree type)
1396{
1397  /* For very wide vectors, try using a smaller vector mode.  */
1398  tree compute_type = type;
1399  if (op
1400      && (!VECTOR_MODE_P (TYPE_MODE (type))
1401	  || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing))
1402    {
1403      tree vector_compute_type
1404	= type_for_widest_vector_mode (TREE_TYPE (type), op);
1405      if (vector_compute_type != NULL_TREE
1406	  && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
1407	      < TYPE_VECTOR_SUBPARTS (compute_type))
1408	  && (optab_handler (op, TYPE_MODE (vector_compute_type))
1409	      != CODE_FOR_nothing))
1410	compute_type = vector_compute_type;
1411    }
1412
1413  /* If we are breaking a BLKmode vector into smaller pieces,
1414     type_for_widest_vector_mode has already looked into the optab,
1415     so skip these checks.  */
1416  if (compute_type == type)
1417    {
1418      machine_mode compute_mode = TYPE_MODE (compute_type);
1419      if (VECTOR_MODE_P (compute_mode))
1420	{
1421	  if (op && optab_handler (op, compute_mode) != CODE_FOR_nothing)
1422	    return compute_type;
1423	  if (code == MULT_HIGHPART_EXPR
1424	      && can_mult_highpart_p (compute_mode,
1425				      TYPE_UNSIGNED (compute_type)))
1426	    return compute_type;
1427	}
1428      /* There is no operation in hardware, so fall back to scalars.  */
1429      compute_type = TREE_TYPE (type);
1430    }
1431
1432  return compute_type;
1433}
1434
1435/* Helper function of expand_vector_operations_1.  Return number of
1436   vector elements for vector types or 1 for other types.  */
1437
1438static inline int
1439count_type_subparts (tree type)
1440{
1441  return VECTOR_TYPE_P (type) ? TYPE_VECTOR_SUBPARTS (type) : 1;
1442}
1443
1444static tree
1445do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
1446	 tree bitpos, tree bitsize, enum tree_code code)
1447{
1448  if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
1449    a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
1450  if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
1451    b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
1452  tree cond = gimple_assign_rhs1 (gsi_stmt (*gsi));
1453  return gimplify_build3 (gsi, code, inner_type, cond, a, b);
1454}
1455
1456/* Expand a vector COND_EXPR to scalars, piecewise.  */
1457static void
1458expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
1459{
1460  gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
1461  tree type = gimple_expr_type (stmt);
1462  tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
1463  machine_mode compute_mode = TYPE_MODE (compute_type);
1464  gcc_assert (compute_mode != BLKmode);
1465  tree lhs = gimple_assign_lhs (stmt);
1466  tree rhs2 = gimple_assign_rhs2 (stmt);
1467  tree rhs3 = gimple_assign_rhs3 (stmt);
1468  tree new_rhs;
1469
1470  /* If the compute mode is not a vector mode (hence we are not decomposing
1471     a BLKmode vector to smaller, hardware-supported vectors), we may want
1472     to expand the operations in parallel.  */
1473  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
1474      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
1475      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
1476      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
1477      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
1478      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
1479    new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
1480				      COND_EXPR);
1481  else
1482    new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
1483				       rhs2, rhs3, COND_EXPR);
1484  if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1485    new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1486			       new_rhs);
1487
1488  /* NOTE:  We should avoid using gimple_assign_set_rhs_from_tree. One
1489     way to do it is change expand_vector_operation and its callees to
1490     return a tree_code, RHS1 and RHS2 instead of a tree. */
1491  gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1492  update_stmt (gsi_stmt (*gsi));
1493}
1494
1495/* Process one statement.  If we identify a vector operation, expand it.  */
1496
1497static void
1498expand_vector_operations_1 (gimple_stmt_iterator *gsi)
1499{
1500  tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
1501  enum tree_code code;
1502  optab op = unknown_optab;
1503  enum gimple_rhs_class rhs_class;
1504  tree new_rhs;
1505
1506  /* Only consider code == GIMPLE_ASSIGN. */
1507  gassign *stmt = dyn_cast <gassign *> (gsi_stmt (*gsi));
1508  if (!stmt)
1509    return;
1510
1511  code = gimple_assign_rhs_code (stmt);
1512  rhs_class = get_gimple_rhs_class (code);
1513  lhs = gimple_assign_lhs (stmt);
1514
1515  if (code == VEC_PERM_EXPR)
1516    {
1517      lower_vec_perm (gsi);
1518      return;
1519    }
1520
1521  if (code == VEC_COND_EXPR)
1522    {
1523      expand_vector_condition (gsi);
1524      return;
1525    }
1526
1527  if (code == COND_EXPR
1528      && TREE_CODE (TREE_TYPE (gimple_assign_lhs (stmt))) == VECTOR_TYPE
1529      && TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))) == BLKmode)
1530    {
1531      expand_vector_scalar_condition (gsi);
1532      return;
1533    }
1534
1535  if (code == CONSTRUCTOR
1536      && TREE_CODE (lhs) == SSA_NAME
1537      && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
1538      && !gimple_clobber_p (stmt)
1539      && optimize)
1540    {
1541      optimize_vector_constructor (gsi);
1542      return;
1543    }
1544
1545  if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
1546    return;
1547
1548  rhs1 = gimple_assign_rhs1 (stmt);
1549  type = gimple_expr_type (stmt);
1550  if (rhs_class == GIMPLE_BINARY_RHS)
1551    rhs2 = gimple_assign_rhs2 (stmt);
1552
1553  if (TREE_CODE (type) != VECTOR_TYPE)
1554    return;
1555
1556  if (CONVERT_EXPR_CODE_P (code)
1557      || code == FLOAT_EXPR
1558      || code == FIX_TRUNC_EXPR
1559      || code == VIEW_CONVERT_EXPR)
1560    return;
1561
1562  /* The signedness is determined from input argument.  */
1563  if (code == VEC_UNPACK_FLOAT_HI_EXPR
1564      || code == VEC_UNPACK_FLOAT_LO_EXPR)
1565    type = TREE_TYPE (rhs1);
1566
1567  /* For widening/narrowing vector operations, the relevant type is of the
1568     arguments, not the widened result.  VEC_UNPACK_FLOAT_*_EXPR is
1569     calculated in the same way above.  */
1570  if (code == WIDEN_SUM_EXPR
1571      || code == VEC_WIDEN_MULT_HI_EXPR
1572      || code == VEC_WIDEN_MULT_LO_EXPR
1573      || code == VEC_WIDEN_MULT_EVEN_EXPR
1574      || code == VEC_WIDEN_MULT_ODD_EXPR
1575      || code == VEC_UNPACK_HI_EXPR
1576      || code == VEC_UNPACK_LO_EXPR
1577      || code == VEC_PACK_TRUNC_EXPR
1578      || code == VEC_PACK_SAT_EXPR
1579      || code == VEC_PACK_FIX_TRUNC_EXPR
1580      || code == VEC_WIDEN_LSHIFT_HI_EXPR
1581      || code == VEC_WIDEN_LSHIFT_LO_EXPR)
1582    type = TREE_TYPE (rhs1);
1583
1584  /* Choose between vector shift/rotate by vector and vector shift/rotate by
1585     scalar */
1586  if (code == LSHIFT_EXPR
1587      || code == RSHIFT_EXPR
1588      || code == LROTATE_EXPR
1589      || code == RROTATE_EXPR)
1590    {
1591      optab opv;
1592
1593      /* Check whether we have vector <op> {x,x,x,x} where x
1594         could be a scalar variable or a constant.  Transform
1595         vector <op> {x,x,x,x} ==> vector <op> scalar.  */
1596      if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1597        {
1598          tree first;
1599          gimple def_stmt;
1600
1601          if ((TREE_CODE (rhs2) == VECTOR_CST
1602	       && (first = uniform_vector_p (rhs2)) != NULL_TREE)
1603	      || (TREE_CODE (rhs2) == SSA_NAME
1604		  && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
1605		  && gimple_assign_single_p (def_stmt)
1606		  && (first = uniform_vector_p
1607		      (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))
1608            {
1609              gimple_assign_set_rhs2 (stmt, first);
1610              update_stmt (stmt);
1611              rhs2 = first;
1612            }
1613        }
1614
1615      opv = optab_for_tree_code (code, type, optab_vector);
1616      if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1617	op = opv;
1618      else
1619	{
1620          op = optab_for_tree_code (code, type, optab_scalar);
1621
1622	  compute_type = get_compute_type (code, op, type);
1623	  if (compute_type == type)
1624	    return;
1625	  /* The rtl expander will expand vector/scalar as vector/vector
1626	     if necessary.  Pick one with wider vector type.  */
1627	  tree compute_vtype = get_compute_type (code, opv, type);
1628	  if (count_type_subparts (compute_vtype)
1629	      > count_type_subparts (compute_type))
1630	    {
1631	      compute_type = compute_vtype;
1632	      op = opv;
1633	    }
1634	}
1635
1636      if (code == LROTATE_EXPR || code == RROTATE_EXPR)
1637	{
1638	  if (compute_type == NULL_TREE)
1639	    compute_type = get_compute_type (code, op, type);
1640	  if (compute_type == type)
1641	    return;
1642	  /* Before splitting vector rotates into scalar rotates,
1643	     see if we can't use vector shifts and BIT_IOR_EXPR
1644	     instead.  For vector by vector rotates we'd also
1645	     need to check BIT_AND_EXPR and NEGATE_EXPR, punt there
1646	     for now, fold doesn't seem to create such rotates anyway.  */
1647	  if (compute_type == TREE_TYPE (type)
1648	      && !VECTOR_INTEGER_TYPE_P (TREE_TYPE (rhs2)))
1649	    {
1650	      optab oplv = vashl_optab, opl = ashl_optab;
1651	      optab oprv = vlshr_optab, opr = lshr_optab, opo = ior_optab;
1652	      tree compute_lvtype = get_compute_type (LSHIFT_EXPR, oplv, type);
1653	      tree compute_rvtype = get_compute_type (RSHIFT_EXPR, oprv, type);
1654	      tree compute_otype = get_compute_type (BIT_IOR_EXPR, opo, type);
1655	      tree compute_ltype = get_compute_type (LSHIFT_EXPR, opl, type);
1656	      tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
1657	      /* The rtl expander will expand vector/scalar as vector/vector
1658		 if necessary.  Pick one with wider vector type.  */
1659	      if (count_type_subparts (compute_lvtype)
1660		  > count_type_subparts (compute_ltype))
1661		{
1662		  compute_ltype = compute_lvtype;
1663		  opl = oplv;
1664		}
1665	      if (count_type_subparts (compute_rvtype)
1666		  > count_type_subparts (compute_rtype))
1667		{
1668		  compute_rtype = compute_rvtype;
1669		  opr = oprv;
1670		}
1671	      /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
1672		 BIT_IOR_EXPR.  */
1673	      compute_type = compute_ltype;
1674	      if (count_type_subparts (compute_type)
1675		  > count_type_subparts (compute_rtype))
1676		compute_type = compute_rtype;
1677	      if (count_type_subparts (compute_type)
1678		  > count_type_subparts (compute_otype))
1679		compute_type = compute_otype;
1680	      /* Verify all 3 operations can be performed in that type.  */
1681	      if (compute_type != TREE_TYPE (type))
1682		{
1683		  if (optab_handler (opl, TYPE_MODE (compute_type))
1684		      == CODE_FOR_nothing
1685		      || optab_handler (opr, TYPE_MODE (compute_type))
1686			 == CODE_FOR_nothing
1687		      || optab_handler (opo, TYPE_MODE (compute_type))
1688			 == CODE_FOR_nothing)
1689		    compute_type = TREE_TYPE (type);
1690		}
1691	    }
1692	}
1693    }
1694  else
1695    op = optab_for_tree_code (code, type, optab_default);
1696
1697  /* Optabs will try converting a negation into a subtraction, so
1698     look for it as well.  TODO: negation of floating-point vectors
1699     might be turned into an exclusive OR toggling the sign bit.  */
1700  if (op == unknown_optab
1701      && code == NEGATE_EXPR
1702      && INTEGRAL_TYPE_P (TREE_TYPE (type)))
1703    op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
1704
1705  if (compute_type == NULL_TREE)
1706    compute_type = get_compute_type (code, op, type);
1707  if (compute_type == type)
1708    return;
1709
1710  new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
1711
1712  /* Leave expression untouched for later expansion.  */
1713  if (new_rhs == NULL_TREE)
1714    return;
1715
1716  if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
1717    new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
1718                               new_rhs);
1719
1720  /* NOTE:  We should avoid using gimple_assign_set_rhs_from_tree. One
1721     way to do it is change expand_vector_operation and its callees to
1722     return a tree_code, RHS1 and RHS2 instead of a tree. */
1723  gimple_assign_set_rhs_from_tree (gsi, new_rhs);
1724  update_stmt (gsi_stmt (*gsi));
1725}
1726
1727/* Use this to lower vector operations introduced by the vectorizer,
1728   if it may need the bit-twiddling tricks implemented in this file.  */
1729
1730static unsigned int
1731expand_vector_operations (void)
1732{
1733  gimple_stmt_iterator gsi;
1734  basic_block bb;
1735  bool cfg_changed = false;
1736
1737  FOR_EACH_BB_FN (bb, cfun)
1738    {
1739      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1740	{
1741	  expand_vector_operations_1 (&gsi);
1742	  /* ???  If we do not cleanup EH then we will ICE in
1743	     verification.  But in reality we have created wrong-code
1744	     as we did not properly transition EH info and edges to
1745	     the piecewise computations.  */
1746	  if (maybe_clean_eh_stmt (gsi_stmt (gsi))
1747	      && gimple_purge_dead_eh_edges (bb))
1748	    cfg_changed = true;
1749	}
1750    }
1751
1752  return cfg_changed ? TODO_cleanup_cfg : 0;
1753}
1754
1755namespace {
1756
1757const pass_data pass_data_lower_vector =
1758{
1759  GIMPLE_PASS, /* type */
1760  "veclower", /* name */
1761  OPTGROUP_VEC, /* optinfo_flags */
1762  TV_NONE, /* tv_id */
1763  PROP_cfg, /* properties_required */
1764  PROP_gimple_lvec, /* properties_provided */
1765  0, /* properties_destroyed */
1766  0, /* todo_flags_start */
1767  TODO_update_ssa, /* todo_flags_finish */
1768};
1769
1770class pass_lower_vector : public gimple_opt_pass
1771{
1772public:
1773  pass_lower_vector (gcc::context *ctxt)
1774    : gimple_opt_pass (pass_data_lower_vector, ctxt)
1775  {}
1776
1777  /* opt_pass methods: */
1778  virtual bool gate (function *fun)
1779    {
1780      return !(fun->curr_properties & PROP_gimple_lvec);
1781    }
1782
1783  virtual unsigned int execute (function *)
1784    {
1785      return expand_vector_operations ();
1786    }
1787
1788}; // class pass_lower_vector
1789
1790} // anon namespace
1791
1792gimple_opt_pass *
1793make_pass_lower_vector (gcc::context *ctxt)
1794{
1795  return new pass_lower_vector (ctxt);
1796}
1797
1798namespace {
1799
1800const pass_data pass_data_lower_vector_ssa =
1801{
1802  GIMPLE_PASS, /* type */
1803  "veclower2", /* name */
1804  OPTGROUP_VEC, /* optinfo_flags */
1805  TV_NONE, /* tv_id */
1806  PROP_cfg, /* properties_required */
1807  PROP_gimple_lvec, /* properties_provided */
1808  0, /* properties_destroyed */
1809  0, /* todo_flags_start */
1810  ( TODO_update_ssa
1811    | TODO_cleanup_cfg ), /* todo_flags_finish */
1812};
1813
1814class pass_lower_vector_ssa : public gimple_opt_pass
1815{
1816public:
1817  pass_lower_vector_ssa (gcc::context *ctxt)
1818    : gimple_opt_pass (pass_data_lower_vector_ssa, ctxt)
1819  {}
1820
1821  /* opt_pass methods: */
1822  opt_pass * clone () { return new pass_lower_vector_ssa (m_ctxt); }
1823  virtual unsigned int execute (function *)
1824    {
1825      return expand_vector_operations ();
1826    }
1827
1828}; // class pass_lower_vector_ssa
1829
1830} // anon namespace
1831
1832gimple_opt_pass *
1833make_pass_lower_vector_ssa (gcc::context *ctxt)
1834{
1835  return new pass_lower_vector_ssa (ctxt);
1836}
1837
1838#include "gt-tree-vect-generic.h"
1839