annotate gcc/omp-simd-clone.c @ 158:494b0b89df80 default tip

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