xref: /dflybsd-src/contrib/gcc-8.0/gcc/omp-general.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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