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