annotate gcc/omp-general.c @ 16:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
16
kono
parents:
diff changeset
1 /* General types and functions that are uselful for processing of OpenMP,
kono
parents:
diff changeset
2 OpenACC and similar directivers at various stages of compilation.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 Copyright (C) 2005-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 /* Find an OMP clause of type KIND within CLAUSES. */
kono
parents:
diff changeset
23
kono
parents:
diff changeset
24 #include "config.h"
kono
parents:
diff changeset
25 #include "system.h"
kono
parents:
diff changeset
26 #include "coretypes.h"
kono
parents:
diff changeset
27 #include "backend.h"
kono
parents:
diff changeset
28 #include "target.h"
kono
parents:
diff changeset
29 #include "tree.h"
kono
parents:
diff changeset
30 #include "gimple.h"
kono
parents:
diff changeset
31 #include "ssa.h"
kono
parents:
diff changeset
32 #include "diagnostic-core.h"
kono
parents:
diff changeset
33 #include "fold-const.h"
kono
parents:
diff changeset
34 #include "langhooks.h"
kono
parents:
diff changeset
35 #include "omp-general.h"
kono
parents:
diff changeset
36 #include "stringpool.h"
kono
parents:
diff changeset
37 #include "attribs.h"
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 tree
kono
parents:
diff changeset
40 omp_find_clause (tree clauses, enum omp_clause_code kind)
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
kono
parents:
diff changeset
43 if (OMP_CLAUSE_CODE (clauses) == kind)
kono
parents:
diff changeset
44 return clauses;
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 return NULL_TREE;
kono
parents:
diff changeset
47 }
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 /* Return true if DECL is a reference type. */
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 bool
kono
parents:
diff changeset
52 omp_is_reference (tree decl)
kono
parents:
diff changeset
53 {
kono
parents:
diff changeset
54 return lang_hooks.decls.omp_privatize_by_reference (decl);
kono
parents:
diff changeset
55 }
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
kono
parents:
diff changeset
58 GT_EXPR. */
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 void
kono
parents:
diff changeset
61 omp_adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
kono
parents:
diff changeset
62 {
kono
parents:
diff changeset
63 switch (*cond_code)
kono
parents:
diff changeset
64 {
kono
parents:
diff changeset
65 case LT_EXPR:
kono
parents:
diff changeset
66 case GT_EXPR:
kono
parents:
diff changeset
67 case NE_EXPR:
kono
parents:
diff changeset
68 break;
kono
parents:
diff changeset
69 case LE_EXPR:
kono
parents:
diff changeset
70 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
kono
parents:
diff changeset
71 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
kono
parents:
diff changeset
72 else
kono
parents:
diff changeset
73 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
kono
parents:
diff changeset
74 build_int_cst (TREE_TYPE (*n2), 1));
kono
parents:
diff changeset
75 *cond_code = LT_EXPR;
kono
parents:
diff changeset
76 break;
kono
parents:
diff changeset
77 case GE_EXPR:
kono
parents:
diff changeset
78 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
kono
parents:
diff changeset
79 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
kono
parents:
diff changeset
80 else
kono
parents:
diff changeset
81 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
kono
parents:
diff changeset
82 build_int_cst (TREE_TYPE (*n2), 1));
kono
parents:
diff changeset
83 *cond_code = GT_EXPR;
kono
parents:
diff changeset
84 break;
kono
parents:
diff changeset
85 default:
kono
parents:
diff changeset
86 gcc_unreachable ();
kono
parents:
diff changeset
87 }
kono
parents:
diff changeset
88 }
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 /* Return the looping step from INCR, extracted from the step of a gimple omp
kono
parents:
diff changeset
91 for statement. */
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 tree
kono
parents:
diff changeset
94 omp_get_for_step_from_incr (location_t loc, tree incr)
kono
parents:
diff changeset
95 {
kono
parents:
diff changeset
96 tree step;
kono
parents:
diff changeset
97 switch (TREE_CODE (incr))
kono
parents:
diff changeset
98 {
kono
parents:
diff changeset
99 case PLUS_EXPR:
kono
parents:
diff changeset
100 step = TREE_OPERAND (incr, 1);
kono
parents:
diff changeset
101 break;
kono
parents:
diff changeset
102 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
103 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
kono
parents:
diff changeset
104 break;
kono
parents:
diff changeset
105 case MINUS_EXPR:
kono
parents:
diff changeset
106 step = TREE_OPERAND (incr, 1);
kono
parents:
diff changeset
107 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
kono
parents:
diff changeset
108 break;
kono
parents:
diff changeset
109 default:
kono
parents:
diff changeset
110 gcc_unreachable ();
kono
parents:
diff changeset
111 }
kono
parents:
diff changeset
112 return step;
kono
parents:
diff changeset
113 }
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 /* Extract the header elements of parallel loop FOR_STMT and store
kono
parents:
diff changeset
116 them into *FD. */
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 void
kono
parents:
diff changeset
119 omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
kono
parents:
diff changeset
120 struct omp_for_data_loop *loops)
kono
parents:
diff changeset
121 {
kono
parents:
diff changeset
122 tree t, var, *collapse_iter, *collapse_count;
kono
parents:
diff changeset
123 tree count = NULL_TREE, iter_type = long_integer_type_node;
kono
parents:
diff changeset
124 struct omp_for_data_loop *loop;
kono
parents:
diff changeset
125 int i;
kono
parents:
diff changeset
126 struct omp_for_data_loop dummy_loop;
kono
parents:
diff changeset
127 location_t loc = gimple_location (for_stmt);
kono
parents:
diff changeset
128 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
kono
parents:
diff changeset
129 bool distribute = gimple_omp_for_kind (for_stmt)
kono
parents:
diff changeset
130 == GF_OMP_FOR_KIND_DISTRIBUTE;
kono
parents:
diff changeset
131 bool taskloop = gimple_omp_for_kind (for_stmt)
kono
parents:
diff changeset
132 == GF_OMP_FOR_KIND_TASKLOOP;
kono
parents:
diff changeset
133 tree iterv, countv;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 fd->for_stmt = for_stmt;
kono
parents:
diff changeset
136 fd->pre = NULL;
kono
parents:
diff changeset
137 fd->have_nowait = distribute || simd;
kono
parents:
diff changeset
138 fd->have_ordered = false;
kono
parents:
diff changeset
139 fd->tiling = NULL_TREE;
kono
parents:
diff changeset
140 fd->collapse = 1;
kono
parents:
diff changeset
141 fd->ordered = 0;
kono
parents:
diff changeset
142 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
kono
parents:
diff changeset
143 fd->sched_modifiers = 0;
kono
parents:
diff changeset
144 fd->chunk_size = NULL_TREE;
kono
parents:
diff changeset
145 fd->simd_schedule = false;
kono
parents:
diff changeset
146 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
kono
parents:
diff changeset
147 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
kono
parents:
diff changeset
148 collapse_iter = NULL;
kono
parents:
diff changeset
149 collapse_count = NULL;
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
kono
parents:
diff changeset
152 switch (OMP_CLAUSE_CODE (t))
kono
parents:
diff changeset
153 {
kono
parents:
diff changeset
154 case OMP_CLAUSE_NOWAIT:
kono
parents:
diff changeset
155 fd->have_nowait = true;
kono
parents:
diff changeset
156 break;
kono
parents:
diff changeset
157 case OMP_CLAUSE_ORDERED:
kono
parents:
diff changeset
158 fd->have_ordered = true;
kono
parents:
diff changeset
159 if (OMP_CLAUSE_ORDERED_EXPR (t))
kono
parents:
diff changeset
160 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
kono
parents:
diff changeset
161 break;
kono
parents:
diff changeset
162 case OMP_CLAUSE_SCHEDULE:
kono
parents:
diff changeset
163 gcc_assert (!distribute && !taskloop);
kono
parents:
diff changeset
164 fd->sched_kind
kono
parents:
diff changeset
165 = (enum omp_clause_schedule_kind)
kono
parents:
diff changeset
166 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
kono
parents:
diff changeset
167 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
kono
parents:
diff changeset
168 & ~OMP_CLAUSE_SCHEDULE_MASK);
kono
parents:
diff changeset
169 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
kono
parents:
diff changeset
170 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
kono
parents:
diff changeset
171 break;
kono
parents:
diff changeset
172 case OMP_CLAUSE_DIST_SCHEDULE:
kono
parents:
diff changeset
173 gcc_assert (distribute);
kono
parents:
diff changeset
174 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
kono
parents:
diff changeset
175 break;
kono
parents:
diff changeset
176 case OMP_CLAUSE_COLLAPSE:
kono
parents:
diff changeset
177 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
kono
parents:
diff changeset
178 if (fd->collapse > 1)
kono
parents:
diff changeset
179 {
kono
parents:
diff changeset
180 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
kono
parents:
diff changeset
181 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
kono
parents:
diff changeset
182 }
kono
parents:
diff changeset
183 break;
kono
parents:
diff changeset
184 case OMP_CLAUSE_TILE:
kono
parents:
diff changeset
185 fd->tiling = OMP_CLAUSE_TILE_LIST (t);
kono
parents:
diff changeset
186 fd->collapse = list_length (fd->tiling);
kono
parents:
diff changeset
187 gcc_assert (fd->collapse);
kono
parents:
diff changeset
188 collapse_iter = &OMP_CLAUSE_TILE_ITERVAR (t);
kono
parents:
diff changeset
189 collapse_count = &OMP_CLAUSE_TILE_COUNT (t);
kono
parents:
diff changeset
190 break;
kono
parents:
diff changeset
191 default:
kono
parents:
diff changeset
192 break;
kono
parents:
diff changeset
193 }
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 if (fd->collapse > 1 || fd->tiling)
kono
parents:
diff changeset
196 fd->loops = loops;
kono
parents:
diff changeset
197 else
kono
parents:
diff changeset
198 fd->loops = &fd->loop;
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 if (fd->ordered && fd->collapse == 1 && loops != NULL)
kono
parents:
diff changeset
201 {
kono
parents:
diff changeset
202 fd->loops = loops;
kono
parents:
diff changeset
203 iterv = NULL_TREE;
kono
parents:
diff changeset
204 countv = NULL_TREE;
kono
parents:
diff changeset
205 collapse_iter = &iterv;
kono
parents:
diff changeset
206 collapse_count = &countv;
kono
parents:
diff changeset
207 }
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 /* FIXME: for now map schedule(auto) to schedule(static).
kono
parents:
diff changeset
210 There should be analysis to determine whether all iterations
kono
parents:
diff changeset
211 are approximately the same amount of work (then schedule(static)
kono
parents:
diff changeset
212 is best) or if it varies (then schedule(dynamic,N) is better). */
kono
parents:
diff changeset
213 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
kono
parents:
diff changeset
214 {
kono
parents:
diff changeset
215 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
kono
parents:
diff changeset
216 gcc_assert (fd->chunk_size == NULL);
kono
parents:
diff changeset
217 }
kono
parents:
diff changeset
218 gcc_assert ((fd->collapse == 1 && !fd->tiling) || collapse_iter != NULL);
kono
parents:
diff changeset
219 if (taskloop)
kono
parents:
diff changeset
220 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
kono
parents:
diff changeset
221 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
kono
parents:
diff changeset
222 gcc_assert (fd->chunk_size == NULL);
kono
parents:
diff changeset
223 else if (fd->chunk_size == NULL)
kono
parents:
diff changeset
224 {
kono
parents:
diff changeset
225 /* We only need to compute a default chunk size for ordered
kono
parents:
diff changeset
226 static loops and dynamic loops. */
kono
parents:
diff changeset
227 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
kono
parents:
diff changeset
228 || fd->have_ordered)
kono
parents:
diff changeset
229 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
kono
parents:
diff changeset
230 ? integer_zero_node : integer_one_node;
kono
parents:
diff changeset
231 }
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 int cnt = fd->ordered ? fd->ordered : fd->collapse;
kono
parents:
diff changeset
234 for (i = 0; i < cnt; i++)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 if (i == 0
kono
parents:
diff changeset
237 && fd->collapse == 1
kono
parents:
diff changeset
238 && !fd->tiling
kono
parents:
diff changeset
239 && (fd->ordered == 0 || loops == NULL))
kono
parents:
diff changeset
240 loop = &fd->loop;
kono
parents:
diff changeset
241 else if (loops != NULL)
kono
parents:
diff changeset
242 loop = loops + i;
kono
parents:
diff changeset
243 else
kono
parents:
diff changeset
244 loop = &dummy_loop;
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 loop->v = gimple_omp_for_index (for_stmt, i);
kono
parents:
diff changeset
247 gcc_assert (SSA_VAR_P (loop->v));
kono
parents:
diff changeset
248 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
kono
parents:
diff changeset
249 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
kono
parents:
diff changeset
250 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
kono
parents:
diff changeset
251 loop->n1 = gimple_omp_for_initial (for_stmt, i);
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
kono
parents:
diff changeset
254 loop->n2 = gimple_omp_for_final (for_stmt, i);
kono
parents:
diff changeset
255 gcc_assert (loop->cond_code != NE_EXPR
kono
parents:
diff changeset
256 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
kono
parents:
diff changeset
257 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
kono
parents:
diff changeset
258 omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2);
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 t = gimple_omp_for_incr (for_stmt, i);
kono
parents:
diff changeset
261 gcc_assert (TREE_OPERAND (t, 0) == var);
kono
parents:
diff changeset
262 loop->step = omp_get_for_step_from_incr (loc, t);
kono
parents:
diff changeset
263
kono
parents:
diff changeset
264 if (simd
kono
parents:
diff changeset
265 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
kono
parents:
diff changeset
266 && !fd->have_ordered))
kono
parents:
diff changeset
267 {
kono
parents:
diff changeset
268 if (fd->collapse == 1 && !fd->tiling)
kono
parents:
diff changeset
269 iter_type = TREE_TYPE (loop->v);
kono
parents:
diff changeset
270 else if (i == 0
kono
parents:
diff changeset
271 || TYPE_PRECISION (iter_type)
kono
parents:
diff changeset
272 < TYPE_PRECISION (TREE_TYPE (loop->v)))
kono
parents:
diff changeset
273 iter_type
kono
parents:
diff changeset
274 = build_nonstandard_integer_type
kono
parents:
diff changeset
275 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277 else if (iter_type != long_long_unsigned_type_node)
kono
parents:
diff changeset
278 {
kono
parents:
diff changeset
279 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
kono
parents:
diff changeset
280 iter_type = long_long_unsigned_type_node;
kono
parents:
diff changeset
281 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
kono
parents:
diff changeset
282 && TYPE_PRECISION (TREE_TYPE (loop->v))
kono
parents:
diff changeset
283 >= TYPE_PRECISION (iter_type))
kono
parents:
diff changeset
284 {
kono
parents:
diff changeset
285 tree n;
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 if (loop->cond_code == LT_EXPR)
kono
parents:
diff changeset
288 n = fold_build2_loc (loc,
kono
parents:
diff changeset
289 PLUS_EXPR, TREE_TYPE (loop->v),
kono
parents:
diff changeset
290 loop->n2, loop->step);
kono
parents:
diff changeset
291 else
kono
parents:
diff changeset
292 n = loop->n1;
kono
parents:
diff changeset
293 if (TREE_CODE (n) != INTEGER_CST
kono
parents:
diff changeset
294 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
kono
parents:
diff changeset
295 iter_type = long_long_unsigned_type_node;
kono
parents:
diff changeset
296 }
kono
parents:
diff changeset
297 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
kono
parents:
diff changeset
298 > TYPE_PRECISION (iter_type))
kono
parents:
diff changeset
299 {
kono
parents:
diff changeset
300 tree n1, n2;
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 if (loop->cond_code == LT_EXPR)
kono
parents:
diff changeset
303 {
kono
parents:
diff changeset
304 n1 = loop->n1;
kono
parents:
diff changeset
305 n2 = fold_build2_loc (loc,
kono
parents:
diff changeset
306 PLUS_EXPR, TREE_TYPE (loop->v),
kono
parents:
diff changeset
307 loop->n2, loop->step);
kono
parents:
diff changeset
308 }
kono
parents:
diff changeset
309 else
kono
parents:
diff changeset
310 {
kono
parents:
diff changeset
311 n1 = fold_build2_loc (loc,
kono
parents:
diff changeset
312 MINUS_EXPR, TREE_TYPE (loop->v),
kono
parents:
diff changeset
313 loop->n2, loop->step);
kono
parents:
diff changeset
314 n2 = loop->n1;
kono
parents:
diff changeset
315 }
kono
parents:
diff changeset
316 if (TREE_CODE (n1) != INTEGER_CST
kono
parents:
diff changeset
317 || TREE_CODE (n2) != INTEGER_CST
kono
parents:
diff changeset
318 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
kono
parents:
diff changeset
319 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
kono
parents:
diff changeset
320 iter_type = long_long_unsigned_type_node;
kono
parents:
diff changeset
321 }
kono
parents:
diff changeset
322 }
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 if (i >= fd->collapse)
kono
parents:
diff changeset
325 continue;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 if (collapse_count && *collapse_count == NULL)
kono
parents:
diff changeset
328 {
kono
parents:
diff changeset
329 t = fold_binary (loop->cond_code, boolean_type_node,
kono
parents:
diff changeset
330 fold_convert (TREE_TYPE (loop->v), loop->n1),
kono
parents:
diff changeset
331 fold_convert (TREE_TYPE (loop->v), loop->n2));
kono
parents:
diff changeset
332 if (t && integer_zerop (t))
kono
parents:
diff changeset
333 count = build_zero_cst (long_long_unsigned_type_node);
kono
parents:
diff changeset
334 else if ((i == 0 || count != NULL_TREE)
kono
parents:
diff changeset
335 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
kono
parents:
diff changeset
336 && TREE_CONSTANT (loop->n1)
kono
parents:
diff changeset
337 && TREE_CONSTANT (loop->n2)
kono
parents:
diff changeset
338 && TREE_CODE (loop->step) == INTEGER_CST)
kono
parents:
diff changeset
339 {
kono
parents:
diff changeset
340 tree itype = TREE_TYPE (loop->v);
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 if (POINTER_TYPE_P (itype))
kono
parents:
diff changeset
343 itype = signed_type_for (itype);
kono
parents:
diff changeset
344 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
kono
parents:
diff changeset
345 t = fold_build2_loc (loc,
kono
parents:
diff changeset
346 PLUS_EXPR, itype,
kono
parents:
diff changeset
347 fold_convert_loc (loc, itype, loop->step), t);
kono
parents:
diff changeset
348 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
kono
parents:
diff changeset
349 fold_convert_loc (loc, itype, loop->n2));
kono
parents:
diff changeset
350 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
kono
parents:
diff changeset
351 fold_convert_loc (loc, itype, loop->n1));
kono
parents:
diff changeset
352 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
kono
parents:
diff changeset
353 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
kono
parents:
diff changeset
354 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
kono
parents:
diff changeset
355 fold_build1_loc (loc, NEGATE_EXPR, itype,
kono
parents:
diff changeset
356 fold_convert_loc (loc, itype,
kono
parents:
diff changeset
357 loop->step)));
kono
parents:
diff changeset
358 else
kono
parents:
diff changeset
359 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
kono
parents:
diff changeset
360 fold_convert_loc (loc, itype, loop->step));
kono
parents:
diff changeset
361 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
kono
parents:
diff changeset
362 if (count != NULL_TREE)
kono
parents:
diff changeset
363 count = fold_build2_loc (loc,
kono
parents:
diff changeset
364 MULT_EXPR, long_long_unsigned_type_node,
kono
parents:
diff changeset
365 count, t);
kono
parents:
diff changeset
366 else
kono
parents:
diff changeset
367 count = t;
kono
parents:
diff changeset
368 if (TREE_CODE (count) != INTEGER_CST)
kono
parents:
diff changeset
369 count = NULL_TREE;
kono
parents:
diff changeset
370 }
kono
parents:
diff changeset
371 else if (count && !integer_zerop (count))
kono
parents:
diff changeset
372 count = NULL_TREE;
kono
parents:
diff changeset
373 }
kono
parents:
diff changeset
374 }
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 if (count
kono
parents:
diff changeset
377 && !simd
kono
parents:
diff changeset
378 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
kono
parents:
diff changeset
379 || fd->have_ordered))
kono
parents:
diff changeset
380 {
kono
parents:
diff changeset
381 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
kono
parents:
diff changeset
382 iter_type = long_long_unsigned_type_node;
kono
parents:
diff changeset
383 else
kono
parents:
diff changeset
384 iter_type = long_integer_type_node;
kono
parents:
diff changeset
385 }
kono
parents:
diff changeset
386 else if (collapse_iter && *collapse_iter != NULL)
kono
parents:
diff changeset
387 iter_type = TREE_TYPE (*collapse_iter);
kono
parents:
diff changeset
388 fd->iter_type = iter_type;
kono
parents:
diff changeset
389 if (collapse_iter && *collapse_iter == NULL)
kono
parents:
diff changeset
390 *collapse_iter = create_tmp_var (iter_type, ".iter");
kono
parents:
diff changeset
391 if (collapse_count && *collapse_count == NULL)
kono
parents:
diff changeset
392 {
kono
parents:
diff changeset
393 if (count)
kono
parents:
diff changeset
394 *collapse_count = fold_convert_loc (loc, iter_type, count);
kono
parents:
diff changeset
395 else
kono
parents:
diff changeset
396 *collapse_count = create_tmp_var (iter_type, ".count");
kono
parents:
diff changeset
397 }
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 if (fd->collapse > 1 || fd->tiling || (fd->ordered && loops))
kono
parents:
diff changeset
400 {
kono
parents:
diff changeset
401 fd->loop.v = *collapse_iter;
kono
parents:
diff changeset
402 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
kono
parents:
diff changeset
403 fd->loop.n2 = *collapse_count;
kono
parents:
diff changeset
404 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
kono
parents:
diff changeset
405 fd->loop.cond_code = LT_EXPR;
kono
parents:
diff changeset
406 }
kono
parents:
diff changeset
407 else if (loops)
kono
parents:
diff changeset
408 loops[0] = fd->loop;
kono
parents:
diff changeset
409 }
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 /* Build a call to GOMP_barrier. */
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 gimple *
kono
parents:
diff changeset
414 omp_build_barrier (tree lhs)
kono
parents:
diff changeset
415 {
kono
parents:
diff changeset
416 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
kono
parents:
diff changeset
417 : BUILT_IN_GOMP_BARRIER);
kono
parents:
diff changeset
418 gcall *g = gimple_build_call (fndecl, 0);
kono
parents:
diff changeset
419 if (lhs)
kono
parents:
diff changeset
420 gimple_call_set_lhs (g, lhs);
kono
parents:
diff changeset
421 return g;
kono
parents:
diff changeset
422 }
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 /* Return maximum possible vectorization factor for the target. */
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 int
kono
parents:
diff changeset
427 omp_max_vf (void)
kono
parents:
diff changeset
428 {
kono
parents:
diff changeset
429 if (!optimize
kono
parents:
diff changeset
430 || optimize_debug
kono
parents:
diff changeset
431 || !flag_tree_loop_optimize
kono
parents:
diff changeset
432 || (!flag_tree_loop_vectorize
kono
parents:
diff changeset
433 && global_options_set.x_flag_tree_loop_vectorize))
kono
parents:
diff changeset
434 return 1;
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 int vf = 1;
kono
parents:
diff changeset
437 int vs = targetm.vectorize.autovectorize_vector_sizes ();
kono
parents:
diff changeset
438 if (vs)
kono
parents:
diff changeset
439 vf = 1 << floor_log2 (vs);
kono
parents:
diff changeset
440 else
kono
parents:
diff changeset
441 {
kono
parents:
diff changeset
442 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
kono
parents:
diff changeset
443 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
kono
parents:
diff changeset
444 vf = GET_MODE_NUNITS (vqimode);
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 return vf;
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Return maximum SIMT width if offloading may target SIMT hardware. */
kono
parents:
diff changeset
450
kono
parents:
diff changeset
451 int
kono
parents:
diff changeset
452 omp_max_simt_vf (void)
kono
parents:
diff changeset
453 {
kono
parents:
diff changeset
454 if (!optimize)
kono
parents:
diff changeset
455 return 0;
kono
parents:
diff changeset
456 if (ENABLE_OFFLOADING)
kono
parents:
diff changeset
457 for (const char *c = getenv ("OFFLOAD_TARGET_NAMES"); c;)
kono
parents:
diff changeset
458 {
kono
parents:
diff changeset
459 if (!strncmp (c, "nvptx", strlen ("nvptx")))
kono
parents:
diff changeset
460 return 32;
kono
parents:
diff changeset
461 else if ((c = strchr (c, ',')))
kono
parents:
diff changeset
462 c++;
kono
parents:
diff changeset
463 }
kono
parents:
diff changeset
464 return 0;
kono
parents:
diff changeset
465 }
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
kono
parents:
diff changeset
468 macro on gomp-constants.h. We do not check for overflow. */
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 tree
kono
parents:
diff changeset
471 oacc_launch_pack (unsigned code, tree device, unsigned op)
kono
parents:
diff changeset
472 {
kono
parents:
diff changeset
473 tree res;
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
kono
parents:
diff changeset
476 if (device)
kono
parents:
diff changeset
477 {
kono
parents:
diff changeset
478 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
kono
parents:
diff changeset
479 device, build_int_cst (unsigned_type_node,
kono
parents:
diff changeset
480 GOMP_LAUNCH_DEVICE_SHIFT));
kono
parents:
diff changeset
481 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483 return res;
kono
parents:
diff changeset
484 }
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* FIXME: What is the following comment for? */
kono
parents:
diff changeset
487 /* Look for compute grid dimension clauses and convert to an attribute
kono
parents:
diff changeset
488 attached to FN. This permits the target-side code to (a) massage
kono
parents:
diff changeset
489 the dimensions, (b) emit that data and (c) optimize. Non-constant
kono
parents:
diff changeset
490 dimensions are pushed onto ARGS.
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 The attribute value is a TREE_LIST. A set of dimensions is
kono
parents:
diff changeset
493 represented as a list of INTEGER_CST. Those that are runtime
kono
parents:
diff changeset
494 exprs are represented as an INTEGER_CST of zero.
kono
parents:
diff changeset
495
kono
parents:
diff changeset
496 TODO: Normally the attribute will just contain a single such list. If
kono
parents:
diff changeset
497 however it contains a list of lists, this will represent the use of
kono
parents:
diff changeset
498 device_type. Each member of the outer list is an assoc list of
kono
parents:
diff changeset
499 dimensions, keyed by the device type. The first entry will be the
kono
parents:
diff changeset
500 default. Well, that's the plan. */
kono
parents:
diff changeset
501
kono
parents:
diff changeset
502 /* Replace any existing oacc fn attribute with updated dimensions. */
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 void
kono
parents:
diff changeset
505 oacc_replace_fn_attrib (tree fn, tree dims)
kono
parents:
diff changeset
506 {
kono
parents:
diff changeset
507 tree ident = get_identifier (OACC_FN_ATTRIB);
kono
parents:
diff changeset
508 tree attribs = DECL_ATTRIBUTES (fn);
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 /* If we happen to be present as the first attrib, drop it. */
kono
parents:
diff changeset
511 if (attribs && TREE_PURPOSE (attribs) == ident)
kono
parents:
diff changeset
512 attribs = TREE_CHAIN (attribs);
kono
parents:
diff changeset
513 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
kono
parents:
diff changeset
514 }
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 /* Scan CLAUSES for launch dimensions and attach them to the oacc
kono
parents:
diff changeset
517 function attribute. Push any that are non-constant onto the ARGS
kono
parents:
diff changeset
518 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 void
kono
parents:
diff changeset
521 oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
kono
parents:
diff changeset
522 {
kono
parents:
diff changeset
523 /* Must match GOMP_DIM ordering. */
kono
parents:
diff changeset
524 static const omp_clause_code ids[]
kono
parents:
diff changeset
525 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
kono
parents:
diff changeset
526 OMP_CLAUSE_VECTOR_LENGTH };
kono
parents:
diff changeset
527 unsigned ix;
kono
parents:
diff changeset
528 tree dims[GOMP_DIM_MAX];
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 tree attr = NULL_TREE;
kono
parents:
diff changeset
531 unsigned non_const = 0;
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 for (ix = GOMP_DIM_MAX; ix--;)
kono
parents:
diff changeset
534 {
kono
parents:
diff changeset
535 tree clause = omp_find_clause (clauses, ids[ix]);
kono
parents:
diff changeset
536 tree dim = NULL_TREE;
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 if (clause)
kono
parents:
diff changeset
539 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
kono
parents:
diff changeset
540 dims[ix] = dim;
kono
parents:
diff changeset
541 if (dim && TREE_CODE (dim) != INTEGER_CST)
kono
parents:
diff changeset
542 {
kono
parents:
diff changeset
543 dim = integer_zero_node;
kono
parents:
diff changeset
544 non_const |= GOMP_DIM_MASK (ix);
kono
parents:
diff changeset
545 }
kono
parents:
diff changeset
546 attr = tree_cons (NULL_TREE, dim, attr);
kono
parents:
diff changeset
547 }
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 oacc_replace_fn_attrib (fn, attr);
kono
parents:
diff changeset
550
kono
parents:
diff changeset
551 if (non_const)
kono
parents:
diff changeset
552 {
kono
parents:
diff changeset
553 /* Push a dynamic argument set. */
kono
parents:
diff changeset
554 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
kono
parents:
diff changeset
555 NULL_TREE, non_const));
kono
parents:
diff changeset
556 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
kono
parents:
diff changeset
557 if (non_const & GOMP_DIM_MASK (ix))
kono
parents:
diff changeset
558 args->safe_push (dims[ix]);
kono
parents:
diff changeset
559 }
kono
parents:
diff changeset
560 }
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 /* Process the routine's dimension clauess to generate an attribute
kono
parents:
diff changeset
563 value. Issue diagnostics as appropriate. We default to SEQ
kono
parents:
diff changeset
564 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
kono
parents:
diff changeset
565 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
kono
parents:
diff changeset
566 can have a loop partitioned on it. non-zero indicates
kono
parents:
diff changeset
567 yes, zero indicates no. By construction once a non-zero has been
kono
parents:
diff changeset
568 reached, further inner dimensions must also be non-zero. We set
kono
parents:
diff changeset
569 TREE_VALUE to zero for the dimensions that may be partitioned and
kono
parents:
diff changeset
570 1 for the other ones -- if a loop is (erroneously) spawned at
kono
parents:
diff changeset
571 an outer level, we don't want to try and partition it. */
kono
parents:
diff changeset
572
kono
parents:
diff changeset
573 tree
kono
parents:
diff changeset
574 oacc_build_routine_dims (tree clauses)
kono
parents:
diff changeset
575 {
kono
parents:
diff changeset
576 /* Must match GOMP_DIM ordering. */
kono
parents:
diff changeset
577 static const omp_clause_code ids[]
kono
parents:
diff changeset
578 = {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
kono
parents:
diff changeset
579 int ix;
kono
parents:
diff changeset
580 int level = -1;
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
kono
parents:
diff changeset
583 for (ix = GOMP_DIM_MAX + 1; ix--;)
kono
parents:
diff changeset
584 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
kono
parents:
diff changeset
585 {
kono
parents:
diff changeset
586 if (level >= 0)
kono
parents:
diff changeset
587 error_at (OMP_CLAUSE_LOCATION (clauses),
kono
parents:
diff changeset
588 "multiple loop axes specified for routine");
kono
parents:
diff changeset
589 level = ix;
kono
parents:
diff changeset
590 break;
kono
parents:
diff changeset
591 }
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 /* Default to SEQ. */
kono
parents:
diff changeset
594 if (level < 0)
kono
parents:
diff changeset
595 level = GOMP_DIM_MAX;
kono
parents:
diff changeset
596
kono
parents:
diff changeset
597 tree dims = NULL_TREE;
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 for (ix = GOMP_DIM_MAX; ix--;)
kono
parents:
diff changeset
600 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
kono
parents:
diff changeset
601 build_int_cst (integer_type_node, ix < level), dims);
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 return dims;
kono
parents:
diff changeset
604 }
kono
parents:
diff changeset
605
kono
parents:
diff changeset
606 /* Retrieve the oacc function attrib and return it. Non-oacc
kono
parents:
diff changeset
607 functions will return NULL. */
kono
parents:
diff changeset
608
kono
parents:
diff changeset
609 tree
kono
parents:
diff changeset
610 oacc_get_fn_attrib (tree fn)
kono
parents:
diff changeset
611 {
kono
parents:
diff changeset
612 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
kono
parents:
diff changeset
613 }
kono
parents:
diff changeset
614
kono
parents:
diff changeset
615 /* Extract an oacc execution dimension from FN. FN must be an
kono
parents:
diff changeset
616 offloaded function or routine that has already had its execution
kono
parents:
diff changeset
617 dimensions lowered to the target-specific values. */
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 int
kono
parents:
diff changeset
620 oacc_get_fn_dim_size (tree fn, int axis)
kono
parents:
diff changeset
621 {
kono
parents:
diff changeset
622 tree attrs = oacc_get_fn_attrib (fn);
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 gcc_assert (axis < GOMP_DIM_MAX);
kono
parents:
diff changeset
625
kono
parents:
diff changeset
626 tree dims = TREE_VALUE (attrs);
kono
parents:
diff changeset
627 while (axis--)
kono
parents:
diff changeset
628 dims = TREE_CHAIN (dims);
kono
parents:
diff changeset
629
kono
parents:
diff changeset
630 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 return size;
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
kono
parents:
diff changeset
636 IFN_GOACC_DIM_SIZE call. */
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 int
kono
parents:
diff changeset
639 oacc_get_ifn_dim_arg (const gimple *stmt)
kono
parents:
diff changeset
640 {
kono
parents:
diff changeset
641 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
kono
parents:
diff changeset
642 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
kono
parents:
diff changeset
643 tree arg = gimple_call_arg (stmt, 0);
kono
parents:
diff changeset
644 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
kono
parents:
diff changeset
647 return (int) axis;
kono
parents:
diff changeset
648 }