annotate gcc/omp-simd-clone.c @ 143:76e1cf5455ef

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