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