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