xref: /netbsd-src/external/gpl3/gcc/dist/gcc/fortran/trans-openmp.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2    Copyright (C) 2005-2022 Free Software Foundation, Inc.
3    Contributed by Jakub Jelinek <jakub@redhat.com>
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "options.h"
26 #include "tree.h"
27 #include "gfortran.h"
28 #include "gimple-expr.h"
29 #include "trans.h"
30 #include "stringpool.h"
31 #include "fold-const.h"
32 #include "gimplify.h"	/* For create_tmp_var_raw.  */
33 #include "trans-stmt.h"
34 #include "trans-types.h"
35 #include "trans-array.h"
36 #include "trans-const.h"
37 #include "arith.h"
38 #include "constructor.h"
39 #include "gomp-constants.h"
40 #include "omp-general.h"
41 #include "omp-low.h"
42 #include "memmodel.h"  /* For MEMMODEL_ enums.  */
43 
44 #undef GCC_DIAG_STYLE
45 #define GCC_DIAG_STYLE __gcc_tdiag__
46 #include "diagnostic-core.h"
47 #undef GCC_DIAG_STYLE
48 #define GCC_DIAG_STYLE __gcc_gfc__
49 #include "attribs.h"
50 #include "function.h"
51 
52 int ompws_flags;
53 
54 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
55    allocatable or pointer attribute.  */
56 
57 bool
gfc_omp_is_allocatable_or_ptr(const_tree decl)58 gfc_omp_is_allocatable_or_ptr (const_tree decl)
59 {
60   return (DECL_P (decl)
61 	  && (GFC_DECL_GET_SCALAR_POINTER (decl)
62 	      || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
63 }
64 
65 /* True if the argument is an optional argument; except that false is also
66    returned for arguments with the value attribute (nonpointers) and for
67    assumed-shape variables (decl is a local variable containing arg->data).
68    Note that for 'procedure(), optional' the value false is used as that's
69    always a pointer and no additional indirection is used.
70    Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc).  */
71 
72 static bool
gfc_omp_is_optional_argument(const_tree decl)73 gfc_omp_is_optional_argument (const_tree decl)
74 {
75   /* Note: VAR_DECL can occur with BIND(C) and array descriptors.  */
76   return ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
77 	  && DECL_LANG_SPECIFIC (decl)
78 	  && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
79 	  && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
80 	  && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
81 	  && GFC_DECL_OPTIONAL_ARGUMENT (decl));
82 }
83 
84 /* Check whether this DECL belongs to a Fortran optional argument.
85    With 'for_present_check' set to false, decls which are optional parameters
86    themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
87    always pointers.  With 'for_present_check' set to true, the decl for checking
88    whether an argument is present is returned; for arguments with value
89    attribute this is the hidden argument and of BOOLEAN_TYPE.  If the decl is
90    unrelated to optional arguments, NULL_TREE is returned.  */
91 
92 tree
gfc_omp_check_optional_argument(tree decl,bool for_present_check)93 gfc_omp_check_optional_argument (tree decl, bool for_present_check)
94 {
95   if (!for_present_check)
96     return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
97 
98   if (!DECL_LANG_SPECIFIC (decl))
99     return NULL_TREE;
100 
101   tree orig_decl = decl;
102 
103   /* For assumed-shape arrays, a local decl with arg->data is used.  */
104   if (TREE_CODE (decl) != PARM_DECL
105       && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
106 	  || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
107     decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
108 
109   /* Note: With BIND(C), array descriptors are converted to a VAR_DECL.  */
110   if (decl == NULL_TREE
111       || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL)
112       || !DECL_LANG_SPECIFIC (decl)
113       || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
114     return NULL_TREE;
115 
116    /* Scalars with VALUE attribute which are passed by value use a hidden
117       argument to denote the present status.  They are passed as nonpointer type
118       with one exception: 'type(c_ptr), value' as 'void*'.  */
119    /* Cf. trans-expr.cc's gfc_conv_expr_present.  */
120    if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
121        || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
122     {
123       char name[GFC_MAX_SYMBOL_LEN + 2];
124       tree tree_name;
125 
126       name[0] = '_';
127       strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
128       tree_name = get_identifier (name);
129 
130       /* Walk function argument list to find the hidden arg.  */
131       decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
132       for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
133 	if (DECL_NAME (decl) == tree_name
134 	    && DECL_ARTIFICIAL (decl))
135 	  break;
136 
137       gcc_assert (decl);
138       return decl;
139     }
140 
141   return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
142 			  orig_decl, null_pointer_node);
143 }
144 
145 
146 /* Returns tree with NULL if it is not an array descriptor and with the tree to
147    access the 'data' component otherwise.  With type_only = true, it returns the
148    TREE_TYPE without creating a new tree.  */
149 
150 tree
gfc_omp_array_data(tree decl,bool type_only)151 gfc_omp_array_data (tree decl, bool type_only)
152 {
153   tree type = TREE_TYPE (decl);
154 
155   if (POINTER_TYPE_P (type))
156     type = TREE_TYPE (type);
157 
158   if (!GFC_DESCRIPTOR_TYPE_P (type))
159     return NULL_TREE;
160 
161   if (type_only)
162     return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
163 
164   if (POINTER_TYPE_P (TREE_TYPE (decl)))
165     decl = build_fold_indirect_ref (decl);
166 
167   decl = gfc_conv_descriptor_data_get (decl);
168   STRIP_NOPS (decl);
169   return decl;
170 }
171 
172 /* True if OpenMP should privatize what this DECL points to rather
173    than the DECL itself.  */
174 
175 bool
gfc_omp_privatize_by_reference(const_tree decl)176 gfc_omp_privatize_by_reference (const_tree decl)
177 {
178   tree type = TREE_TYPE (decl);
179 
180   if (TREE_CODE (type) == REFERENCE_TYPE
181       && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
182     return true;
183 
184   if (TREE_CODE (type) == POINTER_TYPE
185       && gfc_omp_is_optional_argument (decl))
186     return true;
187 
188   if (TREE_CODE (type) == POINTER_TYPE)
189     {
190       while (TREE_CODE (decl) == COMPONENT_REF)
191 	decl = TREE_OPERAND (decl, 1);
192 
193       /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
194 	 that have POINTER_TYPE type and aren't scalar pointers, scalar
195 	 allocatables, Cray pointees or C pointers are supposed to be
196 	 privatized by reference.  */
197       if (GFC_DECL_GET_SCALAR_POINTER (decl)
198 	  || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
199 	  || GFC_DECL_CRAY_POINTEE (decl)
200 	  || GFC_DECL_ASSOCIATE_VAR_P (decl)
201 	  || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
202 	return false;
203 
204       if (!DECL_ARTIFICIAL (decl)
205 	  && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
206 	return true;
207 
208       /* Some arrays are expanded as DECL_ARTIFICIAL pointers
209 	 by the frontend.  */
210       if (DECL_LANG_SPECIFIC (decl)
211 	  && GFC_DECL_SAVED_DESCRIPTOR (decl))
212 	return true;
213     }
214 
215   return false;
216 }
217 
218 /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
219    of DECL is predetermined.  */
220 
221 enum omp_clause_default_kind
gfc_omp_predetermined_sharing(tree decl)222 gfc_omp_predetermined_sharing (tree decl)
223 {
224   /* Associate names preserve the association established during ASSOCIATE.
225      As they are implemented either as pointers to the selector or array
226      descriptor and shouldn't really change in the ASSOCIATE region,
227      this decl can be either shared or firstprivate.  If it is a pointer,
228      use firstprivate, as it is cheaper that way, otherwise make it shared.  */
229   if (GFC_DECL_ASSOCIATE_VAR_P (decl))
230     {
231       if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
232 	return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
233       else
234 	return OMP_CLAUSE_DEFAULT_SHARED;
235     }
236 
237   if (DECL_ARTIFICIAL (decl)
238       && ! GFC_DECL_RESULT (decl)
239       && ! (DECL_LANG_SPECIFIC (decl)
240 	    && GFC_DECL_SAVED_DESCRIPTOR (decl)))
241     return OMP_CLAUSE_DEFAULT_SHARED;
242 
243   /* Cray pointees shouldn't be listed in any clauses and should be
244      gimplified to dereference of the corresponding Cray pointer.
245      Make them all private, so that they are emitted in the debug
246      information.  */
247   if (GFC_DECL_CRAY_POINTEE (decl))
248     return OMP_CLAUSE_DEFAULT_PRIVATE;
249 
250   /* Assumed-size arrays are predetermined shared.  */
251   if (TREE_CODE (decl) == PARM_DECL
252       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
253       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
254       && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
255 				GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
256 	 == NULL)
257     return OMP_CLAUSE_DEFAULT_SHARED;
258 
259   /* Dummy procedures aren't considered variables by OpenMP, thus are
260      disallowed in OpenMP clauses.  They are represented as PARM_DECLs
261      in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
262      to avoid complaining about their uses with default(none).  */
263   if (TREE_CODE (decl) == PARM_DECL
264       && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
265       && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
266     return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
267 
268   /* COMMON and EQUIVALENCE decls are shared.  They
269      are only referenced through DECL_VALUE_EXPR of the variables
270      contained in them.  If those are privatized, they will not be
271      gimplified to the COMMON or EQUIVALENCE decls.  */
272   if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
273     return OMP_CLAUSE_DEFAULT_SHARED;
274 
275   if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
276     return OMP_CLAUSE_DEFAULT_SHARED;
277 
278   /* These are either array or derived parameters, or vtables.
279      In the former cases, the OpenMP standard doesn't consider them to be
280      variables at all (they can't be redefined), but they can nevertheless appear
281      in parallel/task regions and for default(none) purposes treat them as shared.
282      For vtables likely the same handling is desirable.  */
283   if (VAR_P (decl) && TREE_READONLY (decl)
284       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
285     return OMP_CLAUSE_DEFAULT_SHARED;
286 
287   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
288 }
289 
290 
291 /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
292    of DECL is predetermined.  */
293 
294 enum omp_clause_defaultmap_kind
gfc_omp_predetermined_mapping(tree decl)295 gfc_omp_predetermined_mapping (tree decl)
296 {
297   if (DECL_ARTIFICIAL (decl)
298       && ! GFC_DECL_RESULT (decl)
299       && ! (DECL_LANG_SPECIFIC (decl)
300 	    && GFC_DECL_SAVED_DESCRIPTOR (decl)))
301     return OMP_CLAUSE_DEFAULTMAP_TO;
302 
303   /* These are either array or derived parameters, or vtables.  */
304   if (VAR_P (decl) && TREE_READONLY (decl)
305       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
306     return OMP_CLAUSE_DEFAULTMAP_TO;
307 
308   return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
309 }
310 
311 
312 /* Return decl that should be used when reporting DEFAULT(NONE)
313    diagnostics.  */
314 
315 tree
gfc_omp_report_decl(tree decl)316 gfc_omp_report_decl (tree decl)
317 {
318   if (DECL_ARTIFICIAL (decl)
319       && DECL_LANG_SPECIFIC (decl)
320       && GFC_DECL_SAVED_DESCRIPTOR (decl))
321     return GFC_DECL_SAVED_DESCRIPTOR (decl);
322 
323   return decl;
324 }
325 
326 /* Return true if TYPE has any allocatable components.  */
327 
328 static bool
gfc_has_alloc_comps(tree type,tree decl)329 gfc_has_alloc_comps (tree type, tree decl)
330 {
331   tree field, ftype;
332 
333   if (POINTER_TYPE_P (type))
334     {
335       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
336 	type = TREE_TYPE (type);
337       else if (GFC_DECL_GET_SCALAR_POINTER (decl))
338 	return false;
339     }
340 
341   if (GFC_DESCRIPTOR_TYPE_P (type)
342       && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
343 	  || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
344     return false;
345 
346   if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
347     type = gfc_get_element_type (type);
348 
349   if (TREE_CODE (type) != RECORD_TYPE)
350     return false;
351 
352   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
353     {
354       ftype = TREE_TYPE (field);
355       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
356 	return true;
357       if (GFC_DESCRIPTOR_TYPE_P (ftype)
358 	  && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
359 	return true;
360       if (gfc_has_alloc_comps (ftype, field))
361 	return true;
362     }
363   return false;
364 }
365 
366 /* Return true if TYPE is polymorphic but not with pointer attribute.  */
367 
368 static bool
gfc_is_polymorphic_nonptr(tree type)369 gfc_is_polymorphic_nonptr (tree type)
370 {
371   if (POINTER_TYPE_P (type))
372     type = TREE_TYPE (type);
373   return GFC_CLASS_TYPE_P (type);
374 }
375 
376 /* Return true if TYPE is unlimited polymorphic but not with pointer attribute;
377    unlimited means also intrinsic types are handled and _len is used.  */
378 
379 static bool
gfc_is_unlimited_polymorphic_nonptr(tree type)380 gfc_is_unlimited_polymorphic_nonptr (tree type)
381 {
382   if (POINTER_TYPE_P (type))
383     type = TREE_TYPE (type);
384   if (!GFC_CLASS_TYPE_P (type))
385     return false;
386 
387   tree field = TYPE_FIELDS (type); /* _data */
388   gcc_assert (field);
389   field = DECL_CHAIN (field); /* _vptr */
390   gcc_assert (field);
391   field = DECL_CHAIN (field);
392   if (!field)
393     return false;
394   gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0);
395   return true;
396 }
397 
398 /* Return true if the DECL is for an allocatable array or scalar.  */
399 
400 bool
gfc_omp_allocatable_p(tree decl)401 gfc_omp_allocatable_p (tree decl)
402 {
403   if (!DECL_P (decl))
404     return false;
405 
406   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
407     return true;
408 
409   tree type = TREE_TYPE (decl);
410   if (gfc_omp_privatize_by_reference (decl))
411     type = TREE_TYPE (type);
412 
413   if (GFC_DESCRIPTOR_TYPE_P (type)
414       && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
415     return true;
416 
417   return false;
418 }
419 
420 
421 /* Return true if DECL in private clause needs
422    OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause.  */
423 bool
gfc_omp_private_outer_ref(tree decl)424 gfc_omp_private_outer_ref (tree decl)
425 {
426   tree type = TREE_TYPE (decl);
427 
428   if (gfc_omp_privatize_by_reference (decl))
429     type = TREE_TYPE (type);
430 
431   if (GFC_DESCRIPTOR_TYPE_P (type)
432       && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
433     return true;
434 
435   if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
436     return true;
437 
438   if (gfc_has_alloc_comps (type, decl))
439     return true;
440 
441   return false;
442 }
443 
444 /* Callback for gfc_omp_unshare_expr.  */
445 
446 static tree
gfc_omp_unshare_expr_r(tree * tp,int * walk_subtrees,void *)447 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
448 {
449   tree t = *tp;
450   enum tree_code code = TREE_CODE (t);
451 
452   /* Stop at types, decls, constants like copy_tree_r.  */
453   if (TREE_CODE_CLASS (code) == tcc_type
454       || TREE_CODE_CLASS (code) == tcc_declaration
455       || TREE_CODE_CLASS (code) == tcc_constant
456       || code == BLOCK)
457     *walk_subtrees = 0;
458   else if (handled_component_p (t)
459 	   || TREE_CODE (t) == MEM_REF)
460     {
461       *tp = unshare_expr (t);
462       *walk_subtrees = 0;
463     }
464 
465   return NULL_TREE;
466 }
467 
468 /* Unshare in expr anything that the FE which normally doesn't
469    care much about tree sharing (because during gimplification
470    everything is unshared) could cause problems with tree sharing
471    at omp-low.cc time.  */
472 
473 static tree
gfc_omp_unshare_expr(tree expr)474 gfc_omp_unshare_expr (tree expr)
475 {
476   walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
477   return expr;
478 }
479 
480 enum walk_alloc_comps
481 {
482   WALK_ALLOC_COMPS_DTOR,
483   WALK_ALLOC_COMPS_DEFAULT_CTOR,
484   WALK_ALLOC_COMPS_COPY_CTOR
485 };
486 
487 /* Handle allocatable components in OpenMP clauses.  */
488 
489 static tree
gfc_walk_alloc_comps(tree decl,tree dest,tree var,enum walk_alloc_comps kind)490 gfc_walk_alloc_comps (tree decl, tree dest, tree var,
491 		      enum walk_alloc_comps kind)
492 {
493   stmtblock_t block, tmpblock;
494   tree type = TREE_TYPE (decl), then_b, tem, field;
495   gfc_init_block (&block);
496 
497   if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
498     {
499       if (GFC_DESCRIPTOR_TYPE_P (type))
500 	{
501 	  gfc_init_block (&tmpblock);
502 	  tem = gfc_full_array_size (&tmpblock, decl,
503 				     GFC_TYPE_ARRAY_RANK (type));
504 	  then_b = gfc_finish_block (&tmpblock);
505 	  gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
506 	  tem = gfc_omp_unshare_expr (tem);
507 	  tem = fold_build2_loc (input_location, MINUS_EXPR,
508 				 gfc_array_index_type, tem,
509 				 gfc_index_one_node);
510 	}
511       else
512 	{
513 	  bool compute_nelts = false;
514 	  if (!TYPE_DOMAIN (type)
515 	      || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
516 	      || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
517 	      || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
518 	    compute_nelts = true;
519 	  else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
520 	    {
521 	      tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
522 	      if (lookup_attribute ("omp dummy var", a))
523 		compute_nelts = true;
524 	    }
525 	  if (compute_nelts)
526 	    {
527 	      tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
528 				 TYPE_SIZE_UNIT (type),
529 				 TYPE_SIZE_UNIT (TREE_TYPE (type)));
530 	      tem = size_binop (MINUS_EXPR, tem, size_one_node);
531 	    }
532 	  else
533 	    tem = array_type_nelts (type);
534 	  tem = fold_convert (gfc_array_index_type, tem);
535 	}
536 
537       tree nelems = gfc_evaluate_now (tem, &block);
538       tree index = gfc_create_var (gfc_array_index_type, "S");
539 
540       gfc_init_block (&tmpblock);
541       tem = gfc_conv_array_data (decl);
542       tree declvar = build_fold_indirect_ref_loc (input_location, tem);
543       tree declvref = gfc_build_array_ref (declvar, index, NULL);
544       tree destvar, destvref = NULL_TREE;
545       if (dest)
546 	{
547 	  tem = gfc_conv_array_data (dest);
548 	  destvar = build_fold_indirect_ref_loc (input_location, tem);
549 	  destvref = gfc_build_array_ref (destvar, index, NULL);
550 	}
551       gfc_add_expr_to_block (&tmpblock,
552 			     gfc_walk_alloc_comps (declvref, destvref,
553 						   var, kind));
554 
555       gfc_loopinfo loop;
556       gfc_init_loopinfo (&loop);
557       loop.dimen = 1;
558       loop.from[0] = gfc_index_zero_node;
559       loop.loopvar[0] = index;
560       loop.to[0] = nelems;
561       gfc_trans_scalarizing_loops (&loop, &tmpblock);
562       gfc_add_block_to_block (&block, &loop.pre);
563       return gfc_finish_block (&block);
564     }
565   else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
566     {
567       decl = build_fold_indirect_ref_loc (input_location, decl);
568       if (dest)
569 	dest = build_fold_indirect_ref_loc (input_location, dest);
570       type = TREE_TYPE (decl);
571     }
572 
573   gcc_assert (TREE_CODE (type) == RECORD_TYPE);
574   for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
575     {
576       tree ftype = TREE_TYPE (field);
577       tree declf, destf = NULL_TREE;
578       bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
579       if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
580 	   || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
581 	  && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
582 	  && !has_alloc_comps)
583 	continue;
584       declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
585 			       decl, field, NULL_TREE);
586       if (dest)
587 	destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
588 				 dest, field, NULL_TREE);
589 
590       tem = NULL_TREE;
591       switch (kind)
592 	{
593 	case WALK_ALLOC_COMPS_DTOR:
594 	  break;
595 	case WALK_ALLOC_COMPS_DEFAULT_CTOR:
596 	  if (GFC_DESCRIPTOR_TYPE_P (ftype)
597 	      && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
598 	    {
599 	      gfc_add_modify (&block, unshare_expr (destf),
600 			      unshare_expr (declf));
601 	      tem = gfc_duplicate_allocatable_nocopy
602 					(destf, declf, ftype,
603 					 GFC_TYPE_ARRAY_RANK (ftype));
604 	    }
605 	  else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
606 	    tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
607 	  break;
608 	case WALK_ALLOC_COMPS_COPY_CTOR:
609 	  if (GFC_DESCRIPTOR_TYPE_P (ftype)
610 	      && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
611 	    tem = gfc_duplicate_allocatable (destf, declf, ftype,
612 					     GFC_TYPE_ARRAY_RANK (ftype),
613 					     NULL_TREE);
614 	  else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
615 	    tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
616 					     NULL_TREE);
617 	  break;
618 	}
619       if (tem)
620 	gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
621       if (has_alloc_comps)
622 	{
623 	  gfc_init_block (&tmpblock);
624 	  gfc_add_expr_to_block (&tmpblock,
625 				 gfc_walk_alloc_comps (declf, destf,
626 						       field, kind));
627 	  then_b = gfc_finish_block (&tmpblock);
628 	  if (GFC_DESCRIPTOR_TYPE_P (ftype)
629 	      && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
630 	    tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
631 	  else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
632 	    tem = unshare_expr (declf);
633 	  else
634 	    tem = NULL_TREE;
635 	  if (tem)
636 	    {
637 	      tem = fold_convert (pvoid_type_node, tem);
638 	      tem = fold_build2_loc (input_location, NE_EXPR,
639 				     logical_type_node, tem,
640 				     null_pointer_node);
641 	      then_b = build3_loc (input_location, COND_EXPR, void_type_node,
642 				   tem, then_b,
643 				   build_empty_stmt (input_location));
644 	    }
645 	  gfc_add_expr_to_block (&block, then_b);
646 	}
647       if (kind == WALK_ALLOC_COMPS_DTOR)
648 	{
649 	  if (GFC_DESCRIPTOR_TYPE_P (ftype)
650 	      && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
651 	    {
652 	      tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
653 	      tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
654 						NULL_TREE, NULL_TREE, true,
655 						NULL,
656 						GFC_CAF_COARRAY_NOCOARRAY);
657 	      gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
658 	    }
659 	  else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
660 	    {
661 	      tem = gfc_call_free (unshare_expr (declf));
662 	      gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
663 	    }
664 	}
665     }
666 
667   return gfc_finish_block (&block);
668 }
669 
670 /* Return code to initialize DECL with its default constructor, or
671    NULL if there's nothing to do.  */
672 
673 tree
gfc_omp_clause_default_ctor(tree clause,tree decl,tree outer)674 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
675 {
676   tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
677   stmtblock_t block, cond_block;
678 
679   switch (OMP_CLAUSE_CODE (clause))
680     {
681     case OMP_CLAUSE__LOOPTEMP_:
682     case OMP_CLAUSE__REDUCTEMP_:
683     case OMP_CLAUSE__CONDTEMP_:
684     case OMP_CLAUSE__SCANTEMP_:
685       return NULL;
686     case OMP_CLAUSE_PRIVATE:
687     case OMP_CLAUSE_LASTPRIVATE:
688     case OMP_CLAUSE_LINEAR:
689     case OMP_CLAUSE_REDUCTION:
690     case OMP_CLAUSE_IN_REDUCTION:
691     case OMP_CLAUSE_TASK_REDUCTION:
692       break;
693     default:
694       gcc_unreachable ();
695     }
696 
697   if ((! GFC_DESCRIPTOR_TYPE_P (type)
698        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
699       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
700 	  || !POINTER_TYPE_P (type)))
701     {
702       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
703 	{
704 	  gcc_assert (outer);
705 	  gfc_start_block (&block);
706 	  tree tem = gfc_walk_alloc_comps (outer, decl,
707 					   OMP_CLAUSE_DECL (clause),
708 					   WALK_ALLOC_COMPS_DEFAULT_CTOR);
709 	  gfc_add_expr_to_block (&block, tem);
710 	  return gfc_finish_block (&block);
711 	}
712       return NULL_TREE;
713     }
714 
715   gcc_assert (outer != NULL_TREE);
716 
717   /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
718      "not currently allocated" allocation status if outer
719      array is "not currently allocated", otherwise should be allocated.  */
720   gfc_start_block (&block);
721 
722   gfc_init_block (&cond_block);
723 
724   if (GFC_DESCRIPTOR_TYPE_P (type))
725     {
726       gfc_add_modify (&cond_block, decl, outer);
727       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
728       size = gfc_conv_descriptor_ubound_get (decl, rank);
729       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
730 			      size,
731 			      gfc_conv_descriptor_lbound_get (decl, rank));
732       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
733 			      size, gfc_index_one_node);
734       if (GFC_TYPE_ARRAY_RANK (type) > 1)
735 	size = fold_build2_loc (input_location, MULT_EXPR,
736 				gfc_array_index_type, size,
737 				gfc_conv_descriptor_stride_get (decl, rank));
738       tree esize = fold_convert (gfc_array_index_type,
739 				 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
740       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
741 			      size, esize);
742       size = unshare_expr (size);
743       size = gfc_evaluate_now (fold_convert (size_type_node, size),
744 			       &cond_block);
745     }
746   else
747     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
748   ptr = gfc_create_var (pvoid_type_node, NULL);
749   gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
750   if (GFC_DESCRIPTOR_TYPE_P (type))
751     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
752   else
753     gfc_add_modify (&cond_block, unshare_expr (decl),
754 		    fold_convert (TREE_TYPE (decl), ptr));
755   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
756     {
757       tree tem = gfc_walk_alloc_comps (outer, decl,
758 				       OMP_CLAUSE_DECL (clause),
759 				       WALK_ALLOC_COMPS_DEFAULT_CTOR);
760       gfc_add_expr_to_block (&cond_block, tem);
761     }
762   then_b = gfc_finish_block (&cond_block);
763 
764   /* Reduction clause requires allocated ALLOCATABLE.  */
765   if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION
766       && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION
767       && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION)
768     {
769       gfc_init_block (&cond_block);
770       if (GFC_DESCRIPTOR_TYPE_P (type))
771 	gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
772 				      null_pointer_node);
773       else
774 	gfc_add_modify (&cond_block, unshare_expr (decl),
775 			build_zero_cst (TREE_TYPE (decl)));
776       else_b = gfc_finish_block (&cond_block);
777 
778       tree tem = fold_convert (pvoid_type_node,
779 			       GFC_DESCRIPTOR_TYPE_P (type)
780 			       ? gfc_conv_descriptor_data_get (outer) : outer);
781       tem = unshare_expr (tem);
782       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
783 			      tem, null_pointer_node);
784       gfc_add_expr_to_block (&block,
785 			     build3_loc (input_location, COND_EXPR,
786 					 void_type_node, cond, then_b,
787 					 else_b));
788       /* Avoid -W*uninitialized warnings.  */
789       if (DECL_P (decl))
790 	suppress_warning (decl, OPT_Wuninitialized);
791     }
792   else
793     gfc_add_expr_to_block (&block, then_b);
794 
795   return gfc_finish_block (&block);
796 }
797 
798 /* Build and return code for a copy constructor from SRC to DEST.  */
799 
800 tree
gfc_omp_clause_copy_ctor(tree clause,tree dest,tree src)801 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
802 {
803   tree type = TREE_TYPE (dest), ptr, size, call;
804   tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
805   tree cond, then_b, else_b;
806   stmtblock_t block, cond_block;
807 
808   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
809 	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
810 
811   /* Privatize pointer, only; cf. gfc_omp_predetermined_sharing. */
812   if (DECL_P (OMP_CLAUSE_DECL (clause))
813       && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
814     return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
815 
816   if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
817       && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
818       && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
819     decl_type
820       = TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
821 
822   if (gfc_is_polymorphic_nonptr (decl_type))
823     {
824       if (POINTER_TYPE_P (decl_type))
825 	decl_type = TREE_TYPE (decl_type);
826       decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
827       if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
828 	fatal_error (input_location,
829 		     "Sorry, polymorphic arrays not yet supported for "
830 		     "firstprivate");
831       tree src_len;
832       tree nelems = build_int_cst (size_type_node, 1);  /* Scalar.  */
833       tree src_data = gfc_class_data_get (unshare_expr (src));
834       tree dest_data = gfc_class_data_get (unshare_expr (dest));
835       bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type);
836 
837       gfc_start_block (&block);
838       gfc_add_modify (&block, gfc_class_vptr_get (dest),
839 		      gfc_class_vptr_get (src));
840       gfc_init_block (&cond_block);
841 
842       if (unlimited)
843 	{
844 	  src_len = gfc_class_len_get (src);
845 	  gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len);
846 	}
847 
848       /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1).  */
849       size = fold_convert (size_type_node, gfc_class_vtab_size_get (src));
850       if (unlimited)
851 	{
852 	  cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
853 				  unshare_expr (src_len),
854 				  build_zero_cst (TREE_TYPE (src_len)));
855 	  cond = build3_loc (input_location, COND_EXPR, size_type_node, cond,
856 			     fold_convert (size_type_node,
857 					   unshare_expr (src_len)),
858 			     build_int_cst (size_type_node, 1));
859 	  size = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
860 				  size, cond);
861 	}
862 
863       /* Malloc memory + call class->_vpt->_copy.  */
864       call = builtin_decl_explicit (BUILT_IN_MALLOC);
865       call = build_call_expr_loc (input_location, call, 1, size);
866       gfc_add_modify (&cond_block, dest_data,
867 		      fold_convert (TREE_TYPE (dest_data), call));
868       gfc_add_expr_to_block (&cond_block,
869 			     gfc_copy_class_to_class (src, dest, nelems,
870 						      unlimited));
871 
872       gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF);
873       if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1)))
874 	{
875 	  gfc_add_block_to_block (&block, &cond_block);
876 	}
877       else
878 	{
879 	  /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */
880 	  cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
881 				  src_data, null_pointer_node);
882 	  gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
883 				 void_type_node, cond,
884 				 gfc_finish_block (&cond_block),
885 				 fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
886 				 unshare_expr (dest_data), null_pointer_node)));
887 	}
888       return gfc_finish_block (&block);
889     }
890 
891   if ((! GFC_DESCRIPTOR_TYPE_P (type)
892        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
893       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
894 	  || !POINTER_TYPE_P (type)))
895     {
896       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
897 	{
898 	  gfc_start_block (&block);
899 	  gfc_add_modify (&block, dest, src);
900 	  tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
901 					   WALK_ALLOC_COMPS_COPY_CTOR);
902 	  gfc_add_expr_to_block (&block, tem);
903 	  return gfc_finish_block (&block);
904 	}
905       else
906 	return build2_v (MODIFY_EXPR, dest, src);
907     }
908 
909   /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
910      and copied from SRC.  */
911   gfc_start_block (&block);
912 
913   gfc_init_block (&cond_block);
914 
915   gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src));
916   if (GFC_DESCRIPTOR_TYPE_P (type))
917     {
918       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
919       size = gfc_conv_descriptor_ubound_get (dest, rank);
920       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
921 			      size,
922 			      gfc_conv_descriptor_lbound_get (dest, rank));
923       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
924 			      size, gfc_index_one_node);
925       if (GFC_TYPE_ARRAY_RANK (type) > 1)
926 	size = fold_build2_loc (input_location, MULT_EXPR,
927 				gfc_array_index_type, size,
928 				gfc_conv_descriptor_stride_get (dest, rank));
929       tree esize = fold_convert (gfc_array_index_type,
930 				 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
931       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
932 			      size, esize);
933       size = unshare_expr (size);
934       size = gfc_evaluate_now (fold_convert (size_type_node, size),
935 			       &cond_block);
936     }
937   else
938     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
939   ptr = gfc_create_var (pvoid_type_node, NULL);
940   gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
941   if (GFC_DESCRIPTOR_TYPE_P (type))
942     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
943   else
944     gfc_add_modify (&cond_block, unshare_expr (dest),
945 		    fold_convert (TREE_TYPE (dest), ptr));
946 
947   tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
948 		? gfc_conv_descriptor_data_get (src) : src;
949   srcptr = unshare_expr (srcptr);
950   srcptr = fold_convert (pvoid_type_node, srcptr);
951   call = build_call_expr_loc (input_location,
952 			      builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
953 			      srcptr, size);
954   gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
955   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
956     {
957       tree tem = gfc_walk_alloc_comps (src, dest,
958 				       OMP_CLAUSE_DECL (clause),
959 				       WALK_ALLOC_COMPS_COPY_CTOR);
960       gfc_add_expr_to_block (&cond_block, tem);
961     }
962   then_b = gfc_finish_block (&cond_block);
963 
964   gfc_init_block (&cond_block);
965   if (GFC_DESCRIPTOR_TYPE_P (type))
966     gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
967 				  null_pointer_node);
968   else
969     gfc_add_modify (&cond_block, unshare_expr (dest),
970 		    build_zero_cst (TREE_TYPE (dest)));
971   else_b = gfc_finish_block (&cond_block);
972 
973   cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
974 			  unshare_expr (srcptr), null_pointer_node);
975   gfc_add_expr_to_block (&block,
976 			 build3_loc (input_location, COND_EXPR,
977 				     void_type_node, cond, then_b, else_b));
978   /* Avoid -W*uninitialized warnings.  */
979   if (DECL_P (dest))
980     suppress_warning (dest, OPT_Wuninitialized);
981 
982   return gfc_finish_block (&block);
983 }
984 
985 /* Similarly, except use an intrinsic or pointer assignment operator
986    instead.  */
987 
988 tree
gfc_omp_clause_assign_op(tree clause,tree dest,tree src)989 gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
990 {
991   tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
992   tree cond, then_b, else_b;
993   stmtblock_t block, cond_block, cond_block2, inner_block;
994 
995   if ((! GFC_DESCRIPTOR_TYPE_P (type)
996        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
997       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
998 	  || !POINTER_TYPE_P (type)))
999     {
1000       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1001 	{
1002 	  gfc_start_block (&block);
1003 	  /* First dealloc any allocatable components in DEST.  */
1004 	  tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
1005 					   OMP_CLAUSE_DECL (clause),
1006 					   WALK_ALLOC_COMPS_DTOR);
1007 	  gfc_add_expr_to_block (&block, tem);
1008 	  /* Then copy over toplevel data.  */
1009 	  gfc_add_modify (&block, dest, src);
1010 	  /* Finally allocate any allocatable components and copy.  */
1011 	  tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
1012 					   WALK_ALLOC_COMPS_COPY_CTOR);
1013 	  gfc_add_expr_to_block (&block, tem);
1014 	  return gfc_finish_block (&block);
1015 	}
1016       else
1017 	return build2_v (MODIFY_EXPR, dest, src);
1018     }
1019 
1020   gfc_start_block (&block);
1021 
1022   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1023     {
1024       then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
1025 				     WALK_ALLOC_COMPS_DTOR);
1026       tree tem = fold_convert (pvoid_type_node,
1027 			       GFC_DESCRIPTOR_TYPE_P (type)
1028 			       ? gfc_conv_descriptor_data_get (dest) : dest);
1029       tem = unshare_expr (tem);
1030       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1031 			      tem, null_pointer_node);
1032       tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1033 			then_b, build_empty_stmt (input_location));
1034       gfc_add_expr_to_block (&block, tem);
1035     }
1036 
1037   gfc_init_block (&cond_block);
1038 
1039   if (GFC_DESCRIPTOR_TYPE_P (type))
1040     {
1041       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1042       size = gfc_conv_descriptor_ubound_get (src, rank);
1043       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1044 			      size,
1045 			      gfc_conv_descriptor_lbound_get (src, rank));
1046       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1047 			      size, gfc_index_one_node);
1048       if (GFC_TYPE_ARRAY_RANK (type) > 1)
1049 	size = fold_build2_loc (input_location, MULT_EXPR,
1050 				gfc_array_index_type, size,
1051 				gfc_conv_descriptor_stride_get (src, rank));
1052       tree esize = fold_convert (gfc_array_index_type,
1053 				 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1054       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1055 			      size, esize);
1056       size = unshare_expr (size);
1057       size = gfc_evaluate_now (fold_convert (size_type_node, size),
1058 			       &cond_block);
1059     }
1060   else
1061     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1062   ptr = gfc_create_var (pvoid_type_node, NULL);
1063 
1064   tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
1065 		 ? gfc_conv_descriptor_data_get (dest) : dest;
1066   destptr = unshare_expr (destptr);
1067   destptr = fold_convert (pvoid_type_node, destptr);
1068   gfc_add_modify (&cond_block, ptr, destptr);
1069 
1070   nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
1071 			      destptr, null_pointer_node);
1072   cond = nonalloc;
1073   if (GFC_DESCRIPTOR_TYPE_P (type))
1074     {
1075       int i;
1076       for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
1077 	{
1078 	  tree rank = gfc_rank_cst[i];
1079 	  tree tem = gfc_conv_descriptor_ubound_get (src, rank);
1080 	  tem = fold_build2_loc (input_location, MINUS_EXPR,
1081 				 gfc_array_index_type, tem,
1082 				 gfc_conv_descriptor_lbound_get (src, rank));
1083 	  tem = fold_build2_loc (input_location, PLUS_EXPR,
1084 				 gfc_array_index_type, tem,
1085 				 gfc_conv_descriptor_lbound_get (dest, rank));
1086 	  tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1087 				 tem, gfc_conv_descriptor_ubound_get (dest,
1088 								      rank));
1089 	  cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
1090 				  logical_type_node, cond, tem);
1091 	}
1092     }
1093 
1094   gfc_init_block (&cond_block2);
1095 
1096   if (GFC_DESCRIPTOR_TYPE_P (type))
1097     {
1098       gfc_init_block (&inner_block);
1099       gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
1100       then_b = gfc_finish_block (&inner_block);
1101 
1102       gfc_init_block (&inner_block);
1103       gfc_add_modify (&inner_block, ptr,
1104 		      gfc_call_realloc (&inner_block, ptr, size));
1105       else_b = gfc_finish_block (&inner_block);
1106 
1107       gfc_add_expr_to_block (&cond_block2,
1108 			     build3_loc (input_location, COND_EXPR,
1109 					 void_type_node,
1110 					 unshare_expr (nonalloc),
1111 					 then_b, else_b));
1112       gfc_add_modify (&cond_block2, dest, src);
1113       gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
1114     }
1115   else
1116     {
1117       gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
1118       gfc_add_modify (&cond_block2, unshare_expr (dest),
1119 		      fold_convert (type, ptr));
1120     }
1121   then_b = gfc_finish_block (&cond_block2);
1122   else_b = build_empty_stmt (input_location);
1123 
1124   gfc_add_expr_to_block (&cond_block,
1125 			 build3_loc (input_location, COND_EXPR,
1126 				     void_type_node, unshare_expr (cond),
1127 				     then_b, else_b));
1128 
1129   tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
1130 		? gfc_conv_descriptor_data_get (src) : src;
1131   srcptr = unshare_expr (srcptr);
1132   srcptr = fold_convert (pvoid_type_node, srcptr);
1133   call = build_call_expr_loc (input_location,
1134 			      builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
1135 			      srcptr, size);
1136   gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1137   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1138     {
1139       tree tem = gfc_walk_alloc_comps (src, dest,
1140 				       OMP_CLAUSE_DECL (clause),
1141 				       WALK_ALLOC_COMPS_COPY_CTOR);
1142       gfc_add_expr_to_block (&cond_block, tem);
1143     }
1144   then_b = gfc_finish_block (&cond_block);
1145 
1146   if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
1147     {
1148       gfc_init_block (&cond_block);
1149       if (GFC_DESCRIPTOR_TYPE_P (type))
1150 	{
1151 	  tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
1152 	  tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
1153 					    NULL_TREE, NULL_TREE, true, NULL,
1154 					    GFC_CAF_COARRAY_NOCOARRAY);
1155 	  gfc_add_expr_to_block (&cond_block, tmp);
1156 	}
1157       else
1158 	{
1159 	  destptr = gfc_evaluate_now (destptr, &cond_block);
1160 	  gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
1161 	  gfc_add_modify (&cond_block, unshare_expr (dest),
1162 			  build_zero_cst (TREE_TYPE (dest)));
1163 	}
1164       else_b = gfc_finish_block (&cond_block);
1165 
1166       cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1167 			      unshare_expr (srcptr), null_pointer_node);
1168       gfc_add_expr_to_block (&block,
1169 			     build3_loc (input_location, COND_EXPR,
1170 					 void_type_node, cond,
1171 					 then_b, else_b));
1172     }
1173   else
1174     gfc_add_expr_to_block (&block, then_b);
1175 
1176   return gfc_finish_block (&block);
1177 }
1178 
1179 static void
gfc_omp_linear_clause_add_loop(stmtblock_t * block,tree dest,tree src,tree add,tree nelems)1180 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
1181 				tree add, tree nelems)
1182 {
1183   stmtblock_t tmpblock;
1184   tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
1185   nelems = gfc_evaluate_now (nelems, block);
1186 
1187   gfc_init_block (&tmpblock);
1188   if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
1189     {
1190       desta = gfc_build_array_ref (dest, index, NULL);
1191       srca = gfc_build_array_ref (src, index, NULL);
1192     }
1193   else
1194     {
1195       gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1196       tree idx = fold_build2 (MULT_EXPR, sizetype,
1197 			      fold_convert (sizetype, index),
1198 			      TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1199       desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1200 						    TREE_TYPE (dest), dest,
1201 						    idx));
1202       srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1203 						   TREE_TYPE (src), src,
1204 						    idx));
1205     }
1206   gfc_add_modify (&tmpblock, desta,
1207 		  fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1208 			       srca, add));
1209 
1210   gfc_loopinfo loop;
1211   gfc_init_loopinfo (&loop);
1212   loop.dimen = 1;
1213   loop.from[0] = gfc_index_zero_node;
1214   loop.loopvar[0] = index;
1215   loop.to[0] = nelems;
1216   gfc_trans_scalarizing_loops (&loop, &tmpblock);
1217   gfc_add_block_to_block (block, &loop.pre);
1218 }
1219 
1220 /* Build and return code for a constructor of DEST that initializes
1221    it to SRC plus ADD (ADD is scalar integer).  */
1222 
1223 tree
gfc_omp_clause_linear_ctor(tree clause,tree dest,tree src,tree add)1224 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1225 {
1226   tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1227   stmtblock_t block;
1228 
1229   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1230 
1231   gfc_start_block (&block);
1232   add = gfc_evaluate_now (add, &block);
1233 
1234   if ((! GFC_DESCRIPTOR_TYPE_P (type)
1235        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1236       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1237 	  || !POINTER_TYPE_P (type)))
1238     {
1239       bool compute_nelts = false;
1240       gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1241       if (!TYPE_DOMAIN (type)
1242 	  || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1243 	  || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1244 	  || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1245 	compute_nelts = true;
1246       else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1247 	{
1248 	  tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1249 	  if (lookup_attribute ("omp dummy var", a))
1250 	    compute_nelts = true;
1251 	}
1252       if (compute_nelts)
1253 	{
1254 	  nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1255 				TYPE_SIZE_UNIT (type),
1256 				TYPE_SIZE_UNIT (TREE_TYPE (type)));
1257 	  nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1258 	}
1259       else
1260 	nelems = array_type_nelts (type);
1261       nelems = fold_convert (gfc_array_index_type, nelems);
1262 
1263       gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1264       return gfc_finish_block (&block);
1265     }
1266 
1267   /* Allocatable arrays in LINEAR clauses need to be allocated
1268      and copied from SRC.  */
1269   gfc_add_modify (&block, dest, src);
1270   if (GFC_DESCRIPTOR_TYPE_P (type))
1271     {
1272       tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1273       size = gfc_conv_descriptor_ubound_get (dest, rank);
1274       size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1275 			      size,
1276 			      gfc_conv_descriptor_lbound_get (dest, rank));
1277       size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1278 			      size, gfc_index_one_node);
1279       if (GFC_TYPE_ARRAY_RANK (type) > 1)
1280 	size = fold_build2_loc (input_location, MULT_EXPR,
1281 				gfc_array_index_type, size,
1282 				gfc_conv_descriptor_stride_get (dest, rank));
1283       tree esize = fold_convert (gfc_array_index_type,
1284 				 TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1285       nelems = gfc_evaluate_now (unshare_expr (size), &block);
1286       size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1287 			      nelems, unshare_expr (esize));
1288       size = gfc_evaluate_now (fold_convert (size_type_node, size),
1289 			       &block);
1290       nelems = fold_build2_loc (input_location, MINUS_EXPR,
1291 				gfc_array_index_type, nelems,
1292 				gfc_index_one_node);
1293     }
1294   else
1295     size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1296   ptr = gfc_create_var (pvoid_type_node, NULL);
1297   gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1298   if (GFC_DESCRIPTOR_TYPE_P (type))
1299     {
1300       gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1301       tree etype = gfc_get_element_type (type);
1302       ptr = fold_convert (build_pointer_type (etype), ptr);
1303       tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1304       srcptr = fold_convert (build_pointer_type (etype), srcptr);
1305       gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1306     }
1307   else
1308     {
1309       gfc_add_modify (&block, unshare_expr (dest),
1310 		      fold_convert (TREE_TYPE (dest), ptr));
1311       ptr = fold_convert (TREE_TYPE (dest), ptr);
1312       tree dstm = build_fold_indirect_ref (ptr);
1313       tree srcm = build_fold_indirect_ref (unshare_expr (src));
1314       gfc_add_modify (&block, dstm,
1315 		      fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1316     }
1317   return gfc_finish_block (&block);
1318 }
1319 
1320 /* Build and return code destructing DECL.  Return NULL if nothing
1321    to be done.  */
1322 
1323 tree
gfc_omp_clause_dtor(tree clause,tree decl)1324 gfc_omp_clause_dtor (tree clause, tree decl)
1325 {
1326   tree type = TREE_TYPE (decl), tem;
1327   tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause));
1328 
1329   /* Only pointer was privatized; cf. gfc_omp_clause_copy_ctor. */
1330   if (DECL_P (OMP_CLAUSE_DECL (clause))
1331       && GFC_DECL_ASSOCIATE_VAR_P (OMP_CLAUSE_DECL (clause)))
1332     return NULL_TREE;
1333 
1334   if (DECL_ARTIFICIAL (OMP_CLAUSE_DECL (clause))
1335       && DECL_LANG_SPECIFIC (OMP_CLAUSE_DECL (clause))
1336       && GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)))
1337     decl_type
1338 	= TREE_TYPE (GFC_DECL_SAVED_DESCRIPTOR (OMP_CLAUSE_DECL (clause)));
1339   if (gfc_is_polymorphic_nonptr (decl_type))
1340     {
1341       if (POINTER_TYPE_P (decl_type))
1342 	decl_type = TREE_TYPE (decl_type);
1343       decl_type = TREE_TYPE (TYPE_FIELDS (decl_type));
1344       if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type))
1345 	fatal_error (input_location,
1346 		     "Sorry, polymorphic arrays not yet supported for "
1347 		     "firstprivate");
1348       stmtblock_t block, cond_block;
1349       gfc_start_block (&block);
1350       gfc_init_block (&cond_block);
1351       tree final = gfc_class_vtab_final_get (decl);
1352       tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl));
1353       gfc_se se;
1354       gfc_init_se (&se, NULL);
1355       symbol_attribute attr = {};
1356       tree data = gfc_class_data_get (decl);
1357       tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr);
1358 
1359       /* Call class->_vpt->_finalize + free.  */
1360       tree call = build_fold_indirect_ref (final);
1361       call = build_call_expr_loc (input_location, call, 3,
1362 				  gfc_build_addr_expr (NULL, desc),
1363 				  size, boolean_false_node);
1364       gfc_add_block_to_block (&cond_block, &se.pre);
1365       gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
1366       gfc_add_block_to_block (&cond_block, &se.post);
1367       /* Create: if (_vtab && _final) <cond_block>  */
1368       tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1369 				   gfc_class_vptr_get (decl),
1370 				   null_pointer_node);
1371       tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1372 				   final, null_pointer_node);
1373       cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1374 			      boolean_type_node, cond, cond2);
1375       gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1376 				 void_type_node, cond,
1377 				 gfc_finish_block (&cond_block), NULL_TREE));
1378       call = builtin_decl_explicit (BUILT_IN_FREE);
1379       call = build_call_expr_loc (input_location, call, 1, data);
1380       gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
1381       return gfc_finish_block (&block);
1382     }
1383 
1384   if ((! GFC_DESCRIPTOR_TYPE_P (type)
1385        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1386       && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1387 	  || !POINTER_TYPE_P (type)))
1388     {
1389       if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1390 	return gfc_walk_alloc_comps (decl, NULL_TREE,
1391 				     OMP_CLAUSE_DECL (clause),
1392 				     WALK_ALLOC_COMPS_DTOR);
1393       return NULL_TREE;
1394     }
1395 
1396   if (GFC_DESCRIPTOR_TYPE_P (type))
1397     {
1398       /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1399 	 to be deallocated if they were allocated.  */
1400       tem = gfc_conv_descriptor_data_get (decl);
1401       tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1402 					NULL_TREE, true, NULL,
1403 					GFC_CAF_COARRAY_NOCOARRAY);
1404     }
1405   else
1406     tem = gfc_call_free (decl);
1407   tem = gfc_omp_unshare_expr (tem);
1408 
1409   if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1410     {
1411       stmtblock_t block;
1412       tree then_b;
1413 
1414       gfc_init_block (&block);
1415       gfc_add_expr_to_block (&block,
1416 			     gfc_walk_alloc_comps (decl, NULL_TREE,
1417 						   OMP_CLAUSE_DECL (clause),
1418 						   WALK_ALLOC_COMPS_DTOR));
1419       gfc_add_expr_to_block (&block, tem);
1420       then_b = gfc_finish_block (&block);
1421 
1422       tem = fold_convert (pvoid_type_node,
1423 			  GFC_DESCRIPTOR_TYPE_P (type)
1424 			  ? gfc_conv_descriptor_data_get (decl) : decl);
1425       tem = unshare_expr (tem);
1426       tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1427 				   tem, null_pointer_node);
1428       tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1429 			then_b, build_empty_stmt (input_location));
1430     }
1431   return tem;
1432 }
1433 
1434 /* Build a conditional expression in BLOCK.  If COND_VAL is not
1435    null, then the block THEN_B is executed, otherwise ELSE_VAL
1436    is assigned to VAL.  */
1437 
1438 static void
gfc_build_cond_assign(stmtblock_t * block,tree val,tree cond_val,tree then_b,tree else_val)1439 gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1440 		       tree then_b, tree else_val)
1441 {
1442   stmtblock_t cond_block;
1443   tree else_b = NULL_TREE;
1444   tree val_ty = TREE_TYPE (val);
1445 
1446   if (else_val)
1447     {
1448       gfc_init_block (&cond_block);
1449       gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1450       else_b = gfc_finish_block (&cond_block);
1451     }
1452   gfc_add_expr_to_block (block,
1453 			 build3_loc (input_location, COND_EXPR, void_type_node,
1454 				     cond_val, then_b, else_b));
1455 }
1456 
1457 /* Build a conditional expression in BLOCK, returning a temporary
1458    variable containing the result.  If COND_VAL is not null, then
1459    THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1460    is assigned.
1461  */
1462 
1463 static tree
gfc_build_cond_assign_expr(stmtblock_t * block,tree cond_val,tree then_val,tree else_val)1464 gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1465 			    tree then_val, tree else_val)
1466 {
1467   tree val;
1468   tree val_ty = TREE_TYPE (then_val);
1469   stmtblock_t cond_block;
1470 
1471   val = create_tmp_var (val_ty);
1472 
1473   gfc_init_block (&cond_block);
1474   gfc_add_modify (&cond_block, val, then_val);
1475   tree then_b = gfc_finish_block (&cond_block);
1476 
1477   gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1478 
1479   return val;
1480 }
1481 
1482 void
gfc_omp_finish_clause(tree c,gimple_seq * pre_p,bool openacc)1483 gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc)
1484 {
1485   if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1486     return;
1487 
1488   tree decl = OMP_CLAUSE_DECL (c);
1489 
1490   /* Assumed-size arrays can't be mapped implicitly, they have to be
1491      mapped explicitly using array sections.  */
1492   if (TREE_CODE (decl) == PARM_DECL
1493       && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1494       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1495       && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1496 				GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1497 	 == NULL)
1498     {
1499       error_at (OMP_CLAUSE_LOCATION (c),
1500 		"implicit mapping of assumed size array %qD", decl);
1501       return;
1502     }
1503 
1504   tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1505   tree present = gfc_omp_check_optional_argument (decl, true);
1506   if (POINTER_TYPE_P (TREE_TYPE (decl)))
1507     {
1508       if (!gfc_omp_privatize_by_reference (decl)
1509 	  && !GFC_DECL_GET_SCALAR_POINTER (decl)
1510 	  && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1511 	  && !GFC_DECL_CRAY_POINTEE (decl)
1512 	  && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1513 	return;
1514       tree orig_decl = decl;
1515 
1516       c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1517       OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1518       OMP_CLAUSE_DECL (c4) = decl;
1519       OMP_CLAUSE_SIZE (c4) = size_int (0);
1520       decl = build_fold_indirect_ref (decl);
1521       if (present
1522 	  && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1523 	      || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1524 	{
1525 	  c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1526 	  OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1527 	  OMP_CLAUSE_DECL (c2) = decl;
1528 	  OMP_CLAUSE_SIZE (c2) = size_int (0);
1529 
1530 	  stmtblock_t block;
1531 	  gfc_start_block (&block);
1532 	  tree ptr = decl;
1533 	  ptr = gfc_build_cond_assign_expr (&block, present, decl,
1534 					    null_pointer_node);
1535 	  gimplify_and_add (gfc_finish_block (&block), pre_p);
1536 	  ptr = build_fold_indirect_ref (ptr);
1537 	  OMP_CLAUSE_DECL (c) = ptr;
1538 	  OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1539 	}
1540       else
1541 	{
1542 	  OMP_CLAUSE_DECL (c) = decl;
1543 	  OMP_CLAUSE_SIZE (c) = NULL_TREE;
1544 	}
1545       if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1546 	  && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1547 	      || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1548 	{
1549 	  c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1550 	  OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1551 	  OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1552 	  OMP_CLAUSE_SIZE (c3) = size_int (0);
1553 	  decl = build_fold_indirect_ref (decl);
1554 	  OMP_CLAUSE_DECL (c) = decl;
1555 	}
1556     }
1557   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1558     {
1559       stmtblock_t block;
1560       gfc_start_block (&block);
1561       tree type = TREE_TYPE (decl);
1562       tree ptr = gfc_conv_descriptor_data_get (decl);
1563 
1564       /* OpenMP: automatically map pointer targets with the pointer;
1565 	 hence, always update the descriptor/pointer itself.
1566 	 NOTE: This also remaps the pointer for allocatable arrays with
1567 	 'target' attribute which also don't have the 'restrict' qualifier.  */
1568       bool always_modifier = false;
1569 
1570       if (!openacc
1571 	  && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT))
1572 	always_modifier = true;
1573 
1574       if (present)
1575 	ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1576 					  null_pointer_node);
1577       gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
1578       ptr = build_fold_indirect_ref (ptr);
1579       OMP_CLAUSE_DECL (c) = ptr;
1580       c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1581       OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1582       if (present)
1583 	{
1584 	  ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1585 	  gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1586 
1587 	  OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1588 	}
1589       else
1590 	OMP_CLAUSE_DECL (c2) = decl;
1591       OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1592       c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1593       OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER
1594 						   : GOMP_MAP_POINTER);
1595       if (present)
1596 	{
1597 	  ptr = gfc_conv_descriptor_data_get (decl);
1598 	  ptr = gfc_build_addr_expr (NULL, ptr);
1599 	  ptr = gfc_build_cond_assign_expr (&block, present,
1600 					    ptr, null_pointer_node);
1601 	  ptr = build_fold_indirect_ref (ptr);
1602 	  OMP_CLAUSE_DECL (c3) = ptr;
1603 	}
1604       else
1605 	OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1606       OMP_CLAUSE_SIZE (c3) = size_int (0);
1607       tree size = create_tmp_var (gfc_array_index_type);
1608       tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1609       elemsz = fold_convert (gfc_array_index_type, elemsz);
1610       if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
1611 	  || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1612 	  || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1613 	{
1614 	  stmtblock_t cond_block;
1615 	  tree tem, then_b, else_b, zero, cond;
1616 
1617 	  gfc_init_block (&cond_block);
1618 	  tem = gfc_full_array_size (&cond_block, decl,
1619 				     GFC_TYPE_ARRAY_RANK (type));
1620 	  gfc_add_modify (&cond_block, size, tem);
1621 	  gfc_add_modify (&cond_block, size,
1622 			  fold_build2 (MULT_EXPR, gfc_array_index_type,
1623 				       size, elemsz));
1624 	  then_b = gfc_finish_block (&cond_block);
1625 	  gfc_init_block (&cond_block);
1626 	  zero = build_int_cst (gfc_array_index_type, 0);
1627 	  gfc_add_modify (&cond_block, size, zero);
1628 	  else_b = gfc_finish_block (&cond_block);
1629 	  tem = gfc_conv_descriptor_data_get (decl);
1630 	  tem = fold_convert (pvoid_type_node, tem);
1631 	  cond = fold_build2_loc (input_location, NE_EXPR,
1632 				  boolean_type_node, tem, null_pointer_node);
1633 	  if (present)
1634 	    {
1635 	      cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1636 				      boolean_type_node, present, cond);
1637 	    }
1638 	  gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1639 						     void_type_node, cond,
1640 						     then_b, else_b));
1641 	}
1642       else if (present)
1643 	{
1644 	  stmtblock_t cond_block;
1645 	  tree then_b;
1646 
1647 	  gfc_init_block (&cond_block);
1648 	  gfc_add_modify (&cond_block, size,
1649 			  gfc_full_array_size (&cond_block, decl,
1650 					       GFC_TYPE_ARRAY_RANK (type)));
1651 	  gfc_add_modify (&cond_block, size,
1652 			  fold_build2 (MULT_EXPR, gfc_array_index_type,
1653 				       size, elemsz));
1654 	  then_b = gfc_finish_block (&cond_block);
1655 
1656 	  gfc_build_cond_assign (&block, size, present, then_b,
1657 				 build_int_cst (gfc_array_index_type, 0));
1658 	}
1659       else
1660 	{
1661 	  gfc_add_modify (&block, size,
1662 			  gfc_full_array_size (&block, decl,
1663 					       GFC_TYPE_ARRAY_RANK (type)));
1664 	  gfc_add_modify (&block, size,
1665 			  fold_build2 (MULT_EXPR, gfc_array_index_type,
1666 				       size, elemsz));
1667 	}
1668       OMP_CLAUSE_SIZE (c) = size;
1669       tree stmt = gfc_finish_block (&block);
1670       gimplify_and_add (stmt, pre_p);
1671     }
1672   tree last = c;
1673   if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1674     OMP_CLAUSE_SIZE (c)
1675       = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1676 		      : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1677   if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
1678 		     NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
1679     OMP_CLAUSE_SIZE (c) = size_int (0);
1680   if (c2)
1681     {
1682       OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1683       OMP_CLAUSE_CHAIN (last) = c2;
1684       last = c2;
1685     }
1686   if (c3)
1687     {
1688       OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1689       OMP_CLAUSE_CHAIN (last) = c3;
1690       last = c3;
1691     }
1692   if (c4)
1693     {
1694       OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1695       OMP_CLAUSE_CHAIN (last) = c4;
1696     }
1697 }
1698 
1699 
1700 /* Return true if DECL is a scalar variable (for the purpose of
1701    implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.'
1702    is true, allocatables and pointers are permitted. */
1703 
1704 bool
gfc_omp_scalar_p(tree decl,bool ptr_alloc_ok)1705 gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok)
1706 {
1707   tree type = TREE_TYPE (decl);
1708   if (TREE_CODE (type) == REFERENCE_TYPE)
1709     type = TREE_TYPE (type);
1710   if (TREE_CODE (type) == POINTER_TYPE)
1711     {
1712       if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1713 	  || GFC_DECL_GET_SCALAR_POINTER (decl))
1714 	{
1715 	  if (!ptr_alloc_ok)
1716 	    return false;
1717 	  type = TREE_TYPE (type);
1718 	}
1719       if (GFC_ARRAY_TYPE_P (type)
1720 	  || GFC_CLASS_TYPE_P (type))
1721 	return false;
1722     }
1723   if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
1724       && TYPE_STRING_FLAG (type))
1725     return false;
1726   if (INTEGRAL_TYPE_P (type)
1727       || SCALAR_FLOAT_TYPE_P (type)
1728       || COMPLEX_FLOAT_TYPE_P (type))
1729     return true;
1730   return false;
1731 }
1732 
1733 
1734 /* Return true if DECL is a scalar with target attribute but does not have the
1735    allocatable (or pointer) attribute (for the purpose of implicit mapping).  */
1736 
1737 bool
gfc_omp_scalar_target_p(tree decl)1738 gfc_omp_scalar_target_p (tree decl)
1739 {
1740   return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl)
1741 	  && gfc_omp_scalar_p (decl, false));
1742 }
1743 
1744 
1745 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1746    disregarded in OpenMP construct, because it is going to be
1747    remapped during OpenMP lowering.  SHARED is true if DECL
1748    is going to be shared, false if it is going to be privatized.  */
1749 
1750 bool
gfc_omp_disregard_value_expr(tree decl,bool shared)1751 gfc_omp_disregard_value_expr (tree decl, bool shared)
1752 {
1753   if (GFC_DECL_COMMON_OR_EQUIV (decl)
1754       && DECL_HAS_VALUE_EXPR_P (decl))
1755     {
1756       tree value = DECL_VALUE_EXPR (decl);
1757 
1758       if (TREE_CODE (value) == COMPONENT_REF
1759 	  && VAR_P (TREE_OPERAND (value, 0))
1760 	  && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1761 	{
1762 	  /* If variable in COMMON or EQUIVALENCE is privatized, return
1763 	     true, as just that variable is supposed to be privatized,
1764 	     not the whole COMMON or whole EQUIVALENCE.
1765 	     For shared variables in COMMON or EQUIVALENCE, let them be
1766 	     gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1767 	     from the same COMMON or EQUIVALENCE just one sharing of the
1768 	     whole COMMON or EQUIVALENCE is enough.  */
1769 	  return ! shared;
1770 	}
1771     }
1772 
1773   if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1774     return ! shared;
1775 
1776   return false;
1777 }
1778 
1779 /* Return true if DECL that is shared iff SHARED is true should
1780    be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1781    flag set.  */
1782 
1783 bool
gfc_omp_private_debug_clause(tree decl,bool shared)1784 gfc_omp_private_debug_clause (tree decl, bool shared)
1785 {
1786   if (GFC_DECL_CRAY_POINTEE (decl))
1787     return true;
1788 
1789   if (GFC_DECL_COMMON_OR_EQUIV (decl)
1790       && DECL_HAS_VALUE_EXPR_P (decl))
1791     {
1792       tree value = DECL_VALUE_EXPR (decl);
1793 
1794       if (TREE_CODE (value) == COMPONENT_REF
1795 	  && VAR_P (TREE_OPERAND (value, 0))
1796 	  && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1797 	return shared;
1798     }
1799 
1800   return false;
1801 }
1802 
1803 /* Register language specific type size variables as potentially OpenMP
1804    firstprivate variables.  */
1805 
1806 void
gfc_omp_firstprivatize_type_sizes(struct gimplify_omp_ctx * ctx,tree type)1807 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1808 {
1809   if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1810     {
1811       int r;
1812 
1813       gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1814       for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1815 	{
1816 	  omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1817 	  omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1818 	  omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1819 	}
1820       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1821       omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1822     }
1823 }
1824 
1825 
1826 static inline tree
gfc_trans_add_clause(tree node,tree tail)1827 gfc_trans_add_clause (tree node, tree tail)
1828 {
1829   OMP_CLAUSE_CHAIN (node) = tail;
1830   return node;
1831 }
1832 
1833 static tree
gfc_trans_omp_variable(gfc_symbol * sym,bool declare_simd)1834 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1835 {
1836   if (declare_simd)
1837     {
1838       int cnt = 0;
1839       gfc_symbol *proc_sym;
1840       gfc_formal_arglist *f;
1841 
1842       gcc_assert (sym->attr.dummy);
1843       proc_sym = sym->ns->proc_name;
1844       if (proc_sym->attr.entry_master)
1845 	++cnt;
1846       if (gfc_return_by_reference (proc_sym))
1847 	{
1848 	  ++cnt;
1849 	  if (proc_sym->ts.type == BT_CHARACTER)
1850 	    ++cnt;
1851 	}
1852       for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1853 	if (f->sym == sym)
1854 	  break;
1855 	else if (f->sym)
1856 	  ++cnt;
1857       gcc_assert (f);
1858       return build_int_cst (integer_type_node, cnt);
1859     }
1860 
1861   tree t = gfc_get_symbol_decl (sym);
1862   tree parent_decl;
1863   int parent_flag;
1864   bool return_value;
1865   bool alternate_entry;
1866   bool entry_master;
1867 
1868   return_value = sym->attr.function && sym->result == sym;
1869   alternate_entry = sym->attr.function && sym->attr.entry
1870 		    && sym->result == sym;
1871   entry_master = sym->attr.result
1872 		 && sym->ns->proc_name->attr.entry_master
1873 		 && !gfc_return_by_reference (sym->ns->proc_name);
1874   parent_decl = current_function_decl
1875 		? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1876 
1877   if ((t == parent_decl && return_value)
1878        || (sym->ns && sym->ns->proc_name
1879 	   && sym->ns->proc_name->backend_decl == parent_decl
1880 	   && (alternate_entry || entry_master)))
1881     parent_flag = 1;
1882   else
1883     parent_flag = 0;
1884 
1885   /* Special case for assigning the return value of a function.
1886      Self recursive functions must have an explicit return value.  */
1887   if (return_value && (t == current_function_decl || parent_flag))
1888     t = gfc_get_fake_result_decl (sym, parent_flag);
1889 
1890   /* Similarly for alternate entry points.  */
1891   else if (alternate_entry
1892 	   && (sym->ns->proc_name->backend_decl == current_function_decl
1893 	       || parent_flag))
1894     {
1895       gfc_entry_list *el = NULL;
1896 
1897       for (el = sym->ns->entries; el; el = el->next)
1898 	if (sym == el->sym)
1899 	  {
1900 	    t = gfc_get_fake_result_decl (sym, parent_flag);
1901 	    break;
1902 	  }
1903     }
1904 
1905   else if (entry_master
1906 	   && (sym->ns->proc_name->backend_decl == current_function_decl
1907 	       || parent_flag))
1908     t = gfc_get_fake_result_decl (sym, parent_flag);
1909 
1910   return t;
1911 }
1912 
1913 static tree
gfc_trans_omp_variable_list(enum omp_clause_code code,gfc_omp_namelist * namelist,tree list,bool declare_simd)1914 gfc_trans_omp_variable_list (enum omp_clause_code code,
1915 			     gfc_omp_namelist *namelist, tree list,
1916 			     bool declare_simd)
1917 {
1918   for (; namelist != NULL; namelist = namelist->next)
1919     if (namelist->sym->attr.referenced || declare_simd)
1920       {
1921 	tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1922 	if (t != error_mark_node)
1923 	  {
1924 	    tree node;
1925 	    /* For HAS_DEVICE_ADDR of an array descriptor, firstprivatize the
1926 	       descriptor such that the bounds are available; its data component
1927 	       is unmodified; it is handled as device address inside target. */
1928 	    if (code == OMP_CLAUSE_HAS_DEVICE_ADDR
1929 		&& (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (t))
1930 		    || (POINTER_TYPE_P (TREE_TYPE (t))
1931 			&& GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (t))))))
1932 	      node = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
1933 	    else
1934 	      node = build_omp_clause (input_location, code);
1935 	    OMP_CLAUSE_DECL (node) = t;
1936 	    list = gfc_trans_add_clause (node, list);
1937 
1938 	    if (code == OMP_CLAUSE_LASTPRIVATE
1939 		&& namelist->u.lastprivate_conditional)
1940 	      OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1;
1941 	  }
1942       }
1943   return list;
1944 }
1945 
1946 struct omp_udr_find_orig_data
1947 {
1948   gfc_omp_udr *omp_udr;
1949   bool omp_orig_seen;
1950 };
1951 
1952 static int
omp_udr_find_orig(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)1953 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1954 		   void *data)
1955 {
1956   struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1957   if ((*e)->expr_type == EXPR_VARIABLE
1958       && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1959     cd->omp_orig_seen = true;
1960 
1961   return 0;
1962 }
1963 
1964 static void
gfc_trans_omp_array_reduction_or_udr(tree c,gfc_omp_namelist * n,locus where)1965 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
1966 {
1967   gfc_symbol *sym = n->sym;
1968   gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1969   gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1970   gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
1971   gfc_symbol omp_var_copy[4];
1972   gfc_expr *e1, *e2, *e3, *e4;
1973   gfc_ref *ref;
1974   tree decl, backend_decl, stmt, type, outer_decl;
1975   locus old_loc = gfc_current_locus;
1976   const char *iname;
1977   bool t;
1978   gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL;
1979 
1980   decl = OMP_CLAUSE_DECL (c);
1981   gfc_current_locus = where;
1982   type = TREE_TYPE (decl);
1983   outer_decl = create_tmp_var_raw (type);
1984   if (TREE_CODE (decl) == PARM_DECL
1985       && TREE_CODE (type) == REFERENCE_TYPE
1986       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1987       && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1988     {
1989       decl = build_fold_indirect_ref (decl);
1990       type = TREE_TYPE (type);
1991     }
1992 
1993   /* Create a fake symbol for init value.  */
1994   memset (&init_val_sym, 0, sizeof (init_val_sym));
1995   init_val_sym.ns = sym->ns;
1996   init_val_sym.name = sym->name;
1997   init_val_sym.ts = sym->ts;
1998   init_val_sym.attr.referenced = 1;
1999   init_val_sym.declared_at = where;
2000   init_val_sym.attr.flavor = FL_VARIABLE;
2001   if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2002     backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
2003   else if (udr->initializer_ns)
2004     backend_decl = NULL;
2005   else
2006     switch (sym->ts.type)
2007       {
2008       case BT_LOGICAL:
2009       case BT_INTEGER:
2010       case BT_REAL:
2011       case BT_COMPLEX:
2012 	backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
2013 	break;
2014       default:
2015 	backend_decl = NULL_TREE;
2016 	break;
2017       }
2018   init_val_sym.backend_decl = backend_decl;
2019 
2020   /* Create a fake symbol for the outer array reference.  */
2021   outer_sym = *sym;
2022   if (sym->as)
2023     outer_sym.as = gfc_copy_array_spec (sym->as);
2024   outer_sym.attr.dummy = 0;
2025   outer_sym.attr.result = 0;
2026   outer_sym.attr.flavor = FL_VARIABLE;
2027   outer_sym.backend_decl = outer_decl;
2028   if (decl != OMP_CLAUSE_DECL (c))
2029     outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
2030 
2031   /* Create fake symtrees for it.  */
2032   symtree1 = gfc_new_symtree (&root1, sym->name);
2033   symtree1->n.sym = sym;
2034   gcc_assert (symtree1 == root1);
2035 
2036   symtree2 = gfc_new_symtree (&root2, sym->name);
2037   symtree2->n.sym = &init_val_sym;
2038   gcc_assert (symtree2 == root2);
2039 
2040   symtree3 = gfc_new_symtree (&root3, sym->name);
2041   symtree3->n.sym = &outer_sym;
2042   gcc_assert (symtree3 == root3);
2043 
2044   memset (omp_var_copy, 0, sizeof omp_var_copy);
2045   if (udr)
2046     {
2047       omp_var_copy[0] = *udr->omp_out;
2048       omp_var_copy[1] = *udr->omp_in;
2049       *udr->omp_out = outer_sym;
2050       *udr->omp_in = *sym;
2051       if (udr->initializer_ns)
2052 	{
2053 	  omp_var_copy[2] = *udr->omp_priv;
2054 	  omp_var_copy[3] = *udr->omp_orig;
2055 	  *udr->omp_priv = *sym;
2056 	  *udr->omp_orig = outer_sym;
2057 	}
2058     }
2059 
2060   /* Create expressions.  */
2061   e1 = gfc_get_expr ();
2062   e1->expr_type = EXPR_VARIABLE;
2063   e1->where = where;
2064   e1->symtree = symtree1;
2065   e1->ts = sym->ts;
2066   if (sym->attr.dimension)
2067     {
2068       e1->ref = ref = gfc_get_ref ();
2069       ref->type = REF_ARRAY;
2070       ref->u.ar.where = where;
2071       ref->u.ar.as = sym->as;
2072       ref->u.ar.type = AR_FULL;
2073       ref->u.ar.dimen = 0;
2074     }
2075   t = gfc_resolve_expr (e1);
2076   gcc_assert (t);
2077 
2078   e2 = NULL;
2079   if (backend_decl != NULL_TREE)
2080     {
2081       e2 = gfc_get_expr ();
2082       e2->expr_type = EXPR_VARIABLE;
2083       e2->where = where;
2084       e2->symtree = symtree2;
2085       e2->ts = sym->ts;
2086       t = gfc_resolve_expr (e2);
2087       gcc_assert (t);
2088     }
2089   else if (udr->initializer_ns == NULL)
2090     {
2091       gcc_assert (sym->ts.type == BT_DERIVED);
2092       e2 = gfc_default_initializer (&sym->ts);
2093       gcc_assert (e2);
2094       t = gfc_resolve_expr (e2);
2095       gcc_assert (t);
2096     }
2097   else if (n->u2.udr->initializer->op == EXEC_ASSIGN)
2098     {
2099       e2 = gfc_copy_expr (n->u2.udr->initializer->expr2);
2100       t = gfc_resolve_expr (e2);
2101       gcc_assert (t);
2102     }
2103   if (udr && udr->initializer_ns)
2104     {
2105       struct omp_udr_find_orig_data cd;
2106       cd.omp_udr = udr;
2107       cd.omp_orig_seen = false;
2108       gfc_code_walker (&n->u2.udr->initializer,
2109 		       gfc_dummy_code_callback, omp_udr_find_orig, &cd);
2110       if (cd.omp_orig_seen)
2111 	OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
2112     }
2113 
2114   e3 = gfc_copy_expr (e1);
2115   e3->symtree = symtree3;
2116   t = gfc_resolve_expr (e3);
2117   gcc_assert (t);
2118 
2119   iname = NULL;
2120   e4 = NULL;
2121   switch (OMP_CLAUSE_REDUCTION_CODE (c))
2122     {
2123     case PLUS_EXPR:
2124     case MINUS_EXPR:
2125       e4 = gfc_add (e3, e1);
2126       break;
2127     case MULT_EXPR:
2128       e4 = gfc_multiply (e3, e1);
2129       break;
2130     case TRUTH_ANDIF_EXPR:
2131       e4 = gfc_and (e3, e1);
2132       break;
2133     case TRUTH_ORIF_EXPR:
2134       e4 = gfc_or (e3, e1);
2135       break;
2136     case EQ_EXPR:
2137       e4 = gfc_eqv (e3, e1);
2138       break;
2139     case NE_EXPR:
2140       e4 = gfc_neqv (e3, e1);
2141       break;
2142     case MIN_EXPR:
2143       iname = "min";
2144       break;
2145     case MAX_EXPR:
2146       iname = "max";
2147       break;
2148     case BIT_AND_EXPR:
2149       iname = "iand";
2150       break;
2151     case BIT_IOR_EXPR:
2152       iname = "ior";
2153       break;
2154     case BIT_XOR_EXPR:
2155       iname = "ieor";
2156       break;
2157     case ERROR_MARK:
2158       if (n->u2.udr->combiner->op == EXEC_ASSIGN)
2159 	{
2160 	  gfc_free_expr (e3);
2161 	  e3 = gfc_copy_expr (n->u2.udr->combiner->expr1);
2162 	  e4 = gfc_copy_expr (n->u2.udr->combiner->expr2);
2163 	  t = gfc_resolve_expr (e3);
2164 	  gcc_assert (t);
2165 	  t = gfc_resolve_expr (e4);
2166 	  gcc_assert (t);
2167 	}
2168       break;
2169     default:
2170       gcc_unreachable ();
2171     }
2172   if (iname != NULL)
2173     {
2174       memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
2175       intrinsic_sym.ns = sym->ns;
2176       intrinsic_sym.name = iname;
2177       intrinsic_sym.ts = sym->ts;
2178       intrinsic_sym.attr.referenced = 1;
2179       intrinsic_sym.attr.intrinsic = 1;
2180       intrinsic_sym.attr.function = 1;
2181       intrinsic_sym.attr.implicit_type = 1;
2182       intrinsic_sym.result = &intrinsic_sym;
2183       intrinsic_sym.declared_at = where;
2184 
2185       symtree4 = gfc_new_symtree (&root4, iname);
2186       symtree4->n.sym = &intrinsic_sym;
2187       gcc_assert (symtree4 == root4);
2188 
2189       e4 = gfc_get_expr ();
2190       e4->expr_type = EXPR_FUNCTION;
2191       e4->where = where;
2192       e4->symtree = symtree4;
2193       e4->value.function.actual = gfc_get_actual_arglist ();
2194       e4->value.function.actual->expr = e3;
2195       e4->value.function.actual->next = gfc_get_actual_arglist ();
2196       e4->value.function.actual->next->expr = e1;
2197     }
2198   if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
2199     {
2200       /* e1 and e3 have been stored as arguments of e4, avoid sharing.  */
2201       e1 = gfc_copy_expr (e1);
2202       e3 = gfc_copy_expr (e3);
2203       t = gfc_resolve_expr (e4);
2204       gcc_assert (t);
2205     }
2206 
2207   /* Create the init statement list.  */
2208   pushlevel ();
2209   if (e2)
2210     stmt = gfc_trans_assignment (e1, e2, false, false);
2211   else
2212     stmt = gfc_trans_call (n->u2.udr->initializer, false,
2213 			   NULL_TREE, NULL_TREE, false);
2214   if (TREE_CODE (stmt) != BIND_EXPR)
2215     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2216   else
2217     poplevel (0, 0);
2218   OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
2219 
2220   /* Create the merge statement list.  */
2221   pushlevel ();
2222   if (e4)
2223     stmt = gfc_trans_assignment (e3, e4, false, true);
2224   else
2225     stmt = gfc_trans_call (n->u2.udr->combiner, false,
2226 			   NULL_TREE, NULL_TREE, false);
2227   if (TREE_CODE (stmt) != BIND_EXPR)
2228     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
2229   else
2230     poplevel (0, 0);
2231   OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
2232 
2233   /* And stick the placeholder VAR_DECL into the clause as well.  */
2234   OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
2235 
2236   gfc_current_locus = old_loc;
2237 
2238   gfc_free_expr (e1);
2239   if (e2)
2240     gfc_free_expr (e2);
2241   gfc_free_expr (e3);
2242   if (e4)
2243     gfc_free_expr (e4);
2244   free (symtree1);
2245   free (symtree2);
2246   free (symtree3);
2247   free (symtree4);
2248   if (outer_sym.as)
2249     gfc_free_array_spec (outer_sym.as);
2250 
2251   if (udr)
2252     {
2253       *udr->omp_out = omp_var_copy[0];
2254       *udr->omp_in = omp_var_copy[1];
2255       if (udr->initializer_ns)
2256 	{
2257 	  *udr->omp_priv = omp_var_copy[2];
2258 	  *udr->omp_orig = omp_var_copy[3];
2259 	}
2260     }
2261 }
2262 
2263 static tree
gfc_trans_omp_reduction_list(int kind,gfc_omp_namelist * namelist,tree list,locus where,bool mark_addressable)2264 gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list,
2265 			      locus where, bool mark_addressable)
2266 {
2267   omp_clause_code clause = OMP_CLAUSE_REDUCTION;
2268   switch (kind)
2269     {
2270     case OMP_LIST_REDUCTION:
2271     case OMP_LIST_REDUCTION_INSCAN:
2272     case OMP_LIST_REDUCTION_TASK:
2273       break;
2274     case OMP_LIST_IN_REDUCTION:
2275       clause = OMP_CLAUSE_IN_REDUCTION;
2276       break;
2277     case OMP_LIST_TASK_REDUCTION:
2278       clause = OMP_CLAUSE_TASK_REDUCTION;
2279       break;
2280     default:
2281       gcc_unreachable ();
2282     }
2283   for (; namelist != NULL; namelist = namelist->next)
2284     if (namelist->sym->attr.referenced)
2285       {
2286 	tree t = gfc_trans_omp_variable (namelist->sym, false);
2287 	if (t != error_mark_node)
2288 	  {
2289 	    tree node = build_omp_clause (gfc_get_location (&namelist->where),
2290 					  clause);
2291 	    OMP_CLAUSE_DECL (node) = t;
2292 	    if (mark_addressable)
2293 	      TREE_ADDRESSABLE (t) = 1;
2294 	    if (kind == OMP_LIST_REDUCTION_INSCAN)
2295 	      OMP_CLAUSE_REDUCTION_INSCAN (node) = 1;
2296 	    if (kind == OMP_LIST_REDUCTION_TASK)
2297 	      OMP_CLAUSE_REDUCTION_TASK (node) = 1;
2298 	    switch (namelist->u.reduction_op)
2299 	      {
2300 	      case OMP_REDUCTION_PLUS:
2301 		OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
2302 		break;
2303 	      case OMP_REDUCTION_MINUS:
2304 		OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
2305 		break;
2306 	      case OMP_REDUCTION_TIMES:
2307 		OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
2308 		break;
2309 	      case OMP_REDUCTION_AND:
2310 		OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
2311 		break;
2312 	      case OMP_REDUCTION_OR:
2313 		OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
2314 		break;
2315 	      case OMP_REDUCTION_EQV:
2316 		OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
2317 		break;
2318 	      case OMP_REDUCTION_NEQV:
2319 		OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
2320 		break;
2321 	      case OMP_REDUCTION_MAX:
2322 		OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
2323 		break;
2324 	      case OMP_REDUCTION_MIN:
2325 		OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
2326 		break;
2327  	      case OMP_REDUCTION_IAND:
2328 		OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
2329 		break;
2330  	      case OMP_REDUCTION_IOR:
2331 		OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
2332 		break;
2333  	      case OMP_REDUCTION_IEOR:
2334 		OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
2335 		break;
2336 	      case OMP_REDUCTION_USER:
2337 		OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
2338 		break;
2339 	      default:
2340 		gcc_unreachable ();
2341 	      }
2342 	    if (namelist->sym->attr.dimension
2343 		|| namelist->u.reduction_op == OMP_REDUCTION_USER
2344 		|| namelist->sym->attr.allocatable)
2345 	      gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
2346 	    list = gfc_trans_add_clause (node, list);
2347 	  }
2348       }
2349   return list;
2350 }
2351 
2352 static inline tree
gfc_convert_expr_to_tree(stmtblock_t * block,gfc_expr * expr)2353 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
2354 {
2355   gfc_se se;
2356   tree result;
2357 
2358   gfc_init_se (&se, NULL );
2359   gfc_conv_expr (&se, expr);
2360   gfc_add_block_to_block (block, &se.pre);
2361   result = gfc_evaluate_now (se.expr, block);
2362   gfc_add_block_to_block (block, &se.post);
2363 
2364   return result;
2365 }
2366 
2367 static vec<tree, va_heap, vl_embed> *doacross_steps;
2368 
2369 
2370 /* Translate an array section or array element.  */
2371 
2372 static void
gfc_trans_omp_array_section(stmtblock_t * block,gfc_omp_namelist * n,tree decl,bool element,gomp_map_kind ptr_kind,tree & node,tree & node2,tree & node3,tree & node4)2373 gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
2374 			     tree decl, bool element, gomp_map_kind ptr_kind,
2375 			     tree &node, tree &node2, tree &node3, tree &node4)
2376 {
2377   gfc_se se;
2378   tree ptr, ptr2;
2379   tree elemsz = NULL_TREE;
2380 
2381   gfc_init_se (&se, NULL);
2382 
2383   if (element)
2384     {
2385       gfc_conv_expr_reference (&se, n->expr);
2386       gfc_add_block_to_block (block, &se.pre);
2387       ptr = se.expr;
2388       OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr)));
2389       elemsz = OMP_CLAUSE_SIZE (node);
2390     }
2391   else
2392     {
2393       gfc_conv_expr_descriptor (&se, n->expr);
2394       ptr = gfc_conv_array_data (se.expr);
2395       tree type = TREE_TYPE (se.expr);
2396       gfc_add_block_to_block (block, &se.pre);
2397       OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
2398 						    GFC_TYPE_ARRAY_RANK (type));
2399       elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2400       elemsz = fold_convert (gfc_array_index_type, elemsz);
2401       OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
2402 					    OMP_CLAUSE_SIZE (node), elemsz);
2403     }
2404   gcc_assert (se.post.head == NULL_TREE);
2405   gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
2406   OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2407   ptr = fold_convert (ptrdiff_type_node, ptr);
2408 
2409   if (POINTER_TYPE_P (TREE_TYPE (decl))
2410       && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2411       && ptr_kind == GOMP_MAP_POINTER)
2412     {
2413       node4 = build_omp_clause (input_location,
2414 				OMP_CLAUSE_MAP);
2415       OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2416       OMP_CLAUSE_DECL (node4) = decl;
2417       OMP_CLAUSE_SIZE (node4) = size_int (0);
2418       decl = build_fold_indirect_ref (decl);
2419     }
2420   else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER
2421 	   && n->expr->ts.type == BT_CHARACTER
2422 	   && n->expr->ts.deferred)
2423     {
2424       gomp_map_kind map_kind;
2425       if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
2426 	map_kind = GOMP_MAP_TO;
2427       else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE
2428 	       || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE)
2429 	map_kind = OMP_CLAUSE_MAP_KIND (node);
2430       else
2431 	map_kind = GOMP_MAP_ALLOC;
2432       gcc_assert (se.string_length);
2433       node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2434       OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
2435       OMP_CLAUSE_DECL (node4) = se.string_length;
2436       OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node);
2437     }
2438   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2439     {
2440       tree desc_node;
2441       tree type = TREE_TYPE (decl);
2442       ptr2 = gfc_conv_descriptor_data_get (decl);
2443       desc_node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2444       OMP_CLAUSE_DECL (desc_node) = decl;
2445       OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
2446       if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
2447 	{
2448 	  OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO);
2449 	  node2 = node;
2450 	  node = desc_node;  /* Needs to come first.  */
2451 	}
2452       else
2453 	{
2454 	  OMP_CLAUSE_SET_MAP_KIND (desc_node, GOMP_MAP_TO_PSET);
2455 	  node2 = desc_node;
2456 	}
2457       node3 = build_omp_clause (input_location,
2458 				OMP_CLAUSE_MAP);
2459       OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2460       OMP_CLAUSE_DECL (node3)
2461 	= gfc_conv_descriptor_data_get (decl);
2462       /* This purposely does not include GOMP_MAP_ALWAYS_POINTER.  The extra
2463 	 cast prevents gimplify.cc from recognising it as being part of the
2464 	 struct – and adding an 'alloc: for the 'desc.data' pointer, which
2465 	 would break as the 'desc' (the descriptor) is also mapped
2466 	 (see node4 above).  */
2467       if (ptr_kind == GOMP_MAP_ATTACH_DETACH)
2468 	STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2469     }
2470   else
2471     {
2472       if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2473 	{
2474 	  tree offset;
2475 	  ptr2 = build_fold_addr_expr (decl);
2476 	  offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr,
2477 				fold_convert (ptrdiff_type_node, ptr2));
2478 	  offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node,
2479 			   offset, fold_convert (ptrdiff_type_node, elemsz));
2480 	  offset = build4_loc (input_location, ARRAY_REF,
2481 			       TREE_TYPE (TREE_TYPE (decl)),
2482 			       decl, offset, NULL_TREE, NULL_TREE);
2483 	  OMP_CLAUSE_DECL (node) = offset;
2484 
2485 	  if (ptr_kind == GOMP_MAP_ALWAYS_POINTER)
2486 	    return;
2487 	}
2488       else
2489 	{
2490 	  gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2491 	  ptr2 = decl;
2492 	}
2493       node3 = build_omp_clause (input_location,
2494 				OMP_CLAUSE_MAP);
2495       OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2496       OMP_CLAUSE_DECL (node3) = decl;
2497     }
2498   ptr2 = fold_convert (ptrdiff_type_node, ptr2);
2499   OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node,
2500 					 ptr, ptr2);
2501 }
2502 
2503 static tree
handle_iterator(gfc_namespace * ns,stmtblock_t * iter_block,tree block)2504 handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block)
2505 {
2506   tree list = NULL_TREE;
2507   for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink)
2508     {
2509       gfc_constructor *c;
2510       gfc_se se;
2511 
2512       tree last = make_tree_vec (6);
2513       tree iter_var = gfc_get_symbol_decl (sym);
2514       tree type = TREE_TYPE (iter_var);
2515       TREE_VEC_ELT (last, 0) = iter_var;
2516       DECL_CHAIN (iter_var) = BLOCK_VARS (block);
2517       BLOCK_VARS (block) = iter_var;
2518 
2519       /* begin */
2520       c = gfc_constructor_first (sym->value->value.constructor);
2521       gfc_init_se (&se, NULL);
2522       gfc_conv_expr (&se, c->expr);
2523       gfc_add_block_to_block (iter_block, &se.pre);
2524       gfc_add_block_to_block (iter_block, &se.post);
2525       TREE_VEC_ELT (last, 1) = fold_convert (type,
2526 					     gfc_evaluate_now (se.expr,
2527 							       iter_block));
2528       /* end */
2529       c = gfc_constructor_next (c);
2530       gfc_init_se (&se, NULL);
2531       gfc_conv_expr (&se, c->expr);
2532       gfc_add_block_to_block (iter_block, &se.pre);
2533       gfc_add_block_to_block (iter_block, &se.post);
2534       TREE_VEC_ELT (last, 2) = fold_convert (type,
2535 					     gfc_evaluate_now (se.expr,
2536 							       iter_block));
2537       /* step */
2538       c = gfc_constructor_next (c);
2539       tree step;
2540       if (c)
2541 	{
2542 	  gfc_init_se (&se, NULL);
2543 	  gfc_conv_expr (&se, c->expr);
2544 	  gfc_add_block_to_block (iter_block, &se.pre);
2545 	  gfc_add_block_to_block (iter_block, &se.post);
2546 	  gfc_conv_expr (&se, c->expr);
2547 	  step = fold_convert (type,
2548 			       gfc_evaluate_now (se.expr,
2549 						 iter_block));
2550 	}
2551       else
2552 	step = build_int_cst (type, 1);
2553       TREE_VEC_ELT (last, 3) = step;
2554       /* orig_step */
2555       TREE_VEC_ELT (last, 4) = save_expr (step);
2556       TREE_CHAIN (last) = list;
2557       list = last;
2558     }
2559   return list;
2560 }
2561 
2562 static tree
gfc_trans_omp_clauses(stmtblock_t * block,gfc_omp_clauses * clauses,locus where,bool declare_simd=false,bool openacc=false)2563 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
2564 		       locus where, bool declare_simd = false,
2565 		       bool openacc = false)
2566 {
2567   tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c;
2568   tree iterator = NULL_TREE;
2569   tree tree_block = NULL_TREE;
2570   stmtblock_t iter_block;
2571   int list, ifc;
2572   enum omp_clause_code clause_code;
2573   gfc_omp_namelist *prev = NULL;
2574   gfc_se se;
2575 
2576   if (clauses == NULL)
2577     return NULL_TREE;
2578 
2579   for (list = 0; list < OMP_LIST_NUM; list++)
2580     {
2581       gfc_omp_namelist *n = clauses->lists[list];
2582 
2583       if (n == NULL)
2584 	continue;
2585       switch (list)
2586 	{
2587 	case OMP_LIST_REDUCTION:
2588 	case OMP_LIST_REDUCTION_INSCAN:
2589 	case OMP_LIST_REDUCTION_TASK:
2590 	case OMP_LIST_IN_REDUCTION:
2591 	case OMP_LIST_TASK_REDUCTION:
2592 	  /* An OpenACC async clause indicates the need to set reduction
2593 	     arguments addressable, to allow asynchronous copy-out.  */
2594 	  omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses,
2595 						      where, clauses->async);
2596 	  break;
2597 	case OMP_LIST_PRIVATE:
2598 	  clause_code = OMP_CLAUSE_PRIVATE;
2599 	  goto add_clause;
2600 	case OMP_LIST_SHARED:
2601 	  clause_code = OMP_CLAUSE_SHARED;
2602 	  goto add_clause;
2603 	case OMP_LIST_FIRSTPRIVATE:
2604 	  clause_code = OMP_CLAUSE_FIRSTPRIVATE;
2605 	  goto add_clause;
2606 	case OMP_LIST_LASTPRIVATE:
2607 	  clause_code = OMP_CLAUSE_LASTPRIVATE;
2608 	  goto add_clause;
2609 	case OMP_LIST_COPYIN:
2610 	  clause_code = OMP_CLAUSE_COPYIN;
2611 	  goto add_clause;
2612 	case OMP_LIST_COPYPRIVATE:
2613 	  clause_code = OMP_CLAUSE_COPYPRIVATE;
2614 	  goto add_clause;
2615 	case OMP_LIST_UNIFORM:
2616 	  clause_code = OMP_CLAUSE_UNIFORM;
2617 	  goto add_clause;
2618 	case OMP_LIST_USE_DEVICE:
2619 	case OMP_LIST_USE_DEVICE_PTR:
2620 	  clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
2621 	  goto add_clause;
2622 	case OMP_LIST_USE_DEVICE_ADDR:
2623 	  clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
2624 	  goto add_clause;
2625 	case OMP_LIST_IS_DEVICE_PTR:
2626 	  clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
2627 	  goto add_clause;
2628 	case OMP_LIST_HAS_DEVICE_ADDR:
2629 	  clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR;
2630 	  goto add_clause;
2631 	case OMP_LIST_NONTEMPORAL:
2632 	  clause_code = OMP_CLAUSE_NONTEMPORAL;
2633 	  goto add_clause;
2634 	case OMP_LIST_SCAN_IN:
2635 	  clause_code = OMP_CLAUSE_INCLUSIVE;
2636 	  goto add_clause;
2637 	case OMP_LIST_SCAN_EX:
2638 	  clause_code = OMP_CLAUSE_EXCLUSIVE;
2639 	  goto add_clause;
2640 
2641 	add_clause:
2642 	  omp_clauses
2643 	    = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
2644 					   declare_simd);
2645 	  break;
2646 	case OMP_LIST_ALIGNED:
2647 	  for (; n != NULL; n = n->next)
2648 	    if (n->sym->attr.referenced || declare_simd)
2649 	      {
2650 		tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2651 		if (t != error_mark_node)
2652 		  {
2653 		    tree node = build_omp_clause (input_location,
2654 						  OMP_CLAUSE_ALIGNED);
2655 		    OMP_CLAUSE_DECL (node) = t;
2656 		    if (n->expr)
2657 		      {
2658 			tree alignment_var;
2659 
2660 			if (declare_simd)
2661 			  alignment_var = gfc_conv_constant_to_tree (n->expr);
2662 			else
2663 			  {
2664 			    gfc_init_se (&se, NULL);
2665 			    gfc_conv_expr (&se, n->expr);
2666 			    gfc_add_block_to_block (block, &se.pre);
2667 			    alignment_var = gfc_evaluate_now (se.expr, block);
2668 			    gfc_add_block_to_block (block, &se.post);
2669 			  }
2670 			OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
2671 		      }
2672 		    omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2673 		  }
2674 	      }
2675 	  break;
2676 	case OMP_LIST_ALLOCATE:
2677 	  for (; n != NULL; n = n->next)
2678 	    if (n->sym->attr.referenced)
2679 	      {
2680 		tree t = gfc_trans_omp_variable (n->sym, false);
2681 		if (t != error_mark_node)
2682 		  {
2683 		    tree node = build_omp_clause (input_location,
2684 						  OMP_CLAUSE_ALLOCATE);
2685 		    OMP_CLAUSE_DECL (node) = t;
2686 		    if (n->expr)
2687 		      {
2688 			tree allocator_;
2689 			gfc_init_se (&se, NULL);
2690 			gfc_conv_expr (&se, n->expr);
2691 			allocator_ = gfc_evaluate_now (se.expr, block);
2692 			OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_;
2693 		      }
2694 		    omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2695 		  }
2696 	      }
2697 	  break;
2698 	case OMP_LIST_LINEAR:
2699 	  {
2700 	    gfc_expr *last_step_expr = NULL;
2701 	    tree last_step = NULL_TREE;
2702 	    bool last_step_parm = false;
2703 
2704 	    for (; n != NULL; n = n->next)
2705 	      {
2706 		if (n->expr)
2707 		  {
2708 		    last_step_expr = n->expr;
2709 		    last_step = NULL_TREE;
2710 		    last_step_parm = false;
2711 		  }
2712 		if (n->sym->attr.referenced || declare_simd)
2713 		  {
2714 		    tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2715 		    if (t != error_mark_node)
2716 		      {
2717 			tree node = build_omp_clause (input_location,
2718 						      OMP_CLAUSE_LINEAR);
2719 			OMP_CLAUSE_DECL (node) = t;
2720 			omp_clause_linear_kind kind;
2721 			switch (n->u.linear_op)
2722 			  {
2723 			  case OMP_LINEAR_DEFAULT:
2724 			    kind = OMP_CLAUSE_LINEAR_DEFAULT;
2725 			    break;
2726 			  case OMP_LINEAR_REF:
2727 			    kind = OMP_CLAUSE_LINEAR_REF;
2728 			    break;
2729 			  case OMP_LINEAR_VAL:
2730 			    kind = OMP_CLAUSE_LINEAR_VAL;
2731 			    break;
2732 			  case OMP_LINEAR_UVAL:
2733 			    kind = OMP_CLAUSE_LINEAR_UVAL;
2734 			    break;
2735 			  default:
2736 			    gcc_unreachable ();
2737 			  }
2738 			OMP_CLAUSE_LINEAR_KIND (node) = kind;
2739 			if (last_step_expr && last_step == NULL_TREE)
2740 			  {
2741 			    if (!declare_simd)
2742 			      {
2743 				gfc_init_se (&se, NULL);
2744 				gfc_conv_expr (&se, last_step_expr);
2745 				gfc_add_block_to_block (block, &se.pre);
2746 				last_step = gfc_evaluate_now (se.expr, block);
2747 				gfc_add_block_to_block (block, &se.post);
2748 			      }
2749 			    else if (last_step_expr->expr_type == EXPR_VARIABLE)
2750 			      {
2751 				gfc_symbol *s = last_step_expr->symtree->n.sym;
2752 				last_step = gfc_trans_omp_variable (s, true);
2753 				last_step_parm = true;
2754 			      }
2755 			    else
2756 			      last_step
2757 				= gfc_conv_constant_to_tree (last_step_expr);
2758 			  }
2759 			if (last_step_parm)
2760 			  {
2761 			    OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
2762 			    OMP_CLAUSE_LINEAR_STEP (node) = last_step;
2763 			  }
2764 			else
2765 			  {
2766 			    if (kind == OMP_CLAUSE_LINEAR_REF)
2767 			      {
2768 				tree type;
2769 				if (n->sym->attr.flavor == FL_PROCEDURE)
2770 				  {
2771 				    type = gfc_get_function_type (n->sym);
2772 				    type = build_pointer_type (type);
2773 				  }
2774 				else
2775 				  type = gfc_sym_type (n->sym);
2776 				if (POINTER_TYPE_P (type))
2777 				  type = TREE_TYPE (type);
2778 				/* Otherwise to be determined what exactly
2779 				   should be done.  */
2780 				tree t = fold_convert (sizetype, last_step);
2781 				t = size_binop (MULT_EXPR, t,
2782 						TYPE_SIZE_UNIT (type));
2783 				OMP_CLAUSE_LINEAR_STEP (node) = t;
2784 			      }
2785 			    else
2786 			      {
2787 				tree type
2788 				  = gfc_typenode_for_spec (&n->sym->ts);
2789 				OMP_CLAUSE_LINEAR_STEP (node)
2790 				  = fold_convert (type, last_step);
2791 			      }
2792 			  }
2793 			if (n->sym->attr.dimension || n->sym->attr.allocatable)
2794 			  OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
2795 			omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2796 		      }
2797 		  }
2798 	      }
2799 	  }
2800 	  break;
2801 	case OMP_LIST_AFFINITY:
2802 	case OMP_LIST_DEPEND:
2803 	  iterator = NULL_TREE;
2804 	  prev = NULL;
2805 	  prev_clauses = omp_clauses;
2806 	  for (; n != NULL; n = n->next)
2807 	    {
2808 	      if (iterator && prev->u2.ns != n->u2.ns)
2809 		{
2810 		  BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
2811 		  TREE_VEC_ELT (iterator, 5) = tree_block;
2812 		  for (tree c = omp_clauses; c != prev_clauses;
2813 		       c = OMP_CLAUSE_CHAIN (c))
2814 		    OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
2815 							   OMP_CLAUSE_DECL (c));
2816 		  prev_clauses = omp_clauses;
2817 		  iterator = NULL_TREE;
2818 		}
2819 	      if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns))
2820 		{
2821 		  gfc_init_block (&iter_block);
2822 		  tree_block = make_node (BLOCK);
2823 		  TREE_USED (tree_block) = 1;
2824 		  BLOCK_VARS (tree_block) = NULL_TREE;
2825 		  iterator = handle_iterator (n->u2.ns, block,
2826 					      tree_block);
2827 		}
2828 	      if (!iterator)
2829 		gfc_init_block (&iter_block);
2830 	      prev = n;
2831 	      if (list == OMP_LIST_DEPEND
2832 		  && n->u.depend_op == OMP_DEPEND_SINK_FIRST)
2833 		{
2834 		  tree vec = NULL_TREE;
2835 		  unsigned int i;
2836 		  for (i = 0; ; i++)
2837 		    {
2838 		      tree addend = integer_zero_node, t;
2839 		      bool neg = false;
2840 		      if (n->expr)
2841 			{
2842 			  addend = gfc_conv_constant_to_tree (n->expr);
2843 			  if (TREE_CODE (addend) == INTEGER_CST
2844 			      && tree_int_cst_sgn (addend) == -1)
2845 			    {
2846 			      neg = true;
2847 			      addend = const_unop (NEGATE_EXPR,
2848 						   TREE_TYPE (addend), addend);
2849 			    }
2850 			}
2851 		      t = gfc_trans_omp_variable (n->sym, false);
2852 		      if (t != error_mark_node)
2853 			{
2854 			  if (i < vec_safe_length (doacross_steps)
2855 			      && !integer_zerop (addend)
2856 			      && (*doacross_steps)[i])
2857 			    {
2858 			      tree step = (*doacross_steps)[i];
2859 			      addend = fold_convert (TREE_TYPE (step), addend);
2860 			      addend = build2 (TRUNC_DIV_EXPR,
2861 					       TREE_TYPE (step), addend, step);
2862 			    }
2863 			  vec = tree_cons (addend, t, vec);
2864 			  if (neg)
2865 			    OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
2866 			}
2867 		      if (n->next == NULL
2868 			  || n->next->u.depend_op != OMP_DEPEND_SINK)
2869 			break;
2870 		      n = n->next;
2871 		    }
2872 		  if (vec == NULL_TREE)
2873 		    continue;
2874 
2875 		  tree node = build_omp_clause (input_location,
2876 						OMP_CLAUSE_DEPEND);
2877 		  OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
2878 		  OMP_CLAUSE_DECL (node) = nreverse (vec);
2879 		  omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2880 		  continue;
2881 		}
2882 
2883 	      if (!n->sym->attr.referenced)
2884 		continue;
2885 
2886 	      tree node = build_omp_clause (input_location,
2887 					    list == OMP_LIST_DEPEND
2888 					    ? OMP_CLAUSE_DEPEND
2889 					    : OMP_CLAUSE_AFFINITY);
2890 	      if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2891 		{
2892 		  tree decl = gfc_trans_omp_variable (n->sym, false);
2893 		  if (gfc_omp_privatize_by_reference (decl))
2894 		    decl = build_fold_indirect_ref (decl);
2895 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2896 		    {
2897 		      decl = gfc_conv_descriptor_data_get (decl);
2898 		      gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2899 		      decl = build_fold_indirect_ref (decl);
2900 		    }
2901 		  else if (n->sym->attr.allocatable || n->sym->attr.pointer)
2902 		    decl = build_fold_indirect_ref (decl);
2903 		  else if (DECL_P (decl))
2904 		    TREE_ADDRESSABLE (decl) = 1;
2905 		  OMP_CLAUSE_DECL (node) = decl;
2906 		}
2907 	      else
2908 		{
2909 		  tree ptr;
2910 		  gfc_init_se (&se, NULL);
2911 		  if (n->expr->ref->u.ar.type == AR_ELEMENT)
2912 		    {
2913 		      gfc_conv_expr_reference (&se, n->expr);
2914 		      ptr = se.expr;
2915 		    }
2916 		  else
2917 		    {
2918 		      gfc_conv_expr_descriptor (&se, n->expr);
2919 		      ptr = gfc_conv_array_data (se.expr);
2920 		    }
2921 		  gfc_add_block_to_block (&iter_block, &se.pre);
2922 		  gfc_add_block_to_block (&iter_block, &se.post);
2923 		  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
2924 		  OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2925 		}
2926 	      if (list == OMP_LIST_DEPEND)
2927 		switch (n->u.depend_op)
2928 		  {
2929 		  case OMP_DEPEND_IN:
2930 		    OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
2931 		    break;
2932 		  case OMP_DEPEND_OUT:
2933 		    OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
2934 		    break;
2935 		  case OMP_DEPEND_INOUT:
2936 		    OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
2937 		    break;
2938 		  case OMP_DEPEND_MUTEXINOUTSET:
2939 		    OMP_CLAUSE_DEPEND_KIND (node)
2940 		      = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
2941 		    break;
2942 		  case OMP_DEPEND_DEPOBJ:
2943 		    OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ;
2944 		    break;
2945 		  default:
2946 		    gcc_unreachable ();
2947 		  }
2948 	      if (!iterator)
2949 		gfc_add_block_to_block (block, &iter_block);
2950 	      omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2951 	    }
2952 	  if (iterator)
2953 	    {
2954 	      BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block);
2955 	      TREE_VEC_ELT (iterator, 5) = tree_block;
2956 	      for (tree c = omp_clauses; c != prev_clauses;
2957 		   c = OMP_CLAUSE_CHAIN (c))
2958 		OMP_CLAUSE_DECL (c) = build_tree_list (iterator,
2959 						       OMP_CLAUSE_DECL (c));
2960 	    }
2961 	  break;
2962 	case OMP_LIST_MAP:
2963 	  for (; n != NULL; n = n->next)
2964 	    {
2965 	      if (!n->sym->attr.referenced)
2966 		continue;
2967 
2968 	      bool always_modifier = false;
2969 	      tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2970 	      tree node2 = NULL_TREE;
2971 	      tree node3 = NULL_TREE;
2972 	      tree node4 = NULL_TREE;
2973 
2974 	      /* OpenMP: automatically map pointer targets with the pointer;
2975 		 hence, always update the descriptor/pointer itself.  */
2976 	      if (!openacc
2977 		  && ((n->expr == NULL && n->sym->attr.pointer)
2978 		      || (n->expr && gfc_expr_attr (n->expr).pointer)))
2979 		always_modifier = true;
2980 
2981 	      switch (n->u.map_op)
2982 		{
2983 		case OMP_MAP_ALLOC:
2984 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
2985 		  break;
2986 		case OMP_MAP_IF_PRESENT:
2987 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
2988 		  break;
2989 		case OMP_MAP_ATTACH:
2990 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
2991 		  break;
2992 		case OMP_MAP_TO:
2993 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
2994 		  break;
2995 		case OMP_MAP_FROM:
2996 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
2997 		  break;
2998 		case OMP_MAP_TOFROM:
2999 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
3000 		  break;
3001 		case OMP_MAP_ALWAYS_TO:
3002 		  always_modifier = true;
3003 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
3004 		  break;
3005 		case OMP_MAP_ALWAYS_FROM:
3006 		  always_modifier = true;
3007 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
3008 		  break;
3009 		case OMP_MAP_ALWAYS_TOFROM:
3010 		  always_modifier = true;
3011 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
3012 		  break;
3013 		case OMP_MAP_RELEASE:
3014 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
3015 		  break;
3016 		case OMP_MAP_DELETE:
3017 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
3018 		  break;
3019 		case OMP_MAP_DETACH:
3020 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
3021 		  break;
3022 		case OMP_MAP_FORCE_ALLOC:
3023 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
3024 		  break;
3025 		case OMP_MAP_FORCE_TO:
3026 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
3027 		  break;
3028 		case OMP_MAP_FORCE_FROM:
3029 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
3030 		  break;
3031 		case OMP_MAP_FORCE_TOFROM:
3032 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
3033 		  break;
3034 		case OMP_MAP_FORCE_PRESENT:
3035 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
3036 		  break;
3037 		case OMP_MAP_FORCE_DEVICEPTR:
3038 		  OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
3039 		  break;
3040 		default:
3041 		  gcc_unreachable ();
3042 		}
3043 
3044 	      tree decl = gfc_trans_omp_variable (n->sym, false);
3045 	      if (DECL_P (decl))
3046 		TREE_ADDRESSABLE (decl) = 1;
3047 
3048 	      gfc_ref *lastref = NULL;
3049 
3050 	      if (n->expr)
3051 		for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3052 		  if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY)
3053 		    lastref = ref;
3054 
3055 	      bool allocatable = false, pointer = false;
3056 
3057 	      if (lastref && lastref->type == REF_COMPONENT)
3058 		{
3059 		  gfc_component *c = lastref->u.c.component;
3060 
3061 		  if (c->ts.type == BT_CLASS)
3062 		    {
3063 		      pointer = CLASS_DATA (c)->attr.class_pointer;
3064 		      allocatable = CLASS_DATA (c)->attr.allocatable;
3065 		    }
3066 		  else
3067 		    {
3068 		      pointer = c->attr.pointer;
3069 		      allocatable = c->attr.allocatable;
3070 		    }
3071 		}
3072 
3073 	      if (n->expr == NULL
3074 		  || (n->expr->ref->type == REF_ARRAY
3075 		      && n->expr->ref->u.ar.type == AR_FULL))
3076 		{
3077 		  tree present = gfc_omp_check_optional_argument (decl, true);
3078 		  if (openacc && n->sym->ts.type == BT_CLASS)
3079 		    {
3080 		      tree type = TREE_TYPE (decl);
3081 		      if (n->sym->attr.optional)
3082 			sorry ("optional class parameter");
3083 		      if (POINTER_TYPE_P (type))
3084 			{
3085 			  node4 = build_omp_clause (input_location,
3086 						    OMP_CLAUSE_MAP);
3087 			  OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
3088 			  OMP_CLAUSE_DECL (node4) = decl;
3089 			  OMP_CLAUSE_SIZE (node4) = size_int (0);
3090 			  decl = build_fold_indirect_ref (decl);
3091 			}
3092 		      tree ptr = gfc_class_data_get (decl);
3093 		      ptr = build_fold_indirect_ref (ptr);
3094 		      OMP_CLAUSE_DECL (node) = ptr;
3095 		      OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
3096 		      node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3097 		      OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3098 		      OMP_CLAUSE_DECL (node2) = decl;
3099 		      OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3100 		      node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
3101 		      OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
3102 		      OMP_CLAUSE_DECL (node3) = gfc_class_data_get (decl);
3103 		      OMP_CLAUSE_SIZE (node3) = size_int (0);
3104 		      goto finalize_map_clause;
3105 		    }
3106 		  else if (POINTER_TYPE_P (TREE_TYPE (decl))
3107 			   && (gfc_omp_privatize_by_reference (decl)
3108 			       || GFC_DECL_GET_SCALAR_POINTER (decl)
3109 			       || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
3110 			       || GFC_DECL_CRAY_POINTEE (decl)
3111 			       || GFC_DESCRIPTOR_TYPE_P
3112 					     (TREE_TYPE (TREE_TYPE (decl)))
3113 			       || (n->sym->ts.type == BT_DERIVED
3114 				   && (n->sym->ts.u.derived->ts.f90_type
3115 				       != BT_VOID))))
3116 		    {
3117 		      tree orig_decl = decl;
3118 
3119 		      /* For nonallocatable, nonpointer arrays, a temporary
3120 			 variable is generated, but this one is only defined if
3121 			 the variable is present; hence, we now set it to NULL
3122 			 to avoid accessing undefined variables.  We cannot use
3123 			 a temporary variable here as otherwise the replacement
3124 			 of the variables in omp-low.cc will not work.  */
3125 		      if (present && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)))
3126 			{
3127 			  tree tmp = fold_build2_loc (input_location,
3128 						      MODIFY_EXPR,
3129 						      void_type_node, decl,
3130 						      null_pointer_node);
3131 			  tree cond = fold_build1_loc (input_location,
3132 						       TRUTH_NOT_EXPR,
3133 						       boolean_type_node,
3134 						       present);
3135 			  gfc_add_expr_to_block (block,
3136 						 build3_loc (input_location,
3137 							     COND_EXPR,
3138 							     void_type_node,
3139 							     cond, tmp,
3140 							     NULL_TREE));
3141 			}
3142 		      node4 = build_omp_clause (input_location,
3143 						OMP_CLAUSE_MAP);
3144 		      OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
3145 		      OMP_CLAUSE_DECL (node4) = decl;
3146 		      OMP_CLAUSE_SIZE (node4) = size_int (0);
3147 		      decl = build_fold_indirect_ref (decl);
3148 		      if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
3149 			   || gfc_omp_is_optional_argument (orig_decl))
3150 			  && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
3151 			      || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
3152 			{
3153 			  node3 = build_omp_clause (input_location,
3154 						    OMP_CLAUSE_MAP);
3155 			  OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
3156 			  OMP_CLAUSE_DECL (node3) = decl;
3157 			  OMP_CLAUSE_SIZE (node3) = size_int (0);
3158 			  decl = build_fold_indirect_ref (decl);
3159 			}
3160 		    }
3161 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3162 		    {
3163 		      tree type = TREE_TYPE (decl);
3164 		      tree ptr = gfc_conv_descriptor_data_get (decl);
3165 		      if (present)
3166 			ptr = gfc_build_cond_assign_expr (block, present, ptr,
3167 							  null_pointer_node);
3168 		      gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3169 		      ptr = build_fold_indirect_ref (ptr);
3170 		      OMP_CLAUSE_DECL (node) = ptr;
3171 		      node2 = build_omp_clause (input_location,
3172 						OMP_CLAUSE_MAP);
3173 		      OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
3174 		      OMP_CLAUSE_DECL (node2) = decl;
3175 		      OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
3176 		      node3 = build_omp_clause (input_location,
3177 						OMP_CLAUSE_MAP);
3178 		      if (present)
3179 			{
3180 			  ptr = gfc_conv_descriptor_data_get (decl);
3181 			  ptr = gfc_build_addr_expr (NULL, ptr);
3182 			  ptr = gfc_build_cond_assign_expr (block, present, ptr,
3183 							    null_pointer_node);
3184 			  ptr = build_fold_indirect_ref (ptr);
3185 			  OMP_CLAUSE_DECL (node3) = ptr;
3186 			}
3187 		      else
3188 			OMP_CLAUSE_DECL (node3)
3189 			  = gfc_conv_descriptor_data_get (decl);
3190 		      OMP_CLAUSE_SIZE (node3) = size_int (0);
3191 		      if (n->u.map_op == OMP_MAP_ATTACH)
3192 			{
3193 			  /* Standalone attach clauses used with arrays with
3194 			     descriptors must copy the descriptor to the target,
3195 			     else they won't have anything to perform the
3196 			     attachment onto (see OpenACC 2.6, "2.6.3. Data
3197 			     Structures with Pointers").  */
3198 			  OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH);
3199 			  /* We don't want to map PTR at all in this case, so
3200 			     delete its node and shuffle the others down.  */
3201 			  node = node2;
3202 			  node2 = node3;
3203 			  node3 = NULL;
3204 			  goto finalize_map_clause;
3205 			}
3206 		      else if (n->u.map_op == OMP_MAP_DETACH)
3207 			{
3208 			  OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH);
3209 			  /* Similarly to above, we don't want to unmap PTR
3210 			     here.  */
3211 			  node = node2;
3212 			  node2 = node3;
3213 			  node3 = NULL;
3214 			  goto finalize_map_clause;
3215 			}
3216 		      else
3217 			OMP_CLAUSE_SET_MAP_KIND (node3,
3218 						 always_modifier
3219 						 ? GOMP_MAP_ALWAYS_POINTER
3220 						 : GOMP_MAP_POINTER);
3221 
3222 		      /* We have to check for n->sym->attr.dimension because
3223 			 of scalar coarrays.  */
3224 		      if ((n->sym->attr.pointer || n->sym->attr.allocatable)
3225 			  && n->sym->attr.dimension)
3226 			{
3227 			  stmtblock_t cond_block;
3228 			  tree size
3229 			    = gfc_create_var (gfc_array_index_type, NULL);
3230 			  tree tem, then_b, else_b, zero, cond;
3231 
3232 			  gfc_init_block (&cond_block);
3233 			  tem
3234 			    = gfc_full_array_size (&cond_block, decl,
3235 						   GFC_TYPE_ARRAY_RANK (type));
3236 			  gfc_add_modify (&cond_block, size, tem);
3237 			  then_b = gfc_finish_block (&cond_block);
3238 			  gfc_init_block (&cond_block);
3239 			  zero = build_int_cst (gfc_array_index_type, 0);
3240 			  gfc_add_modify (&cond_block, size, zero);
3241 			  else_b = gfc_finish_block (&cond_block);
3242 			  tem = gfc_conv_descriptor_data_get (decl);
3243 			  tem = fold_convert (pvoid_type_node, tem);
3244 			  cond = fold_build2_loc (input_location, NE_EXPR,
3245 						  boolean_type_node,
3246 						  tem, null_pointer_node);
3247 			  if (present)
3248 			    cond = fold_build2_loc (input_location,
3249 						    TRUTH_ANDIF_EXPR,
3250 						    boolean_type_node,
3251 						    present, cond);
3252 			  gfc_add_expr_to_block (block,
3253 						 build3_loc (input_location,
3254 							     COND_EXPR,
3255 							     void_type_node,
3256 							     cond, then_b,
3257 							     else_b));
3258 			  OMP_CLAUSE_SIZE (node) = size;
3259 			}
3260 		      else if (n->sym->attr.dimension)
3261 			{
3262 			  stmtblock_t cond_block;
3263 			  gfc_init_block (&cond_block);
3264 			  tree size = gfc_full_array_size (&cond_block, decl,
3265 					GFC_TYPE_ARRAY_RANK (type));
3266 			  if (present)
3267 			    {
3268 			      tree var = gfc_create_var (gfc_array_index_type,
3269 							 NULL);
3270 			      gfc_add_modify (&cond_block, var, size);
3271 			      tree cond_body = gfc_finish_block (&cond_block);
3272 			      tree cond = build3_loc (input_location, COND_EXPR,
3273 						      void_type_node, present,
3274 						      cond_body, NULL_TREE);
3275 			      gfc_add_expr_to_block (block, cond);
3276 			      OMP_CLAUSE_SIZE (node) = var;
3277 			    }
3278 			  else
3279 			    {
3280 			      gfc_add_block_to_block (block, &cond_block);
3281 			      OMP_CLAUSE_SIZE (node) = size;
3282 			    }
3283 			}
3284 		      if (n->sym->attr.dimension)
3285 			{
3286 			  tree elemsz
3287 			    = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3288 			  elemsz = fold_convert (gfc_array_index_type, elemsz);
3289 			  OMP_CLAUSE_SIZE (node)
3290 			    = fold_build2 (MULT_EXPR, gfc_array_index_type,
3291 					   OMP_CLAUSE_SIZE (node), elemsz);
3292 			}
3293 		    }
3294 		  else if (present
3295 			   && TREE_CODE (decl) == INDIRECT_REF
3296 			   && (TREE_CODE (TREE_OPERAND (decl, 0))
3297 			       == INDIRECT_REF))
3298 		    {
3299 		      /* A single indirectref is handled by the middle end.  */
3300 		      gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
3301 		      decl = TREE_OPERAND (decl, 0);
3302 		      decl = gfc_build_cond_assign_expr (block, present, decl,
3303 							 null_pointer_node);
3304 		      OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl);
3305 		    }
3306 		  else
3307 		    OMP_CLAUSE_DECL (node) = decl;
3308 		}
3309 	      else if (n->expr
3310 		       && n->expr->expr_type == EXPR_VARIABLE
3311 		       && n->expr->ref->type == REF_ARRAY
3312 		       && !n->expr->ref->next)
3313 		{
3314 		  /* An array element or array section which is not part of a
3315 		     derived type, etc.  */
3316 		  bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
3317 		  gfc_trans_omp_array_section (block, n, decl, element,
3318 					       GOMP_MAP_POINTER, node, node2,
3319 					       node3, node4);
3320 		}
3321 	      else if (n->expr
3322 		       && n->expr->expr_type == EXPR_VARIABLE
3323 		       && (n->expr->ref->type == REF_COMPONENT
3324 			   || n->expr->ref->type == REF_ARRAY)
3325 		       && lastref
3326 		       && lastref->type == REF_COMPONENT
3327 		       && lastref->u.c.component->ts.type != BT_CLASS
3328 		       && lastref->u.c.component->ts.type != BT_DERIVED
3329 		       && !lastref->u.c.component->attr.dimension)
3330 		{
3331 		  /* Derived type access with last component being a scalar.  */
3332 		  gfc_init_se (&se, NULL);
3333 
3334 		  gfc_conv_expr (&se, n->expr);
3335 		  gfc_add_block_to_block (block, &se.pre);
3336 		  /* For BT_CHARACTER a pointer is returned.  */
3337 		  OMP_CLAUSE_DECL (node)
3338 		    = POINTER_TYPE_P (TREE_TYPE (se.expr))
3339 		      ? build_fold_indirect_ref (se.expr) : se.expr;
3340 		  gfc_add_block_to_block (block, &se.post);
3341 		  if (pointer || allocatable)
3342 		    {
3343 		      node2 = build_omp_clause (input_location,
3344 						OMP_CLAUSE_MAP);
3345 		      gomp_map_kind kind
3346 			= (openacc ? GOMP_MAP_ATTACH_DETACH
3347 				   : GOMP_MAP_ALWAYS_POINTER);
3348 		      OMP_CLAUSE_SET_MAP_KIND (node2, kind);
3349 		      OMP_CLAUSE_DECL (node2)
3350 			= POINTER_TYPE_P (TREE_TYPE (se.expr))
3351 			  ? se.expr
3352 			  : gfc_build_addr_expr (NULL, se.expr);
3353 		      OMP_CLAUSE_SIZE (node2) = size_int (0);
3354 		      if (!openacc
3355 			  && n->expr->ts.type == BT_CHARACTER
3356 			  && n->expr->ts.deferred)
3357 			{
3358 			  gcc_assert (se.string_length);
3359 			  tree tmp
3360 			    = gfc_get_char_type (n->expr->ts.kind);
3361 			  OMP_CLAUSE_SIZE (node)
3362 			    = fold_build2 (MULT_EXPR, size_type_node,
3363 					   fold_convert (size_type_node,
3364 					       se.string_length),
3365 					   TYPE_SIZE_UNIT (tmp));
3366 			  node3 = build_omp_clause (input_location,
3367 						    OMP_CLAUSE_MAP);
3368 			  OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_TO);
3369 			  OMP_CLAUSE_DECL (node3) = se.string_length;
3370 			  OMP_CLAUSE_SIZE (node3)
3371 			    = TYPE_SIZE_UNIT (gfc_charlen_type_node);
3372 			}
3373 		    }
3374 		}
3375 	      else if (n->expr
3376 		       && n->expr->expr_type == EXPR_VARIABLE
3377 		       && (n->expr->ref->type == REF_COMPONENT
3378 			   || n->expr->ref->type == REF_ARRAY))
3379 		{
3380 		  gfc_init_se (&se, NULL);
3381 		  se.expr = gfc_maybe_dereference_var (n->sym, decl);
3382 
3383 		  for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
3384 		    {
3385 		      if (ref->type == REF_COMPONENT)
3386 			{
3387 			  if (ref->u.c.sym->attr.extension)
3388 			    conv_parent_component_references (&se, ref);
3389 
3390 			  gfc_conv_component_ref (&se, ref);
3391 			}
3392 		      else if (ref->type == REF_ARRAY)
3393 			{
3394 			  if (ref->u.ar.type == AR_ELEMENT && ref->next)
3395 			    gfc_conv_array_ref (&se, &ref->u.ar, n->expr,
3396 						&n->expr->where);
3397 			  else
3398 			    gcc_assert (!ref->next);
3399 			}
3400 		      else
3401 			sorry ("unhandled expression type");
3402 		    }
3403 
3404 		  tree inner = se.expr;
3405 
3406 		  /* Last component is a derived type or class pointer.  */
3407 		  if (lastref->type == REF_COMPONENT
3408 		      && (lastref->u.c.component->ts.type == BT_DERIVED
3409 			  || lastref->u.c.component->ts.type == BT_CLASS))
3410 		    {
3411 		      if (pointer || (openacc && allocatable))
3412 			{
3413 			  tree data, size;
3414 
3415 			  if (lastref->u.c.component->ts.type == BT_CLASS)
3416 			    {
3417 			      data = gfc_class_data_get (inner);
3418 			      gcc_assert (POINTER_TYPE_P (TREE_TYPE (data)));
3419 			      data = build_fold_indirect_ref (data);
3420 			      size = gfc_class_vtab_size_get (inner);
3421 			    }
3422 			  else  /* BT_DERIVED.  */
3423 			    {
3424 			      data = inner;
3425 			      size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3426 			    }
3427 
3428 			  OMP_CLAUSE_DECL (node) = data;
3429 			  OMP_CLAUSE_SIZE (node) = size;
3430 			  node2 = build_omp_clause (input_location,
3431 						    OMP_CLAUSE_MAP);
3432 			  OMP_CLAUSE_SET_MAP_KIND (node2,
3433 						   openacc
3434 						   ? GOMP_MAP_ATTACH_DETACH
3435 						   : GOMP_MAP_ALWAYS_POINTER);
3436 			  OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data);
3437 			  OMP_CLAUSE_SIZE (node2) = size_int (0);
3438 			}
3439 		      else
3440 			{
3441 			  OMP_CLAUSE_DECL (node) = inner;
3442 			  OMP_CLAUSE_SIZE (node)
3443 			    = TYPE_SIZE_UNIT (TREE_TYPE (inner));
3444 			}
3445 		    }
3446 		  else if (lastref->type == REF_ARRAY
3447 			   && lastref->u.ar.type == AR_FULL)
3448 		    {
3449 		      /* Just pass the (auto-dereferenced) decl through for
3450 			 bare attach and detach clauses.  */
3451 		      if (n->u.map_op == OMP_MAP_ATTACH
3452 			  || n->u.map_op == OMP_MAP_DETACH)
3453 			{
3454 			  OMP_CLAUSE_DECL (node) = inner;
3455 			  OMP_CLAUSE_SIZE (node) = size_zero_node;
3456 			  goto finalize_map_clause;
3457 			}
3458 
3459 		      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
3460 			{
3461 			  gomp_map_kind map_kind;
3462 			  tree desc_node;
3463 			  tree type = TREE_TYPE (inner);
3464 			  tree ptr = gfc_conv_descriptor_data_get (inner);
3465 			  ptr = build_fold_indirect_ref (ptr);
3466 			  OMP_CLAUSE_DECL (node) = ptr;
3467 			  int rank = GFC_TYPE_ARRAY_RANK (type);
3468 			  OMP_CLAUSE_SIZE (node)
3469 			    = gfc_full_array_size (block, inner, rank);
3470 			  tree elemsz
3471 			    = TYPE_SIZE_UNIT (gfc_get_element_type (type));
3472 			  if (GOMP_MAP_COPY_TO_P (OMP_CLAUSE_MAP_KIND (node)))
3473 			    map_kind = GOMP_MAP_TO;
3474 			  else if (n->u.map_op == OMP_MAP_RELEASE
3475 				   || n->u.map_op == OMP_MAP_DELETE)
3476 			    map_kind = OMP_CLAUSE_MAP_KIND (node);
3477 			  else
3478 			    map_kind = GOMP_MAP_ALLOC;
3479 			  if (!openacc
3480 			      && n->expr->ts.type == BT_CHARACTER
3481 			      && n->expr->ts.deferred)
3482 			    {
3483 			      gcc_assert (se.string_length);
3484 			      tree len = fold_convert (size_type_node,
3485 						       se.string_length);
3486 			      elemsz = gfc_get_char_type (n->expr->ts.kind);
3487 			      elemsz = TYPE_SIZE_UNIT (elemsz);
3488 			      elemsz = fold_build2 (MULT_EXPR, size_type_node,
3489 						    len, elemsz);
3490 			      node4 = build_omp_clause (input_location,
3491 							OMP_CLAUSE_MAP);
3492 			      OMP_CLAUSE_SET_MAP_KIND (node4, map_kind);
3493 			      OMP_CLAUSE_DECL (node4) = se.string_length;
3494 			      OMP_CLAUSE_SIZE (node4)
3495 				= TYPE_SIZE_UNIT (gfc_charlen_type_node);
3496 			    }
3497 			  elemsz = fold_convert (gfc_array_index_type, elemsz);
3498 			  OMP_CLAUSE_SIZE (node)
3499 			    = fold_build2 (MULT_EXPR, gfc_array_index_type,
3500 					   OMP_CLAUSE_SIZE (node), elemsz);
3501 			  desc_node = build_omp_clause (input_location,
3502 							OMP_CLAUSE_MAP);
3503 			  if (openacc)
3504 			    OMP_CLAUSE_SET_MAP_KIND (desc_node,
3505 						     GOMP_MAP_TO_PSET);
3506 			  else
3507 			    OMP_CLAUSE_SET_MAP_KIND (desc_node, map_kind);
3508 			  OMP_CLAUSE_DECL (desc_node) = inner;
3509 			  OMP_CLAUSE_SIZE (desc_node) = TYPE_SIZE_UNIT (type);
3510 			  if (openacc)
3511 			    node2 = desc_node;
3512 			  else
3513 			    {
3514 			      node2 = node;
3515 			      node = desc_node;  /* Put first.  */
3516 			    }
3517 			  node3 = build_omp_clause (input_location,
3518 						    OMP_CLAUSE_MAP);
3519 			  OMP_CLAUSE_SET_MAP_KIND (node3,
3520 						   openacc
3521 						   ? GOMP_MAP_ATTACH_DETACH
3522 						   : GOMP_MAP_ALWAYS_POINTER);
3523 			  OMP_CLAUSE_DECL (node3)
3524 			    = gfc_conv_descriptor_data_get (inner);
3525 			  /* Similar to gfc_trans_omp_array_section (details
3526 			     there), we add/keep the cast for OpenMP to prevent
3527 			     that an 'alloc:' gets added for node3 ('desc.data')
3528 			     as that is part of the whole descriptor (node3).
3529 			     TODO: Remove once the ME handles this properly.  */
3530 			  if (!openacc)
3531 			    OMP_CLAUSE_DECL (node3)
3532 				= fold_convert (TREE_TYPE (TREE_OPERAND(ptr, 0)),
3533 						OMP_CLAUSE_DECL (node3));
3534 			  else
3535 			    STRIP_NOPS (OMP_CLAUSE_DECL (node3));
3536 			  OMP_CLAUSE_SIZE (node3) = size_int (0);
3537 			}
3538 		      else
3539 			OMP_CLAUSE_DECL (node) = inner;
3540 		    }
3541 		  else if (lastref->type == REF_ARRAY)
3542 		    {
3543 		      /* An array element or section.  */
3544 		      bool element = lastref->u.ar.type == AR_ELEMENT;
3545 		      gomp_map_kind kind = (openacc ? GOMP_MAP_ATTACH_DETACH
3546 						    : GOMP_MAP_ALWAYS_POINTER);
3547 		      gfc_trans_omp_array_section (block, n, inner, element,
3548 						   kind, node, node2, node3,
3549 						   node4);
3550 		    }
3551 		  else
3552 		    gcc_unreachable ();
3553 		}
3554 	      else
3555 		sorry ("unhandled expression");
3556 
3557 	      finalize_map_clause:
3558 
3559 	      omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3560 	      if (node2)
3561 		omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
3562 	      if (node3)
3563 		omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
3564 	      if (node4)
3565 		omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
3566 	    }
3567 	  break;
3568 	case OMP_LIST_TO:
3569 	case OMP_LIST_FROM:
3570 	case OMP_LIST_CACHE:
3571 	  for (; n != NULL; n = n->next)
3572 	    {
3573 	      if (!n->sym->attr.referenced)
3574 		continue;
3575 
3576 	      switch (list)
3577 		{
3578 		case OMP_LIST_TO:
3579 		  clause_code = OMP_CLAUSE_TO;
3580 		  break;
3581 		case OMP_LIST_FROM:
3582 		  clause_code = OMP_CLAUSE_FROM;
3583 		  break;
3584 		case OMP_LIST_CACHE:
3585 		  clause_code = OMP_CLAUSE__CACHE_;
3586 		  break;
3587 		default:
3588 		  gcc_unreachable ();
3589 		}
3590 	      tree node = build_omp_clause (input_location, clause_code);
3591 	      if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
3592 		{
3593 		  tree decl = gfc_trans_omp_variable (n->sym, false);
3594 		  if (gfc_omp_privatize_by_reference (decl))
3595 		    {
3596 		      if (gfc_omp_is_allocatable_or_ptr (decl))
3597 			decl = build_fold_indirect_ref (decl);
3598 		      decl = build_fold_indirect_ref (decl);
3599 		    }
3600 		  else if (DECL_P (decl))
3601 		    TREE_ADDRESSABLE (decl) = 1;
3602 		  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
3603 		    {
3604 		      tree type = TREE_TYPE (decl);
3605 		      tree ptr = gfc_conv_descriptor_data_get (decl);
3606 		      gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3607 		      ptr = build_fold_indirect_ref (ptr);
3608 		      OMP_CLAUSE_DECL (node) = ptr;
3609 		      OMP_CLAUSE_SIZE (node)
3610 			= gfc_full_array_size (block, decl,
3611 					       GFC_TYPE_ARRAY_RANK (type));
3612 		      tree elemsz
3613 			= TYPE_SIZE_UNIT (gfc_get_element_type (type));
3614 		      elemsz = fold_convert (gfc_array_index_type, elemsz);
3615 		      OMP_CLAUSE_SIZE (node)
3616 			= fold_build2 (MULT_EXPR, gfc_array_index_type,
3617 				       OMP_CLAUSE_SIZE (node), elemsz);
3618 		    }
3619 		  else
3620 		    {
3621 		      OMP_CLAUSE_DECL (node) = decl;
3622 		      if (gfc_omp_is_allocatable_or_ptr (decl))
3623 			OMP_CLAUSE_SIZE (node)
3624 				= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
3625 		    }
3626 		}
3627 	      else
3628 		{
3629 		  tree ptr;
3630 		  gfc_init_se (&se, NULL);
3631 		  if (n->expr->ref->u.ar.type == AR_ELEMENT)
3632 		    {
3633 		      gfc_conv_expr_reference (&se, n->expr);
3634 		      ptr = se.expr;
3635 		      gfc_add_block_to_block (block, &se.pre);
3636 		      OMP_CLAUSE_SIZE (node)
3637 			= TYPE_SIZE_UNIT (TREE_TYPE (ptr));
3638 		    }
3639 		  else
3640 		    {
3641 		      gfc_conv_expr_descriptor (&se, n->expr);
3642 		      ptr = gfc_conv_array_data (se.expr);
3643 		      tree type = TREE_TYPE (se.expr);
3644 		      gfc_add_block_to_block (block, &se.pre);
3645 		      OMP_CLAUSE_SIZE (node)
3646 			= gfc_full_array_size (block, se.expr,
3647 					       GFC_TYPE_ARRAY_RANK (type));
3648 		      tree elemsz
3649 			= TYPE_SIZE_UNIT (gfc_get_element_type (type));
3650 		      elemsz = fold_convert (gfc_array_index_type, elemsz);
3651 		      OMP_CLAUSE_SIZE (node)
3652 			= fold_build2 (MULT_EXPR, gfc_array_index_type,
3653 				       OMP_CLAUSE_SIZE (node), elemsz);
3654 		    }
3655 		  gfc_add_block_to_block (block, &se.post);
3656 		  gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr)));
3657 		  OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
3658 		}
3659 	      omp_clauses = gfc_trans_add_clause (node, omp_clauses);
3660 	    }
3661 	  break;
3662 	default:
3663 	  break;
3664 	}
3665     }
3666 
3667   if (clauses->if_expr)
3668     {
3669       tree if_var;
3670 
3671       gfc_init_se (&se, NULL);
3672       gfc_conv_expr (&se, clauses->if_expr);
3673       gfc_add_block_to_block (block, &se.pre);
3674       if_var = gfc_evaluate_now (se.expr, block);
3675       gfc_add_block_to_block (block, &se.post);
3676 
3677       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3678       OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
3679       OMP_CLAUSE_IF_EXPR (c) = if_var;
3680       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3681     }
3682   for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
3683     if (clauses->if_exprs[ifc])
3684       {
3685 	tree if_var;
3686 
3687 	gfc_init_se (&se, NULL);
3688 	gfc_conv_expr (&se, clauses->if_exprs[ifc]);
3689 	gfc_add_block_to_block (block, &se.pre);
3690 	if_var = gfc_evaluate_now (se.expr, block);
3691 	gfc_add_block_to_block (block, &se.post);
3692 
3693 	c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3694 	switch (ifc)
3695 	  {
3696 	  case OMP_IF_CANCEL:
3697 	    OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST;
3698 	    break;
3699 	  case OMP_IF_PARALLEL:
3700 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
3701 	    break;
3702 	  case OMP_IF_SIMD:
3703 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD;
3704 	    break;
3705 	  case OMP_IF_TASK:
3706 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
3707 	    break;
3708 	  case OMP_IF_TASKLOOP:
3709 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
3710 	    break;
3711 	  case OMP_IF_TARGET:
3712 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
3713 	    break;
3714 	  case OMP_IF_TARGET_DATA:
3715 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
3716 	    break;
3717 	  case OMP_IF_TARGET_UPDATE:
3718 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
3719 	    break;
3720 	  case OMP_IF_TARGET_ENTER_DATA:
3721 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
3722 	    break;
3723 	  case OMP_IF_TARGET_EXIT_DATA:
3724 	    OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
3725 	    break;
3726 	  default:
3727 	    gcc_unreachable ();
3728 	  }
3729 	OMP_CLAUSE_IF_EXPR (c) = if_var;
3730 	omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3731       }
3732 
3733   if (clauses->final_expr)
3734     {
3735       tree final_var;
3736 
3737       gfc_init_se (&se, NULL);
3738       gfc_conv_expr (&se, clauses->final_expr);
3739       gfc_add_block_to_block (block, &se.pre);
3740       final_var = gfc_evaluate_now (se.expr, block);
3741       gfc_add_block_to_block (block, &se.post);
3742 
3743       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
3744       OMP_CLAUSE_FINAL_EXPR (c) = final_var;
3745       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3746     }
3747 
3748   if (clauses->num_threads)
3749     {
3750       tree num_threads;
3751 
3752       gfc_init_se (&se, NULL);
3753       gfc_conv_expr (&se, clauses->num_threads);
3754       gfc_add_block_to_block (block, &se.pre);
3755       num_threads = gfc_evaluate_now (se.expr, block);
3756       gfc_add_block_to_block (block, &se.post);
3757 
3758       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
3759       OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
3760       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3761     }
3762 
3763   chunk_size = NULL_TREE;
3764   if (clauses->chunk_size)
3765     {
3766       gfc_init_se (&se, NULL);
3767       gfc_conv_expr (&se, clauses->chunk_size);
3768       gfc_add_block_to_block (block, &se.pre);
3769       chunk_size = gfc_evaluate_now (se.expr, block);
3770       gfc_add_block_to_block (block, &se.post);
3771     }
3772 
3773   if (clauses->sched_kind != OMP_SCHED_NONE)
3774     {
3775       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
3776       OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3777       switch (clauses->sched_kind)
3778 	{
3779 	case OMP_SCHED_STATIC:
3780 	  OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
3781 	  break;
3782 	case OMP_SCHED_DYNAMIC:
3783 	  OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
3784 	  break;
3785 	case OMP_SCHED_GUIDED:
3786 	  OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
3787 	  break;
3788 	case OMP_SCHED_RUNTIME:
3789 	  OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
3790 	  break;
3791 	case OMP_SCHED_AUTO:
3792 	  OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
3793 	  break;
3794 	default:
3795 	  gcc_unreachable ();
3796 	}
3797       if (clauses->sched_monotonic)
3798 	OMP_CLAUSE_SCHEDULE_KIND (c)
3799 	  = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3800 					| OMP_CLAUSE_SCHEDULE_MONOTONIC);
3801       else if (clauses->sched_nonmonotonic)
3802 	OMP_CLAUSE_SCHEDULE_KIND (c)
3803 	  = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3804 					| OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
3805       if (clauses->sched_simd)
3806 	OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
3807       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3808     }
3809 
3810   if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
3811     {
3812       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
3813       switch (clauses->default_sharing)
3814 	{
3815 	case OMP_DEFAULT_NONE:
3816 	  OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
3817 	  break;
3818 	case OMP_DEFAULT_SHARED:
3819 	  OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
3820 	  break;
3821 	case OMP_DEFAULT_PRIVATE:
3822 	  OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
3823 	  break;
3824 	case OMP_DEFAULT_FIRSTPRIVATE:
3825 	  OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
3826 	  break;
3827 	case OMP_DEFAULT_PRESENT:
3828 	  OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
3829 	  break;
3830 	default:
3831 	  gcc_unreachable ();
3832 	}
3833       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3834     }
3835 
3836   if (clauses->nowait)
3837     {
3838       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
3839       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3840     }
3841 
3842   if (clauses->ordered)
3843     {
3844       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
3845       OMP_CLAUSE_ORDERED_EXPR (c)
3846 	= clauses->orderedc ? build_int_cst (integer_type_node,
3847 					     clauses->orderedc) : NULL_TREE;
3848       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3849     }
3850 
3851   if (clauses->order_concurrent)
3852     {
3853       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER);
3854       OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained;
3855       OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible;
3856       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3857     }
3858 
3859   if (clauses->untied)
3860     {
3861       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
3862       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3863     }
3864 
3865   if (clauses->mergeable)
3866     {
3867       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
3868       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3869     }
3870 
3871   if (clauses->collapse)
3872     {
3873       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
3874       OMP_CLAUSE_COLLAPSE_EXPR (c)
3875 	= build_int_cst (integer_type_node, clauses->collapse);
3876       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3877     }
3878 
3879   if (clauses->inbranch)
3880     {
3881       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
3882       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3883     }
3884 
3885   if (clauses->notinbranch)
3886     {
3887       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
3888       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3889     }
3890 
3891   switch (clauses->cancel)
3892     {
3893     case OMP_CANCEL_UNKNOWN:
3894       break;
3895     case OMP_CANCEL_PARALLEL:
3896       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
3897       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3898       break;
3899     case OMP_CANCEL_SECTIONS:
3900       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
3901       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3902       break;
3903     case OMP_CANCEL_DO:
3904       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
3905       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3906       break;
3907     case OMP_CANCEL_TASKGROUP:
3908       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
3909       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3910       break;
3911     }
3912 
3913   if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
3914     {
3915       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
3916       switch (clauses->proc_bind)
3917 	{
3918 	case OMP_PROC_BIND_PRIMARY:
3919 	  OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY;
3920 	  break;
3921 	case OMP_PROC_BIND_MASTER:
3922 	  OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
3923 	  break;
3924 	case OMP_PROC_BIND_SPREAD:
3925 	  OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
3926 	  break;
3927 	case OMP_PROC_BIND_CLOSE:
3928 	  OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
3929 	  break;
3930 	default:
3931 	  gcc_unreachable ();
3932 	}
3933       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3934     }
3935 
3936   if (clauses->safelen_expr)
3937     {
3938       tree safelen_var;
3939 
3940       gfc_init_se (&se, NULL);
3941       gfc_conv_expr (&se, clauses->safelen_expr);
3942       gfc_add_block_to_block (block, &se.pre);
3943       safelen_var = gfc_evaluate_now (se.expr, block);
3944       gfc_add_block_to_block (block, &se.post);
3945 
3946       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
3947       OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
3948       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3949     }
3950 
3951   if (clauses->simdlen_expr)
3952     {
3953       if (declare_simd)
3954 	{
3955 	  c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3956 	  OMP_CLAUSE_SIMDLEN_EXPR (c)
3957 	    = gfc_conv_constant_to_tree (clauses->simdlen_expr);
3958 	  omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3959 	}
3960       else
3961 	{
3962 	  tree simdlen_var;
3963 
3964 	  gfc_init_se (&se, NULL);
3965 	  gfc_conv_expr (&se, clauses->simdlen_expr);
3966 	  gfc_add_block_to_block (block, &se.pre);
3967 	  simdlen_var = gfc_evaluate_now (se.expr, block);
3968 	  gfc_add_block_to_block (block, &se.post);
3969 
3970 	  c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3971 	  OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
3972 	  omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3973 	}
3974     }
3975 
3976   if (clauses->num_teams_upper)
3977     {
3978       tree num_teams_lower = NULL_TREE, num_teams_upper;
3979 
3980       gfc_init_se (&se, NULL);
3981       gfc_conv_expr (&se, clauses->num_teams_upper);
3982       gfc_add_block_to_block (block, &se.pre);
3983       num_teams_upper = gfc_evaluate_now (se.expr, block);
3984       gfc_add_block_to_block (block, &se.post);
3985 
3986       if (clauses->num_teams_lower)
3987 	{
3988 	  gfc_init_se (&se, NULL);
3989 	  gfc_conv_expr (&se, clauses->num_teams_lower);
3990 	  gfc_add_block_to_block (block, &se.pre);
3991 	  num_teams_lower = gfc_evaluate_now (se.expr, block);
3992 	  gfc_add_block_to_block (block, &se.post);
3993 	}
3994       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
3995       OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
3996       OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
3997       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3998     }
3999 
4000   if (clauses->device)
4001     {
4002       tree device;
4003 
4004       gfc_init_se (&se, NULL);
4005       gfc_conv_expr (&se, clauses->device);
4006       gfc_add_block_to_block (block, &se.pre);
4007       device = gfc_evaluate_now (se.expr, block);
4008       gfc_add_block_to_block (block, &se.post);
4009 
4010       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
4011       OMP_CLAUSE_DEVICE_ID (c) = device;
4012 
4013       if (clauses->ancestor)
4014 	OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1;
4015 
4016       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4017     }
4018 
4019   if (clauses->thread_limit)
4020     {
4021       tree thread_limit;
4022 
4023       gfc_init_se (&se, NULL);
4024       gfc_conv_expr (&se, clauses->thread_limit);
4025       gfc_add_block_to_block (block, &se.pre);
4026       thread_limit = gfc_evaluate_now (se.expr, block);
4027       gfc_add_block_to_block (block, &se.post);
4028 
4029       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
4030       OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
4031       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4032     }
4033 
4034   chunk_size = NULL_TREE;
4035   if (clauses->dist_chunk_size)
4036     {
4037       gfc_init_se (&se, NULL);
4038       gfc_conv_expr (&se, clauses->dist_chunk_size);
4039       gfc_add_block_to_block (block, &se.pre);
4040       chunk_size = gfc_evaluate_now (se.expr, block);
4041       gfc_add_block_to_block (block, &se.post);
4042     }
4043 
4044   if (clauses->dist_sched_kind != OMP_SCHED_NONE)
4045     {
4046       c = build_omp_clause (gfc_get_location (&where),
4047 			    OMP_CLAUSE_DIST_SCHEDULE);
4048       OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
4049       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4050     }
4051 
4052   if (clauses->grainsize)
4053     {
4054       tree grainsize;
4055 
4056       gfc_init_se (&se, NULL);
4057       gfc_conv_expr (&se, clauses->grainsize);
4058       gfc_add_block_to_block (block, &se.pre);
4059       grainsize = gfc_evaluate_now (se.expr, block);
4060       gfc_add_block_to_block (block, &se.post);
4061 
4062       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
4063       OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
4064       if (clauses->grainsize_strict)
4065 	OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1;
4066       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4067     }
4068 
4069   if (clauses->num_tasks)
4070     {
4071       tree num_tasks;
4072 
4073       gfc_init_se (&se, NULL);
4074       gfc_conv_expr (&se, clauses->num_tasks);
4075       gfc_add_block_to_block (block, &se.pre);
4076       num_tasks = gfc_evaluate_now (se.expr, block);
4077       gfc_add_block_to_block (block, &se.post);
4078 
4079       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
4080       OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
4081       if (clauses->num_tasks_strict)
4082 	OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1;
4083       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4084     }
4085 
4086   if (clauses->priority)
4087     {
4088       tree priority;
4089 
4090       gfc_init_se (&se, NULL);
4091       gfc_conv_expr (&se, clauses->priority);
4092       gfc_add_block_to_block (block, &se.pre);
4093       priority = gfc_evaluate_now (se.expr, block);
4094       gfc_add_block_to_block (block, &se.post);
4095 
4096       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
4097       OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
4098       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4099     }
4100 
4101   if (clauses->detach)
4102     {
4103       tree detach;
4104 
4105       gfc_init_se (&se, NULL);
4106       gfc_conv_expr (&se, clauses->detach);
4107       gfc_add_block_to_block (block, &se.pre);
4108       detach = se.expr;
4109       gfc_add_block_to_block (block, &se.post);
4110 
4111       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH);
4112       TREE_ADDRESSABLE (detach) = 1;
4113       OMP_CLAUSE_DECL (c) = detach;
4114       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4115     }
4116 
4117   if (clauses->filter)
4118     {
4119       tree filter;
4120 
4121       gfc_init_se (&se, NULL);
4122       gfc_conv_expr (&se, clauses->filter);
4123       gfc_add_block_to_block (block, &se.pre);
4124       filter = gfc_evaluate_now (se.expr, block);
4125       gfc_add_block_to_block (block, &se.post);
4126 
4127       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER);
4128       OMP_CLAUSE_FILTER_EXPR (c) = filter;
4129       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4130     }
4131 
4132   if (clauses->hint)
4133     {
4134       tree hint;
4135 
4136       gfc_init_se (&se, NULL);
4137       gfc_conv_expr (&se, clauses->hint);
4138       gfc_add_block_to_block (block, &se.pre);
4139       hint = gfc_evaluate_now (se.expr, block);
4140       gfc_add_block_to_block (block, &se.post);
4141 
4142       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
4143       OMP_CLAUSE_HINT_EXPR (c) = hint;
4144       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4145     }
4146 
4147   if (clauses->simd)
4148     {
4149       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
4150       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4151     }
4152   if (clauses->threads)
4153     {
4154       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
4155       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4156     }
4157   if (clauses->nogroup)
4158     {
4159       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
4160       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4161     }
4162 
4163   for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
4164     {
4165       if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET)
4166        continue;
4167       enum omp_clause_defaultmap_kind behavior, category;
4168       switch ((gfc_omp_defaultmap_category) i)
4169 	{
4170 	case OMP_DEFAULTMAP_CAT_UNCATEGORIZED:
4171 	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
4172 	  break;
4173 	case OMP_DEFAULTMAP_CAT_SCALAR:
4174 	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
4175 	  break;
4176 	case OMP_DEFAULTMAP_CAT_AGGREGATE:
4177 	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
4178 	  break;
4179 	case OMP_DEFAULTMAP_CAT_ALLOCATABLE:
4180 	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE;
4181 	  break;
4182 	case OMP_DEFAULTMAP_CAT_POINTER:
4183 	  category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
4184 	  break;
4185 	default: gcc_unreachable ();
4186 	}
4187       switch (clauses->defaultmap[i])
4188 	{
4189 	case OMP_DEFAULTMAP_ALLOC:
4190 	  behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
4191 	  break;
4192 	case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break;
4193 	case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break;
4194 	case OMP_DEFAULTMAP_TOFROM:
4195 	  behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
4196 	  break;
4197 	case OMP_DEFAULTMAP_FIRSTPRIVATE:
4198 	  behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
4199 	  break;
4200 	case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break;
4201 	case OMP_DEFAULTMAP_DEFAULT:
4202 	  behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
4203 	  break;
4204 	default: gcc_unreachable ();
4205 	}
4206       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
4207       OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
4208       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4209     }
4210 
4211   if (clauses->depend_source)
4212     {
4213       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
4214       OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
4215       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4216     }
4217 
4218   if (clauses->async)
4219     {
4220       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
4221       if (clauses->async_expr)
4222 	OMP_CLAUSE_ASYNC_EXPR (c)
4223 	  = gfc_convert_expr_to_tree (block, clauses->async_expr);
4224       else
4225 	OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
4226       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4227     }
4228   if (clauses->seq)
4229     {
4230       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
4231       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4232     }
4233   if (clauses->par_auto)
4234     {
4235       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
4236       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4237     }
4238   if (clauses->if_present)
4239     {
4240       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
4241       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4242     }
4243   if (clauses->finalize)
4244     {
4245       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
4246       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4247     }
4248   if (clauses->independent)
4249     {
4250       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
4251       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4252     }
4253   if (clauses->wait_list)
4254     {
4255       gfc_expr_list *el;
4256 
4257       for (el = clauses->wait_list; el; el = el->next)
4258 	{
4259 	  c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
4260 	  OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
4261 	  OMP_CLAUSE_CHAIN (c) = omp_clauses;
4262 	  omp_clauses = c;
4263 	}
4264     }
4265   if (clauses->num_gangs_expr)
4266     {
4267       tree num_gangs_var
4268 	= gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
4269       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
4270       OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
4271       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4272     }
4273   if (clauses->num_workers_expr)
4274     {
4275       tree num_workers_var
4276 	= gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
4277       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
4278       OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
4279       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4280     }
4281   if (clauses->vector_length_expr)
4282     {
4283       tree vector_length_var
4284 	= gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
4285       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
4286       OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
4287       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4288     }
4289   if (clauses->tile_list)
4290     {
4291       vec<tree, va_gc> *tvec;
4292       gfc_expr_list *el;
4293 
4294       vec_alloc (tvec, 4);
4295 
4296       for (el = clauses->tile_list; el; el = el->next)
4297 	vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr));
4298 
4299       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
4300       OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec);
4301       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4302       tvec->truncate (0);
4303     }
4304   if (clauses->vector)
4305     {
4306       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
4307       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4308 
4309       if (clauses->vector_expr)
4310 	{
4311 	  tree vector_var
4312 	    = gfc_convert_expr_to_tree (block, clauses->vector_expr);
4313 	  OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
4314 
4315 	  /* TODO: We're not capturing location information for individual
4316 	     clauses.  However, if we have an expression attached to the
4317 	     clause, that one provides better location information.  */
4318 	  OMP_CLAUSE_LOCATION (c)
4319 	    = gfc_get_location (&clauses->vector_expr->where);
4320 	}
4321     }
4322   if (clauses->worker)
4323     {
4324       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
4325       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4326 
4327       if (clauses->worker_expr)
4328 	{
4329 	  tree worker_var
4330 	    = gfc_convert_expr_to_tree (block, clauses->worker_expr);
4331 	  OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
4332 
4333 	  /* TODO: We're not capturing location information for individual
4334 	     clauses.  However, if we have an expression attached to the
4335 	     clause, that one provides better location information.  */
4336 	  OMP_CLAUSE_LOCATION (c)
4337 	    = gfc_get_location (&clauses->worker_expr->where);
4338 	}
4339     }
4340   if (clauses->gang)
4341     {
4342       tree arg;
4343       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
4344       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4345 
4346       if (clauses->gang_num_expr)
4347 	{
4348 	  arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
4349 	  OMP_CLAUSE_GANG_EXPR (c) = arg;
4350 
4351 	  /* TODO: We're not capturing location information for individual
4352 	     clauses.  However, if we have an expression attached to the
4353 	     clause, that one provides better location information.  */
4354 	  OMP_CLAUSE_LOCATION (c)
4355 	    = gfc_get_location (&clauses->gang_num_expr->where);
4356 	}
4357 
4358       if (clauses->gang_static)
4359 	{
4360 	  arg = clauses->gang_static_expr
4361 	    ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
4362 	    : integer_minus_one_node;
4363 	  OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
4364 	}
4365     }
4366   if (clauses->bind != OMP_BIND_UNSET)
4367     {
4368       c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND);
4369       omp_clauses = gfc_trans_add_clause (c, omp_clauses);
4370       switch (clauses->bind)
4371 	{
4372 	case OMP_BIND_TEAMS:
4373 	  OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS;
4374 	  break;
4375 	case OMP_BIND_PARALLEL:
4376 	  OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL;
4377 	  break;
4378 	case OMP_BIND_THREAD:
4379 	  OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD;
4380 	  break;
4381 	default:
4382 	  gcc_unreachable ();
4383 	}
4384     }
4385   /* OpenACC 'nohost' clauses cannot appear here.  */
4386   gcc_checking_assert (!clauses->nohost);
4387 
4388   return nreverse (omp_clauses);
4389 }
4390 
4391 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it.  */
4392 
4393 static tree
gfc_trans_omp_code(gfc_code * code,bool force_empty)4394 gfc_trans_omp_code (gfc_code *code, bool force_empty)
4395 {
4396   tree stmt;
4397 
4398   pushlevel ();
4399   stmt = gfc_trans_code (code);
4400   if (TREE_CODE (stmt) != BIND_EXPR)
4401     {
4402       if (!IS_EMPTY_STMT (stmt) || force_empty)
4403 	{
4404 	  tree block = poplevel (1, 0);
4405 	  stmt = build3_v (BIND_EXPR, NULL, stmt, block);
4406 	}
4407       else
4408 	poplevel (0, 0);
4409     }
4410   else
4411     poplevel (0, 0);
4412   return stmt;
4413 }
4414 
4415 /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
4416    construct. */
4417 
4418 static tree
gfc_trans_oacc_construct(gfc_code * code)4419 gfc_trans_oacc_construct (gfc_code *code)
4420 {
4421   stmtblock_t block;
4422   tree stmt, oacc_clauses;
4423   enum tree_code construct_code;
4424 
4425   switch (code->op)
4426     {
4427       case EXEC_OACC_PARALLEL:
4428 	construct_code = OACC_PARALLEL;
4429 	break;
4430       case EXEC_OACC_KERNELS:
4431 	construct_code = OACC_KERNELS;
4432 	break;
4433       case EXEC_OACC_SERIAL:
4434 	construct_code = OACC_SERIAL;
4435 	break;
4436       case EXEC_OACC_DATA:
4437 	construct_code = OACC_DATA;
4438 	break;
4439       case EXEC_OACC_HOST_DATA:
4440 	construct_code = OACC_HOST_DATA;
4441 	break;
4442       default:
4443 	gcc_unreachable ();
4444     }
4445 
4446   gfc_start_block (&block);
4447   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4448 					code->loc, false, true);
4449   pushlevel ();
4450   stmt = gfc_trans_omp_code (code->block->next, true);
4451   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4452   stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
4453 		     void_type_node, stmt, oacc_clauses);
4454   gfc_add_expr_to_block (&block, stmt);
4455   return gfc_finish_block (&block);
4456 }
4457 
4458 /* update, enter_data, exit_data, cache. */
4459 static tree
gfc_trans_oacc_executable_directive(gfc_code * code)4460 gfc_trans_oacc_executable_directive (gfc_code *code)
4461 {
4462   stmtblock_t block;
4463   tree stmt, oacc_clauses;
4464   enum tree_code construct_code;
4465 
4466   switch (code->op)
4467     {
4468       case EXEC_OACC_UPDATE:
4469 	construct_code = OACC_UPDATE;
4470 	break;
4471       case EXEC_OACC_ENTER_DATA:
4472 	construct_code = OACC_ENTER_DATA;
4473 	break;
4474       case EXEC_OACC_EXIT_DATA:
4475 	construct_code = OACC_EXIT_DATA;
4476 	break;
4477       case EXEC_OACC_CACHE:
4478 	construct_code = OACC_CACHE;
4479 	break;
4480       default:
4481 	gcc_unreachable ();
4482     }
4483 
4484   gfc_start_block (&block);
4485   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4486 					code->loc, false, true);
4487   stmt = build1_loc (input_location, construct_code, void_type_node,
4488 		     oacc_clauses);
4489   gfc_add_expr_to_block (&block, stmt);
4490   return gfc_finish_block (&block);
4491 }
4492 
4493 static tree
gfc_trans_oacc_wait_directive(gfc_code * code)4494 gfc_trans_oacc_wait_directive (gfc_code *code)
4495 {
4496   stmtblock_t block;
4497   tree stmt, t;
4498   vec<tree, va_gc> *args;
4499   int nparms = 0;
4500   gfc_expr_list *el;
4501   gfc_omp_clauses *clauses = code->ext.omp_clauses;
4502   location_t loc = input_location;
4503 
4504   for (el = clauses->wait_list; el; el = el->next)
4505     nparms++;
4506 
4507   vec_alloc (args, nparms + 2);
4508   stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
4509 
4510   gfc_start_block (&block);
4511 
4512   if (clauses->async_expr)
4513     t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
4514   else
4515     t = build_int_cst (integer_type_node, -2);
4516 
4517   args->quick_push (t);
4518   args->quick_push (build_int_cst (integer_type_node, nparms));
4519 
4520   for (el = clauses->wait_list; el; el = el->next)
4521     args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
4522 
4523   stmt = build_call_expr_loc_vec (loc, stmt, args);
4524   gfc_add_expr_to_block (&block, stmt);
4525 
4526   vec_free (args);
4527 
4528   return gfc_finish_block (&block);
4529 }
4530 
4531 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
4532 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
4533 
4534 static tree
gfc_trans_omp_atomic(gfc_code * code)4535 gfc_trans_omp_atomic (gfc_code *code)
4536 {
4537   gfc_code *atomic_code = code->block;
4538   gfc_se lse;
4539   gfc_se rse;
4540   gfc_se vse;
4541   gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL;
4542   gfc_symbol *var;
4543   stmtblock_t block;
4544   tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE;
4545   enum tree_code op = ERROR_MARK;
4546   enum tree_code aop = OMP_ATOMIC;
4547   bool var_on_left = false, else_branch = false;
4548   enum omp_memory_order mo, fail_mo;
4549   switch (atomic_code->ext.omp_clauses->memorder)
4550     {
4551     case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break;
4552     case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break;
4553     case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break;
4554     case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break;
4555     case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break;
4556     case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break;
4557     default: gcc_unreachable ();
4558     }
4559   switch (atomic_code->ext.omp_clauses->fail)
4560     {
4561     case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break;
4562     case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break;
4563     case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break;
4564     case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break;
4565     default: gcc_unreachable ();
4566     }
4567   mo = (omp_memory_order) (mo | fail_mo);
4568 
4569   code = code->block->next;
4570   if (atomic_code->ext.omp_clauses->compare)
4571     {
4572       gfc_expr *comp_expr;
4573       if (code->op == EXEC_IF)
4574 	{
4575 	  comp_expr = code->block->expr1;
4576 	  gcc_assert (code->block->next->op == EXEC_ASSIGN);
4577 	  expr1 = code->block->next->expr1;
4578 	  expr2 = code->block->next->expr2;
4579 	  if (code->block->block)
4580 	    {
4581 	      gcc_assert (atomic_code->ext.omp_clauses->capture
4582 			  && code->block->block->next->op == EXEC_ASSIGN);
4583 	      else_branch = true;
4584 	      aop = OMP_ATOMIC_CAPTURE_OLD;
4585 	      capture_expr1 = code->block->block->next->expr1;
4586 	      capture_expr2 = code->block->block->next->expr2;
4587 	    }
4588 	  else if (atomic_code->ext.omp_clauses->capture)
4589 	    {
4590 	      gcc_assert (code->next->op == EXEC_ASSIGN);
4591 	      aop = OMP_ATOMIC_CAPTURE_NEW;
4592 	      capture_expr1 = code->next->expr1;
4593 	      capture_expr2 = code->next->expr2;
4594 	    }
4595 	}
4596       else
4597 	{
4598 	  gcc_assert (atomic_code->ext.omp_clauses->capture
4599 		      && code->op == EXEC_ASSIGN
4600 		      && code->next->op == EXEC_IF);
4601 	  aop = OMP_ATOMIC_CAPTURE_OLD;
4602 	  capture_expr1 = code->expr1;
4603 	  capture_expr2 = code->expr2;
4604 	  expr1 = code->next->block->next->expr1;
4605 	  expr2 = code->next->block->next->expr2;
4606 	  comp_expr = code->next->block->expr1;
4607 	}
4608       gfc_init_se (&lse, NULL);
4609       gfc_conv_expr (&lse, comp_expr->value.op.op2);
4610       gfc_add_block_to_block (&block, &lse.pre);
4611       compare = lse.expr;
4612       var = expr1->symtree->n.sym;
4613     }
4614   else
4615     {
4616       gcc_assert (code->op == EXEC_ASSIGN);
4617       expr1 = code->expr1;
4618       expr2 = code->expr2;
4619       if (atomic_code->ext.omp_clauses->capture
4620 	  && (expr2->expr_type == EXPR_VARIABLE
4621 	      || (expr2->expr_type == EXPR_FUNCTION
4622 		  && expr2->value.function.isym
4623 		  && expr2->value.function.isym->id == GFC_ISYM_CONVERSION
4624 		  && (expr2->value.function.actual->expr->expr_type
4625 		      == EXPR_VARIABLE))))
4626 	{
4627 	  capture_expr1 = expr1;
4628 	  capture_expr2 = expr2;
4629 	  expr1 = code->next->expr1;
4630 	  expr2 = code->next->expr2;
4631 	  aop = OMP_ATOMIC_CAPTURE_OLD;
4632 	}
4633       else if (atomic_code->ext.omp_clauses->capture)
4634 	{
4635 	  aop = OMP_ATOMIC_CAPTURE_NEW;
4636 	  capture_expr1 = code->next->expr1;
4637 	  capture_expr2 = code->next->expr2;
4638 	}
4639       var = expr1->symtree->n.sym;
4640     }
4641 
4642   gfc_init_se (&lse, NULL);
4643   gfc_init_se (&rse, NULL);
4644   gfc_init_se (&vse, NULL);
4645   gfc_start_block (&block);
4646 
4647   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4648        != GFC_OMP_ATOMIC_WRITE)
4649       && expr2->expr_type == EXPR_FUNCTION
4650       && expr2->value.function.isym
4651       && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
4652     expr2 = expr2->value.function.actual->expr;
4653 
4654   if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4655       == GFC_OMP_ATOMIC_READ)
4656     {
4657       gfc_conv_expr (&vse, expr1);
4658       gfc_add_block_to_block (&block, &vse.pre);
4659 
4660       gfc_conv_expr (&lse, expr2);
4661       gfc_add_block_to_block (&block, &lse.pre);
4662       type = TREE_TYPE (lse.expr);
4663       lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
4664 
4665       x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
4666       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4667       x = convert (TREE_TYPE (vse.expr), x);
4668       gfc_add_modify (&block, vse.expr, x);
4669 
4670       gfc_add_block_to_block (&block, &lse.pre);
4671       gfc_add_block_to_block (&block, &rse.pre);
4672 
4673       return gfc_finish_block (&block);
4674     }
4675 
4676   if (capture_expr2
4677       && capture_expr2->expr_type == EXPR_FUNCTION
4678       && capture_expr2->value.function.isym
4679       && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
4680     capture_expr2 = capture_expr2->value.function.actual->expr;
4681   gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE);
4682 
4683   if (aop == OMP_ATOMIC_CAPTURE_OLD)
4684     {
4685       gfc_conv_expr (&vse, capture_expr1);
4686       gfc_add_block_to_block (&block, &vse.pre);
4687       gfc_conv_expr (&lse, capture_expr2);
4688       gfc_add_block_to_block (&block, &lse.pre);
4689       gfc_init_se (&lse, NULL);
4690     }
4691 
4692   gfc_conv_expr (&lse, expr1);
4693   gfc_add_block_to_block (&block, &lse.pre);
4694   type = TREE_TYPE (lse.expr);
4695   lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
4696 
4697   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4698        == GFC_OMP_ATOMIC_WRITE)
4699       || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
4700       || compare)
4701     {
4702       gfc_conv_expr (&rse, expr2);
4703       gfc_add_block_to_block (&block, &rse.pre);
4704     }
4705   else if (expr2->expr_type == EXPR_OP)
4706     {
4707       gfc_expr *e;
4708       switch (expr2->value.op.op)
4709 	{
4710 	case INTRINSIC_PLUS:
4711 	  op = PLUS_EXPR;
4712 	  break;
4713 	case INTRINSIC_TIMES:
4714 	  op = MULT_EXPR;
4715 	  break;
4716 	case INTRINSIC_MINUS:
4717 	  op = MINUS_EXPR;
4718 	  break;
4719 	case INTRINSIC_DIVIDE:
4720 	  if (expr2->ts.type == BT_INTEGER)
4721 	    op = TRUNC_DIV_EXPR;
4722 	  else
4723 	    op = RDIV_EXPR;
4724 	  break;
4725 	case INTRINSIC_AND:
4726 	  op = TRUTH_ANDIF_EXPR;
4727 	  break;
4728 	case INTRINSIC_OR:
4729 	  op = TRUTH_ORIF_EXPR;
4730 	  break;
4731 	case INTRINSIC_EQV:
4732 	  op = EQ_EXPR;
4733 	  break;
4734 	case INTRINSIC_NEQV:
4735 	  op = NE_EXPR;
4736 	  break;
4737 	default:
4738 	  gcc_unreachable ();
4739 	}
4740       e = expr2->value.op.op1;
4741       if (e->expr_type == EXPR_FUNCTION
4742 	  && e->value.function.isym
4743 	  && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4744 	e = e->value.function.actual->expr;
4745       if (e->expr_type == EXPR_VARIABLE
4746 	  && e->symtree != NULL
4747 	  && e->symtree->n.sym == var)
4748 	{
4749 	  expr2 = expr2->value.op.op2;
4750 	  var_on_left = true;
4751 	}
4752       else
4753 	{
4754 	  e = expr2->value.op.op2;
4755 	  if (e->expr_type == EXPR_FUNCTION
4756 	      && e->value.function.isym
4757 	      && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4758 	    e = e->value.function.actual->expr;
4759 	  gcc_assert (e->expr_type == EXPR_VARIABLE
4760 		      && e->symtree != NULL
4761 		      && e->symtree->n.sym == var);
4762 	  expr2 = expr2->value.op.op1;
4763 	  var_on_left = false;
4764 	}
4765       gfc_conv_expr (&rse, expr2);
4766       gfc_add_block_to_block (&block, &rse.pre);
4767     }
4768   else
4769     {
4770       gcc_assert (expr2->expr_type == EXPR_FUNCTION);
4771       switch (expr2->value.function.isym->id)
4772 	{
4773 	case GFC_ISYM_MIN:
4774 	  op = MIN_EXPR;
4775 	  break;
4776 	case GFC_ISYM_MAX:
4777 	  op = MAX_EXPR;
4778 	  break;
4779 	case GFC_ISYM_IAND:
4780 	  op = BIT_AND_EXPR;
4781 	  break;
4782 	case GFC_ISYM_IOR:
4783 	  op = BIT_IOR_EXPR;
4784 	  break;
4785 	case GFC_ISYM_IEOR:
4786 	  op = BIT_XOR_EXPR;
4787 	  break;
4788 	default:
4789 	  gcc_unreachable ();
4790 	}
4791       e = expr2->value.function.actual->expr;
4792       if (e->expr_type == EXPR_FUNCTION
4793 	  && e->value.function.isym
4794 	  && e->value.function.isym->id == GFC_ISYM_CONVERSION)
4795 	e = e->value.function.actual->expr;
4796       gcc_assert (e->expr_type == EXPR_VARIABLE
4797 		  && e->symtree != NULL
4798 		  && e->symtree->n.sym == var);
4799 
4800       gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
4801       gfc_add_block_to_block (&block, &rse.pre);
4802       if (expr2->value.function.actual->next->next != NULL)
4803 	{
4804 	  tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
4805 	  gfc_actual_arglist *arg;
4806 
4807 	  gfc_add_modify (&block, accum, rse.expr);
4808 	  for (arg = expr2->value.function.actual->next->next; arg;
4809 	       arg = arg->next)
4810 	    {
4811 	      gfc_init_block (&rse.pre);
4812 	      gfc_conv_expr (&rse, arg->expr);
4813 	      gfc_add_block_to_block (&block, &rse.pre);
4814 	      x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
4815 				   accum, rse.expr);
4816 	      gfc_add_modify (&block, accum, x);
4817 	    }
4818 
4819 	  rse.expr = accum;
4820 	}
4821 
4822       expr2 = expr2->value.function.actual->next->expr;
4823     }
4824 
4825   lhsaddr = save_expr (lhsaddr);
4826   if (TREE_CODE (lhsaddr) != SAVE_EXPR
4827       && (TREE_CODE (lhsaddr) != ADDR_EXPR
4828 	  || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
4829     {
4830       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
4831 	 it even after unsharing function body.  */
4832       tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
4833       DECL_CONTEXT (var) = current_function_decl;
4834       lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
4835 			NULL_TREE, NULL_TREE);
4836     }
4837 
4838   if (compare)
4839     {
4840       tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
4841       DECL_CONTEXT (var) = current_function_decl;
4842       lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL,
4843 			NULL);
4844       lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr);
4845       compare = convert (TREE_TYPE (lse.expr), compare);
4846       compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
4847 				 lse.expr, compare);
4848     }
4849 
4850   if (expr2->expr_type == EXPR_VARIABLE || compare)
4851     rhs = rse.expr;
4852   else
4853     rhs = gfc_evaluate_now (rse.expr, &block);
4854 
4855   if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK)
4856        == GFC_OMP_ATOMIC_WRITE)
4857       || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP)
4858       || compare)
4859     x = rhs;
4860   else
4861     {
4862       x = convert (TREE_TYPE (rhs),
4863 		   build_fold_indirect_ref_loc (input_location, lhsaddr));
4864       if (var_on_left)
4865 	x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
4866       else
4867 	x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
4868     }
4869 
4870   if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
4871       && TREE_CODE (type) != COMPLEX_TYPE)
4872     x = fold_build1_loc (input_location, REALPART_EXPR,
4873 			 TREE_TYPE (TREE_TYPE (rhs)), x);
4874 
4875   gfc_add_block_to_block (&block, &lse.pre);
4876   gfc_add_block_to_block (&block, &rse.pre);
4877 
4878   if (aop == OMP_ATOMIC_CAPTURE_NEW)
4879     {
4880       gfc_conv_expr (&vse, capture_expr1);
4881       gfc_add_block_to_block (&block, &vse.pre);
4882       gfc_add_block_to_block (&block, &lse.pre);
4883     }
4884 
4885   if (compare && else_branch)
4886     {
4887       tree var2 = create_tmp_var_raw (boolean_type_node);
4888       DECL_CONTEXT (var2) = current_function_decl;
4889       comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2,
4890 			 boolean_false_node, NULL, NULL);
4891       compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2),
4892 				 var2, compare);
4893       TREE_OPERAND (compare, 0) = comp_tgt;
4894       compare = omit_one_operand_loc (input_location, boolean_type_node,
4895 				      compare, comp_tgt);
4896     }
4897 
4898   if (compare)
4899     x = build3_loc (input_location, COND_EXPR, type, compare,
4900 		    convert (type, x), lse.expr);
4901 
4902   if (aop == OMP_ATOMIC)
4903     {
4904       x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
4905       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4906       OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
4907       gfc_add_expr_to_block (&block, x);
4908     }
4909   else
4910     {
4911       x = build2 (aop, type, lhsaddr, convert (type, x));
4912       OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4913       OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak;
4914       if (compare && else_branch)
4915 	{
4916 	  tree vtmp = create_tmp_var_raw (TREE_TYPE (x));
4917 	  DECL_CONTEXT (vtmp) = current_function_decl;
4918 	  x = fold_build2_loc (input_location, MODIFY_EXPR,
4919 			       TREE_TYPE (vtmp), vtmp, x);
4920 	  vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
4921 			 build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
4922 	  TREE_OPERAND (x, 0) = vtmp;
4923 	  tree x2 = convert (TREE_TYPE (vse.expr), vtmp);
4924 	  x2 = fold_build2_loc (input_location, MODIFY_EXPR,
4925 			       TREE_TYPE (vse.expr), vse.expr, x2);
4926 	  x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt,
4927 			   void_node, x2);
4928 	  x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x);
4929 	  gfc_add_expr_to_block (&block, x);
4930 	}
4931       else
4932 	{
4933 	  x = convert (TREE_TYPE (vse.expr), x);
4934 	  gfc_add_modify (&block, vse.expr, x);
4935 	}
4936     }
4937 
4938   return gfc_finish_block (&block);
4939 }
4940 
4941 static tree
gfc_trans_omp_barrier(void)4942 gfc_trans_omp_barrier (void)
4943 {
4944   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
4945   return build_call_expr_loc (input_location, decl, 0);
4946 }
4947 
4948 static tree
gfc_trans_omp_cancel(gfc_code * code)4949 gfc_trans_omp_cancel (gfc_code *code)
4950 {
4951   int mask = 0;
4952   tree ifc = boolean_true_node;
4953   stmtblock_t block;
4954   switch (code->ext.omp_clauses->cancel)
4955     {
4956     case OMP_CANCEL_PARALLEL: mask = 1; break;
4957     case OMP_CANCEL_DO: mask = 2; break;
4958     case OMP_CANCEL_SECTIONS: mask = 4; break;
4959     case OMP_CANCEL_TASKGROUP: mask = 8; break;
4960     default: gcc_unreachable ();
4961     }
4962   gfc_start_block (&block);
4963   if (code->ext.omp_clauses->if_expr
4964       || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL])
4965     {
4966       gfc_se se;
4967       tree if_var;
4968 
4969       gcc_assert ((code->ext.omp_clauses->if_expr == NULL)
4970 		  ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL));
4971       gfc_init_se (&se, NULL);
4972       gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL
4973 			  ? code->ext.omp_clauses->if_expr
4974 			  : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]);
4975       gfc_add_block_to_block (&block, &se.pre);
4976       if_var = gfc_evaluate_now (se.expr, &block);
4977       gfc_add_block_to_block (&block, &se.post);
4978       tree type = TREE_TYPE (if_var);
4979       ifc = fold_build2_loc (input_location, NE_EXPR,
4980 			     boolean_type_node, if_var,
4981 			     build_zero_cst (type));
4982     }
4983   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
4984   tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
4985   ifc = fold_convert (c_bool_type, ifc);
4986   gfc_add_expr_to_block (&block,
4987 			 build_call_expr_loc (input_location, decl, 2,
4988 					      build_int_cst (integer_type_node,
4989 							     mask), ifc));
4990   return gfc_finish_block (&block);
4991 }
4992 
4993 static tree
gfc_trans_omp_cancellation_point(gfc_code * code)4994 gfc_trans_omp_cancellation_point (gfc_code *code)
4995 {
4996   int mask = 0;
4997   switch (code->ext.omp_clauses->cancel)
4998     {
4999     case OMP_CANCEL_PARALLEL: mask = 1; break;
5000     case OMP_CANCEL_DO: mask = 2; break;
5001     case OMP_CANCEL_SECTIONS: mask = 4; break;
5002     case OMP_CANCEL_TASKGROUP: mask = 8; break;
5003     default: gcc_unreachable ();
5004     }
5005   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
5006   return build_call_expr_loc (input_location, decl, 1,
5007 			      build_int_cst (integer_type_node, mask));
5008 }
5009 
5010 static tree
gfc_trans_omp_critical(gfc_code * code)5011 gfc_trans_omp_critical (gfc_code *code)
5012 {
5013   stmtblock_t block;
5014   tree stmt, name = NULL_TREE;
5015   if (code->ext.omp_clauses->critical_name != NULL)
5016     name = get_identifier (code->ext.omp_clauses->critical_name);
5017   gfc_start_block (&block);
5018   stmt = make_node (OMP_CRITICAL);
5019   TREE_TYPE (stmt) = void_type_node;
5020   OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
5021   OMP_CRITICAL_NAME (stmt) = name;
5022   OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
5023 						       code->ext.omp_clauses,
5024 						       code->loc);
5025   gfc_add_expr_to_block (&block, stmt);
5026   return gfc_finish_block (&block);
5027 }
5028 
5029 typedef struct dovar_init_d {
5030   tree var;
5031   tree init;
5032 } dovar_init;
5033 
5034 
5035 static tree
gfc_trans_omp_do(gfc_code * code,gfc_exec_op op,stmtblock_t * pblock,gfc_omp_clauses * do_clauses,tree par_clauses)5036 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
5037 		  gfc_omp_clauses *do_clauses, tree par_clauses)
5038 {
5039   gfc_se se;
5040   tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
5041   tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
5042   stmtblock_t block;
5043   stmtblock_t body;
5044   gfc_omp_clauses *clauses = code->ext.omp_clauses;
5045   int i, collapse = clauses->collapse;
5046   vec<dovar_init> inits = vNULL;
5047   dovar_init *di;
5048   unsigned ix;
5049   vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
5050   gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
5051 
5052   /* Both collapsed and tiled loops are lowered the same way.  In
5053      OpenACC, those clauses are not compatible, so prioritize the tile
5054      clause, if present.  */
5055   if (tile)
5056     {
5057       collapse = 0;
5058       for (gfc_expr_list *el = tile; el; el = el->next)
5059 	collapse++;
5060     }
5061 
5062   doacross_steps = NULL;
5063   if (clauses->orderedc)
5064     collapse = clauses->orderedc;
5065   if (collapse <= 0)
5066     collapse = 1;
5067 
5068   code = code->block->next;
5069   gcc_assert (code->op == EXEC_DO);
5070 
5071   init = make_tree_vec (collapse);
5072   cond = make_tree_vec (collapse);
5073   incr = make_tree_vec (collapse);
5074   orig_decls = clauses->orderedc ? make_tree_vec (collapse) : NULL_TREE;
5075 
5076   if (pblock == NULL)
5077     {
5078       gfc_start_block (&block);
5079       pblock = &block;
5080     }
5081 
5082   /* simd schedule modifier is only useful for composite do simd and other
5083      constructs including that, where gfc_trans_omp_do is only called
5084      on the simd construct and DO's clauses are translated elsewhere.  */
5085   do_clauses->sched_simd = false;
5086 
5087   omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
5088 
5089   for (i = 0; i < collapse; i++)
5090     {
5091       int simple = 0;
5092       int dovar_found = 0;
5093       tree dovar_decl;
5094 
5095       if (clauses)
5096 	{
5097 	  gfc_omp_namelist *n = NULL;
5098 	  if (op == EXEC_OMP_SIMD && collapse == 1)
5099 	    for (n = clauses->lists[OMP_LIST_LINEAR];
5100 		 n != NULL; n = n->next)
5101 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
5102 		{
5103 		  dovar_found = 3;
5104 		  break;
5105 		}
5106 	  if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
5107 	    for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
5108 		 n != NULL; n = n->next)
5109 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
5110 		{
5111 		  dovar_found = 2;
5112 		  break;
5113 		}
5114 	  if (n == NULL)
5115 	    for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
5116 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
5117 		{
5118 		  dovar_found = 1;
5119 		  break;
5120 		}
5121 	}
5122 
5123       /* Evaluate all the expressions in the iterator.  */
5124       gfc_init_se (&se, NULL);
5125       gfc_conv_expr_lhs (&se, code->ext.iterator->var);
5126       gfc_add_block_to_block (pblock, &se.pre);
5127       dovar = se.expr;
5128       type = TREE_TYPE (dovar);
5129       gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
5130 
5131       gfc_init_se (&se, NULL);
5132       gfc_conv_expr_val (&se, code->ext.iterator->start);
5133       gfc_add_block_to_block (pblock, &se.pre);
5134       from = gfc_evaluate_now (se.expr, pblock);
5135 
5136       gfc_init_se (&se, NULL);
5137       gfc_conv_expr_val (&se, code->ext.iterator->end);
5138       gfc_add_block_to_block (pblock, &se.pre);
5139       to = gfc_evaluate_now (se.expr, pblock);
5140 
5141       gfc_init_se (&se, NULL);
5142       gfc_conv_expr_val (&se, code->ext.iterator->step);
5143       gfc_add_block_to_block (pblock, &se.pre);
5144       step = gfc_evaluate_now (se.expr, pblock);
5145       dovar_decl = dovar;
5146 
5147       /* Special case simple loops.  */
5148       if (VAR_P (dovar))
5149 	{
5150 	  if (integer_onep (step))
5151 	    simple = 1;
5152 	  else if (tree_int_cst_equal (step, integer_minus_one_node))
5153 	    simple = -1;
5154 	}
5155       else
5156 	dovar_decl
5157 	  = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
5158 				    false);
5159 
5160       /* Loop body.  */
5161       if (simple)
5162 	{
5163 	  TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
5164 	  /* The condition should not be folded.  */
5165 	  TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
5166 					       ? LE_EXPR : GE_EXPR,
5167 					       logical_type_node, dovar, to);
5168 	  TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5169 						    type, dovar, step);
5170 	  TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5171 						    MODIFY_EXPR,
5172 						    type, dovar,
5173 						    TREE_VEC_ELT (incr, i));
5174 	}
5175       else
5176 	{
5177 	  /* STEP is not 1 or -1.  Use:
5178 	     for (count = 0; count < (to + step - from) / step; count++)
5179 	       {
5180 		 dovar = from + count * step;
5181 		 body;
5182 	       cycle_label:;
5183 	       }  */
5184 	  tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
5185 	  tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
5186 	  tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
5187 				 step);
5188 	  tmp = gfc_evaluate_now (tmp, pblock);
5189 	  count = gfc_create_var (type, "count");
5190 	  TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
5191 					     build_int_cst (type, 0));
5192 	  /* The condition should not be folded.  */
5193 	  TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
5194 					       logical_type_node,
5195 					       count, tmp);
5196 	  TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
5197 						    type, count,
5198 						    build_int_cst (type, 1));
5199 	  TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
5200 						    MODIFY_EXPR, type, count,
5201 						    TREE_VEC_ELT (incr, i));
5202 
5203 	  /* Initialize DOVAR.  */
5204 	  tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
5205 	  tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
5206 	  dovar_init e = {dovar, tmp};
5207 	  inits.safe_push (e);
5208 	  if (clauses->orderedc)
5209 	    {
5210 	      if (doacross_steps == NULL)
5211 		vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true);
5212 	      (*doacross_steps)[i] = step;
5213 	    }
5214 	}
5215       if (orig_decls)
5216 	TREE_VEC_ELT (orig_decls, i) = dovar_decl;
5217 
5218       if (dovar_found == 3
5219 	  && op == EXEC_OMP_SIMD
5220 	  && collapse == 1
5221 	  && !simple)
5222 	{
5223 	  for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
5224 	    if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
5225 		&& OMP_CLAUSE_DECL (tmp) == dovar)
5226 	      {
5227 		OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5228 		break;
5229 	      }
5230 	}
5231       if (!dovar_found && op == EXEC_OMP_SIMD)
5232 	{
5233 	  if (collapse == 1)
5234 	    {
5235 	      tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
5236 	      OMP_CLAUSE_LINEAR_STEP (tmp) = step;
5237 	      OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5238 	      OMP_CLAUSE_DECL (tmp) = dovar_decl;
5239 	      omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5240 	    }
5241 	  if (!simple)
5242 	    dovar_found = 3;
5243 	}
5244       else if (!dovar_found && !simple)
5245 	{
5246 	  tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
5247 	  OMP_CLAUSE_DECL (tmp) = dovar_decl;
5248 	  omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5249 	}
5250       if (dovar_found > 1)
5251 	{
5252 	  tree c = NULL;
5253 
5254 	  tmp = NULL;
5255 	  if (!simple)
5256 	    {
5257 	      /* If dovar is lastprivate, but different counter is used,
5258 		 dovar += step needs to be added to
5259 		 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
5260 		 will have the value on entry of the last loop, rather
5261 		 than value after iterator increment.  */
5262 	      if (clauses->orderedc)
5263 		{
5264 		  if (clauses->collapse <= 1 || i >= clauses->collapse)
5265 		    tmp = count;
5266 		  else
5267 		    tmp = fold_build2_loc (input_location, PLUS_EXPR,
5268 					   type, count, build_one_cst (type));
5269 		  tmp = fold_build2_loc (input_location, MULT_EXPR, type,
5270 					 tmp, step);
5271 		  tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
5272 					 from, tmp);
5273 		}
5274 	      else
5275 		{
5276 		  tmp = gfc_evaluate_now (step, pblock);
5277 		  tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
5278 					 dovar, tmp);
5279 		}
5280 	      tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
5281 				     dovar, tmp);
5282 	      for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5283 		if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5284 		    && OMP_CLAUSE_DECL (c) == dovar_decl)
5285 		  {
5286 		    OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
5287 		    break;
5288 		  }
5289 		else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5290 			 && OMP_CLAUSE_DECL (c) == dovar_decl)
5291 		  {
5292 		    OMP_CLAUSE_LINEAR_STMT (c) = tmp;
5293 		    break;
5294 		  }
5295 	    }
5296 	  if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
5297 	    {
5298 	      for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5299 		if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5300 		    && OMP_CLAUSE_DECL (c) == dovar_decl)
5301 		  {
5302 		    tree l = build_omp_clause (input_location,
5303 					       OMP_CLAUSE_LASTPRIVATE);
5304 		    if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
5305 		      OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1;
5306 		    OMP_CLAUSE_DECL (l) = dovar_decl;
5307 		    OMP_CLAUSE_CHAIN (l) = omp_clauses;
5308 		    OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
5309 		    omp_clauses = l;
5310 		    OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
5311 		    break;
5312 		  }
5313 	    }
5314 	  gcc_assert (simple || c != NULL);
5315 	}
5316       if (!simple)
5317 	{
5318 	  if (op != EXEC_OMP_SIMD || dovar_found == 1)
5319 	    tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
5320 	  else if (collapse == 1)
5321 	    {
5322 	      tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
5323 	      OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
5324 	      OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
5325 	      OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
5326 	    }
5327 	  else
5328 	    tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
5329 	  OMP_CLAUSE_DECL (tmp) = count;
5330 	  omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
5331 	}
5332 
5333       if (i + 1 < collapse)
5334 	code = code->block->next;
5335     }
5336 
5337   if (pblock != &block)
5338     {
5339       pushlevel ();
5340       gfc_start_block (&block);
5341     }
5342 
5343   gfc_start_block (&body);
5344 
5345   FOR_EACH_VEC_ELT (inits, ix, di)
5346     gfc_add_modify (&body, di->var, di->init);
5347   inits.release ();
5348 
5349   /* Cycle statement is implemented with a goto.  Exit statement must not be
5350      present for this loop.  */
5351   cycle_label = gfc_build_label_decl (NULL_TREE);
5352 
5353   /* Put these labels where they can be found later.  */
5354 
5355   code->cycle_label = cycle_label;
5356   code->exit_label = NULL_TREE;
5357 
5358   /* Main loop body.  */
5359   if (clauses->lists[OMP_LIST_REDUCTION_INSCAN])
5360     {
5361       gcc_assert (code->block->next->next->op == EXEC_OMP_SCAN);
5362       gcc_assert (code->block->next->next->next->next == NULL);
5363       locus *cloc = &code->block->next->next->loc;
5364       location_t loc = gfc_get_location (cloc);
5365 
5366       gfc_code code2 = *code->block->next;
5367       code2.next = NULL;
5368       tmp = gfc_trans_code (&code2);
5369       tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE);
5370       SET_EXPR_LOCATION (tmp, loc);
5371       gfc_add_expr_to_block (&body, tmp);
5372       input_location = loc;
5373       tree c = gfc_trans_omp_clauses (&body,
5374 				      code->block->next->next->ext.omp_clauses,
5375 				      *cloc);
5376       code2 = *code->block->next->next->next;
5377       code2.next = NULL;
5378       tmp = gfc_trans_code (&code2);
5379       tmp = build2 (OMP_SCAN, void_type_node, tmp, c);
5380       SET_EXPR_LOCATION (tmp, loc);
5381     }
5382   else
5383     tmp = gfc_trans_omp_code (code->block->next, true);
5384   gfc_add_expr_to_block (&body, tmp);
5385 
5386   /* Label for cycle statements (if needed).  */
5387   if (TREE_USED (cycle_label))
5388     {
5389       tmp = build1_v (LABEL_EXPR, cycle_label);
5390       gfc_add_expr_to_block (&body, tmp);
5391     }
5392 
5393   /* End of loop body.  */
5394   switch (op)
5395     {
5396     case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
5397     case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
5398     case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
5399     case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break;
5400     case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
5401     case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
5402     default: gcc_unreachable ();
5403     }
5404 
5405   TREE_TYPE (stmt) = void_type_node;
5406   OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
5407   OMP_FOR_CLAUSES (stmt) = omp_clauses;
5408   OMP_FOR_INIT (stmt) = init;
5409   OMP_FOR_COND (stmt) = cond;
5410   OMP_FOR_INCR (stmt) = incr;
5411   if (orig_decls)
5412     OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
5413   gfc_add_expr_to_block (&block, stmt);
5414 
5415   vec_free (doacross_steps);
5416   doacross_steps = saved_doacross_steps;
5417 
5418   return gfc_finish_block (&block);
5419 }
5420 
5421 /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
5422    construct. */
5423 
5424 static tree
gfc_trans_oacc_combined_directive(gfc_code * code)5425 gfc_trans_oacc_combined_directive (gfc_code *code)
5426 {
5427   stmtblock_t block, *pblock = NULL;
5428   gfc_omp_clauses construct_clauses, loop_clauses;
5429   tree stmt, oacc_clauses = NULL_TREE;
5430   enum tree_code construct_code;
5431   location_t loc = input_location;
5432 
5433   switch (code->op)
5434     {
5435       case EXEC_OACC_PARALLEL_LOOP:
5436 	construct_code = OACC_PARALLEL;
5437 	break;
5438       case EXEC_OACC_KERNELS_LOOP:
5439 	construct_code = OACC_KERNELS;
5440 	break;
5441       case EXEC_OACC_SERIAL_LOOP:
5442 	construct_code = OACC_SERIAL;
5443 	break;
5444       default:
5445 	gcc_unreachable ();
5446     }
5447 
5448   gfc_start_block (&block);
5449 
5450   memset (&loop_clauses, 0, sizeof (loop_clauses));
5451   if (code->ext.omp_clauses != NULL)
5452     {
5453       memcpy (&construct_clauses, code->ext.omp_clauses,
5454 	      sizeof (construct_clauses));
5455       loop_clauses.collapse = construct_clauses.collapse;
5456       loop_clauses.gang = construct_clauses.gang;
5457       loop_clauses.gang_static = construct_clauses.gang_static;
5458       loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
5459       loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
5460       loop_clauses.vector = construct_clauses.vector;
5461       loop_clauses.vector_expr = construct_clauses.vector_expr;
5462       loop_clauses.worker = construct_clauses.worker;
5463       loop_clauses.worker_expr = construct_clauses.worker_expr;
5464       loop_clauses.seq = construct_clauses.seq;
5465       loop_clauses.par_auto = construct_clauses.par_auto;
5466       loop_clauses.independent = construct_clauses.independent;
5467       loop_clauses.tile_list = construct_clauses.tile_list;
5468       loop_clauses.lists[OMP_LIST_PRIVATE]
5469 	= construct_clauses.lists[OMP_LIST_PRIVATE];
5470       loop_clauses.lists[OMP_LIST_REDUCTION]
5471 	= construct_clauses.lists[OMP_LIST_REDUCTION];
5472       construct_clauses.gang = false;
5473       construct_clauses.gang_static = false;
5474       construct_clauses.gang_num_expr = NULL;
5475       construct_clauses.gang_static_expr = NULL;
5476       construct_clauses.vector = false;
5477       construct_clauses.vector_expr = NULL;
5478       construct_clauses.worker = false;
5479       construct_clauses.worker_expr = NULL;
5480       construct_clauses.seq = false;
5481       construct_clauses.par_auto = false;
5482       construct_clauses.independent = false;
5483       construct_clauses.independent = false;
5484       construct_clauses.tile_list = NULL;
5485       construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
5486       if (construct_code == OACC_KERNELS)
5487 	construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
5488       oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
5489 					    code->loc, false, true);
5490     }
5491   if (!loop_clauses.seq)
5492     pblock = &block;
5493   else
5494     pushlevel ();
5495   stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
5496   protected_set_expr_location (stmt, loc);
5497   if (TREE_CODE (stmt) != BIND_EXPR)
5498     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5499   else
5500     poplevel (0, 0);
5501   stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
5502   gfc_add_expr_to_block (&block, stmt);
5503   return gfc_finish_block (&block);
5504 }
5505 
5506 static tree
gfc_trans_omp_depobj(gfc_code * code)5507 gfc_trans_omp_depobj (gfc_code *code)
5508 {
5509   stmtblock_t block;
5510   gfc_se se;
5511   gfc_init_se (&se, NULL);
5512   gfc_init_block (&block);
5513   gfc_conv_expr (&se, code->ext.omp_clauses->depobj);
5514   gcc_assert (se.pre.head == NULL && se.post.head == NULL);
5515   tree depobj = se.expr;
5516   location_t loc = EXPR_LOCATION (depobj);
5517   if (!POINTER_TYPE_P (TREE_TYPE (depobj)))
5518     depobj = gfc_build_addr_expr (NULL, depobj);
5519   depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node,
5520 						      TYPE_MODE (ptr_type_node),
5521 						      true), depobj);
5522   gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND];
5523   if (n)
5524     {
5525       tree var;
5526       if (n->expr && n->expr->ref->u.ar.type != AR_FULL)
5527 	{
5528 	  gfc_init_se (&se, NULL);
5529 	  if (n->expr->ref->u.ar.type == AR_ELEMENT)
5530 	    {
5531 	      gfc_conv_expr_reference (&se, n->expr);
5532 	      var = se.expr;
5533 	    }
5534 	  else
5535 	    {
5536 	      gfc_conv_expr_descriptor (&se, n->expr);
5537 	      var = gfc_conv_array_data (se.expr);
5538 	    }
5539 	  gfc_add_block_to_block (&block, &se.pre);
5540 	  gfc_add_block_to_block (&block, &se.post);
5541 	  gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
5542 	}
5543       else
5544 	{
5545 	  var = gfc_get_symbol_decl (n->sym);
5546 	  if (POINTER_TYPE_P (TREE_TYPE (var))
5547 	      && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var))))
5548 	    var = build_fold_indirect_ref (var);
5549 	  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var)))
5550 	    {
5551 	      var = gfc_conv_descriptor_data_get (var);
5552 	      gcc_assert (POINTER_TYPE_P (TREE_TYPE (var)));
5553 	    }
5554 	  else if ((n->sym->attr.allocatable || n->sym->attr.pointer)
5555 		   && n->sym->attr.dummy)
5556 	    var = build_fold_indirect_ref (var);
5557 	  else if (!POINTER_TYPE_P (TREE_TYPE (var))
5558 		   || (n->sym->ts.f90_type == BT_VOID
5559 		       && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var)))
5560 		       && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var)))))
5561 	    {
5562 	      TREE_ADDRESSABLE (var) = 1;
5563 	      var = gfc_build_addr_expr (NULL, var);
5564 	    }
5565 	}
5566       depobj = save_expr (depobj);
5567       tree r = build_fold_indirect_ref_loc (loc, depobj);
5568       gfc_add_expr_to_block (&block,
5569 			     build2 (MODIFY_EXPR, void_type_node, r, var));
5570     }
5571 
5572   /* Only one may be set. */
5573   gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy)
5574 	      + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET))
5575 	      == 1);
5576   int k = -1; /* omp_clauses->destroy */
5577   if (!code->ext.omp_clauses->destroy)
5578     switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET
5579 	    ? code->ext.omp_clauses->depobj_update : n->u.depend_op)
5580       {
5581       case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break;
5582       case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break;
5583       case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break;
5584       case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break;
5585       default: gcc_unreachable ();
5586       }
5587   tree t = build_int_cst (ptr_type_node, k);
5588   depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
5589                        TYPE_SIZE_UNIT (ptr_type_node));
5590   depobj = build_fold_indirect_ref_loc (loc, depobj);
5591   gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t));
5592 
5593   return gfc_finish_block (&block);
5594 }
5595 
5596 static tree
gfc_trans_omp_error(gfc_code * code)5597 gfc_trans_omp_error (gfc_code *code)
5598 {
5599   stmtblock_t block;
5600   gfc_se se;
5601   tree len, message;
5602   bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL;
5603   tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR
5604 					     : BUILT_IN_GOMP_WARNING);
5605   gfc_start_block (&block);
5606   gfc_init_se (&se, NULL );
5607   if (!code->ext.omp_clauses->message)
5608     {
5609       message = null_pointer_node;
5610       len = build_int_cst (size_type_node, 0);
5611     }
5612   else
5613     {
5614       gfc_conv_expr (&se, code->ext.omp_clauses->message);
5615       message = se.expr;
5616       if (!POINTER_TYPE_P (TREE_TYPE (message)))
5617 	/* To ensure an ARRAY_TYPE is not passed as such.  */
5618 	message = gfc_build_addr_expr (NULL, message);
5619       len = se.string_length;
5620     }
5621   gfc_add_block_to_block (&block, &se.pre);
5622   gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl,
5623 						      2, message, len));
5624   gfc_add_block_to_block (&block, &se.post);
5625   return gfc_finish_block (&block);
5626 }
5627 
5628 static tree
gfc_trans_omp_flush(gfc_code * code)5629 gfc_trans_omp_flush (gfc_code *code)
5630 {
5631   tree call;
5632   if (!code->ext.omp_clauses
5633       || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET
5634       || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST)
5635     {
5636       call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
5637       call = build_call_expr_loc (input_location, call, 0);
5638     }
5639   else
5640     {
5641       enum memmodel mo = MEMMODEL_LAST;
5642       switch (code->ext.omp_clauses->memorder)
5643 	{
5644 	case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break;
5645 	case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break;
5646 	case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break;
5647 	default: gcc_unreachable (); break;
5648 	}
5649       call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
5650       call = build_call_expr_loc (input_location, call, 1,
5651 				  build_int_cst (integer_type_node, mo));
5652     }
5653   return call;
5654 }
5655 
5656 static tree
gfc_trans_omp_master(gfc_code * code)5657 gfc_trans_omp_master (gfc_code *code)
5658 {
5659   tree stmt = gfc_trans_code (code->block->next);
5660   if (IS_EMPTY_STMT (stmt))
5661     return stmt;
5662   return build1_v (OMP_MASTER, stmt);
5663 }
5664 
5665 static tree
gfc_trans_omp_masked(gfc_code * code,gfc_omp_clauses * clauses)5666 gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses)
5667 {
5668   stmtblock_t block;
5669   tree body = gfc_trans_code (code->block->next);
5670   if (IS_EMPTY_STMT (body))
5671     return body;
5672   if (!clauses)
5673     clauses = code->ext.omp_clauses;
5674   gfc_start_block (&block);
5675   tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
5676   tree stmt = make_node (OMP_MASKED);
5677   TREE_TYPE (stmt) = void_type_node;
5678   OMP_MASKED_BODY (stmt) = body;
5679   OMP_MASKED_CLAUSES (stmt) = omp_clauses;
5680   gfc_add_expr_to_block (&block, stmt);
5681   return gfc_finish_block (&block);
5682 }
5683 
5684 
5685 static tree
gfc_trans_omp_ordered(gfc_code * code)5686 gfc_trans_omp_ordered (gfc_code *code)
5687 {
5688   if (!flag_openmp)
5689     {
5690       if (!code->ext.omp_clauses->simd)
5691 	return gfc_trans_code (code->block ? code->block->next : NULL);
5692       code->ext.omp_clauses->threads = 0;
5693     }
5694   tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
5695 					    code->loc);
5696   return build2_loc (input_location, OMP_ORDERED, void_type_node,
5697 		     code->block ? gfc_trans_code (code->block->next)
5698 		     : NULL_TREE, omp_clauses);
5699 }
5700 
5701 static tree
gfc_trans_omp_parallel(gfc_code * code)5702 gfc_trans_omp_parallel (gfc_code *code)
5703 {
5704   stmtblock_t block;
5705   tree stmt, omp_clauses;
5706 
5707   gfc_start_block (&block);
5708   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5709 				       code->loc);
5710   pushlevel ();
5711   stmt = gfc_trans_omp_code (code->block->next, true);
5712   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5713   stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5714 		     omp_clauses);
5715   gfc_add_expr_to_block (&block, stmt);
5716   return gfc_finish_block (&block);
5717 }
5718 
5719 enum
5720 {
5721   GFC_OMP_SPLIT_SIMD,
5722   GFC_OMP_SPLIT_DO,
5723   GFC_OMP_SPLIT_PARALLEL,
5724   GFC_OMP_SPLIT_DISTRIBUTE,
5725   GFC_OMP_SPLIT_TEAMS,
5726   GFC_OMP_SPLIT_TARGET,
5727   GFC_OMP_SPLIT_TASKLOOP,
5728   GFC_OMP_SPLIT_MASKED,
5729   GFC_OMP_SPLIT_NUM
5730 };
5731 
5732 enum
5733 {
5734   GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
5735   GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
5736   GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
5737   GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
5738   GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
5739   GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
5740   GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP),
5741   GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED)
5742 };
5743 
5744 /* If a var is in lastprivate/firstprivate/reduction but not in a
5745    data mapping/sharing clause, add it to 'map(tofrom:' if is_target
5746    and to 'shared' otherwise.  */
5747 static void
gfc_add_clause_implicitly(gfc_omp_clauses * clauses_out,gfc_omp_clauses * clauses_in,bool is_target,bool is_parallel_do)5748 gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
5749 			   gfc_omp_clauses *clauses_in,
5750 			   bool is_target, bool is_parallel_do)
5751 {
5752   int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
5753   gfc_omp_namelist *tail = NULL;
5754   for (int i = 0; i < 5; ++i)
5755     {
5756       gfc_omp_namelist *n;
5757       switch (i)
5758 	{
5759 	case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
5760 	case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
5761 	case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
5762 	case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
5763 	case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
5764 	default: gcc_unreachable ();
5765 	}
5766       for (; n != NULL; n = n->next)
5767 	{
5768 	  gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
5769 	  for (int j = 0; j < 6; ++j)
5770 	    {
5771 	      gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
5772 	      switch (j)
5773 		{
5774 		case 0:
5775 		  n2ref = &clauses_out->lists[clauselist_to_add];
5776 		  break;
5777 		case 1:
5778 		  n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
5779 		  break;
5780 		case 2:
5781 		  if (is_target)
5782 		    n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
5783 		  else
5784 		    n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
5785 		  break;
5786 		case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
5787 		case 4:
5788 		  n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
5789 		  break;
5790 		case 5:
5791 		  n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
5792 		  break;
5793 		default: gcc_unreachable ();
5794 		}
5795 	      for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
5796 		if (n2->sym == n->sym)
5797 		  break;
5798 	      if (n2)
5799 		{
5800 		  if (j == 0 /* clauselist_to_add */)
5801 		    break;  /* Already present.  */
5802 		  if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
5803 		    {
5804 		      n_firstp = prev2 ? &prev2->next : n2ref;
5805 		      continue;
5806 		    }
5807 		  if (j == 2 /* OMP_LIST_LASTPRIVATE */)
5808 		    {
5809 		      n_lastp = prev2 ? &prev2->next : n2ref;
5810 		      continue;
5811 		    }
5812 		  break;
5813 		}
5814 	    }
5815 	  if (n_firstp && n_lastp)
5816 	    {
5817 	      /* For parallel do, GCC puts firstprivatee/lastprivate
5818 		 on the parallel.  */
5819 	      if (is_parallel_do)
5820 		continue;
5821 	      *n_firstp = (*n_firstp)->next;
5822 	      if (!is_target)
5823 		*n_lastp = (*n_lastp)->next;
5824 	    }
5825 	  else if (is_target && n_lastp)
5826 	    ;
5827 	  else if (n2 || n_firstp || n_lastp)
5828 	    continue;
5829 	  if (clauses_out->lists[clauselist_to_add]
5830 	      && (clauses_out->lists[clauselist_to_add]
5831 		  == clauses_in->lists[clauselist_to_add]))
5832 	    {
5833 	      gfc_omp_namelist *p = NULL;
5834 	      for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next)
5835 		{
5836 		  if (p)
5837 		    {
5838 		      p->next = gfc_get_omp_namelist ();
5839 		      p = p->next;
5840 		    }
5841 		  else
5842 		    {
5843 		      p = gfc_get_omp_namelist ();
5844 		      clauses_out->lists[clauselist_to_add] = p;
5845 		    }
5846 		  *p = *n2;
5847 		}
5848 	    }
5849 	  if (!tail)
5850 	    {
5851 	      tail = clauses_out->lists[clauselist_to_add];
5852 	      for (; tail && tail->next; tail = tail->next)
5853 		;
5854 	    }
5855 	  n2 = gfc_get_omp_namelist ();
5856 	  n2->where = n->where;
5857 	  n2->sym = n->sym;
5858 	  if (is_target)
5859 	    n2->u.map_op = OMP_MAP_TOFROM;
5860 	  if (tail)
5861 	    {
5862 	      tail->next = n2;
5863 	      tail = n2;
5864 	    }
5865 	  else
5866 	    clauses_out->lists[clauselist_to_add] = n2;
5867 	}
5868     }
5869 }
5870 
5871 static void
gfc_free_split_omp_clauses(gfc_code * code,gfc_omp_clauses * clausesa)5872 gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa)
5873 {
5874   for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i)
5875     for (int j = 0; j < OMP_LIST_NUM; ++j)
5876       if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j])
5877 	for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;)
5878 	  {
5879 	    gfc_omp_namelist *p = n;
5880 	    n = n->next;
5881 	    free (p);
5882 	  }
5883 }
5884 
5885 static void
gfc_split_omp_clauses(gfc_code * code,gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])5886 gfc_split_omp_clauses (gfc_code *code,
5887 		       gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
5888 {
5889   int mask = 0, innermost = 0;
5890   bool is_loop = false;
5891   memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
5892   switch (code->op)
5893     {
5894     case EXEC_OMP_DISTRIBUTE:
5895       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
5896       break;
5897     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5898       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5899       innermost = GFC_OMP_SPLIT_DO;
5900       break;
5901     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5902       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
5903 	     | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5904       innermost = GFC_OMP_SPLIT_SIMD;
5905       break;
5906     case EXEC_OMP_DISTRIBUTE_SIMD:
5907       mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
5908       innermost = GFC_OMP_SPLIT_SIMD;
5909       break;
5910     case EXEC_OMP_DO:
5911     case EXEC_OMP_LOOP:
5912       innermost = GFC_OMP_SPLIT_DO;
5913       break;
5914     case EXEC_OMP_DO_SIMD:
5915       mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5916       innermost = GFC_OMP_SPLIT_SIMD;
5917       break;
5918     case EXEC_OMP_PARALLEL:
5919       innermost = GFC_OMP_SPLIT_PARALLEL;
5920       break;
5921     case EXEC_OMP_PARALLEL_DO:
5922     case EXEC_OMP_PARALLEL_LOOP:
5923       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5924       innermost = GFC_OMP_SPLIT_DO;
5925       break;
5926     case EXEC_OMP_PARALLEL_DO_SIMD:
5927       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5928       innermost = GFC_OMP_SPLIT_SIMD;
5929       break;
5930     case EXEC_OMP_PARALLEL_MASKED:
5931       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED;
5932       innermost = GFC_OMP_SPLIT_MASKED;
5933       break;
5934     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
5935       mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
5936 	      | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
5937       innermost = GFC_OMP_SPLIT_TASKLOOP;
5938       break;
5939     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
5940       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
5941       innermost = GFC_OMP_SPLIT_TASKLOOP;
5942       break;
5943     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
5944       mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED
5945 	      | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD);
5946       innermost = GFC_OMP_SPLIT_SIMD;
5947       break;
5948     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
5949       mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
5950       innermost = GFC_OMP_SPLIT_SIMD;
5951       break;
5952     case EXEC_OMP_SIMD:
5953       innermost = GFC_OMP_SPLIT_SIMD;
5954       break;
5955     case EXEC_OMP_TARGET:
5956       innermost = GFC_OMP_SPLIT_TARGET;
5957       break;
5958     case EXEC_OMP_TARGET_PARALLEL:
5959       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
5960       innermost = GFC_OMP_SPLIT_PARALLEL;
5961       break;
5962     case EXEC_OMP_TARGET_PARALLEL_DO:
5963     case EXEC_OMP_TARGET_PARALLEL_LOOP:
5964       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5965       innermost = GFC_OMP_SPLIT_DO;
5966       break;
5967     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5968       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
5969 	     | GFC_OMP_MASK_SIMD;
5970       innermost = GFC_OMP_SPLIT_SIMD;
5971       break;
5972     case EXEC_OMP_TARGET_SIMD:
5973       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
5974       innermost = GFC_OMP_SPLIT_SIMD;
5975       break;
5976     case EXEC_OMP_TARGET_TEAMS:
5977       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
5978       innermost = GFC_OMP_SPLIT_TEAMS;
5979       break;
5980     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5981       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
5982 	     | GFC_OMP_MASK_DISTRIBUTE;
5983       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
5984       break;
5985     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5986       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
5987 	     | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
5988       innermost = GFC_OMP_SPLIT_DO;
5989       break;
5990     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5991       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
5992 	     | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
5993       innermost = GFC_OMP_SPLIT_SIMD;
5994       break;
5995     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5996       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
5997 	     | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
5998       innermost = GFC_OMP_SPLIT_SIMD;
5999       break;
6000     case EXEC_OMP_TARGET_TEAMS_LOOP:
6001       mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6002       innermost = GFC_OMP_SPLIT_DO;
6003       break;
6004     case EXEC_OMP_MASKED_TASKLOOP:
6005       mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP;
6006       innermost = GFC_OMP_SPLIT_TASKLOOP;
6007       break;
6008     case EXEC_OMP_MASTER_TASKLOOP:
6009     case EXEC_OMP_TASKLOOP:
6010       innermost = GFC_OMP_SPLIT_TASKLOOP;
6011       break;
6012     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
6013       mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6014       innermost = GFC_OMP_SPLIT_SIMD;
6015       break;
6016     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
6017     case EXEC_OMP_TASKLOOP_SIMD:
6018       mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
6019       innermost = GFC_OMP_SPLIT_SIMD;
6020       break;
6021     case EXEC_OMP_TEAMS:
6022       innermost = GFC_OMP_SPLIT_TEAMS;
6023       break;
6024     case EXEC_OMP_TEAMS_DISTRIBUTE:
6025       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
6026       innermost = GFC_OMP_SPLIT_DISTRIBUTE;
6027       break;
6028     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6029       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6030 	     | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
6031       innermost = GFC_OMP_SPLIT_DO;
6032       break;
6033     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6034       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
6035 	     | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
6036       innermost = GFC_OMP_SPLIT_SIMD;
6037       break;
6038     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6039       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
6040       innermost = GFC_OMP_SPLIT_SIMD;
6041       break;
6042     case EXEC_OMP_TEAMS_LOOP:
6043       mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO;
6044       innermost = GFC_OMP_SPLIT_DO;
6045       break;
6046     default:
6047       gcc_unreachable ();
6048     }
6049   if (mask == 0)
6050     {
6051       clausesa[innermost] = *code->ext.omp_clauses;
6052       return;
6053     }
6054   /* Loops are similar to DO but still a bit different.  */
6055   switch (code->op)
6056     {
6057     case EXEC_OMP_LOOP:
6058     case EXEC_OMP_PARALLEL_LOOP:
6059     case EXEC_OMP_TEAMS_LOOP:
6060     case EXEC_OMP_TARGET_PARALLEL_LOOP:
6061     case EXEC_OMP_TARGET_TEAMS_LOOP:
6062       is_loop = true;
6063     default:
6064       break;
6065     }
6066   if (code->ext.omp_clauses != NULL)
6067     {
6068       if (mask & GFC_OMP_MASK_TARGET)
6069 	{
6070 	  /* First the clauses that are unique to some constructs.  */
6071 	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
6072 	    = code->ext.omp_clauses->lists[OMP_LIST_MAP];
6073 	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
6074 	    = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
6075 	  clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR]
6076 	    = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR];
6077 	  clausesa[GFC_OMP_SPLIT_TARGET].device
6078 	    = code->ext.omp_clauses->device;
6079 	  clausesa[GFC_OMP_SPLIT_TARGET].thread_limit
6080 	    = code->ext.omp_clauses->thread_limit;
6081 	  for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++)
6082 	    clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i]
6083 	      = code->ext.omp_clauses->defaultmap[i];
6084 	  clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
6085 	    = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
6086 	  /* And this is copied to all.  */
6087 	  clausesa[GFC_OMP_SPLIT_TARGET].if_expr
6088 	    = code->ext.omp_clauses->if_expr;
6089 	  clausesa[GFC_OMP_SPLIT_TARGET].nowait
6090 	    = code->ext.omp_clauses->nowait;
6091 	}
6092       if (mask & GFC_OMP_MASK_TEAMS)
6093 	{
6094 	  /* First the clauses that are unique to some constructs.  */
6095 	  clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower
6096 	    = code->ext.omp_clauses->num_teams_lower;
6097 	  clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
6098 	    = code->ext.omp_clauses->num_teams_upper;
6099 	  clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
6100 	    = code->ext.omp_clauses->thread_limit;
6101 	  /* Shared and default clauses are allowed on parallel, teams
6102 	     and taskloop.  */
6103 	  clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
6104 	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6105 	  clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
6106 	    = code->ext.omp_clauses->default_sharing;
6107 	}
6108       if (mask & GFC_OMP_MASK_DISTRIBUTE)
6109 	{
6110 	  /* First the clauses that are unique to some constructs.  */
6111 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
6112 	    = code->ext.omp_clauses->dist_sched_kind;
6113 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
6114 	    = code->ext.omp_clauses->dist_chunk_size;
6115 	  /* Duplicate collapse.  */
6116 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
6117 	    = code->ext.omp_clauses->collapse;
6118 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent
6119 	    = code->ext.omp_clauses->order_concurrent;
6120 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained
6121 	    = code->ext.omp_clauses->order_unconstrained;
6122 	  clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible
6123 	    = code->ext.omp_clauses->order_reproducible;
6124 	}
6125       if (mask & GFC_OMP_MASK_PARALLEL)
6126 	{
6127 	  /* First the clauses that are unique to some constructs.  */
6128 	  clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
6129 	    = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
6130 	  clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
6131 	    = code->ext.omp_clauses->num_threads;
6132 	  clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
6133 	    = code->ext.omp_clauses->proc_bind;
6134 	  /* Shared and default clauses are allowed on parallel, teams
6135 	     and taskloop.  */
6136 	  clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
6137 	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6138 	  clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
6139 	    = code->ext.omp_clauses->default_sharing;
6140 	  clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
6141 	    = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
6142 	  /* And this is copied to all.  */
6143 	  clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
6144 	    = code->ext.omp_clauses->if_expr;
6145 	}
6146       if (mask & GFC_OMP_MASK_MASKED)
6147 	clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter;
6148       if ((mask & GFC_OMP_MASK_DO) && !is_loop)
6149 	{
6150 	  /* First the clauses that are unique to some constructs.  */
6151 	  clausesa[GFC_OMP_SPLIT_DO].ordered
6152 	    = code->ext.omp_clauses->ordered;
6153 	  clausesa[GFC_OMP_SPLIT_DO].orderedc
6154 	    = code->ext.omp_clauses->orderedc;
6155 	  clausesa[GFC_OMP_SPLIT_DO].sched_kind
6156 	    = code->ext.omp_clauses->sched_kind;
6157 	  if (innermost == GFC_OMP_SPLIT_SIMD)
6158 	    clausesa[GFC_OMP_SPLIT_DO].sched_simd
6159 	      = code->ext.omp_clauses->sched_simd;
6160 	  clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
6161 	    = code->ext.omp_clauses->sched_monotonic;
6162 	  clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
6163 	    = code->ext.omp_clauses->sched_nonmonotonic;
6164 	  clausesa[GFC_OMP_SPLIT_DO].chunk_size
6165 	    = code->ext.omp_clauses->chunk_size;
6166 	  clausesa[GFC_OMP_SPLIT_DO].nowait
6167 	    = code->ext.omp_clauses->nowait;
6168 	}
6169       if (mask & GFC_OMP_MASK_DO)
6170 	{
6171 	  clausesa[GFC_OMP_SPLIT_DO].bind
6172 	    = code->ext.omp_clauses->bind;
6173 	  /* Duplicate collapse.  */
6174 	  clausesa[GFC_OMP_SPLIT_DO].collapse
6175 	    = code->ext.omp_clauses->collapse;
6176 	  clausesa[GFC_OMP_SPLIT_DO].order_concurrent
6177 	    = code->ext.omp_clauses->order_concurrent;
6178 	  clausesa[GFC_OMP_SPLIT_DO].order_unconstrained
6179 	    = code->ext.omp_clauses->order_unconstrained;
6180 	  clausesa[GFC_OMP_SPLIT_DO].order_reproducible
6181 	    = code->ext.omp_clauses->order_reproducible;
6182 	}
6183       if (mask & GFC_OMP_MASK_SIMD)
6184 	{
6185 	  clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
6186 	    = code->ext.omp_clauses->safelen_expr;
6187 	  clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
6188 	    = code->ext.omp_clauses->simdlen_expr;
6189 	  clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
6190 	    = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
6191 	  /* Duplicate collapse.  */
6192 	  clausesa[GFC_OMP_SPLIT_SIMD].collapse
6193 	    = code->ext.omp_clauses->collapse;
6194 	  clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD]
6195 	    = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD];
6196 	  clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent
6197 	    = code->ext.omp_clauses->order_concurrent;
6198 	  clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained
6199 	    = code->ext.omp_clauses->order_unconstrained;
6200 	  clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible
6201 	    = code->ext.omp_clauses->order_reproducible;
6202 	  /* And this is copied to all.  */
6203 	  clausesa[GFC_OMP_SPLIT_SIMD].if_expr
6204 	    = code->ext.omp_clauses->if_expr;
6205 	}
6206       if (mask & GFC_OMP_MASK_TASKLOOP)
6207 	{
6208 	  /* First the clauses that are unique to some constructs.  */
6209 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
6210 	    = code->ext.omp_clauses->nogroup;
6211 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
6212 	    = code->ext.omp_clauses->grainsize;
6213 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict
6214 	    = code->ext.omp_clauses->grainsize_strict;
6215 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
6216 	    = code->ext.omp_clauses->num_tasks;
6217 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict
6218 	    = code->ext.omp_clauses->num_tasks_strict;
6219 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
6220 	    = code->ext.omp_clauses->priority;
6221 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
6222 	    = code->ext.omp_clauses->final_expr;
6223 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
6224 	    = code->ext.omp_clauses->untied;
6225 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
6226 	    = code->ext.omp_clauses->mergeable;
6227 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
6228 	    = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
6229 	  /* And this is copied to all.  */
6230 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
6231 	    = code->ext.omp_clauses->if_expr;
6232 	  /* Shared and default clauses are allowed on parallel, teams
6233 	     and taskloop.  */
6234 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
6235 	    = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
6236 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
6237 	    = code->ext.omp_clauses->default_sharing;
6238 	  /* Duplicate collapse.  */
6239 	  clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
6240 	    = code->ext.omp_clauses->collapse;
6241 	}
6242       /* Private clause is supported on all constructs but master/masked,
6243 	 it is enough to put it on the innermost one except for master/masked.  For
6244 	 !$ omp parallel do put it on parallel though,
6245 	 as that's what we did for OpenMP 3.1.  */
6246       clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop)
6247 		|| code->op == EXEC_OMP_PARALLEL_MASTER
6248 		|| code->op == EXEC_OMP_PARALLEL_MASKED)
6249 	       ? (int) GFC_OMP_SPLIT_PARALLEL
6250 	       : innermost].lists[OMP_LIST_PRIVATE]
6251 	= code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
6252       /* Firstprivate clause is supported on all constructs but
6253 	 simd and masked/master.  Put it on the outermost of those and duplicate
6254 	 on parallel and teams.  */
6255       if (mask & GFC_OMP_MASK_TARGET)
6256 	clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
6257 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6258       if (mask & GFC_OMP_MASK_TEAMS)
6259 	clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
6260 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6261       else if (mask & GFC_OMP_MASK_DISTRIBUTE)
6262 	clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
6263 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6264       if (mask & GFC_OMP_MASK_TASKLOOP)
6265 	clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE]
6266 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6267       if ((mask & GFC_OMP_MASK_PARALLEL)
6268 	  && !(mask & GFC_OMP_MASK_TASKLOOP))
6269 	clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
6270 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6271       else if ((mask & GFC_OMP_MASK_DO) && !is_loop)
6272 	clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
6273 	  = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
6274       /* Lastprivate is allowed on distribute, do, simd, taskloop and loop.
6275          In parallel do{, simd} we actually want to put it on
6276 	 parallel rather than do.  */
6277       if (mask & GFC_OMP_MASK_DISTRIBUTE)
6278 	clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
6279 	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6280       if (mask & GFC_OMP_MASK_TASKLOOP)
6281 	clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE]
6282 	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6283       if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop
6284 	  && !(mask & GFC_OMP_MASK_TASKLOOP))
6285 	clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
6286 	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6287       else if (mask & GFC_OMP_MASK_DO)
6288 	clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
6289 	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6290       if (mask & GFC_OMP_MASK_SIMD)
6291 	clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
6292 	  = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
6293       /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop.
6294 	 Duplicate it on all of them, but
6295 	 - omit on do if parallel is present;
6296 	 - omit on task and parallel if loop is present;
6297 	 additionally, inscan applies to do/simd only.  */
6298       for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++)
6299 	{
6300 	  if (mask & GFC_OMP_MASK_TASKLOOP
6301 	      && i != OMP_LIST_REDUCTION_INSCAN)
6302 	    clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i]
6303 	      = code->ext.omp_clauses->lists[i];
6304 	  if (mask & GFC_OMP_MASK_TEAMS
6305 	      && i != OMP_LIST_REDUCTION_INSCAN
6306 	      && !is_loop)
6307 	    clausesa[GFC_OMP_SPLIT_TEAMS].lists[i]
6308 	      = code->ext.omp_clauses->lists[i];
6309 	  if (mask & GFC_OMP_MASK_PARALLEL
6310 	      && i != OMP_LIST_REDUCTION_INSCAN
6311 	      && !(mask & GFC_OMP_MASK_TASKLOOP)
6312 	      && !is_loop)
6313 	    clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i]
6314 	      = code->ext.omp_clauses->lists[i];
6315 	  else if (mask & GFC_OMP_MASK_DO)
6316 	    clausesa[GFC_OMP_SPLIT_DO].lists[i]
6317 	      = code->ext.omp_clauses->lists[i];
6318 	  if (mask & GFC_OMP_MASK_SIMD)
6319 	    clausesa[GFC_OMP_SPLIT_SIMD].lists[i]
6320 	      = code->ext.omp_clauses->lists[i];
6321 	}
6322       if (mask & GFC_OMP_MASK_TARGET)
6323 	clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION]
6324 	  = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
6325       if (mask & GFC_OMP_MASK_TASKLOOP)
6326 	clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION]
6327 	  = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION];
6328       /* Linear clause is supported on do and simd,
6329 	 put it on the innermost one.  */
6330       clausesa[innermost].lists[OMP_LIST_LINEAR]
6331 	= code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
6332     }
6333    /* Propagate firstprivate/lastprivate/reduction vars to
6334       shared (parallel, teams) and map-tofrom (target).  */
6335    if (mask & GFC_OMP_MASK_TARGET)
6336      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET],
6337 				code->ext.omp_clauses, true, false);
6338    if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL)
6339      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL],
6340 				code->ext.omp_clauses, false,
6341 				mask & GFC_OMP_MASK_DO);
6342    if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS)
6343      gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS],
6344 				code->ext.omp_clauses, false, false);
6345    if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
6346 	== (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
6347        && !is_loop)
6348     clausesa[GFC_OMP_SPLIT_DO].nowait = true;
6349 
6350    /* Distribute allocate clause to do, parallel, distribute, teams, target
6351       and taskloop.  The code below itereates over variables in the
6352       allocate list and checks if that available is also in any
6353       privatization clause on those construct.  If yes, then we add it
6354       to the list of 'allocate'ed variables for that construct.  If a
6355       variable is found in none of them then we issue an error.  */
6356 
6357    if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE])
6358      {
6359        gfc_omp_namelist *alloc_nl, *priv_nl;
6360        gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM];
6361        for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE];
6362 	   alloc_nl; alloc_nl = alloc_nl->next)
6363 	 {
6364 	   bool found = false;
6365 	   for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++)
6366 	     {
6367 	       gfc_omp_namelist *p;
6368 	       int list;
6369 	       for (list = 0; list < OMP_LIST_NUM; list++)
6370 		 {
6371 		   switch (list)
6372 		   {
6373 		     case OMP_LIST_PRIVATE:
6374 		     case OMP_LIST_FIRSTPRIVATE:
6375 		     case OMP_LIST_LASTPRIVATE:
6376 		     case OMP_LIST_REDUCTION:
6377 		     case OMP_LIST_REDUCTION_INSCAN:
6378 		     case OMP_LIST_REDUCTION_TASK:
6379 		     case OMP_LIST_IN_REDUCTION:
6380 		     case OMP_LIST_TASK_REDUCTION:
6381 		     case OMP_LIST_LINEAR:
6382 		       for (priv_nl = clausesa[i].lists[list]; priv_nl;
6383 			    priv_nl = priv_nl->next)
6384 			 if (alloc_nl->sym == priv_nl->sym)
6385 			   {
6386 			     found = true;
6387 			     p = gfc_get_omp_namelist ();
6388 			     p->sym = alloc_nl->sym;
6389 			     p->expr = alloc_nl->expr;
6390 			     p->where = alloc_nl->where;
6391 			     if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL)
6392 			       {
6393 				 clausesa[i].lists[OMP_LIST_ALLOCATE] = p;
6394 				 tails[i] = p;
6395 			       }
6396 			     else
6397 			       {
6398 				 tails[i]->next = p;
6399 				 tails[i] = tails[i]->next;
6400 			       }
6401 			   }
6402 		       break;
6403 		     default:
6404 		       break;
6405 		   }
6406 		 }
6407 	     }
6408 	   if (!found)
6409 	     gfc_error ("%qs specified in 'allocate' clause at %L but not "
6410 			"in an explicit privatization clause",
6411 			alloc_nl->sym->name, &alloc_nl->where);
6412 	 }
6413      }
6414 }
6415 
6416 static tree
gfc_trans_omp_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa,tree omp_clauses)6417 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
6418 		       gfc_omp_clauses *clausesa, tree omp_clauses)
6419 {
6420   stmtblock_t block;
6421   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6422   tree stmt, body, omp_do_clauses = NULL_TREE;
6423   bool free_clausesa = false;
6424 
6425   if (pblock == NULL)
6426     gfc_start_block (&block);
6427   else
6428     gfc_init_block (&block);
6429 
6430   if (clausesa == NULL)
6431     {
6432       clausesa = clausesa_buf;
6433       gfc_split_omp_clauses (code, clausesa);
6434       free_clausesa = true;
6435     }
6436   if (flag_openmp)
6437     omp_do_clauses
6438       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
6439   body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
6440 			   &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
6441   if (pblock == NULL)
6442     {
6443       if (TREE_CODE (body) != BIND_EXPR)
6444 	body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
6445       else
6446 	poplevel (0, 0);
6447     }
6448   else if (TREE_CODE (body) != BIND_EXPR)
6449     body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
6450   if (flag_openmp)
6451     {
6452       stmt = make_node (OMP_FOR);
6453       TREE_TYPE (stmt) = void_type_node;
6454       OMP_FOR_BODY (stmt) = body;
6455       OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
6456     }
6457   else
6458     stmt = body;
6459   gfc_add_expr_to_block (&block, stmt);
6460   if (free_clausesa)
6461     gfc_free_split_omp_clauses (code, clausesa);
6462   return gfc_finish_block (&block);
6463 }
6464 
6465 static tree
gfc_trans_omp_parallel_do(gfc_code * code,bool is_loop,stmtblock_t * pblock,gfc_omp_clauses * clausesa)6466 gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock,
6467 			   gfc_omp_clauses *clausesa)
6468 {
6469   stmtblock_t block, *new_pblock = pblock;
6470   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6471   tree stmt, omp_clauses = NULL_TREE;
6472   bool free_clausesa = false;
6473 
6474   if (pblock == NULL)
6475     gfc_start_block (&block);
6476   else
6477     gfc_init_block (&block);
6478 
6479   if (clausesa == NULL)
6480     {
6481       clausesa = clausesa_buf;
6482       gfc_split_omp_clauses (code, clausesa);
6483       free_clausesa = true;
6484     }
6485   omp_clauses
6486     = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6487 			     code->loc);
6488   if (pblock == NULL)
6489     {
6490       if (!clausesa[GFC_OMP_SPLIT_DO].ordered
6491 	  && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
6492 	new_pblock = &block;
6493       else
6494 	pushlevel ();
6495     }
6496   stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO,
6497 			   new_pblock, &clausesa[GFC_OMP_SPLIT_DO],
6498 			   omp_clauses);
6499   if (pblock == NULL)
6500     {
6501       if (TREE_CODE (stmt) != BIND_EXPR)
6502 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6503       else
6504 	poplevel (0, 0);
6505     }
6506   else if (TREE_CODE (stmt) != BIND_EXPR)
6507     stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
6508   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6509 		     void_type_node, stmt, omp_clauses);
6510   OMP_PARALLEL_COMBINED (stmt) = 1;
6511   gfc_add_expr_to_block (&block, stmt);
6512   if (free_clausesa)
6513     gfc_free_split_omp_clauses (code, clausesa);
6514   return gfc_finish_block (&block);
6515 }
6516 
6517 static tree
gfc_trans_omp_parallel_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa)6518 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
6519 				gfc_omp_clauses *clausesa)
6520 {
6521   stmtblock_t block;
6522   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6523   tree stmt, omp_clauses = NULL_TREE;
6524   bool free_clausesa = false;
6525 
6526   if (pblock == NULL)
6527     gfc_start_block (&block);
6528   else
6529     gfc_init_block (&block);
6530 
6531   if (clausesa == NULL)
6532     {
6533       clausesa = clausesa_buf;
6534       gfc_split_omp_clauses (code, clausesa);
6535       free_clausesa = true;
6536     }
6537   if (flag_openmp)
6538     omp_clauses
6539       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6540 			       code->loc);
6541   if (pblock == NULL)
6542     pushlevel ();
6543   stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
6544   if (pblock == NULL)
6545     {
6546       if (TREE_CODE (stmt) != BIND_EXPR)
6547 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6548       else
6549 	poplevel (0, 0);
6550     }
6551   else if (TREE_CODE (stmt) != BIND_EXPR)
6552     stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
6553   if (flag_openmp)
6554     {
6555       stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6556 			 void_type_node, stmt, omp_clauses);
6557       OMP_PARALLEL_COMBINED (stmt) = 1;
6558     }
6559   gfc_add_expr_to_block (&block, stmt);
6560   if (free_clausesa)
6561     gfc_free_split_omp_clauses (code, clausesa);
6562   return gfc_finish_block (&block);
6563 }
6564 
6565 static tree
gfc_trans_omp_parallel_sections(gfc_code * code)6566 gfc_trans_omp_parallel_sections (gfc_code *code)
6567 {
6568   stmtblock_t block;
6569   gfc_omp_clauses section_clauses;
6570   tree stmt, omp_clauses;
6571 
6572   memset (&section_clauses, 0, sizeof (section_clauses));
6573   section_clauses.nowait = true;
6574 
6575   gfc_start_block (&block);
6576   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6577 				       code->loc);
6578   pushlevel ();
6579   stmt = gfc_trans_omp_sections (code, &section_clauses);
6580   if (TREE_CODE (stmt) != BIND_EXPR)
6581     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6582   else
6583     poplevel (0, 0);
6584   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6585 		     void_type_node, stmt, omp_clauses);
6586   OMP_PARALLEL_COMBINED (stmt) = 1;
6587   gfc_add_expr_to_block (&block, stmt);
6588   return gfc_finish_block (&block);
6589 }
6590 
6591 static tree
gfc_trans_omp_parallel_workshare(gfc_code * code)6592 gfc_trans_omp_parallel_workshare (gfc_code *code)
6593 {
6594   stmtblock_t block;
6595   gfc_omp_clauses workshare_clauses;
6596   tree stmt, omp_clauses;
6597 
6598   memset (&workshare_clauses, 0, sizeof (workshare_clauses));
6599   workshare_clauses.nowait = true;
6600 
6601   gfc_start_block (&block);
6602   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6603 				       code->loc);
6604   pushlevel ();
6605   stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
6606   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6607   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
6608 		     void_type_node, stmt, omp_clauses);
6609   OMP_PARALLEL_COMBINED (stmt) = 1;
6610   gfc_add_expr_to_block (&block, stmt);
6611   return gfc_finish_block (&block);
6612 }
6613 
6614 static tree
gfc_trans_omp_scope(gfc_code * code)6615 gfc_trans_omp_scope (gfc_code *code)
6616 {
6617   stmtblock_t block;
6618   tree body = gfc_trans_code (code->block->next);
6619   if (IS_EMPTY_STMT (body))
6620     return body;
6621   gfc_start_block (&block);
6622   tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6623 					    code->loc);
6624   tree stmt = make_node (OMP_SCOPE);
6625   TREE_TYPE (stmt) = void_type_node;
6626   OMP_SCOPE_BODY (stmt) = body;
6627   OMP_SCOPE_CLAUSES (stmt) = omp_clauses;
6628   gfc_add_expr_to_block (&block, stmt);
6629   return gfc_finish_block (&block);
6630 }
6631 
6632 static tree
gfc_trans_omp_sections(gfc_code * code,gfc_omp_clauses * clauses)6633 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
6634 {
6635   stmtblock_t block, body;
6636   tree omp_clauses, stmt;
6637   bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
6638   location_t loc = gfc_get_location (&code->loc);
6639 
6640   gfc_start_block (&block);
6641 
6642   omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
6643 
6644   gfc_init_block (&body);
6645   for (code = code->block; code; code = code->block)
6646     {
6647       /* Last section is special because of lastprivate, so even if it
6648 	 is empty, chain it in.  */
6649       stmt = gfc_trans_omp_code (code->next,
6650 				 has_lastprivate && code->block == NULL);
6651       if (! IS_EMPTY_STMT (stmt))
6652 	{
6653 	  stmt = build1_v (OMP_SECTION, stmt);
6654 	  gfc_add_expr_to_block (&body, stmt);
6655 	}
6656     }
6657   stmt = gfc_finish_block (&body);
6658 
6659   stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
6660   gfc_add_expr_to_block (&block, stmt);
6661 
6662   return gfc_finish_block (&block);
6663 }
6664 
6665 static tree
gfc_trans_omp_single(gfc_code * code,gfc_omp_clauses * clauses)6666 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
6667 {
6668   tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
6669   tree stmt = gfc_trans_omp_code (code->block->next, true);
6670   stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
6671 		     stmt, omp_clauses);
6672   return stmt;
6673 }
6674 
6675 static tree
gfc_trans_omp_task(gfc_code * code)6676 gfc_trans_omp_task (gfc_code *code)
6677 {
6678   stmtblock_t block;
6679   tree stmt, omp_clauses;
6680 
6681   gfc_start_block (&block);
6682   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
6683 				       code->loc);
6684   pushlevel ();
6685   stmt = gfc_trans_omp_code (code->block->next, true);
6686   stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6687   stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
6688 		     stmt, omp_clauses);
6689   gfc_add_expr_to_block (&block, stmt);
6690   return gfc_finish_block (&block);
6691 }
6692 
6693 static tree
gfc_trans_omp_taskgroup(gfc_code * code)6694 gfc_trans_omp_taskgroup (gfc_code *code)
6695 {
6696   stmtblock_t block;
6697   gfc_start_block (&block);
6698   tree body = gfc_trans_code (code->block->next);
6699   tree stmt = make_node (OMP_TASKGROUP);
6700   TREE_TYPE (stmt) = void_type_node;
6701   OMP_TASKGROUP_BODY (stmt) = body;
6702   OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
6703 							code->ext.omp_clauses,
6704 							code->loc);
6705   gfc_add_expr_to_block (&block, stmt);
6706   return gfc_finish_block (&block);
6707 }
6708 
6709 static tree
gfc_trans_omp_taskwait(gfc_code * code)6710 gfc_trans_omp_taskwait (gfc_code *code)
6711 {
6712   if (!code->ext.omp_clauses)
6713     {
6714       tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
6715       return build_call_expr_loc (input_location, decl, 0);
6716     }
6717   stmtblock_t block;
6718   gfc_start_block (&block);
6719   tree stmt = make_node (OMP_TASK);
6720   TREE_TYPE (stmt) = void_type_node;
6721   OMP_TASK_BODY (stmt) = NULL_TREE;
6722   OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
6723 						   code->ext.omp_clauses,
6724 						   code->loc);
6725   gfc_add_expr_to_block (&block, stmt);
6726   return gfc_finish_block (&block);
6727 }
6728 
6729 static tree
gfc_trans_omp_taskyield(void)6730 gfc_trans_omp_taskyield (void)
6731 {
6732   tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
6733   return build_call_expr_loc (input_location, decl, 0);
6734 }
6735 
6736 static tree
gfc_trans_omp_distribute(gfc_code * code,gfc_omp_clauses * clausesa)6737 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
6738 {
6739   stmtblock_t block;
6740   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6741   tree stmt, omp_clauses = NULL_TREE;
6742   bool free_clausesa = false;
6743 
6744   gfc_start_block (&block);
6745   if (clausesa == NULL)
6746     {
6747       clausesa = clausesa_buf;
6748       gfc_split_omp_clauses (code, clausesa);
6749       free_clausesa = true;
6750     }
6751   if (flag_openmp)
6752     omp_clauses
6753       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
6754 			       code->loc);
6755   switch (code->op)
6756     {
6757     case EXEC_OMP_DISTRIBUTE:
6758     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6759     case EXEC_OMP_TEAMS_DISTRIBUTE:
6760       /* This is handled in gfc_trans_omp_do.  */
6761       gcc_unreachable ();
6762       break;
6763     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
6764     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
6765     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
6766       stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa);
6767       if (TREE_CODE (stmt) != BIND_EXPR)
6768 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6769       else
6770 	poplevel (0, 0);
6771       break;
6772     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
6773     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6774     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
6775       stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
6776       if (TREE_CODE (stmt) != BIND_EXPR)
6777 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6778       else
6779 	poplevel (0, 0);
6780       break;
6781     case EXEC_OMP_DISTRIBUTE_SIMD:
6782     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
6783     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
6784       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
6785 			       &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
6786       if (TREE_CODE (stmt) != BIND_EXPR)
6787 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6788       else
6789 	poplevel (0, 0);
6790       break;
6791     default:
6792       gcc_unreachable ();
6793     }
6794   if (flag_openmp)
6795     {
6796       tree distribute = make_node (OMP_DISTRIBUTE);
6797       TREE_TYPE (distribute) = void_type_node;
6798       OMP_FOR_BODY (distribute) = stmt;
6799       OMP_FOR_CLAUSES (distribute) = omp_clauses;
6800       stmt = distribute;
6801     }
6802   gfc_add_expr_to_block (&block, stmt);
6803   if (free_clausesa)
6804     gfc_free_split_omp_clauses (code, clausesa);
6805   return gfc_finish_block (&block);
6806 }
6807 
6808 static tree
gfc_trans_omp_teams(gfc_code * code,gfc_omp_clauses * clausesa,tree omp_clauses)6809 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
6810 		     tree omp_clauses)
6811 {
6812   stmtblock_t block;
6813   gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
6814   tree stmt;
6815   bool combined = true, free_clausesa = false;
6816 
6817   gfc_start_block (&block);
6818   if (clausesa == NULL)
6819     {
6820       clausesa = clausesa_buf;
6821       gfc_split_omp_clauses (code, clausesa);
6822       free_clausesa = true;
6823     }
6824   if (flag_openmp)
6825     {
6826       omp_clauses
6827 	= chainon (omp_clauses,
6828 		   gfc_trans_omp_clauses (&block,
6829 					  &clausesa[GFC_OMP_SPLIT_TEAMS],
6830 					  code->loc));
6831       pushlevel ();
6832     }
6833   switch (code->op)
6834     {
6835     case EXEC_OMP_TARGET_TEAMS:
6836     case EXEC_OMP_TEAMS:
6837       stmt = gfc_trans_omp_code (code->block->next, true);
6838       combined = false;
6839       break;
6840     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
6841     case EXEC_OMP_TEAMS_DISTRIBUTE:
6842       stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
6843 			       &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
6844 			       NULL);
6845       break;
6846     case EXEC_OMP_TARGET_TEAMS_LOOP:
6847     case EXEC_OMP_TEAMS_LOOP:
6848       stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL,
6849 			       &clausesa[GFC_OMP_SPLIT_DO],
6850 			       NULL);
6851       break;
6852     default:
6853       stmt = gfc_trans_omp_distribute (code, clausesa);
6854       break;
6855     }
6856   if (flag_openmp)
6857     {
6858       stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6859       stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
6860 			 void_type_node, stmt, omp_clauses);
6861       if (combined)
6862 	OMP_TEAMS_COMBINED (stmt) = 1;
6863     }
6864   gfc_add_expr_to_block (&block, stmt);
6865   if (free_clausesa)
6866     gfc_free_split_omp_clauses (code, clausesa);
6867   return gfc_finish_block (&block);
6868 }
6869 
6870 static tree
gfc_trans_omp_target(gfc_code * code)6871 gfc_trans_omp_target (gfc_code *code)
6872 {
6873   stmtblock_t block;
6874   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
6875   tree stmt, omp_clauses = NULL_TREE;
6876 
6877   gfc_start_block (&block);
6878   gfc_split_omp_clauses (code, clausesa);
6879   if (flag_openmp)
6880     omp_clauses
6881       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
6882 			       code->loc);
6883   switch (code->op)
6884     {
6885     case EXEC_OMP_TARGET:
6886       pushlevel ();
6887       stmt = gfc_trans_omp_code (code->block->next, true);
6888       stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6889       break;
6890     case EXEC_OMP_TARGET_PARALLEL:
6891       {
6892 	stmtblock_t iblock;
6893 
6894 	pushlevel ();
6895 	gfc_start_block (&iblock);
6896 	tree inner_clauses
6897 	  = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL],
6898 				   code->loc);
6899 	stmt = gfc_trans_omp_code (code->block->next, true);
6900 	stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
6901 			   inner_clauses);
6902 	gfc_add_expr_to_block (&iblock, stmt);
6903 	stmt = gfc_finish_block (&iblock);
6904 	if (TREE_CODE (stmt) != BIND_EXPR)
6905 	  stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6906 	else
6907 	  poplevel (0, 0);
6908       }
6909       break;
6910     case EXEC_OMP_TARGET_PARALLEL_DO:
6911     case EXEC_OMP_TARGET_PARALLEL_LOOP:
6912       stmt = gfc_trans_omp_parallel_do (code,
6913 					(code->op
6914 					 == EXEC_OMP_TARGET_PARALLEL_LOOP),
6915 					&block, clausesa);
6916       if (TREE_CODE (stmt) != BIND_EXPR)
6917 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6918       else
6919 	poplevel (0, 0);
6920       break;
6921     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
6922       stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
6923       if (TREE_CODE (stmt) != BIND_EXPR)
6924 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6925       else
6926 	poplevel (0, 0);
6927       break;
6928     case EXEC_OMP_TARGET_SIMD:
6929       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
6930 			       &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
6931       if (TREE_CODE (stmt) != BIND_EXPR)
6932 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6933       else
6934 	poplevel (0, 0);
6935       break;
6936     default:
6937       if (flag_openmp
6938 	  && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper
6939 	      || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
6940 	{
6941 	  gfc_omp_clauses clausesb;
6942 	  tree teams_clauses;
6943 	  /* For combined !$omp target teams, the num_teams and
6944 	     thread_limit clauses are evaluated before entering the
6945 	     target construct.  */
6946 	  memset (&clausesb, '\0', sizeof (clausesb));
6947 	  clausesb.num_teams_lower
6948 	    = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower;
6949 	  clausesb.num_teams_upper
6950 	    = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper;
6951 	  clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
6952 	  clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL;
6953 	  clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL;
6954 	  clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
6955 	  teams_clauses
6956 	    = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
6957 	  pushlevel ();
6958 	  stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
6959 	}
6960       else
6961 	{
6962 	  pushlevel ();
6963 	  stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
6964 	}
6965       if (TREE_CODE (stmt) != BIND_EXPR)
6966 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
6967       else
6968 	poplevel (0, 0);
6969       break;
6970     }
6971   if (flag_openmp)
6972     {
6973       stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
6974 			 void_type_node, stmt, omp_clauses);
6975       if (code->op != EXEC_OMP_TARGET)
6976 	OMP_TARGET_COMBINED (stmt) = 1;
6977       cfun->has_omp_target = true;
6978     }
6979   gfc_add_expr_to_block (&block, stmt);
6980   gfc_free_split_omp_clauses (code, clausesa);
6981   return gfc_finish_block (&block);
6982 }
6983 
6984 static tree
gfc_trans_omp_taskloop(gfc_code * code,gfc_exec_op op)6985 gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op)
6986 {
6987   stmtblock_t block;
6988   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
6989   tree stmt, omp_clauses = NULL_TREE;
6990 
6991   gfc_start_block (&block);
6992   gfc_split_omp_clauses (code, clausesa);
6993   if (flag_openmp)
6994     omp_clauses
6995       = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
6996 			       code->loc);
6997   switch (op)
6998     {
6999     case EXEC_OMP_TASKLOOP:
7000       /* This is handled in gfc_trans_omp_do.  */
7001       gcc_unreachable ();
7002       break;
7003     case EXEC_OMP_TASKLOOP_SIMD:
7004       stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
7005 			       &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
7006       if (TREE_CODE (stmt) != BIND_EXPR)
7007 	stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7008       else
7009 	poplevel (0, 0);
7010       break;
7011     default:
7012       gcc_unreachable ();
7013     }
7014   if (flag_openmp)
7015     {
7016       tree taskloop = make_node (OMP_TASKLOOP);
7017       TREE_TYPE (taskloop) = void_type_node;
7018       OMP_FOR_BODY (taskloop) = stmt;
7019       OMP_FOR_CLAUSES (taskloop) = omp_clauses;
7020       stmt = taskloop;
7021     }
7022   gfc_add_expr_to_block (&block, stmt);
7023   gfc_free_split_omp_clauses (code, clausesa);
7024   return gfc_finish_block (&block);
7025 }
7026 
7027 static tree
gfc_trans_omp_master_masked_taskloop(gfc_code * code,gfc_exec_op op)7028 gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op)
7029 {
7030   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7031   stmtblock_t block;
7032   tree stmt;
7033 
7034   if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7035       && code->op != EXEC_OMP_MASTER_TASKLOOP)
7036     gfc_split_omp_clauses (code, clausesa);
7037 
7038   pushlevel ();
7039   if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD
7040       || op == EXEC_OMP_MASTER_TASKLOOP_SIMD)
7041     stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD);
7042   else
7043     {
7044       gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP
7045 		  || op == EXEC_OMP_MASTER_TASKLOOP);
7046       stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL,
7047 			       code->op != EXEC_OMP_MASTER_TASKLOOP
7048 			       ? &clausesa[GFC_OMP_SPLIT_TASKLOOP]
7049 			       : code->ext.omp_clauses, NULL);
7050     }
7051   if (TREE_CODE (stmt) != BIND_EXPR)
7052     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7053   else
7054     poplevel (0, 0);
7055   gfc_start_block (&block);
7056   if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD)
7057     {
7058       tree clauses = gfc_trans_omp_clauses (&block,
7059 					    &clausesa[GFC_OMP_SPLIT_MASKED],
7060 					    code->loc);
7061       tree msk = make_node (OMP_MASKED);
7062       TREE_TYPE (msk) = void_type_node;
7063       OMP_MASKED_BODY (msk) = stmt;
7064       OMP_MASKED_CLAUSES (msk) = clauses;
7065       OMP_MASKED_COMBINED (msk) = 1;
7066       gfc_add_expr_to_block (&block, msk);
7067     }
7068   else
7069     {
7070       gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP
7071 		  || op == EXEC_OMP_MASTER_TASKLOOP_SIMD);
7072       stmt = build1_v (OMP_MASTER, stmt);
7073       gfc_add_expr_to_block (&block, stmt);
7074     }
7075   if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD
7076       && code->op != EXEC_OMP_MASTER_TASKLOOP)
7077     gfc_free_split_omp_clauses (code, clausesa);
7078   return gfc_finish_block (&block);
7079 }
7080 
7081 static tree
gfc_trans_omp_parallel_master_masked(gfc_code * code)7082 gfc_trans_omp_parallel_master_masked (gfc_code *code)
7083 {
7084   stmtblock_t block;
7085   tree stmt, omp_clauses;
7086   gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
7087   bool parallel_combined = false;
7088 
7089   if (code->op != EXEC_OMP_PARALLEL_MASTER)
7090     gfc_split_omp_clauses (code, clausesa);
7091 
7092   gfc_start_block (&block);
7093   omp_clauses = gfc_trans_omp_clauses (&block,
7094 				       code->op == EXEC_OMP_PARALLEL_MASTER
7095 				       ? code->ext.omp_clauses
7096 				       : &clausesa[GFC_OMP_SPLIT_PARALLEL],
7097 				       code->loc);
7098   pushlevel ();
7099   if (code->op == EXEC_OMP_PARALLEL_MASTER)
7100     stmt = gfc_trans_omp_master (code);
7101   else if (code->op == EXEC_OMP_PARALLEL_MASKED)
7102     stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]);
7103   else
7104     {
7105       gfc_exec_op op;
7106       switch (code->op)
7107 	{
7108 	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7109 	  op = EXEC_OMP_MASKED_TASKLOOP;
7110 	  break;
7111 	case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7112 	  op = EXEC_OMP_MASKED_TASKLOOP_SIMD;
7113 	  break;
7114 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7115 	  op = EXEC_OMP_MASTER_TASKLOOP;
7116 	  break;
7117 	case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
7118 	  op = EXEC_OMP_MASTER_TASKLOOP_SIMD;
7119 	  break;
7120 	default:
7121 	  gcc_unreachable ();
7122 	}
7123       stmt = gfc_trans_omp_master_masked_taskloop (code, op);
7124       parallel_combined = true;
7125     }
7126   if (TREE_CODE (stmt) != BIND_EXPR)
7127     stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
7128   else
7129     poplevel (0, 0);
7130   stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
7131 		     void_type_node, stmt, omp_clauses);
7132   /* masked does have just filter clause, but during gimplification
7133      isn't represented by a gimplification omp context, so for
7134        !$omp parallel masked don't set OMP_PARALLEL_COMBINED,
7135      so that
7136        !$omp parallel masked
7137        !$omp taskloop simd lastprivate (x)
7138      isn't confused with
7139        !$omp parallel masked taskloop simd lastprivate (x)  */
7140   if (parallel_combined)
7141     OMP_PARALLEL_COMBINED (stmt) = 1;
7142   gfc_add_expr_to_block (&block, stmt);
7143   if (code->op != EXEC_OMP_PARALLEL_MASTER)
7144     gfc_free_split_omp_clauses (code, clausesa);
7145   return gfc_finish_block (&block);
7146 }
7147 
7148 static tree
gfc_trans_omp_target_data(gfc_code * code)7149 gfc_trans_omp_target_data (gfc_code *code)
7150 {
7151   stmtblock_t block;
7152   tree stmt, omp_clauses;
7153 
7154   gfc_start_block (&block);
7155   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7156 				       code->loc);
7157   stmt = gfc_trans_omp_code (code->block->next, true);
7158   stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
7159 		     void_type_node, stmt, omp_clauses);
7160   gfc_add_expr_to_block (&block, stmt);
7161   return gfc_finish_block (&block);
7162 }
7163 
7164 static tree
gfc_trans_omp_target_enter_data(gfc_code * code)7165 gfc_trans_omp_target_enter_data (gfc_code *code)
7166 {
7167   stmtblock_t block;
7168   tree stmt, omp_clauses;
7169 
7170   gfc_start_block (&block);
7171   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7172 				       code->loc);
7173   stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
7174 		     omp_clauses);
7175   gfc_add_expr_to_block (&block, stmt);
7176   return gfc_finish_block (&block);
7177 }
7178 
7179 static tree
gfc_trans_omp_target_exit_data(gfc_code * code)7180 gfc_trans_omp_target_exit_data (gfc_code *code)
7181 {
7182   stmtblock_t block;
7183   tree stmt, omp_clauses;
7184 
7185   gfc_start_block (&block);
7186   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7187 				       code->loc);
7188   stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
7189 		     omp_clauses);
7190   gfc_add_expr_to_block (&block, stmt);
7191   return gfc_finish_block (&block);
7192 }
7193 
7194 static tree
gfc_trans_omp_target_update(gfc_code * code)7195 gfc_trans_omp_target_update (gfc_code *code)
7196 {
7197   stmtblock_t block;
7198   tree stmt, omp_clauses;
7199 
7200   gfc_start_block (&block);
7201   omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
7202 				       code->loc);
7203   stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
7204 		     omp_clauses);
7205   gfc_add_expr_to_block (&block, stmt);
7206   return gfc_finish_block (&block);
7207 }
7208 
7209 static tree
gfc_trans_omp_workshare(gfc_code * code,gfc_omp_clauses * clauses)7210 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
7211 {
7212   tree res, tmp, stmt;
7213   stmtblock_t block, *pblock = NULL;
7214   stmtblock_t singleblock;
7215   int saved_ompws_flags;
7216   bool singleblock_in_progress = false;
7217   /* True if previous gfc_code in workshare construct is not workshared.  */
7218   bool prev_singleunit;
7219   location_t loc = gfc_get_location (&code->loc);
7220 
7221   code = code->block->next;
7222 
7223   pushlevel ();
7224 
7225   gfc_start_block (&block);
7226   pblock = &block;
7227 
7228   ompws_flags = OMPWS_WORKSHARE_FLAG;
7229   prev_singleunit = false;
7230 
7231   /* Translate statements one by one to trees until we reach
7232      the end of the workshare construct.  Adjacent gfc_codes that
7233      are a single unit of work are clustered and encapsulated in a
7234      single OMP_SINGLE construct.  */
7235   for (; code; code = code->next)
7236     {
7237       if (code->here != 0)
7238 	{
7239 	  res = gfc_trans_label_here (code);
7240 	  gfc_add_expr_to_block (pblock, res);
7241 	}
7242 
7243       /* No dependence analysis, use for clauses with wait.
7244 	 If this is the last gfc_code, use default omp_clauses.  */
7245       if (code->next == NULL && clauses->nowait)
7246 	ompws_flags |= OMPWS_NOWAIT;
7247 
7248       /* By default, every gfc_code is a single unit of work.  */
7249       ompws_flags |= OMPWS_CURR_SINGLEUNIT;
7250       ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
7251 
7252       switch (code->op)
7253 	{
7254 	case EXEC_NOP:
7255 	  res = NULL_TREE;
7256 	  break;
7257 
7258 	case EXEC_ASSIGN:
7259 	  res = gfc_trans_assign (code);
7260 	  break;
7261 
7262 	case EXEC_POINTER_ASSIGN:
7263 	  res = gfc_trans_pointer_assign (code);
7264 	  break;
7265 
7266 	case EXEC_INIT_ASSIGN:
7267 	  res = gfc_trans_init_assign (code);
7268 	  break;
7269 
7270 	case EXEC_FORALL:
7271 	  res = gfc_trans_forall (code);
7272 	  break;
7273 
7274 	case EXEC_WHERE:
7275 	  res = gfc_trans_where (code);
7276 	  break;
7277 
7278 	case EXEC_OMP_ATOMIC:
7279 	  res = gfc_trans_omp_directive (code);
7280 	  break;
7281 
7282 	case EXEC_OMP_PARALLEL:
7283 	case EXEC_OMP_PARALLEL_DO:
7284 	case EXEC_OMP_PARALLEL_MASTER:
7285 	case EXEC_OMP_PARALLEL_SECTIONS:
7286 	case EXEC_OMP_PARALLEL_WORKSHARE:
7287 	case EXEC_OMP_CRITICAL:
7288 	  saved_ompws_flags = ompws_flags;
7289 	  ompws_flags = 0;
7290 	  res = gfc_trans_omp_directive (code);
7291 	  ompws_flags = saved_ompws_flags;
7292 	  break;
7293 
7294 	case EXEC_BLOCK:
7295 	  res = gfc_trans_block_construct (code);
7296 	  break;
7297 
7298 	default:
7299 	  gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
7300 	}
7301 
7302       gfc_set_backend_locus (&code->loc);
7303 
7304       if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
7305 	{
7306 	  if (prev_singleunit)
7307 	    {
7308 	      if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
7309 		/* Add current gfc_code to single block.  */
7310 		gfc_add_expr_to_block (&singleblock, res);
7311 	      else
7312 		{
7313 		  /* Finish single block and add it to pblock.  */
7314 		  tmp = gfc_finish_block (&singleblock);
7315 		  tmp = build2_loc (loc, OMP_SINGLE,
7316 				    void_type_node, tmp, NULL_TREE);
7317 		  gfc_add_expr_to_block (pblock, tmp);
7318 		  /* Add current gfc_code to pblock.  */
7319 		  gfc_add_expr_to_block (pblock, res);
7320 		  singleblock_in_progress = false;
7321 		}
7322 	    }
7323 	  else
7324 	    {
7325 	      if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
7326 		{
7327 		  /* Start single block.  */
7328 		  gfc_init_block (&singleblock);
7329 		  gfc_add_expr_to_block (&singleblock, res);
7330 		  singleblock_in_progress = true;
7331 		  loc = gfc_get_location (&code->loc);
7332 		}
7333 	      else
7334 		/* Add the new statement to the block.  */
7335 		gfc_add_expr_to_block (pblock, res);
7336 	    }
7337 	  prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
7338 	}
7339     }
7340 
7341   /* Finish remaining SINGLE block, if we were in the middle of one.  */
7342   if (singleblock_in_progress)
7343     {
7344       /* Finish single block and add it to pblock.  */
7345       tmp = gfc_finish_block (&singleblock);
7346       tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
7347 			clauses->nowait
7348 			? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
7349 			: NULL_TREE);
7350       gfc_add_expr_to_block (pblock, tmp);
7351     }
7352 
7353   stmt = gfc_finish_block (pblock);
7354   if (TREE_CODE (stmt) != BIND_EXPR)
7355     {
7356       if (!IS_EMPTY_STMT (stmt))
7357 	{
7358 	  tree bindblock = poplevel (1, 0);
7359 	  stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
7360 	}
7361       else
7362 	poplevel (0, 0);
7363     }
7364   else
7365     poplevel (0, 0);
7366 
7367   if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
7368     stmt = gfc_trans_omp_barrier ();
7369 
7370   ompws_flags = 0;
7371   return stmt;
7372 }
7373 
7374 tree
gfc_trans_oacc_declare(gfc_code * code)7375 gfc_trans_oacc_declare (gfc_code *code)
7376 {
7377   stmtblock_t block;
7378   tree stmt, oacc_clauses;
7379   enum tree_code construct_code;
7380 
7381   construct_code = OACC_DATA;
7382 
7383   gfc_start_block (&block);
7384 
7385   oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
7386 					code->loc, false, true);
7387   stmt = gfc_trans_omp_code (code->block->next, true);
7388   stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
7389 		     oacc_clauses);
7390   gfc_add_expr_to_block (&block, stmt);
7391 
7392   return gfc_finish_block (&block);
7393 }
7394 
7395 tree
gfc_trans_oacc_directive(gfc_code * code)7396 gfc_trans_oacc_directive (gfc_code *code)
7397 {
7398   switch (code->op)
7399     {
7400     case EXEC_OACC_PARALLEL_LOOP:
7401     case EXEC_OACC_KERNELS_LOOP:
7402     case EXEC_OACC_SERIAL_LOOP:
7403       return gfc_trans_oacc_combined_directive (code);
7404     case EXEC_OACC_PARALLEL:
7405     case EXEC_OACC_KERNELS:
7406     case EXEC_OACC_SERIAL:
7407     case EXEC_OACC_DATA:
7408     case EXEC_OACC_HOST_DATA:
7409       return gfc_trans_oacc_construct (code);
7410     case EXEC_OACC_LOOP:
7411       return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
7412 			       NULL);
7413     case EXEC_OACC_UPDATE:
7414     case EXEC_OACC_CACHE:
7415     case EXEC_OACC_ENTER_DATA:
7416     case EXEC_OACC_EXIT_DATA:
7417       return gfc_trans_oacc_executable_directive (code);
7418     case EXEC_OACC_WAIT:
7419       return gfc_trans_oacc_wait_directive (code);
7420     case EXEC_OACC_ATOMIC:
7421       return gfc_trans_omp_atomic (code);
7422     case EXEC_OACC_DECLARE:
7423       return gfc_trans_oacc_declare (code);
7424     default:
7425       gcc_unreachable ();
7426     }
7427 }
7428 
7429 tree
gfc_trans_omp_directive(gfc_code * code)7430 gfc_trans_omp_directive (gfc_code *code)
7431 {
7432   switch (code->op)
7433     {
7434     case EXEC_OMP_ATOMIC:
7435       return gfc_trans_omp_atomic (code);
7436     case EXEC_OMP_BARRIER:
7437       return gfc_trans_omp_barrier ();
7438     case EXEC_OMP_CANCEL:
7439       return gfc_trans_omp_cancel (code);
7440     case EXEC_OMP_CANCELLATION_POINT:
7441       return gfc_trans_omp_cancellation_point (code);
7442     case EXEC_OMP_CRITICAL:
7443       return gfc_trans_omp_critical (code);
7444     case EXEC_OMP_DEPOBJ:
7445       return gfc_trans_omp_depobj (code);
7446     case EXEC_OMP_DISTRIBUTE:
7447     case EXEC_OMP_DO:
7448     case EXEC_OMP_LOOP:
7449     case EXEC_OMP_SIMD:
7450     case EXEC_OMP_TASKLOOP:
7451       return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
7452 			       NULL);
7453     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
7454     case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
7455     case EXEC_OMP_DISTRIBUTE_SIMD:
7456       return gfc_trans_omp_distribute (code, NULL);
7457     case EXEC_OMP_DO_SIMD:
7458       return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
7459     case EXEC_OMP_ERROR:
7460       return gfc_trans_omp_error (code);
7461     case EXEC_OMP_FLUSH:
7462       return gfc_trans_omp_flush (code);
7463     case EXEC_OMP_MASKED:
7464       return gfc_trans_omp_masked (code, NULL);
7465     case EXEC_OMP_MASTER:
7466       return gfc_trans_omp_master (code);
7467     case EXEC_OMP_MASKED_TASKLOOP:
7468     case EXEC_OMP_MASKED_TASKLOOP_SIMD:
7469     case EXEC_OMP_MASTER_TASKLOOP:
7470     case EXEC_OMP_MASTER_TASKLOOP_SIMD:
7471       return gfc_trans_omp_master_masked_taskloop (code, code->op);
7472     case EXEC_OMP_ORDERED:
7473       return gfc_trans_omp_ordered (code);
7474     case EXEC_OMP_PARALLEL:
7475       return gfc_trans_omp_parallel (code);
7476     case EXEC_OMP_PARALLEL_DO:
7477       return gfc_trans_omp_parallel_do (code, false, NULL, NULL);
7478     case EXEC_OMP_PARALLEL_LOOP:
7479       return gfc_trans_omp_parallel_do (code, true, NULL, NULL);
7480     case EXEC_OMP_PARALLEL_DO_SIMD:
7481       return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
7482     case EXEC_OMP_PARALLEL_MASKED:
7483     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
7484     case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
7485     case EXEC_OMP_PARALLEL_MASTER:
7486     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
7487     case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
7488       return gfc_trans_omp_parallel_master_masked (code);
7489     case EXEC_OMP_PARALLEL_SECTIONS:
7490       return gfc_trans_omp_parallel_sections (code);
7491     case EXEC_OMP_PARALLEL_WORKSHARE:
7492       return gfc_trans_omp_parallel_workshare (code);
7493     case EXEC_OMP_SCOPE:
7494       return gfc_trans_omp_scope (code);
7495     case EXEC_OMP_SECTIONS:
7496       return gfc_trans_omp_sections (code, code->ext.omp_clauses);
7497     case EXEC_OMP_SINGLE:
7498       return gfc_trans_omp_single (code, code->ext.omp_clauses);
7499     case EXEC_OMP_TARGET:
7500     case EXEC_OMP_TARGET_PARALLEL:
7501     case EXEC_OMP_TARGET_PARALLEL_DO:
7502     case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
7503     case EXEC_OMP_TARGET_PARALLEL_LOOP:
7504     case EXEC_OMP_TARGET_SIMD:
7505     case EXEC_OMP_TARGET_TEAMS:
7506     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
7507     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
7508     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7509     case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
7510     case EXEC_OMP_TARGET_TEAMS_LOOP:
7511       return gfc_trans_omp_target (code);
7512     case EXEC_OMP_TARGET_DATA:
7513       return gfc_trans_omp_target_data (code);
7514     case EXEC_OMP_TARGET_ENTER_DATA:
7515       return gfc_trans_omp_target_enter_data (code);
7516     case EXEC_OMP_TARGET_EXIT_DATA:
7517       return gfc_trans_omp_target_exit_data (code);
7518     case EXEC_OMP_TARGET_UPDATE:
7519       return gfc_trans_omp_target_update (code);
7520     case EXEC_OMP_TASK:
7521       return gfc_trans_omp_task (code);
7522     case EXEC_OMP_TASKGROUP:
7523       return gfc_trans_omp_taskgroup (code);
7524     case EXEC_OMP_TASKLOOP_SIMD:
7525       return gfc_trans_omp_taskloop (code, code->op);
7526     case EXEC_OMP_TASKWAIT:
7527       return gfc_trans_omp_taskwait (code);
7528     case EXEC_OMP_TASKYIELD:
7529       return gfc_trans_omp_taskyield ();
7530     case EXEC_OMP_TEAMS:
7531     case EXEC_OMP_TEAMS_DISTRIBUTE:
7532     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
7533     case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
7534     case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
7535     case EXEC_OMP_TEAMS_LOOP:
7536       return gfc_trans_omp_teams (code, NULL, NULL_TREE);
7537     case EXEC_OMP_WORKSHARE:
7538       return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
7539     default:
7540       gcc_unreachable ();
7541     }
7542 }
7543 
7544 void
gfc_trans_omp_declare_simd(gfc_namespace * ns)7545 gfc_trans_omp_declare_simd (gfc_namespace *ns)
7546 {
7547   if (ns->entries)
7548     return;
7549 
7550   gfc_omp_declare_simd *ods;
7551   for (ods = ns->omp_declare_simd; ods; ods = ods->next)
7552     {
7553       tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
7554       tree fndecl = ns->proc_name->backend_decl;
7555       if (c != NULL_TREE)
7556 	c = tree_cons (NULL_TREE, c, NULL_TREE);
7557       c = build_tree_list (get_identifier ("omp declare simd"), c);
7558       TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
7559       DECL_ATTRIBUTES (fndecl) = c;
7560     }
7561 }
7562 
7563 void
gfc_trans_omp_declare_variant(gfc_namespace * ns)7564 gfc_trans_omp_declare_variant (gfc_namespace *ns)
7565 {
7566   tree base_fn_decl = ns->proc_name->backend_decl;
7567   gfc_namespace *search_ns = ns;
7568   gfc_omp_declare_variant *next;
7569 
7570   for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant;
7571        search_ns; odv = next)
7572     {
7573       /* Look in the parent namespace if there are no more directives in the
7574 	 current namespace.  */
7575       if (!odv)
7576 	{
7577 	  search_ns = search_ns->parent;
7578 	  if (search_ns)
7579 	    next = search_ns->omp_declare_variant;
7580 	  continue;
7581 	}
7582 
7583       next = odv->next;
7584 
7585       if (odv->error_p)
7586 	continue;
7587 
7588       /* Check directive the first time it is encountered.  */
7589       bool error_found = true;
7590 
7591       if (odv->checked_p)
7592 	error_found = false;
7593       if (odv->base_proc_symtree == NULL)
7594 	{
7595 	  if (!search_ns->proc_name->attr.function
7596 	      && !search_ns->proc_name->attr.subroutine)
7597 	    gfc_error ("The base name for 'declare variant' must be "
7598 		       "specified at %L ", &odv->where);
7599 	  else
7600 	    error_found = false;
7601 	}
7602       else
7603 	{
7604 	  if (!search_ns->contained
7605 	      && strcmp (odv->base_proc_symtree->name,
7606 			 ns->proc_name->name))
7607 	    gfc_error ("The base name at %L does not match the name of the "
7608 		       "current procedure", &odv->where);
7609 	  else if (odv->base_proc_symtree->n.sym->attr.entry)
7610 	    gfc_error ("The base name at %L must not be an entry name",
7611 			&odv->where);
7612 	  else if (odv->base_proc_symtree->n.sym->attr.generic)
7613 	    gfc_error ("The base name at %L must not be a generic name",
7614 			&odv->where);
7615 	  else if (odv->base_proc_symtree->n.sym->attr.proc_pointer)
7616 	    gfc_error ("The base name at %L must not be a procedure pointer",
7617 			&odv->where);
7618 	  else if (odv->base_proc_symtree->n.sym->attr.implicit_type)
7619 	    gfc_error ("The base procedure at %L must have an explicit "
7620 			"interface", &odv->where);
7621 	  else
7622 	    error_found = false;
7623 	}
7624 
7625       odv->checked_p = true;
7626       if (error_found)
7627 	{
7628 	  odv->error_p = true;
7629 	  continue;
7630 	}
7631 
7632       /* Ignore directives that do not apply to the current procedure.  */
7633       if ((odv->base_proc_symtree == NULL && search_ns != ns)
7634 	  || (odv->base_proc_symtree != NULL
7635 	      && strcmp (odv->base_proc_symtree->name, ns->proc_name->name)))
7636 	continue;
7637 
7638       tree set_selectors = NULL_TREE;
7639       gfc_omp_set_selector *oss;
7640 
7641       for (oss = odv->set_selectors; oss; oss = oss->next)
7642 	{
7643 	  tree selectors = NULL_TREE;
7644 	  gfc_omp_selector *os;
7645 	  for (os = oss->trait_selectors; os; os = os->next)
7646 	    {
7647 	      tree properties = NULL_TREE;
7648 	      gfc_omp_trait_property *otp;
7649 
7650 	      for (otp = os->properties; otp; otp = otp->next)
7651 		{
7652 		  switch (otp->property_kind)
7653 		    {
7654 		    case CTX_PROPERTY_USER:
7655 		    case CTX_PROPERTY_EXPR:
7656 		      {
7657 			gfc_se se;
7658 			gfc_init_se (&se, NULL);
7659 			gfc_conv_expr (&se, otp->expr);
7660 			properties = tree_cons (NULL_TREE, se.expr,
7661 						properties);
7662 		      }
7663 		      break;
7664 		    case CTX_PROPERTY_ID:
7665 		      properties = tree_cons (get_identifier (otp->name),
7666 					      NULL_TREE, properties);
7667 		      break;
7668 		    case CTX_PROPERTY_NAME_LIST:
7669 		      {
7670 			tree prop = NULL_TREE, value = NULL_TREE;
7671 			if (otp->is_name)
7672 			  prop = get_identifier (otp->name);
7673 			else
7674 			  value = gfc_conv_constant_to_tree (otp->expr);
7675 
7676 			properties = tree_cons (prop, value, properties);
7677 		      }
7678 		      break;
7679 		    case CTX_PROPERTY_SIMD:
7680 		      properties = gfc_trans_omp_clauses (NULL, otp->clauses,
7681 							  odv->where, true);
7682 		      break;
7683 		    default:
7684 		      gcc_unreachable ();
7685 		    }
7686 		}
7687 
7688 	      if (os->score)
7689 		{
7690 		  gfc_se se;
7691 		  gfc_init_se (&se, NULL);
7692 		  gfc_conv_expr (&se, os->score);
7693 		  properties = tree_cons (get_identifier (" score"),
7694 					  se.expr, properties);
7695 		}
7696 
7697 	      selectors = tree_cons (get_identifier (os->trait_selector_name),
7698 				     properties, selectors);
7699 	    }
7700 
7701 	  set_selectors
7702 	    = tree_cons (get_identifier (oss->trait_set_selector_name),
7703 			 selectors, set_selectors);
7704 	}
7705 
7706       const char *variant_proc_name = odv->variant_proc_symtree->name;
7707       gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym;
7708       if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type)
7709 	{
7710 	  gfc_symtree *proc_st;
7711 	  gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st);
7712 	  variant_proc_sym = proc_st->n.sym;
7713 	}
7714       if (variant_proc_sym == NULL)
7715 	{
7716 	  gfc_error ("Cannot find symbol %qs", variant_proc_name);
7717 	  continue;
7718 	}
7719       set_selectors = omp_check_context_selector
7720 	  (gfc_get_location (&odv->where), set_selectors);
7721       if (set_selectors != error_mark_node)
7722 	{
7723 	  if (!variant_proc_sym->attr.implicit_type
7724 	      && !variant_proc_sym->attr.subroutine
7725 	      && !variant_proc_sym->attr.function)
7726 	    {
7727 	      gfc_error ("variant %qs at %L is not a function or subroutine",
7728 			 variant_proc_name, &odv->where);
7729 	      variant_proc_sym = NULL;
7730 	    }
7731 	  else if (omp_get_context_selector (set_selectors, "construct",
7732 					     "simd") == NULL_TREE)
7733 	    {
7734 	      char err[256];
7735 	      if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym,
7736 					   variant_proc_sym->name, 0, 1,
7737 					   err, sizeof (err), NULL, NULL))
7738 		{
7739 		  gfc_error ("variant %qs and base %qs at %L have "
7740 			     "incompatible types: %s",
7741 			     variant_proc_name, ns->proc_name->name,
7742 			     &odv->where, err);
7743 		  variant_proc_sym = NULL;
7744 		}
7745 	    }
7746 	  if (variant_proc_sym != NULL)
7747 	    {
7748 	      gfc_set_sym_referenced (variant_proc_sym);
7749 	      tree construct = omp_get_context_selector (set_selectors,
7750 							 "construct", NULL);
7751 	      omp_mark_declare_variant (gfc_get_location (&odv->where),
7752 					gfc_get_symbol_decl (variant_proc_sym),
7753 					construct);
7754 	      if (omp_context_selector_matches (set_selectors))
7755 		{
7756 		  tree id = get_identifier ("omp declare variant base");
7757 		  tree variant = gfc_get_symbol_decl (variant_proc_sym);
7758 		  DECL_ATTRIBUTES (base_fn_decl)
7759 		    = tree_cons (id, build_tree_list (variant, set_selectors),
7760 				 DECL_ATTRIBUTES (base_fn_decl));
7761 		}
7762 	    }
7763 	}
7764     }
7765 }
7766