annotate gcc/omp-simd-clone.c @ 123:ab229f40eab2

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