1 /* OMP constructs' SIMD clone supporting code.
2 
3 Copyright (C) 2005-2018 Free Software Foundation, Inc.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "target.h"
26 #include "tree.h"
27 #include "gimple.h"
28 #include "cfghooks.h"
29 #include "alloc-pool.h"
30 #include "tree-pass.h"
31 #include "ssa.h"
32 #include "cgraph.h"
33 #include "pretty-print.h"
34 #include "diagnostic-core.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "cfganal.h"
38 #include "gimplify.h"
39 #include "gimple-iterator.h"
40 #include "gimplify-me.h"
41 #include "gimple-walk.h"
42 #include "langhooks.h"
43 #include "tree-cfg.h"
44 #include "tree-into-ssa.h"
45 #include "tree-dfa.h"
46 #include "cfgloop.h"
47 #include "symbol-summary.h"
48 #include "ipa-param-manipulation.h"
49 #include "tree-eh.h"
50 #include "varasm.h"
51 #include "stringpool.h"
52 #include "attribs.h"
53 #include "omp-simd-clone.h"
54 
55 /* Return the number of elements in vector type VECTYPE, which is associated
56    with a SIMD clone.  At present these always have a constant length.  */
57 
58 static unsigned HOST_WIDE_INT
59 simd_clone_subparts (tree vectype)
60 {
61   return TYPE_VECTOR_SUBPARTS (vectype).to_constant ();
62 }
63 
64 /* Allocate a fresh `simd_clone' and return it.  NARGS is the number
65    of arguments to reserve space for.  */
66 
67 static struct cgraph_simd_clone *
68 simd_clone_struct_alloc (int nargs)
69 {
70   struct cgraph_simd_clone *clone_info;
71   size_t len = (sizeof (struct cgraph_simd_clone)
72 		+ nargs * sizeof (struct cgraph_simd_clone_arg));
73   clone_info = (struct cgraph_simd_clone *)
74 	       ggc_internal_cleared_alloc (len);
75   return clone_info;
76 }
77 
78 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO.  */
79 
80 static inline void
81 simd_clone_struct_copy (struct cgraph_simd_clone *to,
82 			struct cgraph_simd_clone *from)
83 {
84   memcpy (to, from, (sizeof (struct cgraph_simd_clone)
85 		     + ((from->nargs - from->inbranch)
86 			* sizeof (struct cgraph_simd_clone_arg))));
87 }
88 
89 /* Return vector of parameter types of function FNDECL.  This uses
90    TYPE_ARG_TYPES if available, otherwise falls back to types of
91    DECL_ARGUMENTS types.  */
92 
93 static vec<tree>
94 simd_clone_vector_of_formal_parm_types (tree fndecl)
95 {
96   if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
97     return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
98   vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
99   unsigned int i;
100   tree arg;
101   FOR_EACH_VEC_ELT (args, i, arg)
102     args[i] = TREE_TYPE (args[i]);
103   return args;
104 }
105 
106 /* Given a simd function in NODE, extract the simd specific
107    information from the OMP clauses passed in CLAUSES, and return
108    the struct cgraph_simd_clone * if it should be cloned.  *INBRANCH_SPECIFIED
109    is set to TRUE if the `inbranch' or `notinbranch' clause specified,
110    otherwise set to FALSE.  */
111 
112 static struct cgraph_simd_clone *
113 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
114 			    bool *inbranch_specified)
115 {
116   vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
117   tree t;
118   int n;
119   *inbranch_specified = false;
120 
121   n = args.length ();
122   if (n > 0 && args.last () == void_type_node)
123     n--;
124 
125   /* Allocate one more than needed just in case this is an in-branch
126      clone which will require a mask argument.  */
127   struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
128   clone_info->nargs = n;
129 
130   if (!clauses)
131     goto out;
132 
133   clauses = TREE_VALUE (clauses);
134   if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
135     goto out;
136 
137   for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
138     {
139       switch (OMP_CLAUSE_CODE (t))
140 	{
141 	case OMP_CLAUSE_INBRANCH:
142 	  clone_info->inbranch = 1;
143 	  *inbranch_specified = true;
144 	  break;
145 	case OMP_CLAUSE_NOTINBRANCH:
146 	  clone_info->inbranch = 0;
147 	  *inbranch_specified = true;
148 	  break;
149 	case OMP_CLAUSE_SIMDLEN:
150 	  clone_info->simdlen
151 	    = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
152 	  break;
153 	case OMP_CLAUSE_LINEAR:
154 	  {
155 	    tree decl = OMP_CLAUSE_DECL (t);
156 	    tree step = OMP_CLAUSE_LINEAR_STEP (t);
157 	    int argno = TREE_INT_CST_LOW (decl);
158 	    if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
159 	      {
160 		enum cgraph_simd_clone_arg_type arg_type;
161 		if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
162 		  switch (OMP_CLAUSE_LINEAR_KIND (t))
163 		    {
164 		    case OMP_CLAUSE_LINEAR_REF:
165 		      arg_type
166 			= SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
167 		      break;
168 		    case OMP_CLAUSE_LINEAR_UVAL:
169 		      arg_type
170 			= SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
171 		      break;
172 		    case OMP_CLAUSE_LINEAR_VAL:
173 		    case OMP_CLAUSE_LINEAR_DEFAULT:
174 		      arg_type
175 			= SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
176 		      break;
177 		    default:
178 		      gcc_unreachable ();
179 		    }
180 		else
181 		  arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
182 		clone_info->args[argno].arg_type = arg_type;
183 		clone_info->args[argno].linear_step = tree_to_shwi (step);
184 		gcc_assert (clone_info->args[argno].linear_step >= 0
185 			    && clone_info->args[argno].linear_step < n);
186 	      }
187 	    else
188 	      {
189 		if (POINTER_TYPE_P (args[argno]))
190 		  step = fold_convert (ssizetype, step);
191 		if (!tree_fits_shwi_p (step))
192 		  {
193 		    warning_at (OMP_CLAUSE_LOCATION (t), 0,
194 				"ignoring large linear step");
195 		    args.release ();
196 		    return NULL;
197 		  }
198 		else if (integer_zerop (step))
199 		  {
200 		    warning_at (OMP_CLAUSE_LOCATION (t), 0,
201 				"ignoring zero linear step");
202 		    args.release ();
203 		    return NULL;
204 		  }
205 		else
206 		  {
207 		    enum cgraph_simd_clone_arg_type arg_type;
208 		    if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
209 		      switch (OMP_CLAUSE_LINEAR_KIND (t))
210 			{
211 			case OMP_CLAUSE_LINEAR_REF:
212 			  arg_type
213 			    = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
214 			  break;
215 			case OMP_CLAUSE_LINEAR_UVAL:
216 			  arg_type
217 			    = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
218 			  break;
219 			case OMP_CLAUSE_LINEAR_VAL:
220 			case OMP_CLAUSE_LINEAR_DEFAULT:
221 			  arg_type
222 			    = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
223 			  break;
224 			default:
225 			  gcc_unreachable ();
226 			}
227 		    else
228 		      arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
229 		    clone_info->args[argno].arg_type = arg_type;
230 		    clone_info->args[argno].linear_step = tree_to_shwi (step);
231 		  }
232 	      }
233 	    break;
234 	  }
235 	case OMP_CLAUSE_UNIFORM:
236 	  {
237 	    tree decl = OMP_CLAUSE_DECL (t);
238 	    int argno = tree_to_uhwi (decl);
239 	    clone_info->args[argno].arg_type
240 	      = SIMD_CLONE_ARG_TYPE_UNIFORM;
241 	    break;
242 	  }
243 	case OMP_CLAUSE_ALIGNED:
244 	  {
245 	    /* Ignore aligned (x) for declare simd, for the ABI we really
246 	       need an alignment specified.  */
247 	    if (OMP_CLAUSE_ALIGNED_ALIGNMENT (t) == NULL_TREE)
248 	      break;
249 	    tree decl = OMP_CLAUSE_DECL (t);
250 	    int argno = tree_to_uhwi (decl);
251 	    clone_info->args[argno].alignment
252 	      = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
253 	    break;
254 	  }
255 	default:
256 	  break;
257 	}
258     }
259 
260  out:
261   if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (node->decl))))
262     {
263       warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
264 		  "ignoring %<#pragma omp declare simd%> on function "
265 		  "with %<_Atomic%> qualified return type");
266       args.release ();
267       return NULL;
268     }
269 
270   for (unsigned int argno = 0; argno < clone_info->nargs; argno++)
271     if (TYPE_ATOMIC (args[argno])
272 	&& clone_info->args[argno].arg_type != SIMD_CLONE_ARG_TYPE_UNIFORM)
273       {
274 	warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
275 		    "ignoring %<#pragma omp declare simd%> on function "
276 		    "with %<_Atomic%> qualified non-%<uniform%> argument");
277 	args.release ();
278 	return NULL;
279       }
280 
281   args.release ();
282   return clone_info;
283 }
284 
285 /* Given a SIMD clone in NODE, calculate the characteristic data
286    type and return the coresponding type.  The characteristic data
287    type is computed as described in the Intel Vector ABI.  */
288 
289 static tree
290 simd_clone_compute_base_data_type (struct cgraph_node *node,
291 				   struct cgraph_simd_clone *clone_info)
292 {
293   tree type = integer_type_node;
294   tree fndecl = node->decl;
295 
296   /* a) For non-void function, the characteristic data type is the
297         return type.  */
298   if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
299     type = TREE_TYPE (TREE_TYPE (fndecl));
300 
301   /* b) If the function has any non-uniform, non-linear parameters,
302         then the characteristic data type is the type of the first
303         such parameter.  */
304   else
305     {
306       vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
307       for (unsigned int i = 0; i < clone_info->nargs; ++i)
308 	if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
309 	  {
310 	    type = map[i];
311 	    break;
312 	  }
313       map.release ();
314     }
315 
316   /* c) If the characteristic data type determined by a) or b) above
317         is struct, union, or class type which is pass-by-value (except
318         for the type that maps to the built-in complex data type), the
319         characteristic data type is int.  */
320   if (RECORD_OR_UNION_TYPE_P (type)
321       && !aggregate_value_p (type, NULL)
322       && TREE_CODE (type) != COMPLEX_TYPE)
323     return integer_type_node;
324 
325   /* d) If none of the above three classes is applicable, the
326         characteristic data type is int.  */
327 
328   return type;
329 
330   /* e) For Intel Xeon Phi native and offload compilation, if the
331         resulting characteristic data type is 8-bit or 16-bit integer
332         data type, the characteristic data type is int.  */
333   /* Well, we don't handle Xeon Phi yet.  */
334 }
335 
336 static tree
337 simd_clone_mangle (struct cgraph_node *node,
338 		   struct cgraph_simd_clone *clone_info)
339 {
340   char vecsize_mangle = clone_info->vecsize_mangle;
341   char mask = clone_info->inbranch ? 'M' : 'N';
342   unsigned int simdlen = clone_info->simdlen;
343   unsigned int n;
344   pretty_printer pp;
345 
346   gcc_assert (vecsize_mangle && simdlen);
347 
348   pp_string (&pp, "_ZGV");
349   pp_character (&pp, vecsize_mangle);
350   pp_character (&pp, mask);
351   pp_decimal_int (&pp, simdlen);
352 
353   for (n = 0; n < clone_info->nargs; ++n)
354     {
355       struct cgraph_simd_clone_arg arg = clone_info->args[n];
356 
357       switch (arg.arg_type)
358 	{
359 	case SIMD_CLONE_ARG_TYPE_UNIFORM:
360 	  pp_character (&pp, 'u');
361 	  break;
362 	case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
363 	  pp_character (&pp, 'l');
364 	  goto mangle_linear;
365 	case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
366 	  pp_character (&pp, 'R');
367 	  goto mangle_linear;
368 	case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
369 	  pp_character (&pp, 'L');
370 	  goto mangle_linear;
371 	case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
372 	  pp_character (&pp, 'U');
373 	  goto mangle_linear;
374 	mangle_linear:
375 	  gcc_assert (arg.linear_step != 0);
376 	  if (arg.linear_step > 1)
377 	    pp_unsigned_wide_integer (&pp, arg.linear_step);
378 	  else if (arg.linear_step < 0)
379 	    {
380 	      pp_character (&pp, 'n');
381 	      pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
382 					      arg.linear_step));
383 	    }
384 	  break;
385 	case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
386 	  pp_string (&pp, "ls");
387 	  pp_unsigned_wide_integer (&pp, arg.linear_step);
388 	  break;
389 	case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
390 	  pp_string (&pp, "Rs");
391 	  pp_unsigned_wide_integer (&pp, arg.linear_step);
392 	  break;
393 	case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
394 	  pp_string (&pp, "Ls");
395 	  pp_unsigned_wide_integer (&pp, arg.linear_step);
396 	  break;
397 	case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
398 	  pp_string (&pp, "Us");
399 	  pp_unsigned_wide_integer (&pp, arg.linear_step);
400 	  break;
401 	default:
402 	  pp_character (&pp, 'v');
403 	}
404       if (arg.alignment)
405 	{
406 	  pp_character (&pp, 'a');
407 	  pp_decimal_int (&pp, arg.alignment);
408 	}
409     }
410 
411   pp_underscore (&pp);
412   const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
413   if (*str == '*')
414     ++str;
415   pp_string (&pp, str);
416   str = pp_formatted_text (&pp);
417 
418   /* If there already is a SIMD clone with the same mangled name, don't
419      add another one.  This can happen e.g. for
420      #pragma omp declare simd
421      #pragma omp declare simd simdlen(8)
422      int foo (int, int);
423      if the simdlen is assumed to be 8 for the first one, etc.  */
424   for (struct cgraph_node *clone = node->simd_clones; clone;
425        clone = clone->simdclone->next_clone)
426     if (id_equal (DECL_ASSEMBLER_NAME (clone->decl), str))
427       return NULL_TREE;
428 
429   return get_identifier (str);
430 }
431 
432 /* Create a simd clone of OLD_NODE and return it.  */
433 
434 static struct cgraph_node *
435 simd_clone_create (struct cgraph_node *old_node)
436 {
437   struct cgraph_node *new_node;
438   if (old_node->definition)
439     {
440       if (!old_node->has_gimple_body_p ())
441 	return NULL;
442       old_node->get_body ();
443       new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
444 							   false, NULL, NULL,
445 							   "simdclone");
446     }
447   else
448     {
449       tree old_decl = old_node->decl;
450       tree new_decl = copy_node (old_node->decl);
451       DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
452       SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
453       SET_DECL_RTL (new_decl, NULL);
454       DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
455       DECL_STATIC_DESTRUCTOR (new_decl) = 0;
456       new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
457       if (old_node->in_other_partition)
458 	new_node->in_other_partition = 1;
459     }
460   if (new_node == NULL)
461     return new_node;
462 
463   DECL_BUILT_IN_CLASS (new_node->decl) = NOT_BUILT_IN;
464   DECL_FUNCTION_CODE (new_node->decl) = (enum built_in_function) 0;
465   TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
466   DECL_COMDAT (new_node->decl) = DECL_COMDAT (old_node->decl);
467   DECL_WEAK (new_node->decl) = DECL_WEAK (old_node->decl);
468   DECL_EXTERNAL (new_node->decl) = DECL_EXTERNAL (old_node->decl);
469   DECL_VISIBILITY_SPECIFIED (new_node->decl)
470     = DECL_VISIBILITY_SPECIFIED (old_node->decl);
471   DECL_VISIBILITY (new_node->decl) = DECL_VISIBILITY (old_node->decl);
472   DECL_DLLIMPORT_P (new_node->decl) = DECL_DLLIMPORT_P (old_node->decl);
473   if (DECL_ONE_ONLY (old_node->decl))
474     make_decl_one_only (new_node->decl, DECL_ASSEMBLER_NAME (new_node->decl));
475 
476   /* The method cgraph_version_clone_with_body () will force the new
477      symbol local.  Undo this, and inherit external visibility from
478      the old node.  */
479   new_node->local.local = old_node->local.local;
480   new_node->externally_visible = old_node->externally_visible;
481 
482   return new_node;
483 }
484 
485 /* Adjust the return type of the given function to its appropriate
486    vector counterpart.  Returns a simd array to be used throughout the
487    function as a return value.  */
488 
489 static tree
490 simd_clone_adjust_return_type (struct cgraph_node *node)
491 {
492   tree fndecl = node->decl;
493   tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
494   unsigned int veclen;
495   tree t;
496 
497   /* Adjust the function return type.  */
498   if (orig_rettype == void_type_node)
499     return NULL_TREE;
500   TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
501   t = TREE_TYPE (TREE_TYPE (fndecl));
502   if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
503     veclen = node->simdclone->vecsize_int;
504   else
505     veclen = node->simdclone->vecsize_float;
506   veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (t));
507   if (veclen > node->simdclone->simdlen)
508     veclen = node->simdclone->simdlen;
509   if (POINTER_TYPE_P (t))
510     t = pointer_sized_int_node;
511   if (veclen == node->simdclone->simdlen)
512     t = build_vector_type (t, node->simdclone->simdlen);
513   else
514     {
515       t = build_vector_type (t, veclen);
516       t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
517     }
518   TREE_TYPE (TREE_TYPE (fndecl)) = t;
519   if (!node->definition)
520     return NULL_TREE;
521 
522   t = DECL_RESULT (fndecl);
523   /* Adjust the DECL_RESULT.  */
524   gcc_assert (TREE_TYPE (t) != void_type_node);
525   TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
526   relayout_decl (t);
527 
528   tree atype = build_array_type_nelts (orig_rettype,
529 				       node->simdclone->simdlen);
530   if (veclen != node->simdclone->simdlen)
531     return build1 (VIEW_CONVERT_EXPR, atype, t);
532 
533   /* Set up a SIMD array to use as the return value.  */
534   tree retval = create_tmp_var_raw (atype, "retval");
535   gimple_add_tmp_var (retval);
536   return retval;
537 }
538 
539 /* Each vector argument has a corresponding array to be used locally
540    as part of the eventual loop.  Create such temporary array and
541    return it.
542 
543    PREFIX is the prefix to be used for the temporary.
544 
545    TYPE is the inner element type.
546 
547    SIMDLEN is the number of elements.  */
548 
549 static tree
550 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
551 {
552   tree atype = build_array_type_nelts (type, simdlen);
553   tree avar = create_tmp_var_raw (atype, prefix);
554   gimple_add_tmp_var (avar);
555   return avar;
556 }
557 
558 /* Modify the function argument types to their corresponding vector
559    counterparts if appropriate.  Also, create one array for each simd
560    argument to be used locally when using the function arguments as
561    part of the loop.
562 
563    NODE is the function whose arguments are to be adjusted.
564 
565    Returns an adjustment vector that will be filled describing how the
566    argument types will be adjusted.  */
567 
568 static ipa_parm_adjustment_vec
569 simd_clone_adjust_argument_types (struct cgraph_node *node)
570 {
571   vec<tree> args;
572   ipa_parm_adjustment_vec adjustments;
573 
574   if (node->definition)
575     args = ipa_get_vector_of_formal_parms (node->decl);
576   else
577     args = simd_clone_vector_of_formal_parm_types (node->decl);
578   adjustments.create (args.length ());
579   unsigned i, j, veclen;
580   struct ipa_parm_adjustment adj;
581   struct cgraph_simd_clone *sc = node->simdclone;
582 
583   for (i = 0; i < sc->nargs; ++i)
584     {
585       memset (&adj, 0, sizeof (adj));
586       tree parm = args[i];
587       tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
588       adj.base_index = i;
589       adj.base = parm;
590 
591       sc->args[i].orig_arg = node->definition ? parm : NULL_TREE;
592       sc->args[i].orig_type = parm_type;
593 
594       switch (sc->args[i].arg_type)
595 	{
596 	default:
597 	  /* No adjustment necessary for scalar arguments.  */
598 	  adj.op = IPA_PARM_OP_COPY;
599 	  break;
600 	case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
601 	case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
602 	  if (node->definition)
603 	    sc->args[i].simd_array
604 	      = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
605 				       TREE_TYPE (parm_type),
606 				       sc->simdlen);
607 	  adj.op = IPA_PARM_OP_COPY;
608 	  break;
609 	case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
610 	case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
611 	case SIMD_CLONE_ARG_TYPE_VECTOR:
612 	  if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
613 	    veclen = sc->vecsize_int;
614 	  else
615 	    veclen = sc->vecsize_float;
616 	  veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (parm_type));
617 	  if (veclen > sc->simdlen)
618 	    veclen = sc->simdlen;
619 	  adj.arg_prefix = "simd";
620 	  if (POINTER_TYPE_P (parm_type))
621 	    adj.type = build_vector_type (pointer_sized_int_node, veclen);
622 	  else
623 	    adj.type = build_vector_type (parm_type, veclen);
624 	  sc->args[i].vector_type = adj.type;
625 	  for (j = veclen; j < sc->simdlen; j += veclen)
626 	    {
627 	      adjustments.safe_push (adj);
628 	      if (j == veclen)
629 		{
630 		  memset (&adj, 0, sizeof (adj));
631 		  adj.op = IPA_PARM_OP_NEW;
632 		  adj.arg_prefix = "simd";
633 		  adj.base_index = i;
634 		  adj.type = sc->args[i].vector_type;
635 		}
636 	    }
637 
638 	  if (node->definition)
639 	    sc->args[i].simd_array
640 	      = create_tmp_simd_array (DECL_NAME (parm)
641 				       ? IDENTIFIER_POINTER (DECL_NAME (parm))
642 				       : NULL, parm_type, sc->simdlen);
643 	}
644       adjustments.safe_push (adj);
645     }
646 
647   if (sc->inbranch)
648     {
649       tree base_type = simd_clone_compute_base_data_type (sc->origin, sc);
650 
651       memset (&adj, 0, sizeof (adj));
652       adj.op = IPA_PARM_OP_NEW;
653       adj.arg_prefix = "mask";
654 
655       adj.base_index = i;
656       if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
657 	veclen = sc->vecsize_int;
658       else
659 	veclen = sc->vecsize_float;
660       veclen /= GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type));
661       if (veclen > sc->simdlen)
662 	veclen = sc->simdlen;
663       if (sc->mask_mode != VOIDmode)
664 	adj.type
665 	  = lang_hooks.types.type_for_mode (sc->mask_mode, 1);
666       else if (POINTER_TYPE_P (base_type))
667 	adj.type = build_vector_type (pointer_sized_int_node, veclen);
668       else
669 	adj.type = build_vector_type (base_type, veclen);
670       adjustments.safe_push (adj);
671 
672       for (j = veclen; j < sc->simdlen; j += veclen)
673 	adjustments.safe_push (adj);
674 
675       /* We have previously allocated one extra entry for the mask.  Use
676 	 it and fill it.  */
677       sc->nargs++;
678       if (sc->mask_mode != VOIDmode)
679 	base_type = boolean_type_node;
680       if (node->definition)
681 	{
682 	  sc->args[i].orig_arg
683 	    = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
684 	  if (sc->mask_mode == VOIDmode)
685 	    sc->args[i].simd_array
686 	      = create_tmp_simd_array ("mask", base_type, sc->simdlen);
687 	  else if (veclen < sc->simdlen)
688 	    sc->args[i].simd_array
689 	      = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
690 	  else
691 	    sc->args[i].simd_array = NULL_TREE;
692 	}
693       sc->args[i].orig_type = base_type;
694       sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
695     }
696 
697   if (node->definition)
698     ipa_modify_formal_parameters (node->decl, adjustments);
699   else
700     {
701       tree new_arg_types = NULL_TREE, new_reversed;
702       bool last_parm_void = false;
703       if (args.length () > 0 && args.last () == void_type_node)
704 	last_parm_void = true;
705 
706       gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
707       j = adjustments.length ();
708       for (i = 0; i < j; i++)
709 	{
710 	  struct ipa_parm_adjustment *adj = &adjustments[i];
711 	  tree ptype;
712 	  if (adj->op == IPA_PARM_OP_COPY)
713 	    ptype = args[adj->base_index];
714 	  else
715 	    ptype = adj->type;
716 	  new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
717 	}
718       new_reversed = nreverse (new_arg_types);
719       if (last_parm_void)
720 	{
721 	  if (new_reversed)
722 	    TREE_CHAIN (new_arg_types) = void_list_node;
723 	  else
724 	    new_reversed = void_list_node;
725 	}
726 
727       tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
728       TYPE_ARG_TYPES (new_type) = new_reversed;
729       TREE_TYPE (node->decl) = new_type;
730 
731       adjustments.release ();
732     }
733   args.release ();
734   return adjustments;
735 }
736 
737 /* Initialize and copy the function arguments in NODE to their
738    corresponding local simd arrays.  Returns a fresh gimple_seq with
739    the instruction sequence generated.  */
740 
741 static gimple_seq
742 simd_clone_init_simd_arrays (struct cgraph_node *node,
743 			     ipa_parm_adjustment_vec adjustments)
744 {
745   gimple_seq seq = NULL;
746   unsigned i = 0, j = 0, k;
747 
748   for (tree arg = DECL_ARGUMENTS (node->decl);
749        arg;
750        arg = DECL_CHAIN (arg), i++, j++)
751     {
752       if (adjustments[j].op == IPA_PARM_OP_COPY
753 	  || POINTER_TYPE_P (TREE_TYPE (arg)))
754 	continue;
755 
756       node->simdclone->args[i].vector_arg = arg;
757 
758       tree array = node->simdclone->args[i].simd_array;
759       if (node->simdclone->mask_mode != VOIDmode
760 	  && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_MASK)
761 	{
762 	  if (array == NULL_TREE)
763 	    continue;
764 	  unsigned int l
765 	    = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array))));
766 	  for (k = 0; k <= l; k++)
767 	    {
768 	      if (k)
769 		{
770 		  arg = DECL_CHAIN (arg);
771 		  j++;
772 		}
773 	      tree t = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
774 			       array, size_int (k), NULL, NULL);
775 	      t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
776 	      gimplify_and_add (t, &seq);
777 	    }
778 	  continue;
779 	}
780       if (simd_clone_subparts (TREE_TYPE (arg)) == node->simdclone->simdlen)
781 	{
782 	  tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
783 	  tree ptr = build_fold_addr_expr (array);
784 	  tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
785 			   build_int_cst (ptype, 0));
786 	  t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
787 	  gimplify_and_add (t, &seq);
788 	}
789       else
790 	{
791 	  unsigned int simdlen = simd_clone_subparts (TREE_TYPE (arg));
792 	  tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
793 	  for (k = 0; k < node->simdclone->simdlen; k += simdlen)
794 	    {
795 	      tree ptr = build_fold_addr_expr (array);
796 	      int elemsize;
797 	      if (k)
798 		{
799 		  arg = DECL_CHAIN (arg);
800 		  j++;
801 		}
802 	      tree elemtype = TREE_TYPE (TREE_TYPE (arg));
803 	      elemsize = GET_MODE_SIZE (SCALAR_TYPE_MODE (elemtype));
804 	      tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
805 			       build_int_cst (ptype, k * elemsize));
806 	      t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
807 	      gimplify_and_add (t, &seq);
808 	    }
809 	}
810     }
811   return seq;
812 }
813 
814 /* Callback info for ipa_simd_modify_stmt_ops below.  */
815 
816 struct modify_stmt_info {
817   ipa_parm_adjustment_vec adjustments;
818   gimple *stmt;
819   /* True if the parent statement was modified by
820      ipa_simd_modify_stmt_ops.  */
821   bool modified;
822 };
823 
824 /* Callback for walk_gimple_op.
825 
826    Adjust operands from a given statement as specified in the
827    adjustments vector in the callback data.  */
828 
829 static tree
830 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
831 {
832   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
833   struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
834   tree *orig_tp = tp;
835   if (TREE_CODE (*tp) == ADDR_EXPR)
836     tp = &TREE_OPERAND (*tp, 0);
837   struct ipa_parm_adjustment *cand = NULL;
838   if (TREE_CODE (*tp) == PARM_DECL)
839     cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
840   else
841     {
842       if (TYPE_P (*tp))
843 	*walk_subtrees = 0;
844     }
845 
846   tree repl = NULL_TREE;
847   if (cand)
848     repl = unshare_expr (cand->new_decl);
849   else
850     {
851       if (tp != orig_tp)
852 	{
853 	  *walk_subtrees = 0;
854 	  bool modified = info->modified;
855 	  info->modified = false;
856 	  walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
857 	  if (!info->modified)
858 	    {
859 	      info->modified = modified;
860 	      return NULL_TREE;
861 	    }
862 	  info->modified = modified;
863 	  repl = *tp;
864 	}
865       else
866 	return NULL_TREE;
867     }
868 
869   if (tp != orig_tp)
870     {
871       repl = build_fold_addr_expr (repl);
872       gimple *stmt;
873       if (is_gimple_debug (info->stmt))
874 	{
875 	  tree vexpr = make_node (DEBUG_EXPR_DECL);
876 	  stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
877 	  DECL_ARTIFICIAL (vexpr) = 1;
878 	  TREE_TYPE (vexpr) = TREE_TYPE (repl);
879 	  SET_DECL_MODE (vexpr, TYPE_MODE (TREE_TYPE (repl)));
880 	  repl = vexpr;
881 	}
882       else
883 	{
884 	  stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
885 	  repl = gimple_assign_lhs (stmt);
886 	}
887       gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
888       gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
889       *orig_tp = repl;
890     }
891   else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
892     {
893       tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
894       *tp = vce;
895     }
896   else
897     *tp = repl;
898 
899   info->modified = true;
900   return NULL_TREE;
901 }
902 
903 /* Traverse the function body and perform all modifications as
904    described in ADJUSTMENTS.  At function return, ADJUSTMENTS will be
905    modified such that the replacement/reduction value will now be an
906    offset into the corresponding simd_array.
907 
908    This function will replace all function argument uses with their
909    corresponding simd array elements, and ajust the return values
910    accordingly.  */
911 
912 static void
913 ipa_simd_modify_function_body (struct cgraph_node *node,
914 			       ipa_parm_adjustment_vec adjustments,
915 			       tree retval_array, tree iter)
916 {
917   basic_block bb;
918   unsigned int i, j, l;
919 
920   /* Re-use the adjustments array, but this time use it to replace
921      every function argument use to an offset into the corresponding
922      simd_array.  */
923   for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
924     {
925       if (!node->simdclone->args[i].vector_arg)
926 	continue;
927 
928       tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
929       tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
930       adjustments[j].new_decl
931 	= build4 (ARRAY_REF,
932 		  basetype,
933 		  node->simdclone->args[i].simd_array,
934 		  iter,
935 		  NULL_TREE, NULL_TREE);
936       if (adjustments[j].op == IPA_PARM_OP_NONE
937 	  && simd_clone_subparts (vectype) < node->simdclone->simdlen)
938 	j += node->simdclone->simdlen / simd_clone_subparts (vectype) - 1;
939     }
940 
941   l = adjustments.length ();
942   tree name;
943 
944   FOR_EACH_SSA_NAME (i, name, cfun)
945     {
946       if (SSA_NAME_VAR (name)
947 	  && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
948 	{
949 	  for (j = 0; j < l; j++)
950 	    if (SSA_NAME_VAR (name) == adjustments[j].base
951 		&& adjustments[j].new_decl)
952 	      {
953 		tree base_var;
954 		if (adjustments[j].new_ssa_base == NULL_TREE)
955 		  {
956 		    base_var
957 		      = copy_var_decl (adjustments[j].base,
958 				       DECL_NAME (adjustments[j].base),
959 				       TREE_TYPE (adjustments[j].base));
960 		    adjustments[j].new_ssa_base = base_var;
961 		  }
962 		else
963 		  base_var = adjustments[j].new_ssa_base;
964 		if (SSA_NAME_IS_DEFAULT_DEF (name))
965 		  {
966 		    bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
967 		    gimple_stmt_iterator gsi = gsi_after_labels (bb);
968 		    tree new_decl = unshare_expr (adjustments[j].new_decl);
969 		    set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
970 		    SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
971 		    SSA_NAME_IS_DEFAULT_DEF (name) = 0;
972 		    gimple *stmt = gimple_build_assign (name, new_decl);
973 		    gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
974 		  }
975 		else
976 		  SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
977 	      }
978 	}
979     }
980 
981   struct modify_stmt_info info;
982   info.adjustments = adjustments;
983 
984   FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
985     {
986       gimple_stmt_iterator gsi;
987 
988       gsi = gsi_start_bb (bb);
989       while (!gsi_end_p (gsi))
990 	{
991 	  gimple *stmt = gsi_stmt (gsi);
992 	  info.stmt = stmt;
993 	  struct walk_stmt_info wi;
994 
995 	  memset (&wi, 0, sizeof (wi));
996 	  info.modified = false;
997 	  wi.info = &info;
998 	  walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
999 
1000 	  if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
1001 	    {
1002 	      tree retval = gimple_return_retval (return_stmt);
1003 	      edge e = find_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun));
1004 	      e->flags |= EDGE_FALLTHRU;
1005 	      if (!retval)
1006 		{
1007 		  gsi_remove (&gsi, true);
1008 		  continue;
1009 		}
1010 
1011 	      /* Replace `return foo' with `retval_array[iter] = foo'.  */
1012 	      tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
1013 				 retval_array, iter, NULL, NULL);
1014 	      stmt = gimple_build_assign (ref, retval);
1015 	      gsi_replace (&gsi, stmt, true);
1016 	      info.modified = true;
1017 	    }
1018 
1019 	  if (info.modified)
1020 	    {
1021 	      update_stmt (stmt);
1022 	      /* If the above changed the var of a debug bind into something
1023 		 different, remove the debug stmt.  We could also for all the
1024 		 replaced parameters add VAR_DECLs for debug info purposes,
1025 		 add debug stmts for those to be the simd array accesses and
1026 		 replace debug stmt var operand with that var.  Debugging of
1027 		 vectorized loops doesn't work too well, so don't bother for
1028 		 now.  */
1029 	      if ((gimple_debug_bind_p (stmt)
1030 		   && !DECL_P (gimple_debug_bind_get_var (stmt)))
1031 		  || (gimple_debug_source_bind_p (stmt)
1032 		      && !DECL_P (gimple_debug_source_bind_get_var (stmt))))
1033 		{
1034 		  gsi_remove (&gsi, true);
1035 		  continue;
1036 		}
1037 	      if (maybe_clean_eh_stmt (stmt))
1038 		gimple_purge_dead_eh_edges (gimple_bb (stmt));
1039 	    }
1040 	  gsi_next (&gsi);
1041 	}
1042     }
1043 }
1044 
1045 /* Helper function of simd_clone_adjust, return linear step addend
1046    of Ith argument.  */
1047 
1048 static tree
1049 simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
1050 			  tree addtype, basic_block entry_bb)
1051 {
1052   tree ptype = NULL_TREE;
1053   switch (node->simdclone->args[i].arg_type)
1054     {
1055     case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
1056     case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
1057     case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
1058     case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
1059       return build_int_cst (addtype, node->simdclone->args[i].linear_step);
1060     case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
1061     case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
1062       ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
1063       break;
1064     case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
1065     case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
1066       ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
1067       break;
1068     default:
1069       gcc_unreachable ();
1070     }
1071 
1072   unsigned int idx = node->simdclone->args[i].linear_step;
1073   tree arg = node->simdclone->args[idx].orig_arg;
1074   gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
1075   gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
1076   gimple *g;
1077   tree ret;
1078   if (is_gimple_reg (arg))
1079     ret = get_or_create_ssa_default_def (cfun, arg);
1080   else
1081     {
1082       g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
1083       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1084       ret = gimple_assign_lhs (g);
1085     }
1086   if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
1087     {
1088       g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
1089 			       build_simple_mem_ref (ret));
1090       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1091       ret = gimple_assign_lhs (g);
1092     }
1093   if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
1094     {
1095       g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
1096       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1097       ret = gimple_assign_lhs (g);
1098     }
1099   if (POINTER_TYPE_P (ptype))
1100     {
1101       tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
1102       if (size && TREE_CODE (size) == INTEGER_CST)
1103 	{
1104 	  g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
1105 				   ret, fold_convert (addtype, size));
1106 	  gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1107 	  ret = gimple_assign_lhs (g);
1108 	}
1109     }
1110   return ret;
1111 }
1112 
1113 /* Adjust the argument types in NODE to their appropriate vector
1114    counterparts.  */
1115 
1116 static void
1117 simd_clone_adjust (struct cgraph_node *node)
1118 {
1119   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
1120 
1121   targetm.simd_clone.adjust (node);
1122 
1123   tree retval = simd_clone_adjust_return_type (node);
1124   ipa_parm_adjustment_vec adjustments
1125     = simd_clone_adjust_argument_types (node);
1126 
1127   push_gimplify_context ();
1128 
1129   gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
1130 
1131   /* Adjust all uses of vector arguments accordingly.  Adjust all
1132      return values accordingly.  */
1133   tree iter = create_tmp_var (unsigned_type_node, "iter");
1134   tree iter1 = make_ssa_name (iter);
1135   tree iter2 = NULL_TREE;
1136   ipa_simd_modify_function_body (node, adjustments, retval, iter1);
1137   adjustments.release ();
1138 
1139   /* Initialize the iteration variable.  */
1140   basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
1141   basic_block body_bb = split_block_after_labels (entry_bb)->dest;
1142   gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
1143   /* Insert the SIMD array and iv initialization at function
1144      entry.  */
1145   gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
1146 
1147   pop_gimplify_context (NULL);
1148 
1149   gimple *g;
1150   basic_block incr_bb = NULL;
1151   struct loop *loop = NULL;
1152 
1153   /* Create a new BB right before the original exit BB, to hold the
1154      iteration increment and the condition/branch.  */
1155   if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
1156     {
1157       basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
1158       incr_bb = create_empty_bb (orig_exit);
1159       incr_bb->count = profile_count::zero ();
1160       add_bb_to_loop (incr_bb, body_bb->loop_father);
1161       while (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds))
1162 	{
1163 	  edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
1164 	  redirect_edge_succ (e, incr_bb);
1165 	  incr_bb->count += e->count ();
1166 	}
1167     }
1168   else if (node->simdclone->inbranch)
1169     {
1170       incr_bb = create_empty_bb (entry_bb);
1171       incr_bb->count = profile_count::zero ();
1172       add_bb_to_loop (incr_bb, body_bb->loop_father);
1173     }
1174 
1175   if (incr_bb)
1176     {
1177       make_single_succ_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
1178       gsi = gsi_last_bb (incr_bb);
1179       iter2 = make_ssa_name (iter);
1180       g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
1181 			       build_int_cst (unsigned_type_node, 1));
1182       gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1183 
1184       /* Mostly annotate the loop for the vectorizer (the rest is done
1185 	 below).  */
1186       loop = alloc_loop ();
1187       cfun->has_force_vectorize_loops = true;
1188       loop->safelen = node->simdclone->simdlen;
1189       loop->force_vectorize = true;
1190       loop->header = body_bb;
1191     }
1192 
1193   /* Branch around the body if the mask applies.  */
1194   if (node->simdclone->inbranch)
1195     {
1196       gsi = gsi_last_bb (loop->header);
1197       tree mask_array
1198 	= node->simdclone->args[node->simdclone->nargs - 1].simd_array;
1199       tree mask;
1200       if (node->simdclone->mask_mode != VOIDmode)
1201 	{
1202 	  tree shift_cnt;
1203 	  if (mask_array == NULL_TREE)
1204 	    {
1205 	      tree arg = node->simdclone->args[node->simdclone->nargs
1206 					       - 1].vector_arg;
1207 	      mask = get_or_create_ssa_default_def (cfun, arg);
1208 	      shift_cnt = iter1;
1209 	    }
1210 	  else
1211 	    {
1212 	      tree maskt = TREE_TYPE (mask_array);
1213 	      int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
1214 	      c = node->simdclone->simdlen / (c + 1);
1215 	      int s = exact_log2 (c);
1216 	      gcc_assert (s > 0);
1217 	      c--;
1218 	      tree idx = make_ssa_name (TREE_TYPE (iter1));
1219 	      g = gimple_build_assign (idx, RSHIFT_EXPR, iter1,
1220 				       build_int_cst (NULL_TREE, s));
1221 	      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1222 	      mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
1223 	      tree aref = build4 (ARRAY_REF,
1224 				  TREE_TYPE (TREE_TYPE (mask_array)),
1225 				  mask_array, idx, NULL, NULL);
1226 	      g = gimple_build_assign (mask, aref);
1227 	      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1228 	      shift_cnt = make_ssa_name (TREE_TYPE (iter1));
1229 	      g = gimple_build_assign (shift_cnt, BIT_AND_EXPR, iter1,
1230 				       build_int_cst (TREE_TYPE (iter1), c));
1231 	      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1232 	    }
1233 	  g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
1234 				   RSHIFT_EXPR, mask, shift_cnt);
1235 	  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1236 	  mask = gimple_assign_lhs (g);
1237 	  g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
1238 				   BIT_AND_EXPR, mask,
1239 				   build_int_cst (TREE_TYPE (mask), 1));
1240 	  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1241 	  mask = gimple_assign_lhs (g);
1242 	}
1243       else
1244 	{
1245 	  mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
1246 	  tree aref = build4 (ARRAY_REF,
1247 			      TREE_TYPE (TREE_TYPE (mask_array)),
1248 			      mask_array, iter1, NULL, NULL);
1249 	  g = gimple_build_assign (mask, aref);
1250 	  gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1251 	  int bitsize = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (aref)));
1252 	  if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
1253 	    {
1254 	      aref = build1 (VIEW_CONVERT_EXPR,
1255 			     build_nonstandard_integer_type (bitsize, 0),
1256 							     mask);
1257 	      mask = make_ssa_name (TREE_TYPE (aref));
1258 	      g = gimple_build_assign (mask, aref);
1259 	      gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1260 	    }
1261 	}
1262 
1263       g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
1264 			     NULL, NULL);
1265       gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1266       edge e = make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
1267       e->probability = profile_probability::unlikely ().guessed ();
1268       incr_bb->count += e->count ();
1269       edge fallthru = FALLTHRU_EDGE (loop->header);
1270       fallthru->flags = EDGE_FALSE_VALUE;
1271       fallthru->probability = profile_probability::likely ().guessed ();
1272     }
1273 
1274   basic_block latch_bb = NULL;
1275   basic_block new_exit_bb = NULL;
1276 
1277   /* Generate the condition.  */
1278   if (incr_bb)
1279     {
1280       gsi = gsi_last_bb (incr_bb);
1281       g = gimple_build_cond (LT_EXPR, iter2,
1282 			     build_int_cst (unsigned_type_node,
1283 					    node->simdclone->simdlen),
1284 			     NULL, NULL);
1285       gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1286       edge e = split_block (incr_bb, gsi_stmt (gsi));
1287       latch_bb = e->dest;
1288       new_exit_bb = split_block_after_labels (latch_bb)->dest;
1289       loop->latch = latch_bb;
1290 
1291       redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
1292 
1293       edge new_e = make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
1294 
1295       /* FIXME: Do we need to distribute probabilities for the conditional? */
1296       new_e->probability = profile_probability::guessed_never ();
1297       /* The successor of incr_bb is already pointing to latch_bb; just
1298 	 change the flags.
1299 	 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE);  */
1300       FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
1301     }
1302 
1303   gphi *phi = create_phi_node (iter1, body_bb);
1304   edge preheader_edge = find_edge (entry_bb, body_bb);
1305   edge latch_edge = NULL;
1306   add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
1307 	       UNKNOWN_LOCATION);
1308   if (incr_bb)
1309     {
1310       latch_edge = single_succ_edge (latch_bb);
1311       add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
1312 
1313       /* Generate the new return.  */
1314       gsi = gsi_last_bb (new_exit_bb);
1315       if (retval
1316 	  && TREE_CODE (retval) == VIEW_CONVERT_EXPR
1317 	  && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
1318 	retval = TREE_OPERAND (retval, 0);
1319       else if (retval)
1320 	{
1321 	  retval = build1 (VIEW_CONVERT_EXPR,
1322 			   TREE_TYPE (TREE_TYPE (node->decl)),
1323 			   retval);
1324 	  retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
1325 					     false, GSI_CONTINUE_LINKING);
1326 	}
1327       g = gimple_build_return (retval);
1328       gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
1329     }
1330 
1331   /* Handle aligned clauses by replacing default defs of the aligned
1332      uniform args with __builtin_assume_aligned (arg_N(D), alignment)
1333      lhs.  Handle linear by adding PHIs.  */
1334   for (unsigned i = 0; i < node->simdclone->nargs; i++)
1335     if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
1336 	&& (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
1337 	    || !is_gimple_reg_type
1338 			(TREE_TYPE (node->simdclone->args[i].orig_arg))))
1339       {
1340 	tree orig_arg = node->simdclone->args[i].orig_arg;
1341 	if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
1342 	  iter1 = make_ssa_name (TREE_TYPE (orig_arg));
1343 	else
1344 	  {
1345 	    iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
1346 	    gimple_add_tmp_var (iter1);
1347 	  }
1348 	gsi = gsi_after_labels (entry_bb);
1349 	g = gimple_build_assign (iter1, orig_arg);
1350 	gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1351 	gsi = gsi_after_labels (body_bb);
1352 	g = gimple_build_assign (orig_arg, iter1);
1353 	gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1354       }
1355     else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
1356 	     && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
1357 	     && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
1358 		== REFERENCE_TYPE
1359 	     && TREE_ADDRESSABLE
1360 		  (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
1361       {
1362 	tree orig_arg = node->simdclone->args[i].orig_arg;
1363 	tree def = ssa_default_def (cfun, orig_arg);
1364 	if (def && !has_zero_uses (def))
1365 	  {
1366 	    iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
1367 	    gimple_add_tmp_var (iter1);
1368 	    gsi = gsi_after_labels (entry_bb);
1369 	    g = gimple_build_assign (iter1, build_simple_mem_ref (def));
1370 	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1371 	    gsi = gsi_after_labels (body_bb);
1372 	    g = gimple_build_assign (build_simple_mem_ref (def), iter1);
1373 	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1374 	  }
1375       }
1376     else if (node->simdclone->args[i].alignment
1377 	     && node->simdclone->args[i].arg_type
1378 		== SIMD_CLONE_ARG_TYPE_UNIFORM
1379 	     && (node->simdclone->args[i].alignment
1380 		 & (node->simdclone->args[i].alignment - 1)) == 0
1381 	     && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
1382 		== POINTER_TYPE)
1383       {
1384 	unsigned int alignment = node->simdclone->args[i].alignment;
1385 	tree orig_arg = node->simdclone->args[i].orig_arg;
1386 	tree def = ssa_default_def (cfun, orig_arg);
1387 	if (def && !has_zero_uses (def))
1388 	  {
1389 	    tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
1390 	    gimple_seq seq = NULL;
1391 	    bool need_cvt = false;
1392 	    gcall *call
1393 	      = gimple_build_call (fn, 2, def, size_int (alignment));
1394 	    g = call;
1395 	    if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
1396 					    ptr_type_node))
1397 	      need_cvt = true;
1398 	    tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
1399 	    gimple_call_set_lhs (g, t);
1400 	    gimple_seq_add_stmt_without_update (&seq, g);
1401 	    if (need_cvt)
1402 	      {
1403 		t = make_ssa_name (orig_arg);
1404 		g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
1405 		gimple_seq_add_stmt_without_update (&seq, g);
1406 	      }
1407 	    gsi_insert_seq_on_edge_immediate
1408 	      (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
1409 
1410 	    entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
1411 	    node->create_edge (cgraph_node::get_create (fn),
1412 			       call, entry_bb->count);
1413 
1414 	    imm_use_iterator iter;
1415 	    use_operand_p use_p;
1416 	    gimple *use_stmt;
1417 	    tree repl = gimple_get_lhs (g);
1418 	    FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
1419 	      if (is_gimple_debug (use_stmt) || use_stmt == call)
1420 		continue;
1421 	      else
1422 		FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1423 		  SET_USE (use_p, repl);
1424 	  }
1425       }
1426     else if ((node->simdclone->args[i].arg_type
1427 	      == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
1428 	     || (node->simdclone->args[i].arg_type
1429 		 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
1430 	     || (node->simdclone->args[i].arg_type
1431 		 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
1432 	     || (node->simdclone->args[i].arg_type
1433 		 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
1434       {
1435 	tree orig_arg = node->simdclone->args[i].orig_arg;
1436 	gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
1437 		    || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
1438 	tree def = NULL_TREE;
1439 	if (TREE_ADDRESSABLE (orig_arg))
1440 	  {
1441 	    def = make_ssa_name (TREE_TYPE (orig_arg));
1442 	    iter1 = make_ssa_name (TREE_TYPE (orig_arg));
1443 	    if (incr_bb)
1444 	      iter2 = make_ssa_name (TREE_TYPE (orig_arg));
1445 	    gsi = gsi_after_labels (entry_bb);
1446 	    g = gimple_build_assign (def, orig_arg);
1447 	    gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1448 	  }
1449 	else
1450 	  {
1451 	    def = ssa_default_def (cfun, orig_arg);
1452 	    if (!def || has_zero_uses (def))
1453 	      def = NULL_TREE;
1454 	    else
1455 	      {
1456 		iter1 = make_ssa_name (orig_arg);
1457 		if (incr_bb)
1458 		  iter2 = make_ssa_name (orig_arg);
1459 	      }
1460 	  }
1461 	if (def)
1462 	  {
1463 	    phi = create_phi_node (iter1, body_bb);
1464 	    add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
1465 	    if (incr_bb)
1466 	      {
1467 		add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
1468 		enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
1469 				      ? PLUS_EXPR : POINTER_PLUS_EXPR;
1470 		tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
1471 			       ? TREE_TYPE (orig_arg) : sizetype;
1472 		tree addcst = simd_clone_linear_addend (node, i, addtype,
1473 							entry_bb);
1474 		gsi = gsi_last_bb (incr_bb);
1475 		g = gimple_build_assign (iter2, code, iter1, addcst);
1476 		gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1477 	      }
1478 
1479 	    imm_use_iterator iter;
1480 	    use_operand_p use_p;
1481 	    gimple *use_stmt;
1482 	    if (TREE_ADDRESSABLE (orig_arg))
1483 	      {
1484 		gsi = gsi_after_labels (body_bb);
1485 		g = gimple_build_assign (orig_arg, iter1);
1486 		gsi_insert_before (&gsi, g, GSI_NEW_STMT);
1487 	      }
1488 	    else
1489 	      FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
1490 		if (use_stmt == phi)
1491 		  continue;
1492 		else
1493 		  FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1494 		    SET_USE (use_p, iter1);
1495 	  }
1496       }
1497     else if (node->simdclone->args[i].arg_type
1498 	     == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
1499 	     || (node->simdclone->args[i].arg_type
1500 		 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
1501       {
1502 	tree orig_arg = node->simdclone->args[i].orig_arg;
1503 	tree def = ssa_default_def (cfun, orig_arg);
1504 	gcc_assert (!TREE_ADDRESSABLE (orig_arg)
1505 		    && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
1506 	if (def && !has_zero_uses (def))
1507 	  {
1508 	    tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
1509 	    iter1 = make_ssa_name (orig_arg);
1510 	    if (incr_bb)
1511 	      iter2 = make_ssa_name (orig_arg);
1512 	    tree iter3 = make_ssa_name (rtype);
1513 	    tree iter4 = make_ssa_name (rtype);
1514 	    tree iter5 = incr_bb ? make_ssa_name (rtype) : NULL_TREE;
1515 	    gsi = gsi_after_labels (entry_bb);
1516 	    gimple *load
1517 	      = gimple_build_assign (iter3, build_simple_mem_ref (def));
1518 	    gsi_insert_before (&gsi, load, GSI_NEW_STMT);
1519 
1520 	    tree array = node->simdclone->args[i].simd_array;
1521 	    TREE_ADDRESSABLE (array) = 1;
1522 	    tree ptr = build_fold_addr_expr (array);
1523 	    phi = create_phi_node (iter1, body_bb);
1524 	    add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
1525 	    if (incr_bb)
1526 	      {
1527 		add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
1528 		g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
1529 					 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
1530 		gsi = gsi_last_bb (incr_bb);
1531 		gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1532 	      }
1533 
1534 	    phi = create_phi_node (iter4, body_bb);
1535 	    add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
1536 	    if (incr_bb)
1537 	      {
1538 		add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
1539 		enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
1540 				      ? PLUS_EXPR : POINTER_PLUS_EXPR;
1541 		tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
1542 			       ? TREE_TYPE (iter3) : sizetype;
1543 		tree addcst = simd_clone_linear_addend (node, i, addtype,
1544 							entry_bb);
1545 		g = gimple_build_assign (iter5, code, iter4, addcst);
1546 		gsi = gsi_last_bb (incr_bb);
1547 		gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1548 	      }
1549 
1550 	    g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
1551 	    gsi = gsi_after_labels (body_bb);
1552 	    gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1553 
1554 	    imm_use_iterator iter;
1555 	    use_operand_p use_p;
1556 	    gimple *use_stmt;
1557 	    FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
1558 	      if (use_stmt == load)
1559 		continue;
1560 	      else
1561 		FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
1562 		  SET_USE (use_p, iter1);
1563 
1564 	    if (!TYPE_READONLY (rtype) && incr_bb)
1565 	      {
1566 		tree v = make_ssa_name (rtype);
1567 		tree aref = build4 (ARRAY_REF, rtype, array,
1568 				    size_zero_node, NULL_TREE,
1569 				    NULL_TREE);
1570 		gsi = gsi_after_labels (new_exit_bb);
1571 		g = gimple_build_assign (v, aref);
1572 		gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1573 		g = gimple_build_assign (build_simple_mem_ref (def), v);
1574 		gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1575 	      }
1576 	  }
1577       }
1578 
1579   calculate_dominance_info (CDI_DOMINATORS);
1580   if (loop)
1581     add_loop (loop, loop->header->loop_father);
1582   update_ssa (TODO_update_ssa);
1583 
1584   pop_cfun ();
1585 }
1586 
1587 /* If the function in NODE is tagged as an elemental SIMD function,
1588    create the appropriate SIMD clones.  */
1589 
1590 void
1591 expand_simd_clones (struct cgraph_node *node)
1592 {
1593   tree attr = lookup_attribute ("omp declare simd",
1594 				DECL_ATTRIBUTES (node->decl));
1595   if (attr == NULL_TREE
1596       || node->global.inlined_to
1597       || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
1598     return;
1599 
1600   /* Ignore
1601      #pragma omp declare simd
1602      extern int foo ();
1603      in C, there we don't know the argument types at all.  */
1604   if (!node->definition
1605       && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
1606     return;
1607 
1608   /* Call this before creating clone_info, as it might ggc_collect.  */
1609   if (node->definition && node->has_gimple_body_p ())
1610     node->get_body ();
1611 
1612   do
1613     {
1614       /* Start with parsing the "omp declare simd" attribute(s).  */
1615       bool inbranch_clause_specified;
1616       struct cgraph_simd_clone *clone_info
1617 	= simd_clone_clauses_extract (node, TREE_VALUE (attr),
1618 				      &inbranch_clause_specified);
1619       if (clone_info == NULL)
1620 	continue;
1621 
1622       int orig_simdlen = clone_info->simdlen;
1623       tree base_type = simd_clone_compute_base_data_type (node, clone_info);
1624       /* The target can return 0 (no simd clones should be created),
1625 	 1 (just one ISA of simd clones should be created) or higher
1626 	 count of ISA variants.  In that case, clone_info is initialized
1627 	 for the first ISA variant.  */
1628       int count
1629 	= targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
1630 							  base_type, 0);
1631       if (count == 0)
1632 	continue;
1633 
1634       /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
1635 	 also create one inbranch and one !inbranch clone of it.  */
1636       for (int i = 0; i < count * 2; i++)
1637 	{
1638 	  struct cgraph_simd_clone *clone = clone_info;
1639 	  if (inbranch_clause_specified && (i & 1) != 0)
1640 	    continue;
1641 
1642 	  if (i != 0)
1643 	    {
1644 	      clone = simd_clone_struct_alloc (clone_info->nargs
1645 					       + ((i & 1) != 0));
1646 	      simd_clone_struct_copy (clone, clone_info);
1647 	      /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
1648 		 and simd_clone_adjust_argument_types did to the first
1649 		 clone's info.  */
1650 	      clone->nargs -= clone_info->inbranch;
1651 	      clone->simdlen = orig_simdlen;
1652 	      /* And call the target hook again to get the right ISA.  */
1653 	      targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
1654 							      base_type,
1655 							      i / 2);
1656 	      if ((i & 1) != 0)
1657 		clone->inbranch = 1;
1658 	    }
1659 
1660 	  /* simd_clone_mangle might fail if such a clone has been created
1661 	     already.  */
1662 	  tree id = simd_clone_mangle (node, clone);
1663 	  if (id == NULL_TREE)
1664 	    continue;
1665 
1666 	  /* Only when we are sure we want to create the clone actually
1667 	     clone the function (or definitions) or create another
1668 	     extern FUNCTION_DECL (for prototypes without definitions).  */
1669 	  struct cgraph_node *n = simd_clone_create (node);
1670 	  if (n == NULL)
1671 	    continue;
1672 
1673 	  n->simdclone = clone;
1674 	  clone->origin = node;
1675 	  clone->next_clone = NULL;
1676 	  if (node->simd_clones == NULL)
1677 	    {
1678 	      clone->prev_clone = n;
1679 	      node->simd_clones = n;
1680 	    }
1681 	  else
1682 	    {
1683 	      clone->prev_clone = node->simd_clones->simdclone->prev_clone;
1684 	      clone->prev_clone->simdclone->next_clone = n;
1685 	      node->simd_clones->simdclone->prev_clone = n;
1686 	    }
1687 	  symtab->change_decl_assembler_name (n->decl, id);
1688 	  /* And finally adjust the return type, parameters and for
1689 	     definitions also function body.  */
1690 	  if (node->definition)
1691 	    simd_clone_adjust (n);
1692 	  else
1693 	    {
1694 	      simd_clone_adjust_return_type (n);
1695 	      simd_clone_adjust_argument_types (n);
1696 	    }
1697 	}
1698     }
1699   while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
1700 }
1701 
1702 /* Entry point for IPA simd clone creation pass.  */
1703 
1704 static unsigned int
1705 ipa_omp_simd_clone (void)
1706 {
1707   struct cgraph_node *node;
1708   FOR_EACH_FUNCTION (node)
1709     expand_simd_clones (node);
1710   return 0;
1711 }
1712 
1713 namespace {
1714 
1715 const pass_data pass_data_omp_simd_clone =
1716 {
1717   SIMPLE_IPA_PASS,		/* type */
1718   "simdclone",			/* name */
1719   OPTGROUP_OMP,			/* optinfo_flags */
1720   TV_NONE,			/* tv_id */
1721   ( PROP_ssa | PROP_cfg ),	/* properties_required */
1722   0,				/* properties_provided */
1723   0,				/* properties_destroyed */
1724   0,				/* todo_flags_start */
1725   0,				/* todo_flags_finish */
1726 };
1727 
1728 class pass_omp_simd_clone : public simple_ipa_opt_pass
1729 {
1730 public:
1731   pass_omp_simd_clone(gcc::context *ctxt)
1732     : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
1733   {}
1734 
1735   /* opt_pass methods: */
1736   virtual bool gate (function *);
1737   virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
1738 };
1739 
1740 bool
1741 pass_omp_simd_clone::gate (function *)
1742 {
1743   return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
1744 }
1745 
1746 } // anon namespace
1747 
1748 simple_ipa_opt_pass *
1749 make_pass_omp_simd_clone (gcc::context *ctxt)
1750 {
1751   return new pass_omp_simd_clone (ctxt);
1752 }
1753