1627f7eb2Smrg /* OpenMP directive translation -- generate GCC trees from gfc_code.
2*4c3eb207Smrg Copyright (C) 2005-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Jakub Jelinek <jakub@redhat.com>
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg
22627f7eb2Smrg #include "config.h"
23627f7eb2Smrg #include "system.h"
24627f7eb2Smrg #include "coretypes.h"
25627f7eb2Smrg #include "options.h"
26627f7eb2Smrg #include "tree.h"
27627f7eb2Smrg #include "gfortran.h"
28627f7eb2Smrg #include "gimple-expr.h"
29627f7eb2Smrg #include "trans.h"
30627f7eb2Smrg #include "stringpool.h"
31627f7eb2Smrg #include "fold-const.h"
32627f7eb2Smrg #include "gimplify.h" /* For create_tmp_var_raw. */
33627f7eb2Smrg #include "trans-stmt.h"
34627f7eb2Smrg #include "trans-types.h"
35627f7eb2Smrg #include "trans-array.h"
36627f7eb2Smrg #include "trans-const.h"
37627f7eb2Smrg #include "arith.h"
38627f7eb2Smrg #include "gomp-constants.h"
39627f7eb2Smrg #include "omp-general.h"
40627f7eb2Smrg #include "omp-low.h"
41627f7eb2Smrg #undef GCC_DIAG_STYLE
42627f7eb2Smrg #define GCC_DIAG_STYLE __gcc_tdiag__
43627f7eb2Smrg #include "diagnostic-core.h"
44627f7eb2Smrg #undef GCC_DIAG_STYLE
45627f7eb2Smrg #define GCC_DIAG_STYLE __gcc_gfc__
46627f7eb2Smrg #include "attribs.h"
47627f7eb2Smrg
48627f7eb2Smrg int ompws_flags;
49627f7eb2Smrg
50*4c3eb207Smrg /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
51*4c3eb207Smrg allocatable or pointer attribute. */
52*4c3eb207Smrg
53*4c3eb207Smrg bool
gfc_omp_is_allocatable_or_ptr(const_tree decl)54*4c3eb207Smrg gfc_omp_is_allocatable_or_ptr (const_tree decl)
55*4c3eb207Smrg {
56*4c3eb207Smrg return (DECL_P (decl)
57*4c3eb207Smrg && (GFC_DECL_GET_SCALAR_POINTER (decl)
58*4c3eb207Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)));
59*4c3eb207Smrg }
60*4c3eb207Smrg
61*4c3eb207Smrg /* True if the argument is an optional argument; except that false is also
62*4c3eb207Smrg returned for arguments with the value attribute (nonpointers) and for
63*4c3eb207Smrg assumed-shape variables (decl is a local variable containing arg->data).
64*4c3eb207Smrg Note that for 'procedure(), optional' the value false is used as that's
65*4c3eb207Smrg always a pointer and no additional indirection is used.
66*4c3eb207Smrg Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc). */
67*4c3eb207Smrg
68*4c3eb207Smrg static bool
gfc_omp_is_optional_argument(const_tree decl)69*4c3eb207Smrg gfc_omp_is_optional_argument (const_tree decl)
70*4c3eb207Smrg {
71*4c3eb207Smrg return (TREE_CODE (decl) == PARM_DECL
72*4c3eb207Smrg && DECL_LANG_SPECIFIC (decl)
73*4c3eb207Smrg && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
74*4c3eb207Smrg && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
75*4c3eb207Smrg && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE
76*4c3eb207Smrg && GFC_DECL_OPTIONAL_ARGUMENT (decl));
77*4c3eb207Smrg }
78*4c3eb207Smrg
79*4c3eb207Smrg /* Check whether this DECL belongs to a Fortran optional argument.
80*4c3eb207Smrg With 'for_present_check' set to false, decls which are optional parameters
81*4c3eb207Smrg themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
82*4c3eb207Smrg always pointers. With 'for_present_check' set to true, the decl for checking
83*4c3eb207Smrg whether an argument is present is returned; for arguments with value
84*4c3eb207Smrg attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is
85*4c3eb207Smrg unrelated to optional arguments, NULL_TREE is returned. */
86*4c3eb207Smrg
87*4c3eb207Smrg tree
gfc_omp_check_optional_argument(tree decl,bool for_present_check)88*4c3eb207Smrg gfc_omp_check_optional_argument (tree decl, bool for_present_check)
89*4c3eb207Smrg {
90*4c3eb207Smrg if (!for_present_check)
91*4c3eb207Smrg return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE;
92*4c3eb207Smrg
93*4c3eb207Smrg if (!DECL_LANG_SPECIFIC (decl))
94*4c3eb207Smrg return NULL_TREE;
95*4c3eb207Smrg
96*4c3eb207Smrg tree orig_decl = decl;
97*4c3eb207Smrg
98*4c3eb207Smrg /* For assumed-shape arrays, a local decl with arg->data is used. */
99*4c3eb207Smrg if (TREE_CODE (decl) != PARM_DECL
100*4c3eb207Smrg && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
101*4c3eb207Smrg || GFC_ARRAY_TYPE_P (TREE_TYPE (decl))))
102*4c3eb207Smrg decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
103*4c3eb207Smrg
104*4c3eb207Smrg if (decl == NULL_TREE
105*4c3eb207Smrg || TREE_CODE (decl) != PARM_DECL
106*4c3eb207Smrg || !DECL_LANG_SPECIFIC (decl)
107*4c3eb207Smrg || !GFC_DECL_OPTIONAL_ARGUMENT (decl))
108*4c3eb207Smrg return NULL_TREE;
109*4c3eb207Smrg
110*4c3eb207Smrg /* Scalars with VALUE attribute which are passed by value use a hidden
111*4c3eb207Smrg argument to denote the present status. They are passed as nonpointer type
112*4c3eb207Smrg with one exception: 'type(c_ptr), value' as 'void*'. */
113*4c3eb207Smrg /* Cf. trans-expr.c's gfc_conv_expr_present. */
114*4c3eb207Smrg if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
115*4c3eb207Smrg || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
116*4c3eb207Smrg {
117*4c3eb207Smrg char name[GFC_MAX_SYMBOL_LEN + 2];
118*4c3eb207Smrg tree tree_name;
119*4c3eb207Smrg
120*4c3eb207Smrg name[0] = '_';
121*4c3eb207Smrg strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl)));
122*4c3eb207Smrg tree_name = get_identifier (name);
123*4c3eb207Smrg
124*4c3eb207Smrg /* Walk function argument list to find the hidden arg. */
125*4c3eb207Smrg decl = DECL_ARGUMENTS (DECL_CONTEXT (decl));
126*4c3eb207Smrg for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl))
127*4c3eb207Smrg if (DECL_NAME (decl) == tree_name
128*4c3eb207Smrg && DECL_ARTIFICIAL (decl))
129*4c3eb207Smrg break;
130*4c3eb207Smrg
131*4c3eb207Smrg gcc_assert (decl);
132*4c3eb207Smrg return decl;
133*4c3eb207Smrg }
134*4c3eb207Smrg
135*4c3eb207Smrg return fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
136*4c3eb207Smrg orig_decl, null_pointer_node);
137*4c3eb207Smrg }
138*4c3eb207Smrg
139*4c3eb207Smrg
140*4c3eb207Smrg /* Returns tree with NULL if it is not an array descriptor and with the tree to
141*4c3eb207Smrg access the 'data' component otherwise. With type_only = true, it returns the
142*4c3eb207Smrg TREE_TYPE without creating a new tree. */
143*4c3eb207Smrg
144*4c3eb207Smrg tree
gfc_omp_array_data(tree decl,bool type_only)145*4c3eb207Smrg gfc_omp_array_data (tree decl, bool type_only)
146*4c3eb207Smrg {
147*4c3eb207Smrg tree type = TREE_TYPE (decl);
148*4c3eb207Smrg
149*4c3eb207Smrg if (POINTER_TYPE_P (type))
150*4c3eb207Smrg type = TREE_TYPE (type);
151*4c3eb207Smrg
152*4c3eb207Smrg if (!GFC_DESCRIPTOR_TYPE_P (type))
153*4c3eb207Smrg return NULL_TREE;
154*4c3eb207Smrg
155*4c3eb207Smrg if (type_only)
156*4c3eb207Smrg return GFC_TYPE_ARRAY_DATAPTR_TYPE (type);
157*4c3eb207Smrg
158*4c3eb207Smrg if (POINTER_TYPE_P (TREE_TYPE (decl)))
159*4c3eb207Smrg decl = build_fold_indirect_ref (decl);
160*4c3eb207Smrg
161*4c3eb207Smrg decl = gfc_conv_descriptor_data_get (decl);
162*4c3eb207Smrg STRIP_NOPS (decl);
163*4c3eb207Smrg return decl;
164*4c3eb207Smrg }
165*4c3eb207Smrg
166627f7eb2Smrg /* True if OpenMP should privatize what this DECL points to rather
167627f7eb2Smrg than the DECL itself. */
168627f7eb2Smrg
169627f7eb2Smrg bool
gfc_omp_privatize_by_reference(const_tree decl)170627f7eb2Smrg gfc_omp_privatize_by_reference (const_tree decl)
171627f7eb2Smrg {
172627f7eb2Smrg tree type = TREE_TYPE (decl);
173627f7eb2Smrg
174627f7eb2Smrg if (TREE_CODE (type) == REFERENCE_TYPE
175627f7eb2Smrg && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
176627f7eb2Smrg return true;
177627f7eb2Smrg
178*4c3eb207Smrg if (TREE_CODE (type) == POINTER_TYPE
179*4c3eb207Smrg && gfc_omp_is_optional_argument (decl))
180*4c3eb207Smrg return true;
181*4c3eb207Smrg
182627f7eb2Smrg if (TREE_CODE (type) == POINTER_TYPE)
183627f7eb2Smrg {
184*4c3eb207Smrg while (TREE_CODE (decl) == COMPONENT_REF)
185*4c3eb207Smrg decl = TREE_OPERAND (decl, 1);
186*4c3eb207Smrg
187627f7eb2Smrg /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
188627f7eb2Smrg that have POINTER_TYPE type and aren't scalar pointers, scalar
189627f7eb2Smrg allocatables, Cray pointees or C pointers are supposed to be
190627f7eb2Smrg privatized by reference. */
191627f7eb2Smrg if (GFC_DECL_GET_SCALAR_POINTER (decl)
192627f7eb2Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
193627f7eb2Smrg || GFC_DECL_CRAY_POINTEE (decl)
194627f7eb2Smrg || GFC_DECL_ASSOCIATE_VAR_P (decl)
195627f7eb2Smrg || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
196627f7eb2Smrg return false;
197627f7eb2Smrg
198627f7eb2Smrg if (!DECL_ARTIFICIAL (decl)
199627f7eb2Smrg && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
200627f7eb2Smrg return true;
201627f7eb2Smrg
202627f7eb2Smrg /* Some arrays are expanded as DECL_ARTIFICIAL pointers
203627f7eb2Smrg by the frontend. */
204627f7eb2Smrg if (DECL_LANG_SPECIFIC (decl)
205627f7eb2Smrg && GFC_DECL_SAVED_DESCRIPTOR (decl))
206627f7eb2Smrg return true;
207627f7eb2Smrg }
208627f7eb2Smrg
209627f7eb2Smrg return false;
210627f7eb2Smrg }
211627f7eb2Smrg
212627f7eb2Smrg /* True if OpenMP sharing attribute of DECL is predetermined. */
213627f7eb2Smrg
214627f7eb2Smrg enum omp_clause_default_kind
gfc_omp_predetermined_sharing(tree decl)215627f7eb2Smrg gfc_omp_predetermined_sharing (tree decl)
216627f7eb2Smrg {
217627f7eb2Smrg /* Associate names preserve the association established during ASSOCIATE.
218627f7eb2Smrg As they are implemented either as pointers to the selector or array
219627f7eb2Smrg descriptor and shouldn't really change in the ASSOCIATE region,
220627f7eb2Smrg this decl can be either shared or firstprivate. If it is a pointer,
221627f7eb2Smrg use firstprivate, as it is cheaper that way, otherwise make it shared. */
222627f7eb2Smrg if (GFC_DECL_ASSOCIATE_VAR_P (decl))
223627f7eb2Smrg {
224627f7eb2Smrg if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
225627f7eb2Smrg return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
226627f7eb2Smrg else
227627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
228627f7eb2Smrg }
229627f7eb2Smrg
230627f7eb2Smrg if (DECL_ARTIFICIAL (decl)
231627f7eb2Smrg && ! GFC_DECL_RESULT (decl)
232627f7eb2Smrg && ! (DECL_LANG_SPECIFIC (decl)
233627f7eb2Smrg && GFC_DECL_SAVED_DESCRIPTOR (decl)))
234627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
235627f7eb2Smrg
236627f7eb2Smrg /* Cray pointees shouldn't be listed in any clauses and should be
237627f7eb2Smrg gimplified to dereference of the corresponding Cray pointer.
238627f7eb2Smrg Make them all private, so that they are emitted in the debug
239627f7eb2Smrg information. */
240627f7eb2Smrg if (GFC_DECL_CRAY_POINTEE (decl))
241627f7eb2Smrg return OMP_CLAUSE_DEFAULT_PRIVATE;
242627f7eb2Smrg
243627f7eb2Smrg /* Assumed-size arrays are predetermined shared. */
244627f7eb2Smrg if (TREE_CODE (decl) == PARM_DECL
245627f7eb2Smrg && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
246627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
247627f7eb2Smrg && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
248627f7eb2Smrg GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
249627f7eb2Smrg == NULL)
250627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
251627f7eb2Smrg
252627f7eb2Smrg /* Dummy procedures aren't considered variables by OpenMP, thus are
253627f7eb2Smrg disallowed in OpenMP clauses. They are represented as PARM_DECLs
254627f7eb2Smrg in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
255627f7eb2Smrg to avoid complaining about their uses with default(none). */
256627f7eb2Smrg if (TREE_CODE (decl) == PARM_DECL
257627f7eb2Smrg && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
258627f7eb2Smrg && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
259627f7eb2Smrg return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
260627f7eb2Smrg
261627f7eb2Smrg /* COMMON and EQUIVALENCE decls are shared. They
262627f7eb2Smrg are only referenced through DECL_VALUE_EXPR of the variables
263627f7eb2Smrg contained in them. If those are privatized, they will not be
264627f7eb2Smrg gimplified to the COMMON or EQUIVALENCE decls. */
265627f7eb2Smrg if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
266627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
267627f7eb2Smrg
268627f7eb2Smrg if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
269627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
270627f7eb2Smrg
271627f7eb2Smrg /* These are either array or derived parameters, or vtables.
272627f7eb2Smrg In the former cases, the OpenMP standard doesn't consider them to be
273627f7eb2Smrg variables at all (they can't be redefined), but they can nevertheless appear
274627f7eb2Smrg in parallel/task regions and for default(none) purposes treat them as shared.
275627f7eb2Smrg For vtables likely the same handling is desirable. */
276627f7eb2Smrg if (VAR_P (decl) && TREE_READONLY (decl)
277627f7eb2Smrg && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
278627f7eb2Smrg return OMP_CLAUSE_DEFAULT_SHARED;
279627f7eb2Smrg
280627f7eb2Smrg return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
281627f7eb2Smrg }
282627f7eb2Smrg
283627f7eb2Smrg /* Return decl that should be used when reporting DEFAULT(NONE)
284627f7eb2Smrg diagnostics. */
285627f7eb2Smrg
286627f7eb2Smrg tree
gfc_omp_report_decl(tree decl)287627f7eb2Smrg gfc_omp_report_decl (tree decl)
288627f7eb2Smrg {
289627f7eb2Smrg if (DECL_ARTIFICIAL (decl)
290627f7eb2Smrg && DECL_LANG_SPECIFIC (decl)
291627f7eb2Smrg && GFC_DECL_SAVED_DESCRIPTOR (decl))
292627f7eb2Smrg return GFC_DECL_SAVED_DESCRIPTOR (decl);
293627f7eb2Smrg
294627f7eb2Smrg return decl;
295627f7eb2Smrg }
296627f7eb2Smrg
297627f7eb2Smrg /* Return true if TYPE has any allocatable components. */
298627f7eb2Smrg
299627f7eb2Smrg static bool
gfc_has_alloc_comps(tree type,tree decl)300627f7eb2Smrg gfc_has_alloc_comps (tree type, tree decl)
301627f7eb2Smrg {
302627f7eb2Smrg tree field, ftype;
303627f7eb2Smrg
304627f7eb2Smrg if (POINTER_TYPE_P (type))
305627f7eb2Smrg {
306627f7eb2Smrg if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
307627f7eb2Smrg type = TREE_TYPE (type);
308627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_POINTER (decl))
309627f7eb2Smrg return false;
310627f7eb2Smrg }
311627f7eb2Smrg
312627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
313627f7eb2Smrg type = gfc_get_element_type (type);
314627f7eb2Smrg
315627f7eb2Smrg if (TREE_CODE (type) != RECORD_TYPE)
316627f7eb2Smrg return false;
317627f7eb2Smrg
318627f7eb2Smrg for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
319627f7eb2Smrg {
320627f7eb2Smrg ftype = TREE_TYPE (field);
321627f7eb2Smrg if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
322627f7eb2Smrg return true;
323627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (ftype)
324627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
325627f7eb2Smrg return true;
326627f7eb2Smrg if (gfc_has_alloc_comps (ftype, field))
327627f7eb2Smrg return true;
328627f7eb2Smrg }
329627f7eb2Smrg return false;
330627f7eb2Smrg }
331627f7eb2Smrg
332627f7eb2Smrg /* Return true if DECL in private clause needs
333627f7eb2Smrg OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
334627f7eb2Smrg bool
gfc_omp_private_outer_ref(tree decl)335627f7eb2Smrg gfc_omp_private_outer_ref (tree decl)
336627f7eb2Smrg {
337627f7eb2Smrg tree type = TREE_TYPE (decl);
338627f7eb2Smrg
339627f7eb2Smrg if (gfc_omp_privatize_by_reference (decl))
340627f7eb2Smrg type = TREE_TYPE (type);
341627f7eb2Smrg
342627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type)
343627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
344627f7eb2Smrg return true;
345627f7eb2Smrg
346627f7eb2Smrg if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
347627f7eb2Smrg return true;
348627f7eb2Smrg
349627f7eb2Smrg if (gfc_has_alloc_comps (type, decl))
350627f7eb2Smrg return true;
351627f7eb2Smrg
352627f7eb2Smrg return false;
353627f7eb2Smrg }
354627f7eb2Smrg
355627f7eb2Smrg /* Callback for gfc_omp_unshare_expr. */
356627f7eb2Smrg
357627f7eb2Smrg static tree
gfc_omp_unshare_expr_r(tree * tp,int * walk_subtrees,void *)358627f7eb2Smrg gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
359627f7eb2Smrg {
360627f7eb2Smrg tree t = *tp;
361627f7eb2Smrg enum tree_code code = TREE_CODE (t);
362627f7eb2Smrg
363627f7eb2Smrg /* Stop at types, decls, constants like copy_tree_r. */
364627f7eb2Smrg if (TREE_CODE_CLASS (code) == tcc_type
365627f7eb2Smrg || TREE_CODE_CLASS (code) == tcc_declaration
366627f7eb2Smrg || TREE_CODE_CLASS (code) == tcc_constant
367627f7eb2Smrg || code == BLOCK)
368627f7eb2Smrg *walk_subtrees = 0;
369627f7eb2Smrg else if (handled_component_p (t)
370627f7eb2Smrg || TREE_CODE (t) == MEM_REF)
371627f7eb2Smrg {
372627f7eb2Smrg *tp = unshare_expr (t);
373627f7eb2Smrg *walk_subtrees = 0;
374627f7eb2Smrg }
375627f7eb2Smrg
376627f7eb2Smrg return NULL_TREE;
377627f7eb2Smrg }
378627f7eb2Smrg
379627f7eb2Smrg /* Unshare in expr anything that the FE which normally doesn't
380627f7eb2Smrg care much about tree sharing (because during gimplification
381627f7eb2Smrg everything is unshared) could cause problems with tree sharing
382627f7eb2Smrg at omp-low.c time. */
383627f7eb2Smrg
384627f7eb2Smrg static tree
gfc_omp_unshare_expr(tree expr)385627f7eb2Smrg gfc_omp_unshare_expr (tree expr)
386627f7eb2Smrg {
387627f7eb2Smrg walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
388627f7eb2Smrg return expr;
389627f7eb2Smrg }
390627f7eb2Smrg
391627f7eb2Smrg enum walk_alloc_comps
392627f7eb2Smrg {
393627f7eb2Smrg WALK_ALLOC_COMPS_DTOR,
394627f7eb2Smrg WALK_ALLOC_COMPS_DEFAULT_CTOR,
395627f7eb2Smrg WALK_ALLOC_COMPS_COPY_CTOR
396627f7eb2Smrg };
397627f7eb2Smrg
398627f7eb2Smrg /* Handle allocatable components in OpenMP clauses. */
399627f7eb2Smrg
400627f7eb2Smrg static tree
gfc_walk_alloc_comps(tree decl,tree dest,tree var,enum walk_alloc_comps kind)401627f7eb2Smrg gfc_walk_alloc_comps (tree decl, tree dest, tree var,
402627f7eb2Smrg enum walk_alloc_comps kind)
403627f7eb2Smrg {
404627f7eb2Smrg stmtblock_t block, tmpblock;
405627f7eb2Smrg tree type = TREE_TYPE (decl), then_b, tem, field;
406627f7eb2Smrg gfc_init_block (&block);
407627f7eb2Smrg
408627f7eb2Smrg if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
409627f7eb2Smrg {
410627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
411627f7eb2Smrg {
412627f7eb2Smrg gfc_init_block (&tmpblock);
413627f7eb2Smrg tem = gfc_full_array_size (&tmpblock, decl,
414627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
415627f7eb2Smrg then_b = gfc_finish_block (&tmpblock);
416627f7eb2Smrg gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
417627f7eb2Smrg tem = gfc_omp_unshare_expr (tem);
418627f7eb2Smrg tem = fold_build2_loc (input_location, MINUS_EXPR,
419627f7eb2Smrg gfc_array_index_type, tem,
420627f7eb2Smrg gfc_index_one_node);
421627f7eb2Smrg }
422627f7eb2Smrg else
423627f7eb2Smrg {
424627f7eb2Smrg bool compute_nelts = false;
425627f7eb2Smrg if (!TYPE_DOMAIN (type)
426627f7eb2Smrg || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
427627f7eb2Smrg || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
428627f7eb2Smrg || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
429627f7eb2Smrg compute_nelts = true;
430627f7eb2Smrg else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
431627f7eb2Smrg {
432627f7eb2Smrg tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
433627f7eb2Smrg if (lookup_attribute ("omp dummy var", a))
434627f7eb2Smrg compute_nelts = true;
435627f7eb2Smrg }
436627f7eb2Smrg if (compute_nelts)
437627f7eb2Smrg {
438627f7eb2Smrg tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
439627f7eb2Smrg TYPE_SIZE_UNIT (type),
440627f7eb2Smrg TYPE_SIZE_UNIT (TREE_TYPE (type)));
441627f7eb2Smrg tem = size_binop (MINUS_EXPR, tem, size_one_node);
442627f7eb2Smrg }
443627f7eb2Smrg else
444627f7eb2Smrg tem = array_type_nelts (type);
445627f7eb2Smrg tem = fold_convert (gfc_array_index_type, tem);
446627f7eb2Smrg }
447627f7eb2Smrg
448627f7eb2Smrg tree nelems = gfc_evaluate_now (tem, &block);
449627f7eb2Smrg tree index = gfc_create_var (gfc_array_index_type, "S");
450627f7eb2Smrg
451627f7eb2Smrg gfc_init_block (&tmpblock);
452627f7eb2Smrg tem = gfc_conv_array_data (decl);
453627f7eb2Smrg tree declvar = build_fold_indirect_ref_loc (input_location, tem);
454627f7eb2Smrg tree declvref = gfc_build_array_ref (declvar, index, NULL);
455627f7eb2Smrg tree destvar, destvref = NULL_TREE;
456627f7eb2Smrg if (dest)
457627f7eb2Smrg {
458627f7eb2Smrg tem = gfc_conv_array_data (dest);
459627f7eb2Smrg destvar = build_fold_indirect_ref_loc (input_location, tem);
460627f7eb2Smrg destvref = gfc_build_array_ref (destvar, index, NULL);
461627f7eb2Smrg }
462627f7eb2Smrg gfc_add_expr_to_block (&tmpblock,
463627f7eb2Smrg gfc_walk_alloc_comps (declvref, destvref,
464627f7eb2Smrg var, kind));
465627f7eb2Smrg
466627f7eb2Smrg gfc_loopinfo loop;
467627f7eb2Smrg gfc_init_loopinfo (&loop);
468627f7eb2Smrg loop.dimen = 1;
469627f7eb2Smrg loop.from[0] = gfc_index_zero_node;
470627f7eb2Smrg loop.loopvar[0] = index;
471627f7eb2Smrg loop.to[0] = nelems;
472627f7eb2Smrg gfc_trans_scalarizing_loops (&loop, &tmpblock);
473627f7eb2Smrg gfc_add_block_to_block (&block, &loop.pre);
474627f7eb2Smrg return gfc_finish_block (&block);
475627f7eb2Smrg }
476627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
477627f7eb2Smrg {
478627f7eb2Smrg decl = build_fold_indirect_ref_loc (input_location, decl);
479627f7eb2Smrg if (dest)
480627f7eb2Smrg dest = build_fold_indirect_ref_loc (input_location, dest);
481627f7eb2Smrg type = TREE_TYPE (decl);
482627f7eb2Smrg }
483627f7eb2Smrg
484627f7eb2Smrg gcc_assert (TREE_CODE (type) == RECORD_TYPE);
485627f7eb2Smrg for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
486627f7eb2Smrg {
487627f7eb2Smrg tree ftype = TREE_TYPE (field);
488627f7eb2Smrg tree declf, destf = NULL_TREE;
489627f7eb2Smrg bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
490627f7eb2Smrg if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
491627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
492627f7eb2Smrg && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
493627f7eb2Smrg && !has_alloc_comps)
494627f7eb2Smrg continue;
495627f7eb2Smrg declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
496627f7eb2Smrg decl, field, NULL_TREE);
497627f7eb2Smrg if (dest)
498627f7eb2Smrg destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
499627f7eb2Smrg dest, field, NULL_TREE);
500627f7eb2Smrg
501627f7eb2Smrg tem = NULL_TREE;
502627f7eb2Smrg switch (kind)
503627f7eb2Smrg {
504627f7eb2Smrg case WALK_ALLOC_COMPS_DTOR:
505627f7eb2Smrg break;
506627f7eb2Smrg case WALK_ALLOC_COMPS_DEFAULT_CTOR:
507627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (ftype)
508627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
509627f7eb2Smrg {
510627f7eb2Smrg gfc_add_modify (&block, unshare_expr (destf),
511627f7eb2Smrg unshare_expr (declf));
512627f7eb2Smrg tem = gfc_duplicate_allocatable_nocopy
513627f7eb2Smrg (destf, declf, ftype,
514627f7eb2Smrg GFC_TYPE_ARRAY_RANK (ftype));
515627f7eb2Smrg }
516627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
517627f7eb2Smrg tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
518627f7eb2Smrg break;
519627f7eb2Smrg case WALK_ALLOC_COMPS_COPY_CTOR:
520627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (ftype)
521627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
522627f7eb2Smrg tem = gfc_duplicate_allocatable (destf, declf, ftype,
523627f7eb2Smrg GFC_TYPE_ARRAY_RANK (ftype),
524627f7eb2Smrg NULL_TREE);
525627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
526627f7eb2Smrg tem = gfc_duplicate_allocatable (destf, declf, ftype, 0,
527627f7eb2Smrg NULL_TREE);
528627f7eb2Smrg break;
529627f7eb2Smrg }
530627f7eb2Smrg if (tem)
531627f7eb2Smrg gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
532627f7eb2Smrg if (has_alloc_comps)
533627f7eb2Smrg {
534627f7eb2Smrg gfc_init_block (&tmpblock);
535627f7eb2Smrg gfc_add_expr_to_block (&tmpblock,
536627f7eb2Smrg gfc_walk_alloc_comps (declf, destf,
537627f7eb2Smrg field, kind));
538627f7eb2Smrg then_b = gfc_finish_block (&tmpblock);
539627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (ftype)
540627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
541627f7eb2Smrg tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
542627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
543627f7eb2Smrg tem = unshare_expr (declf);
544627f7eb2Smrg else
545627f7eb2Smrg tem = NULL_TREE;
546627f7eb2Smrg if (tem)
547627f7eb2Smrg {
548627f7eb2Smrg tem = fold_convert (pvoid_type_node, tem);
549627f7eb2Smrg tem = fold_build2_loc (input_location, NE_EXPR,
550627f7eb2Smrg logical_type_node, tem,
551627f7eb2Smrg null_pointer_node);
552627f7eb2Smrg then_b = build3_loc (input_location, COND_EXPR, void_type_node,
553627f7eb2Smrg tem, then_b,
554627f7eb2Smrg build_empty_stmt (input_location));
555627f7eb2Smrg }
556627f7eb2Smrg gfc_add_expr_to_block (&block, then_b);
557627f7eb2Smrg }
558627f7eb2Smrg if (kind == WALK_ALLOC_COMPS_DTOR)
559627f7eb2Smrg {
560627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (ftype)
561627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
562627f7eb2Smrg {
563627f7eb2Smrg tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
564627f7eb2Smrg tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE,
565627f7eb2Smrg NULL_TREE, NULL_TREE, true,
566627f7eb2Smrg NULL,
567627f7eb2Smrg GFC_CAF_COARRAY_NOCOARRAY);
568627f7eb2Smrg gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
569627f7eb2Smrg }
570627f7eb2Smrg else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
571627f7eb2Smrg {
572627f7eb2Smrg tem = gfc_call_free (unshare_expr (declf));
573627f7eb2Smrg gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
574627f7eb2Smrg }
575627f7eb2Smrg }
576627f7eb2Smrg }
577627f7eb2Smrg
578627f7eb2Smrg return gfc_finish_block (&block);
579627f7eb2Smrg }
580627f7eb2Smrg
581627f7eb2Smrg /* Return code to initialize DECL with its default constructor, or
582627f7eb2Smrg NULL if there's nothing to do. */
583627f7eb2Smrg
584627f7eb2Smrg tree
gfc_omp_clause_default_ctor(tree clause,tree decl,tree outer)585627f7eb2Smrg gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
586627f7eb2Smrg {
587627f7eb2Smrg tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
588627f7eb2Smrg stmtblock_t block, cond_block;
589627f7eb2Smrg
590627f7eb2Smrg gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
591627f7eb2Smrg || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
592627f7eb2Smrg || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
593627f7eb2Smrg || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
594627f7eb2Smrg
595627f7eb2Smrg if ((! GFC_DESCRIPTOR_TYPE_P (type)
596627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
597627f7eb2Smrg && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
598627f7eb2Smrg || !POINTER_TYPE_P (type)))
599627f7eb2Smrg {
600627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
601627f7eb2Smrg {
602627f7eb2Smrg gcc_assert (outer);
603627f7eb2Smrg gfc_start_block (&block);
604627f7eb2Smrg tree tem = gfc_walk_alloc_comps (outer, decl,
605627f7eb2Smrg OMP_CLAUSE_DECL (clause),
606627f7eb2Smrg WALK_ALLOC_COMPS_DEFAULT_CTOR);
607627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
608627f7eb2Smrg return gfc_finish_block (&block);
609627f7eb2Smrg }
610627f7eb2Smrg return NULL_TREE;
611627f7eb2Smrg }
612627f7eb2Smrg
613627f7eb2Smrg gcc_assert (outer != NULL_TREE);
614627f7eb2Smrg
615627f7eb2Smrg /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
616627f7eb2Smrg "not currently allocated" allocation status if outer
617627f7eb2Smrg array is "not currently allocated", otherwise should be allocated. */
618627f7eb2Smrg gfc_start_block (&block);
619627f7eb2Smrg
620627f7eb2Smrg gfc_init_block (&cond_block);
621627f7eb2Smrg
622627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
623627f7eb2Smrg {
624627f7eb2Smrg gfc_add_modify (&cond_block, decl, outer);
625627f7eb2Smrg tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
626627f7eb2Smrg size = gfc_conv_descriptor_ubound_get (decl, rank);
627627f7eb2Smrg size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
628627f7eb2Smrg size,
629627f7eb2Smrg gfc_conv_descriptor_lbound_get (decl, rank));
630627f7eb2Smrg size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
631627f7eb2Smrg size, gfc_index_one_node);
632627f7eb2Smrg if (GFC_TYPE_ARRAY_RANK (type) > 1)
633627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR,
634627f7eb2Smrg gfc_array_index_type, size,
635627f7eb2Smrg gfc_conv_descriptor_stride_get (decl, rank));
636627f7eb2Smrg tree esize = fold_convert (gfc_array_index_type,
637627f7eb2Smrg TYPE_SIZE_UNIT (gfc_get_element_type (type)));
638627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
639627f7eb2Smrg size, esize);
640627f7eb2Smrg size = unshare_expr (size);
641627f7eb2Smrg size = gfc_evaluate_now (fold_convert (size_type_node, size),
642627f7eb2Smrg &cond_block);
643627f7eb2Smrg }
644627f7eb2Smrg else
645627f7eb2Smrg size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
646627f7eb2Smrg ptr = gfc_create_var (pvoid_type_node, NULL);
647627f7eb2Smrg gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
648627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
649627f7eb2Smrg gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
650627f7eb2Smrg else
651627f7eb2Smrg gfc_add_modify (&cond_block, unshare_expr (decl),
652627f7eb2Smrg fold_convert (TREE_TYPE (decl), ptr));
653627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
654627f7eb2Smrg {
655627f7eb2Smrg tree tem = gfc_walk_alloc_comps (outer, decl,
656627f7eb2Smrg OMP_CLAUSE_DECL (clause),
657627f7eb2Smrg WALK_ALLOC_COMPS_DEFAULT_CTOR);
658627f7eb2Smrg gfc_add_expr_to_block (&cond_block, tem);
659627f7eb2Smrg }
660627f7eb2Smrg then_b = gfc_finish_block (&cond_block);
661627f7eb2Smrg
662627f7eb2Smrg /* Reduction clause requires allocated ALLOCATABLE. */
663627f7eb2Smrg if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
664627f7eb2Smrg {
665627f7eb2Smrg gfc_init_block (&cond_block);
666627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
667627f7eb2Smrg gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
668627f7eb2Smrg null_pointer_node);
669627f7eb2Smrg else
670627f7eb2Smrg gfc_add_modify (&cond_block, unshare_expr (decl),
671627f7eb2Smrg build_zero_cst (TREE_TYPE (decl)));
672627f7eb2Smrg else_b = gfc_finish_block (&cond_block);
673627f7eb2Smrg
674627f7eb2Smrg tree tem = fold_convert (pvoid_type_node,
675627f7eb2Smrg GFC_DESCRIPTOR_TYPE_P (type)
676627f7eb2Smrg ? gfc_conv_descriptor_data_get (outer) : outer);
677627f7eb2Smrg tem = unshare_expr (tem);
678627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
679627f7eb2Smrg tem, null_pointer_node);
680627f7eb2Smrg gfc_add_expr_to_block (&block,
681627f7eb2Smrg build3_loc (input_location, COND_EXPR,
682627f7eb2Smrg void_type_node, cond, then_b,
683627f7eb2Smrg else_b));
684627f7eb2Smrg /* Avoid -W*uninitialized warnings. */
685627f7eb2Smrg if (DECL_P (decl))
686627f7eb2Smrg TREE_NO_WARNING (decl) = 1;
687627f7eb2Smrg }
688627f7eb2Smrg else
689627f7eb2Smrg gfc_add_expr_to_block (&block, then_b);
690627f7eb2Smrg
691627f7eb2Smrg return gfc_finish_block (&block);
692627f7eb2Smrg }
693627f7eb2Smrg
694627f7eb2Smrg /* Build and return code for a copy constructor from SRC to DEST. */
695627f7eb2Smrg
696627f7eb2Smrg tree
gfc_omp_clause_copy_ctor(tree clause,tree dest,tree src)697627f7eb2Smrg gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
698627f7eb2Smrg {
699627f7eb2Smrg tree type = TREE_TYPE (dest), ptr, size, call;
700627f7eb2Smrg tree cond, then_b, else_b;
701627f7eb2Smrg stmtblock_t block, cond_block;
702627f7eb2Smrg
703627f7eb2Smrg gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
704627f7eb2Smrg || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
705627f7eb2Smrg
706627f7eb2Smrg if ((! GFC_DESCRIPTOR_TYPE_P (type)
707627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
708627f7eb2Smrg && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
709627f7eb2Smrg || !POINTER_TYPE_P (type)))
710627f7eb2Smrg {
711627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
712627f7eb2Smrg {
713627f7eb2Smrg gfc_start_block (&block);
714627f7eb2Smrg gfc_add_modify (&block, dest, src);
715627f7eb2Smrg tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
716627f7eb2Smrg WALK_ALLOC_COMPS_COPY_CTOR);
717627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
718627f7eb2Smrg return gfc_finish_block (&block);
719627f7eb2Smrg }
720627f7eb2Smrg else
721627f7eb2Smrg return build2_v (MODIFY_EXPR, dest, src);
722627f7eb2Smrg }
723627f7eb2Smrg
724627f7eb2Smrg /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
725627f7eb2Smrg and copied from SRC. */
726627f7eb2Smrg gfc_start_block (&block);
727627f7eb2Smrg
728627f7eb2Smrg gfc_init_block (&cond_block);
729627f7eb2Smrg
730627f7eb2Smrg gfc_add_modify (&cond_block, dest, src);
731627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
732627f7eb2Smrg {
733627f7eb2Smrg tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
734627f7eb2Smrg size = gfc_conv_descriptor_ubound_get (dest, rank);
735627f7eb2Smrg size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
736627f7eb2Smrg size,
737627f7eb2Smrg gfc_conv_descriptor_lbound_get (dest, rank));
738627f7eb2Smrg size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
739627f7eb2Smrg size, gfc_index_one_node);
740627f7eb2Smrg if (GFC_TYPE_ARRAY_RANK (type) > 1)
741627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR,
742627f7eb2Smrg gfc_array_index_type, size,
743627f7eb2Smrg gfc_conv_descriptor_stride_get (dest, rank));
744627f7eb2Smrg tree esize = fold_convert (gfc_array_index_type,
745627f7eb2Smrg TYPE_SIZE_UNIT (gfc_get_element_type (type)));
746627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
747627f7eb2Smrg size, esize);
748627f7eb2Smrg size = unshare_expr (size);
749627f7eb2Smrg size = gfc_evaluate_now (fold_convert (size_type_node, size),
750627f7eb2Smrg &cond_block);
751627f7eb2Smrg }
752627f7eb2Smrg else
753627f7eb2Smrg size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
754627f7eb2Smrg ptr = gfc_create_var (pvoid_type_node, NULL);
755627f7eb2Smrg gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
756627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
757627f7eb2Smrg gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
758627f7eb2Smrg else
759627f7eb2Smrg gfc_add_modify (&cond_block, unshare_expr (dest),
760627f7eb2Smrg fold_convert (TREE_TYPE (dest), ptr));
761627f7eb2Smrg
762627f7eb2Smrg tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
763627f7eb2Smrg ? gfc_conv_descriptor_data_get (src) : src;
764627f7eb2Smrg srcptr = unshare_expr (srcptr);
765627f7eb2Smrg srcptr = fold_convert (pvoid_type_node, srcptr);
766627f7eb2Smrg call = build_call_expr_loc (input_location,
767627f7eb2Smrg builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
768627f7eb2Smrg srcptr, size);
769627f7eb2Smrg gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
770627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
771627f7eb2Smrg {
772627f7eb2Smrg tree tem = gfc_walk_alloc_comps (src, dest,
773627f7eb2Smrg OMP_CLAUSE_DECL (clause),
774627f7eb2Smrg WALK_ALLOC_COMPS_COPY_CTOR);
775627f7eb2Smrg gfc_add_expr_to_block (&cond_block, tem);
776627f7eb2Smrg }
777627f7eb2Smrg then_b = gfc_finish_block (&cond_block);
778627f7eb2Smrg
779627f7eb2Smrg gfc_init_block (&cond_block);
780627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
781627f7eb2Smrg gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
782627f7eb2Smrg null_pointer_node);
783627f7eb2Smrg else
784627f7eb2Smrg gfc_add_modify (&cond_block, unshare_expr (dest),
785627f7eb2Smrg build_zero_cst (TREE_TYPE (dest)));
786627f7eb2Smrg else_b = gfc_finish_block (&cond_block);
787627f7eb2Smrg
788627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
789627f7eb2Smrg unshare_expr (srcptr), null_pointer_node);
790627f7eb2Smrg gfc_add_expr_to_block (&block,
791627f7eb2Smrg build3_loc (input_location, COND_EXPR,
792627f7eb2Smrg void_type_node, cond, then_b, else_b));
793627f7eb2Smrg /* Avoid -W*uninitialized warnings. */
794627f7eb2Smrg if (DECL_P (dest))
795627f7eb2Smrg TREE_NO_WARNING (dest) = 1;
796627f7eb2Smrg
797627f7eb2Smrg return gfc_finish_block (&block);
798627f7eb2Smrg }
799627f7eb2Smrg
800627f7eb2Smrg /* Similarly, except use an intrinsic or pointer assignment operator
801627f7eb2Smrg instead. */
802627f7eb2Smrg
803627f7eb2Smrg tree
gfc_omp_clause_assign_op(tree clause,tree dest,tree src)804627f7eb2Smrg gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
805627f7eb2Smrg {
806627f7eb2Smrg tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
807627f7eb2Smrg tree cond, then_b, else_b;
808627f7eb2Smrg stmtblock_t block, cond_block, cond_block2, inner_block;
809627f7eb2Smrg
810627f7eb2Smrg if ((! GFC_DESCRIPTOR_TYPE_P (type)
811627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
812627f7eb2Smrg && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
813627f7eb2Smrg || !POINTER_TYPE_P (type)))
814627f7eb2Smrg {
815627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
816627f7eb2Smrg {
817627f7eb2Smrg gfc_start_block (&block);
818627f7eb2Smrg /* First dealloc any allocatable components in DEST. */
819627f7eb2Smrg tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
820627f7eb2Smrg OMP_CLAUSE_DECL (clause),
821627f7eb2Smrg WALK_ALLOC_COMPS_DTOR);
822627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
823627f7eb2Smrg /* Then copy over toplevel data. */
824627f7eb2Smrg gfc_add_modify (&block, dest, src);
825627f7eb2Smrg /* Finally allocate any allocatable components and copy. */
826627f7eb2Smrg tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
827627f7eb2Smrg WALK_ALLOC_COMPS_COPY_CTOR);
828627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
829627f7eb2Smrg return gfc_finish_block (&block);
830627f7eb2Smrg }
831627f7eb2Smrg else
832627f7eb2Smrg return build2_v (MODIFY_EXPR, dest, src);
833627f7eb2Smrg }
834627f7eb2Smrg
835627f7eb2Smrg gfc_start_block (&block);
836627f7eb2Smrg
837627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
838627f7eb2Smrg {
839627f7eb2Smrg then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
840627f7eb2Smrg WALK_ALLOC_COMPS_DTOR);
841627f7eb2Smrg tree tem = fold_convert (pvoid_type_node,
842627f7eb2Smrg GFC_DESCRIPTOR_TYPE_P (type)
843627f7eb2Smrg ? gfc_conv_descriptor_data_get (dest) : dest);
844627f7eb2Smrg tem = unshare_expr (tem);
845627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
846627f7eb2Smrg tem, null_pointer_node);
847627f7eb2Smrg tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
848627f7eb2Smrg then_b, build_empty_stmt (input_location));
849627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
850627f7eb2Smrg }
851627f7eb2Smrg
852627f7eb2Smrg gfc_init_block (&cond_block);
853627f7eb2Smrg
854627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
855627f7eb2Smrg {
856627f7eb2Smrg tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
857627f7eb2Smrg size = gfc_conv_descriptor_ubound_get (src, rank);
858627f7eb2Smrg size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
859627f7eb2Smrg size,
860627f7eb2Smrg gfc_conv_descriptor_lbound_get (src, rank));
861627f7eb2Smrg size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
862627f7eb2Smrg size, gfc_index_one_node);
863627f7eb2Smrg if (GFC_TYPE_ARRAY_RANK (type) > 1)
864627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR,
865627f7eb2Smrg gfc_array_index_type, size,
866627f7eb2Smrg gfc_conv_descriptor_stride_get (src, rank));
867627f7eb2Smrg tree esize = fold_convert (gfc_array_index_type,
868627f7eb2Smrg TYPE_SIZE_UNIT (gfc_get_element_type (type)));
869627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
870627f7eb2Smrg size, esize);
871627f7eb2Smrg size = unshare_expr (size);
872627f7eb2Smrg size = gfc_evaluate_now (fold_convert (size_type_node, size),
873627f7eb2Smrg &cond_block);
874627f7eb2Smrg }
875627f7eb2Smrg else
876627f7eb2Smrg size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
877627f7eb2Smrg ptr = gfc_create_var (pvoid_type_node, NULL);
878627f7eb2Smrg
879627f7eb2Smrg tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
880627f7eb2Smrg ? gfc_conv_descriptor_data_get (dest) : dest;
881627f7eb2Smrg destptr = unshare_expr (destptr);
882627f7eb2Smrg destptr = fold_convert (pvoid_type_node, destptr);
883627f7eb2Smrg gfc_add_modify (&cond_block, ptr, destptr);
884627f7eb2Smrg
885627f7eb2Smrg nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
886627f7eb2Smrg destptr, null_pointer_node);
887627f7eb2Smrg cond = nonalloc;
888627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
889627f7eb2Smrg {
890627f7eb2Smrg int i;
891627f7eb2Smrg for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
892627f7eb2Smrg {
893627f7eb2Smrg tree rank = gfc_rank_cst[i];
894627f7eb2Smrg tree tem = gfc_conv_descriptor_ubound_get (src, rank);
895627f7eb2Smrg tem = fold_build2_loc (input_location, MINUS_EXPR,
896627f7eb2Smrg gfc_array_index_type, tem,
897627f7eb2Smrg gfc_conv_descriptor_lbound_get (src, rank));
898627f7eb2Smrg tem = fold_build2_loc (input_location, PLUS_EXPR,
899627f7eb2Smrg gfc_array_index_type, tem,
900627f7eb2Smrg gfc_conv_descriptor_lbound_get (dest, rank));
901627f7eb2Smrg tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
902627f7eb2Smrg tem, gfc_conv_descriptor_ubound_get (dest,
903627f7eb2Smrg rank));
904627f7eb2Smrg cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
905627f7eb2Smrg logical_type_node, cond, tem);
906627f7eb2Smrg }
907627f7eb2Smrg }
908627f7eb2Smrg
909627f7eb2Smrg gfc_init_block (&cond_block2);
910627f7eb2Smrg
911627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
912627f7eb2Smrg {
913627f7eb2Smrg gfc_init_block (&inner_block);
914627f7eb2Smrg gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
915627f7eb2Smrg then_b = gfc_finish_block (&inner_block);
916627f7eb2Smrg
917627f7eb2Smrg gfc_init_block (&inner_block);
918627f7eb2Smrg gfc_add_modify (&inner_block, ptr,
919627f7eb2Smrg gfc_call_realloc (&inner_block, ptr, size));
920627f7eb2Smrg else_b = gfc_finish_block (&inner_block);
921627f7eb2Smrg
922627f7eb2Smrg gfc_add_expr_to_block (&cond_block2,
923627f7eb2Smrg build3_loc (input_location, COND_EXPR,
924627f7eb2Smrg void_type_node,
925627f7eb2Smrg unshare_expr (nonalloc),
926627f7eb2Smrg then_b, else_b));
927627f7eb2Smrg gfc_add_modify (&cond_block2, dest, src);
928627f7eb2Smrg gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
929627f7eb2Smrg }
930627f7eb2Smrg else
931627f7eb2Smrg {
932627f7eb2Smrg gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
933627f7eb2Smrg gfc_add_modify (&cond_block2, unshare_expr (dest),
934627f7eb2Smrg fold_convert (type, ptr));
935627f7eb2Smrg }
936627f7eb2Smrg then_b = gfc_finish_block (&cond_block2);
937627f7eb2Smrg else_b = build_empty_stmt (input_location);
938627f7eb2Smrg
939627f7eb2Smrg gfc_add_expr_to_block (&cond_block,
940627f7eb2Smrg build3_loc (input_location, COND_EXPR,
941627f7eb2Smrg void_type_node, unshare_expr (cond),
942627f7eb2Smrg then_b, else_b));
943627f7eb2Smrg
944627f7eb2Smrg tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
945627f7eb2Smrg ? gfc_conv_descriptor_data_get (src) : src;
946627f7eb2Smrg srcptr = unshare_expr (srcptr);
947627f7eb2Smrg srcptr = fold_convert (pvoid_type_node, srcptr);
948627f7eb2Smrg call = build_call_expr_loc (input_location,
949627f7eb2Smrg builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
950627f7eb2Smrg srcptr, size);
951627f7eb2Smrg gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
952627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
953627f7eb2Smrg {
954627f7eb2Smrg tree tem = gfc_walk_alloc_comps (src, dest,
955627f7eb2Smrg OMP_CLAUSE_DECL (clause),
956627f7eb2Smrg WALK_ALLOC_COMPS_COPY_CTOR);
957627f7eb2Smrg gfc_add_expr_to_block (&cond_block, tem);
958627f7eb2Smrg }
959627f7eb2Smrg then_b = gfc_finish_block (&cond_block);
960627f7eb2Smrg
961627f7eb2Smrg if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
962627f7eb2Smrg {
963627f7eb2Smrg gfc_init_block (&cond_block);
964627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
965627f7eb2Smrg {
966627f7eb2Smrg tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest));
967627f7eb2Smrg tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE,
968627f7eb2Smrg NULL_TREE, NULL_TREE, true, NULL,
969627f7eb2Smrg GFC_CAF_COARRAY_NOCOARRAY);
970627f7eb2Smrg gfc_add_expr_to_block (&cond_block, tmp);
971627f7eb2Smrg }
972627f7eb2Smrg else
973627f7eb2Smrg {
974627f7eb2Smrg destptr = gfc_evaluate_now (destptr, &cond_block);
975627f7eb2Smrg gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
976627f7eb2Smrg gfc_add_modify (&cond_block, unshare_expr (dest),
977627f7eb2Smrg build_zero_cst (TREE_TYPE (dest)));
978627f7eb2Smrg }
979627f7eb2Smrg else_b = gfc_finish_block (&cond_block);
980627f7eb2Smrg
981627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
982627f7eb2Smrg unshare_expr (srcptr), null_pointer_node);
983627f7eb2Smrg gfc_add_expr_to_block (&block,
984627f7eb2Smrg build3_loc (input_location, COND_EXPR,
985627f7eb2Smrg void_type_node, cond,
986627f7eb2Smrg then_b, else_b));
987627f7eb2Smrg }
988627f7eb2Smrg else
989627f7eb2Smrg gfc_add_expr_to_block (&block, then_b);
990627f7eb2Smrg
991627f7eb2Smrg return gfc_finish_block (&block);
992627f7eb2Smrg }
993627f7eb2Smrg
994627f7eb2Smrg static void
gfc_omp_linear_clause_add_loop(stmtblock_t * block,tree dest,tree src,tree add,tree nelems)995627f7eb2Smrg gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
996627f7eb2Smrg tree add, tree nelems)
997627f7eb2Smrg {
998627f7eb2Smrg stmtblock_t tmpblock;
999627f7eb2Smrg tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
1000627f7eb2Smrg nelems = gfc_evaluate_now (nelems, block);
1001627f7eb2Smrg
1002627f7eb2Smrg gfc_init_block (&tmpblock);
1003627f7eb2Smrg if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
1004627f7eb2Smrg {
1005627f7eb2Smrg desta = gfc_build_array_ref (dest, index, NULL);
1006627f7eb2Smrg srca = gfc_build_array_ref (src, index, NULL);
1007627f7eb2Smrg }
1008627f7eb2Smrg else
1009627f7eb2Smrg {
1010627f7eb2Smrg gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
1011627f7eb2Smrg tree idx = fold_build2 (MULT_EXPR, sizetype,
1012627f7eb2Smrg fold_convert (sizetype, index),
1013627f7eb2Smrg TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
1014627f7eb2Smrg desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1015627f7eb2Smrg TREE_TYPE (dest), dest,
1016627f7eb2Smrg idx));
1017627f7eb2Smrg srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
1018627f7eb2Smrg TREE_TYPE (src), src,
1019627f7eb2Smrg idx));
1020627f7eb2Smrg }
1021627f7eb2Smrg gfc_add_modify (&tmpblock, desta,
1022627f7eb2Smrg fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
1023627f7eb2Smrg srca, add));
1024627f7eb2Smrg
1025627f7eb2Smrg gfc_loopinfo loop;
1026627f7eb2Smrg gfc_init_loopinfo (&loop);
1027627f7eb2Smrg loop.dimen = 1;
1028627f7eb2Smrg loop.from[0] = gfc_index_zero_node;
1029627f7eb2Smrg loop.loopvar[0] = index;
1030627f7eb2Smrg loop.to[0] = nelems;
1031627f7eb2Smrg gfc_trans_scalarizing_loops (&loop, &tmpblock);
1032627f7eb2Smrg gfc_add_block_to_block (block, &loop.pre);
1033627f7eb2Smrg }
1034627f7eb2Smrg
1035627f7eb2Smrg /* Build and return code for a constructor of DEST that initializes
1036627f7eb2Smrg it to SRC plus ADD (ADD is scalar integer). */
1037627f7eb2Smrg
1038627f7eb2Smrg tree
gfc_omp_clause_linear_ctor(tree clause,tree dest,tree src,tree add)1039627f7eb2Smrg gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
1040627f7eb2Smrg {
1041627f7eb2Smrg tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
1042627f7eb2Smrg stmtblock_t block;
1043627f7eb2Smrg
1044627f7eb2Smrg gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
1045627f7eb2Smrg
1046627f7eb2Smrg gfc_start_block (&block);
1047627f7eb2Smrg add = gfc_evaluate_now (add, &block);
1048627f7eb2Smrg
1049627f7eb2Smrg if ((! GFC_DESCRIPTOR_TYPE_P (type)
1050627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1051627f7eb2Smrg && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1052627f7eb2Smrg || !POINTER_TYPE_P (type)))
1053627f7eb2Smrg {
1054627f7eb2Smrg bool compute_nelts = false;
1055627f7eb2Smrg gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1056627f7eb2Smrg if (!TYPE_DOMAIN (type)
1057627f7eb2Smrg || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
1058627f7eb2Smrg || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
1059627f7eb2Smrg || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
1060627f7eb2Smrg compute_nelts = true;
1061627f7eb2Smrg else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
1062627f7eb2Smrg {
1063627f7eb2Smrg tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
1064627f7eb2Smrg if (lookup_attribute ("omp dummy var", a))
1065627f7eb2Smrg compute_nelts = true;
1066627f7eb2Smrg }
1067627f7eb2Smrg if (compute_nelts)
1068627f7eb2Smrg {
1069627f7eb2Smrg nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
1070627f7eb2Smrg TYPE_SIZE_UNIT (type),
1071627f7eb2Smrg TYPE_SIZE_UNIT (TREE_TYPE (type)));
1072627f7eb2Smrg nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
1073627f7eb2Smrg }
1074627f7eb2Smrg else
1075627f7eb2Smrg nelems = array_type_nelts (type);
1076627f7eb2Smrg nelems = fold_convert (gfc_array_index_type, nelems);
1077627f7eb2Smrg
1078627f7eb2Smrg gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
1079627f7eb2Smrg return gfc_finish_block (&block);
1080627f7eb2Smrg }
1081627f7eb2Smrg
1082627f7eb2Smrg /* Allocatable arrays in LINEAR clauses need to be allocated
1083627f7eb2Smrg and copied from SRC. */
1084627f7eb2Smrg gfc_add_modify (&block, dest, src);
1085627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
1086627f7eb2Smrg {
1087627f7eb2Smrg tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
1088627f7eb2Smrg size = gfc_conv_descriptor_ubound_get (dest, rank);
1089627f7eb2Smrg size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
1090627f7eb2Smrg size,
1091627f7eb2Smrg gfc_conv_descriptor_lbound_get (dest, rank));
1092627f7eb2Smrg size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
1093627f7eb2Smrg size, gfc_index_one_node);
1094627f7eb2Smrg if (GFC_TYPE_ARRAY_RANK (type) > 1)
1095627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR,
1096627f7eb2Smrg gfc_array_index_type, size,
1097627f7eb2Smrg gfc_conv_descriptor_stride_get (dest, rank));
1098627f7eb2Smrg tree esize = fold_convert (gfc_array_index_type,
1099627f7eb2Smrg TYPE_SIZE_UNIT (gfc_get_element_type (type)));
1100627f7eb2Smrg nelems = gfc_evaluate_now (unshare_expr (size), &block);
1101627f7eb2Smrg size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
1102627f7eb2Smrg nelems, unshare_expr (esize));
1103627f7eb2Smrg size = gfc_evaluate_now (fold_convert (size_type_node, size),
1104627f7eb2Smrg &block);
1105627f7eb2Smrg nelems = fold_build2_loc (input_location, MINUS_EXPR,
1106627f7eb2Smrg gfc_array_index_type, nelems,
1107627f7eb2Smrg gfc_index_one_node);
1108627f7eb2Smrg }
1109627f7eb2Smrg else
1110627f7eb2Smrg size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
1111627f7eb2Smrg ptr = gfc_create_var (pvoid_type_node, NULL);
1112627f7eb2Smrg gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
1113627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
1114627f7eb2Smrg {
1115627f7eb2Smrg gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
1116627f7eb2Smrg tree etype = gfc_get_element_type (type);
1117627f7eb2Smrg ptr = fold_convert (build_pointer_type (etype), ptr);
1118627f7eb2Smrg tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
1119627f7eb2Smrg srcptr = fold_convert (build_pointer_type (etype), srcptr);
1120627f7eb2Smrg gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
1121627f7eb2Smrg }
1122627f7eb2Smrg else
1123627f7eb2Smrg {
1124627f7eb2Smrg gfc_add_modify (&block, unshare_expr (dest),
1125627f7eb2Smrg fold_convert (TREE_TYPE (dest), ptr));
1126627f7eb2Smrg ptr = fold_convert (TREE_TYPE (dest), ptr);
1127627f7eb2Smrg tree dstm = build_fold_indirect_ref (ptr);
1128627f7eb2Smrg tree srcm = build_fold_indirect_ref (unshare_expr (src));
1129627f7eb2Smrg gfc_add_modify (&block, dstm,
1130627f7eb2Smrg fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
1131627f7eb2Smrg }
1132627f7eb2Smrg return gfc_finish_block (&block);
1133627f7eb2Smrg }
1134627f7eb2Smrg
1135627f7eb2Smrg /* Build and return code destructing DECL. Return NULL if nothing
1136627f7eb2Smrg to be done. */
1137627f7eb2Smrg
1138627f7eb2Smrg tree
gfc_omp_clause_dtor(tree clause,tree decl)1139627f7eb2Smrg gfc_omp_clause_dtor (tree clause, tree decl)
1140627f7eb2Smrg {
1141627f7eb2Smrg tree type = TREE_TYPE (decl), tem;
1142627f7eb2Smrg
1143627f7eb2Smrg if ((! GFC_DESCRIPTOR_TYPE_P (type)
1144627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
1145627f7eb2Smrg && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause))
1146627f7eb2Smrg || !POINTER_TYPE_P (type)))
1147627f7eb2Smrg {
1148627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1149627f7eb2Smrg return gfc_walk_alloc_comps (decl, NULL_TREE,
1150627f7eb2Smrg OMP_CLAUSE_DECL (clause),
1151627f7eb2Smrg WALK_ALLOC_COMPS_DTOR);
1152627f7eb2Smrg return NULL_TREE;
1153627f7eb2Smrg }
1154627f7eb2Smrg
1155627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (type))
1156627f7eb2Smrg {
1157627f7eb2Smrg /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
1158627f7eb2Smrg to be deallocated if they were allocated. */
1159627f7eb2Smrg tem = gfc_conv_descriptor_data_get (decl);
1160627f7eb2Smrg tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE,
1161627f7eb2Smrg NULL_TREE, true, NULL,
1162627f7eb2Smrg GFC_CAF_COARRAY_NOCOARRAY);
1163627f7eb2Smrg }
1164627f7eb2Smrg else
1165627f7eb2Smrg tem = gfc_call_free (decl);
1166627f7eb2Smrg tem = gfc_omp_unshare_expr (tem);
1167627f7eb2Smrg
1168627f7eb2Smrg if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
1169627f7eb2Smrg {
1170627f7eb2Smrg stmtblock_t block;
1171627f7eb2Smrg tree then_b;
1172627f7eb2Smrg
1173627f7eb2Smrg gfc_init_block (&block);
1174627f7eb2Smrg gfc_add_expr_to_block (&block,
1175627f7eb2Smrg gfc_walk_alloc_comps (decl, NULL_TREE,
1176627f7eb2Smrg OMP_CLAUSE_DECL (clause),
1177627f7eb2Smrg WALK_ALLOC_COMPS_DTOR));
1178627f7eb2Smrg gfc_add_expr_to_block (&block, tem);
1179627f7eb2Smrg then_b = gfc_finish_block (&block);
1180627f7eb2Smrg
1181627f7eb2Smrg tem = fold_convert (pvoid_type_node,
1182627f7eb2Smrg GFC_DESCRIPTOR_TYPE_P (type)
1183627f7eb2Smrg ? gfc_conv_descriptor_data_get (decl) : decl);
1184627f7eb2Smrg tem = unshare_expr (tem);
1185627f7eb2Smrg tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1186627f7eb2Smrg tem, null_pointer_node);
1187627f7eb2Smrg tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
1188627f7eb2Smrg then_b, build_empty_stmt (input_location));
1189627f7eb2Smrg }
1190627f7eb2Smrg return tem;
1191627f7eb2Smrg }
1192627f7eb2Smrg
1193*4c3eb207Smrg /* Build a conditional expression in BLOCK. If COND_VAL is not
1194*4c3eb207Smrg null, then the block THEN_B is executed, otherwise ELSE_VAL
1195*4c3eb207Smrg is assigned to VAL. */
1196*4c3eb207Smrg
1197*4c3eb207Smrg static void
gfc_build_cond_assign(stmtblock_t * block,tree val,tree cond_val,tree then_b,tree else_val)1198*4c3eb207Smrg gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val,
1199*4c3eb207Smrg tree then_b, tree else_val)
1200*4c3eb207Smrg {
1201*4c3eb207Smrg stmtblock_t cond_block;
1202*4c3eb207Smrg tree else_b = NULL_TREE;
1203*4c3eb207Smrg tree val_ty = TREE_TYPE (val);
1204*4c3eb207Smrg
1205*4c3eb207Smrg if (else_val)
1206*4c3eb207Smrg {
1207*4c3eb207Smrg gfc_init_block (&cond_block);
1208*4c3eb207Smrg gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val));
1209*4c3eb207Smrg else_b = gfc_finish_block (&cond_block);
1210*4c3eb207Smrg }
1211*4c3eb207Smrg gfc_add_expr_to_block (block,
1212*4c3eb207Smrg build3_loc (input_location, COND_EXPR, void_type_node,
1213*4c3eb207Smrg cond_val, then_b, else_b));
1214*4c3eb207Smrg }
1215*4c3eb207Smrg
1216*4c3eb207Smrg /* Build a conditional expression in BLOCK, returning a temporary
1217*4c3eb207Smrg variable containing the result. If COND_VAL is not null, then
1218*4c3eb207Smrg THEN_VAL will be assigned to the variable, otherwise ELSE_VAL
1219*4c3eb207Smrg is assigned.
1220*4c3eb207Smrg */
1221*4c3eb207Smrg
1222*4c3eb207Smrg static tree
gfc_build_cond_assign_expr(stmtblock_t * block,tree cond_val,tree then_val,tree else_val)1223*4c3eb207Smrg gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val,
1224*4c3eb207Smrg tree then_val, tree else_val)
1225*4c3eb207Smrg {
1226*4c3eb207Smrg tree val;
1227*4c3eb207Smrg tree val_ty = TREE_TYPE (then_val);
1228*4c3eb207Smrg stmtblock_t cond_block;
1229*4c3eb207Smrg
1230*4c3eb207Smrg val = create_tmp_var (val_ty);
1231*4c3eb207Smrg
1232*4c3eb207Smrg gfc_init_block (&cond_block);
1233*4c3eb207Smrg gfc_add_modify (&cond_block, val, then_val);
1234*4c3eb207Smrg tree then_b = gfc_finish_block (&cond_block);
1235*4c3eb207Smrg
1236*4c3eb207Smrg gfc_build_cond_assign (block, val, cond_val, then_b, else_val);
1237*4c3eb207Smrg
1238*4c3eb207Smrg return val;
1239*4c3eb207Smrg }
1240627f7eb2Smrg
1241627f7eb2Smrg void
gfc_omp_finish_clause(tree c,gimple_seq * pre_p)1242627f7eb2Smrg gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
1243627f7eb2Smrg {
1244627f7eb2Smrg if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
1245627f7eb2Smrg return;
1246627f7eb2Smrg
1247627f7eb2Smrg tree decl = OMP_CLAUSE_DECL (c);
1248627f7eb2Smrg
1249627f7eb2Smrg /* Assumed-size arrays can't be mapped implicitly, they have to be
1250627f7eb2Smrg mapped explicitly using array sections. */
1251627f7eb2Smrg if (TREE_CODE (decl) == PARM_DECL
1252627f7eb2Smrg && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
1253627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
1254627f7eb2Smrg && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
1255627f7eb2Smrg GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
1256627f7eb2Smrg == NULL)
1257627f7eb2Smrg {
1258627f7eb2Smrg error_at (OMP_CLAUSE_LOCATION (c),
1259627f7eb2Smrg "implicit mapping of assumed size array %qD", decl);
1260627f7eb2Smrg return;
1261627f7eb2Smrg }
1262627f7eb2Smrg
1263627f7eb2Smrg tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
1264*4c3eb207Smrg tree present = gfc_omp_check_optional_argument (decl, true);
1265627f7eb2Smrg if (POINTER_TYPE_P (TREE_TYPE (decl)))
1266627f7eb2Smrg {
1267627f7eb2Smrg if (!gfc_omp_privatize_by_reference (decl)
1268627f7eb2Smrg && !GFC_DECL_GET_SCALAR_POINTER (decl)
1269627f7eb2Smrg && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1270627f7eb2Smrg && !GFC_DECL_CRAY_POINTEE (decl)
1271627f7eb2Smrg && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
1272627f7eb2Smrg return;
1273627f7eb2Smrg tree orig_decl = decl;
1274*4c3eb207Smrg
1275627f7eb2Smrg c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1276627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
1277627f7eb2Smrg OMP_CLAUSE_DECL (c4) = decl;
1278627f7eb2Smrg OMP_CLAUSE_SIZE (c4) = size_int (0);
1279627f7eb2Smrg decl = build_fold_indirect_ref (decl);
1280*4c3eb207Smrg if (present
1281*4c3eb207Smrg && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1282*4c3eb207Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1283*4c3eb207Smrg {
1284*4c3eb207Smrg c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1285*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
1286*4c3eb207Smrg OMP_CLAUSE_DECL (c2) = decl;
1287*4c3eb207Smrg OMP_CLAUSE_SIZE (c2) = size_int (0);
1288*4c3eb207Smrg
1289*4c3eb207Smrg stmtblock_t block;
1290*4c3eb207Smrg gfc_start_block (&block);
1291*4c3eb207Smrg tree ptr = decl;
1292*4c3eb207Smrg ptr = gfc_build_cond_assign_expr (&block, present, decl,
1293*4c3eb207Smrg null_pointer_node);
1294*4c3eb207Smrg gimplify_and_add (gfc_finish_block (&block), pre_p);
1295*4c3eb207Smrg ptr = build_fold_indirect_ref (ptr);
1296*4c3eb207Smrg OMP_CLAUSE_DECL (c) = ptr;
1297*4c3eb207Smrg OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
1298*4c3eb207Smrg }
1299*4c3eb207Smrg else
1300*4c3eb207Smrg {
1301627f7eb2Smrg OMP_CLAUSE_DECL (c) = decl;
1302627f7eb2Smrg OMP_CLAUSE_SIZE (c) = NULL_TREE;
1303*4c3eb207Smrg }
1304627f7eb2Smrg if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
1305627f7eb2Smrg && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
1306627f7eb2Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
1307627f7eb2Smrg {
1308627f7eb2Smrg c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1309627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1310627f7eb2Smrg OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
1311627f7eb2Smrg OMP_CLAUSE_SIZE (c3) = size_int (0);
1312627f7eb2Smrg decl = build_fold_indirect_ref (decl);
1313627f7eb2Smrg OMP_CLAUSE_DECL (c) = decl;
1314627f7eb2Smrg }
1315627f7eb2Smrg }
1316627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
1317627f7eb2Smrg {
1318627f7eb2Smrg stmtblock_t block;
1319627f7eb2Smrg gfc_start_block (&block);
1320627f7eb2Smrg tree type = TREE_TYPE (decl);
1321627f7eb2Smrg tree ptr = gfc_conv_descriptor_data_get (decl);
1322*4c3eb207Smrg
1323*4c3eb207Smrg if (present)
1324*4c3eb207Smrg ptr = gfc_build_cond_assign_expr (&block, present, ptr,
1325*4c3eb207Smrg null_pointer_node);
1326627f7eb2Smrg ptr = fold_convert (build_pointer_type (char_type_node), ptr);
1327627f7eb2Smrg ptr = build_fold_indirect_ref (ptr);
1328627f7eb2Smrg OMP_CLAUSE_DECL (c) = ptr;
1329627f7eb2Smrg c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
1330627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
1331*4c3eb207Smrg if (present)
1332*4c3eb207Smrg {
1333*4c3eb207Smrg ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0)));
1334*4c3eb207Smrg gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0));
1335*4c3eb207Smrg
1336*4c3eb207Smrg OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr);
1337*4c3eb207Smrg }
1338*4c3eb207Smrg else
1339627f7eb2Smrg OMP_CLAUSE_DECL (c2) = decl;
1340627f7eb2Smrg OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
1341627f7eb2Smrg c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
1342627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
1343*4c3eb207Smrg if (present)
1344*4c3eb207Smrg {
1345*4c3eb207Smrg ptr = gfc_conv_descriptor_data_get (decl);
1346*4c3eb207Smrg ptr = gfc_build_addr_expr (NULL, ptr);
1347*4c3eb207Smrg ptr = gfc_build_cond_assign_expr (&block, present,
1348*4c3eb207Smrg ptr, null_pointer_node);
1349*4c3eb207Smrg ptr = build_fold_indirect_ref (ptr);
1350*4c3eb207Smrg OMP_CLAUSE_DECL (c3) = ptr;
1351*4c3eb207Smrg }
1352*4c3eb207Smrg else
1353627f7eb2Smrg OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
1354627f7eb2Smrg OMP_CLAUSE_SIZE (c3) = size_int (0);
1355627f7eb2Smrg tree size = create_tmp_var (gfc_array_index_type);
1356627f7eb2Smrg tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
1357627f7eb2Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
1358627f7eb2Smrg if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
1359627f7eb2Smrg || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
1360627f7eb2Smrg {
1361627f7eb2Smrg stmtblock_t cond_block;
1362627f7eb2Smrg tree tem, then_b, else_b, zero, cond;
1363627f7eb2Smrg
1364627f7eb2Smrg gfc_init_block (&cond_block);
1365627f7eb2Smrg tem = gfc_full_array_size (&cond_block, decl,
1366627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
1367627f7eb2Smrg gfc_add_modify (&cond_block, size, tem);
1368627f7eb2Smrg gfc_add_modify (&cond_block, size,
1369627f7eb2Smrg fold_build2 (MULT_EXPR, gfc_array_index_type,
1370627f7eb2Smrg size, elemsz));
1371627f7eb2Smrg then_b = gfc_finish_block (&cond_block);
1372627f7eb2Smrg gfc_init_block (&cond_block);
1373627f7eb2Smrg zero = build_int_cst (gfc_array_index_type, 0);
1374627f7eb2Smrg gfc_add_modify (&cond_block, size, zero);
1375627f7eb2Smrg else_b = gfc_finish_block (&cond_block);
1376627f7eb2Smrg tem = gfc_conv_descriptor_data_get (decl);
1377627f7eb2Smrg tem = fold_convert (pvoid_type_node, tem);
1378627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR,
1379*4c3eb207Smrg boolean_type_node, tem, null_pointer_node);
1380*4c3eb207Smrg if (present)
1381*4c3eb207Smrg {
1382*4c3eb207Smrg cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
1383*4c3eb207Smrg boolean_type_node, present, cond);
1384*4c3eb207Smrg }
1385627f7eb2Smrg gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
1386627f7eb2Smrg void_type_node, cond,
1387627f7eb2Smrg then_b, else_b));
1388627f7eb2Smrg }
1389*4c3eb207Smrg else if (present)
1390*4c3eb207Smrg {
1391*4c3eb207Smrg stmtblock_t cond_block;
1392*4c3eb207Smrg tree then_b;
1393*4c3eb207Smrg
1394*4c3eb207Smrg gfc_init_block (&cond_block);
1395*4c3eb207Smrg gfc_add_modify (&cond_block, size,
1396*4c3eb207Smrg gfc_full_array_size (&cond_block, decl,
1397*4c3eb207Smrg GFC_TYPE_ARRAY_RANK (type)));
1398*4c3eb207Smrg gfc_add_modify (&cond_block, size,
1399*4c3eb207Smrg fold_build2 (MULT_EXPR, gfc_array_index_type,
1400*4c3eb207Smrg size, elemsz));
1401*4c3eb207Smrg then_b = gfc_finish_block (&cond_block);
1402*4c3eb207Smrg
1403*4c3eb207Smrg gfc_build_cond_assign (&block, size, present, then_b,
1404*4c3eb207Smrg build_int_cst (gfc_array_index_type, 0));
1405*4c3eb207Smrg }
1406627f7eb2Smrg else
1407627f7eb2Smrg {
1408627f7eb2Smrg gfc_add_modify (&block, size,
1409627f7eb2Smrg gfc_full_array_size (&block, decl,
1410627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type)));
1411627f7eb2Smrg gfc_add_modify (&block, size,
1412627f7eb2Smrg fold_build2 (MULT_EXPR, gfc_array_index_type,
1413627f7eb2Smrg size, elemsz));
1414627f7eb2Smrg }
1415627f7eb2Smrg OMP_CLAUSE_SIZE (c) = size;
1416627f7eb2Smrg tree stmt = gfc_finish_block (&block);
1417627f7eb2Smrg gimplify_and_add (stmt, pre_p);
1418627f7eb2Smrg }
1419627f7eb2Smrg tree last = c;
1420627f7eb2Smrg if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
1421627f7eb2Smrg OMP_CLAUSE_SIZE (c)
1422627f7eb2Smrg = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
1423627f7eb2Smrg : TYPE_SIZE_UNIT (TREE_TYPE (decl));
1424627f7eb2Smrg if (c2)
1425627f7eb2Smrg {
1426627f7eb2Smrg OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
1427627f7eb2Smrg OMP_CLAUSE_CHAIN (last) = c2;
1428627f7eb2Smrg last = c2;
1429627f7eb2Smrg }
1430627f7eb2Smrg if (c3)
1431627f7eb2Smrg {
1432627f7eb2Smrg OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
1433627f7eb2Smrg OMP_CLAUSE_CHAIN (last) = c3;
1434627f7eb2Smrg last = c3;
1435627f7eb2Smrg }
1436627f7eb2Smrg if (c4)
1437627f7eb2Smrg {
1438627f7eb2Smrg OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
1439627f7eb2Smrg OMP_CLAUSE_CHAIN (last) = c4;
1440627f7eb2Smrg }
1441627f7eb2Smrg }
1442627f7eb2Smrg
1443627f7eb2Smrg
1444627f7eb2Smrg /* Return true if DECL is a scalar variable (for the purpose of
1445627f7eb2Smrg implicit firstprivatization). */
1446627f7eb2Smrg
1447627f7eb2Smrg bool
gfc_omp_scalar_p(tree decl)1448627f7eb2Smrg gfc_omp_scalar_p (tree decl)
1449627f7eb2Smrg {
1450627f7eb2Smrg tree type = TREE_TYPE (decl);
1451627f7eb2Smrg if (TREE_CODE (type) == REFERENCE_TYPE)
1452627f7eb2Smrg type = TREE_TYPE (type);
1453627f7eb2Smrg if (TREE_CODE (type) == POINTER_TYPE)
1454627f7eb2Smrg {
1455627f7eb2Smrg if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
1456627f7eb2Smrg || GFC_DECL_GET_SCALAR_POINTER (decl))
1457627f7eb2Smrg type = TREE_TYPE (type);
1458627f7eb2Smrg if (GFC_ARRAY_TYPE_P (type)
1459627f7eb2Smrg || GFC_CLASS_TYPE_P (type))
1460627f7eb2Smrg return false;
1461627f7eb2Smrg }
1462*4c3eb207Smrg if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
1463*4c3eb207Smrg && TYPE_STRING_FLAG (type))
1464627f7eb2Smrg return false;
1465627f7eb2Smrg if (INTEGRAL_TYPE_P (type)
1466627f7eb2Smrg || SCALAR_FLOAT_TYPE_P (type)
1467627f7eb2Smrg || COMPLEX_FLOAT_TYPE_P (type))
1468627f7eb2Smrg return true;
1469627f7eb2Smrg return false;
1470627f7eb2Smrg }
1471627f7eb2Smrg
1472627f7eb2Smrg
1473627f7eb2Smrg /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
1474627f7eb2Smrg disregarded in OpenMP construct, because it is going to be
1475627f7eb2Smrg remapped during OpenMP lowering. SHARED is true if DECL
1476627f7eb2Smrg is going to be shared, false if it is going to be privatized. */
1477627f7eb2Smrg
1478627f7eb2Smrg bool
gfc_omp_disregard_value_expr(tree decl,bool shared)1479627f7eb2Smrg gfc_omp_disregard_value_expr (tree decl, bool shared)
1480627f7eb2Smrg {
1481627f7eb2Smrg if (GFC_DECL_COMMON_OR_EQUIV (decl)
1482627f7eb2Smrg && DECL_HAS_VALUE_EXPR_P (decl))
1483627f7eb2Smrg {
1484627f7eb2Smrg tree value = DECL_VALUE_EXPR (decl);
1485627f7eb2Smrg
1486627f7eb2Smrg if (TREE_CODE (value) == COMPONENT_REF
1487627f7eb2Smrg && VAR_P (TREE_OPERAND (value, 0))
1488627f7eb2Smrg && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1489627f7eb2Smrg {
1490627f7eb2Smrg /* If variable in COMMON or EQUIVALENCE is privatized, return
1491627f7eb2Smrg true, as just that variable is supposed to be privatized,
1492627f7eb2Smrg not the whole COMMON or whole EQUIVALENCE.
1493627f7eb2Smrg For shared variables in COMMON or EQUIVALENCE, let them be
1494627f7eb2Smrg gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
1495627f7eb2Smrg from the same COMMON or EQUIVALENCE just one sharing of the
1496627f7eb2Smrg whole COMMON or EQUIVALENCE is enough. */
1497627f7eb2Smrg return ! shared;
1498627f7eb2Smrg }
1499627f7eb2Smrg }
1500627f7eb2Smrg
1501627f7eb2Smrg if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
1502627f7eb2Smrg return ! shared;
1503627f7eb2Smrg
1504627f7eb2Smrg return false;
1505627f7eb2Smrg }
1506627f7eb2Smrg
1507627f7eb2Smrg /* Return true if DECL that is shared iff SHARED is true should
1508627f7eb2Smrg be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
1509627f7eb2Smrg flag set. */
1510627f7eb2Smrg
1511627f7eb2Smrg bool
gfc_omp_private_debug_clause(tree decl,bool shared)1512627f7eb2Smrg gfc_omp_private_debug_clause (tree decl, bool shared)
1513627f7eb2Smrg {
1514627f7eb2Smrg if (GFC_DECL_CRAY_POINTEE (decl))
1515627f7eb2Smrg return true;
1516627f7eb2Smrg
1517627f7eb2Smrg if (GFC_DECL_COMMON_OR_EQUIV (decl)
1518627f7eb2Smrg && DECL_HAS_VALUE_EXPR_P (decl))
1519627f7eb2Smrg {
1520627f7eb2Smrg tree value = DECL_VALUE_EXPR (decl);
1521627f7eb2Smrg
1522627f7eb2Smrg if (TREE_CODE (value) == COMPONENT_REF
1523627f7eb2Smrg && VAR_P (TREE_OPERAND (value, 0))
1524627f7eb2Smrg && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
1525627f7eb2Smrg return shared;
1526627f7eb2Smrg }
1527627f7eb2Smrg
1528627f7eb2Smrg return false;
1529627f7eb2Smrg }
1530627f7eb2Smrg
1531627f7eb2Smrg /* Register language specific type size variables as potentially OpenMP
1532627f7eb2Smrg firstprivate variables. */
1533627f7eb2Smrg
1534627f7eb2Smrg void
gfc_omp_firstprivatize_type_sizes(struct gimplify_omp_ctx * ctx,tree type)1535627f7eb2Smrg gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
1536627f7eb2Smrg {
1537627f7eb2Smrg if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
1538627f7eb2Smrg {
1539627f7eb2Smrg int r;
1540627f7eb2Smrg
1541627f7eb2Smrg gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
1542627f7eb2Smrg for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
1543627f7eb2Smrg {
1544627f7eb2Smrg omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
1545627f7eb2Smrg omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
1546627f7eb2Smrg omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
1547627f7eb2Smrg }
1548627f7eb2Smrg omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
1549627f7eb2Smrg omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
1550627f7eb2Smrg }
1551627f7eb2Smrg }
1552627f7eb2Smrg
1553627f7eb2Smrg
1554627f7eb2Smrg static inline tree
gfc_trans_add_clause(tree node,tree tail)1555627f7eb2Smrg gfc_trans_add_clause (tree node, tree tail)
1556627f7eb2Smrg {
1557627f7eb2Smrg OMP_CLAUSE_CHAIN (node) = tail;
1558627f7eb2Smrg return node;
1559627f7eb2Smrg }
1560627f7eb2Smrg
1561627f7eb2Smrg static tree
gfc_trans_omp_variable(gfc_symbol * sym,bool declare_simd)1562627f7eb2Smrg gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
1563627f7eb2Smrg {
1564627f7eb2Smrg if (declare_simd)
1565627f7eb2Smrg {
1566627f7eb2Smrg int cnt = 0;
1567627f7eb2Smrg gfc_symbol *proc_sym;
1568627f7eb2Smrg gfc_formal_arglist *f;
1569627f7eb2Smrg
1570627f7eb2Smrg gcc_assert (sym->attr.dummy);
1571627f7eb2Smrg proc_sym = sym->ns->proc_name;
1572627f7eb2Smrg if (proc_sym->attr.entry_master)
1573627f7eb2Smrg ++cnt;
1574627f7eb2Smrg if (gfc_return_by_reference (proc_sym))
1575627f7eb2Smrg {
1576627f7eb2Smrg ++cnt;
1577627f7eb2Smrg if (proc_sym->ts.type == BT_CHARACTER)
1578627f7eb2Smrg ++cnt;
1579627f7eb2Smrg }
1580627f7eb2Smrg for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
1581627f7eb2Smrg if (f->sym == sym)
1582627f7eb2Smrg break;
1583627f7eb2Smrg else if (f->sym)
1584627f7eb2Smrg ++cnt;
1585627f7eb2Smrg gcc_assert (f);
1586627f7eb2Smrg return build_int_cst (integer_type_node, cnt);
1587627f7eb2Smrg }
1588627f7eb2Smrg
1589627f7eb2Smrg tree t = gfc_get_symbol_decl (sym);
1590627f7eb2Smrg tree parent_decl;
1591627f7eb2Smrg int parent_flag;
1592627f7eb2Smrg bool return_value;
1593627f7eb2Smrg bool alternate_entry;
1594627f7eb2Smrg bool entry_master;
1595627f7eb2Smrg
1596627f7eb2Smrg return_value = sym->attr.function && sym->result == sym;
1597627f7eb2Smrg alternate_entry = sym->attr.function && sym->attr.entry
1598627f7eb2Smrg && sym->result == sym;
1599627f7eb2Smrg entry_master = sym->attr.result
1600627f7eb2Smrg && sym->ns->proc_name->attr.entry_master
1601627f7eb2Smrg && !gfc_return_by_reference (sym->ns->proc_name);
1602627f7eb2Smrg parent_decl = current_function_decl
1603627f7eb2Smrg ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
1604627f7eb2Smrg
1605627f7eb2Smrg if ((t == parent_decl && return_value)
1606627f7eb2Smrg || (sym->ns && sym->ns->proc_name
1607627f7eb2Smrg && sym->ns->proc_name->backend_decl == parent_decl
1608627f7eb2Smrg && (alternate_entry || entry_master)))
1609627f7eb2Smrg parent_flag = 1;
1610627f7eb2Smrg else
1611627f7eb2Smrg parent_flag = 0;
1612627f7eb2Smrg
1613627f7eb2Smrg /* Special case for assigning the return value of a function.
1614627f7eb2Smrg Self recursive functions must have an explicit return value. */
1615627f7eb2Smrg if (return_value && (t == current_function_decl || parent_flag))
1616627f7eb2Smrg t = gfc_get_fake_result_decl (sym, parent_flag);
1617627f7eb2Smrg
1618627f7eb2Smrg /* Similarly for alternate entry points. */
1619627f7eb2Smrg else if (alternate_entry
1620627f7eb2Smrg && (sym->ns->proc_name->backend_decl == current_function_decl
1621627f7eb2Smrg || parent_flag))
1622627f7eb2Smrg {
1623627f7eb2Smrg gfc_entry_list *el = NULL;
1624627f7eb2Smrg
1625627f7eb2Smrg for (el = sym->ns->entries; el; el = el->next)
1626627f7eb2Smrg if (sym == el->sym)
1627627f7eb2Smrg {
1628627f7eb2Smrg t = gfc_get_fake_result_decl (sym, parent_flag);
1629627f7eb2Smrg break;
1630627f7eb2Smrg }
1631627f7eb2Smrg }
1632627f7eb2Smrg
1633627f7eb2Smrg else if (entry_master
1634627f7eb2Smrg && (sym->ns->proc_name->backend_decl == current_function_decl
1635627f7eb2Smrg || parent_flag))
1636627f7eb2Smrg t = gfc_get_fake_result_decl (sym, parent_flag);
1637627f7eb2Smrg
1638627f7eb2Smrg return t;
1639627f7eb2Smrg }
1640627f7eb2Smrg
1641627f7eb2Smrg static tree
gfc_trans_omp_variable_list(enum omp_clause_code code,gfc_omp_namelist * namelist,tree list,bool declare_simd)1642627f7eb2Smrg gfc_trans_omp_variable_list (enum omp_clause_code code,
1643627f7eb2Smrg gfc_omp_namelist *namelist, tree list,
1644627f7eb2Smrg bool declare_simd)
1645627f7eb2Smrg {
1646627f7eb2Smrg for (; namelist != NULL; namelist = namelist->next)
1647627f7eb2Smrg if (namelist->sym->attr.referenced || declare_simd)
1648627f7eb2Smrg {
1649627f7eb2Smrg tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
1650627f7eb2Smrg if (t != error_mark_node)
1651627f7eb2Smrg {
1652627f7eb2Smrg tree node = build_omp_clause (input_location, code);
1653627f7eb2Smrg OMP_CLAUSE_DECL (node) = t;
1654627f7eb2Smrg list = gfc_trans_add_clause (node, list);
1655627f7eb2Smrg }
1656627f7eb2Smrg }
1657627f7eb2Smrg return list;
1658627f7eb2Smrg }
1659627f7eb2Smrg
1660627f7eb2Smrg struct omp_udr_find_orig_data
1661627f7eb2Smrg {
1662627f7eb2Smrg gfc_omp_udr *omp_udr;
1663627f7eb2Smrg bool omp_orig_seen;
1664627f7eb2Smrg };
1665627f7eb2Smrg
1666627f7eb2Smrg static int
omp_udr_find_orig(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)1667627f7eb2Smrg omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1668627f7eb2Smrg void *data)
1669627f7eb2Smrg {
1670627f7eb2Smrg struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
1671627f7eb2Smrg if ((*e)->expr_type == EXPR_VARIABLE
1672627f7eb2Smrg && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
1673627f7eb2Smrg cd->omp_orig_seen = true;
1674627f7eb2Smrg
1675627f7eb2Smrg return 0;
1676627f7eb2Smrg }
1677627f7eb2Smrg
1678627f7eb2Smrg static void
gfc_trans_omp_array_reduction_or_udr(tree c,gfc_omp_namelist * n,locus where)1679627f7eb2Smrg gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
1680627f7eb2Smrg {
1681627f7eb2Smrg gfc_symbol *sym = n->sym;
1682627f7eb2Smrg gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
1683627f7eb2Smrg gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
1684627f7eb2Smrg gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
1685627f7eb2Smrg gfc_symbol omp_var_copy[4];
1686627f7eb2Smrg gfc_expr *e1, *e2, *e3, *e4;
1687627f7eb2Smrg gfc_ref *ref;
1688627f7eb2Smrg tree decl, backend_decl, stmt, type, outer_decl;
1689627f7eb2Smrg locus old_loc = gfc_current_locus;
1690627f7eb2Smrg const char *iname;
1691627f7eb2Smrg bool t;
1692627f7eb2Smrg gfc_omp_udr *udr = n->udr ? n->udr->udr : NULL;
1693627f7eb2Smrg
1694627f7eb2Smrg decl = OMP_CLAUSE_DECL (c);
1695627f7eb2Smrg gfc_current_locus = where;
1696627f7eb2Smrg type = TREE_TYPE (decl);
1697627f7eb2Smrg outer_decl = create_tmp_var_raw (type);
1698627f7eb2Smrg if (TREE_CODE (decl) == PARM_DECL
1699627f7eb2Smrg && TREE_CODE (type) == REFERENCE_TYPE
1700627f7eb2Smrg && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
1701627f7eb2Smrg && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
1702627f7eb2Smrg {
1703627f7eb2Smrg decl = build_fold_indirect_ref (decl);
1704627f7eb2Smrg type = TREE_TYPE (type);
1705627f7eb2Smrg }
1706627f7eb2Smrg
1707627f7eb2Smrg /* Create a fake symbol for init value. */
1708627f7eb2Smrg memset (&init_val_sym, 0, sizeof (init_val_sym));
1709627f7eb2Smrg init_val_sym.ns = sym->ns;
1710627f7eb2Smrg init_val_sym.name = sym->name;
1711627f7eb2Smrg init_val_sym.ts = sym->ts;
1712627f7eb2Smrg init_val_sym.attr.referenced = 1;
1713627f7eb2Smrg init_val_sym.declared_at = where;
1714627f7eb2Smrg init_val_sym.attr.flavor = FL_VARIABLE;
1715627f7eb2Smrg if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1716627f7eb2Smrg backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
1717627f7eb2Smrg else if (udr->initializer_ns)
1718627f7eb2Smrg backend_decl = NULL;
1719627f7eb2Smrg else
1720627f7eb2Smrg switch (sym->ts.type)
1721627f7eb2Smrg {
1722627f7eb2Smrg case BT_LOGICAL:
1723627f7eb2Smrg case BT_INTEGER:
1724627f7eb2Smrg case BT_REAL:
1725627f7eb2Smrg case BT_COMPLEX:
1726627f7eb2Smrg backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
1727627f7eb2Smrg break;
1728627f7eb2Smrg default:
1729627f7eb2Smrg backend_decl = NULL_TREE;
1730627f7eb2Smrg break;
1731627f7eb2Smrg }
1732627f7eb2Smrg init_val_sym.backend_decl = backend_decl;
1733627f7eb2Smrg
1734627f7eb2Smrg /* Create a fake symbol for the outer array reference. */
1735627f7eb2Smrg outer_sym = *sym;
1736627f7eb2Smrg if (sym->as)
1737627f7eb2Smrg outer_sym.as = gfc_copy_array_spec (sym->as);
1738627f7eb2Smrg outer_sym.attr.dummy = 0;
1739627f7eb2Smrg outer_sym.attr.result = 0;
1740627f7eb2Smrg outer_sym.attr.flavor = FL_VARIABLE;
1741627f7eb2Smrg outer_sym.backend_decl = outer_decl;
1742627f7eb2Smrg if (decl != OMP_CLAUSE_DECL (c))
1743627f7eb2Smrg outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
1744627f7eb2Smrg
1745627f7eb2Smrg /* Create fake symtrees for it. */
1746627f7eb2Smrg symtree1 = gfc_new_symtree (&root1, sym->name);
1747627f7eb2Smrg symtree1->n.sym = sym;
1748627f7eb2Smrg gcc_assert (symtree1 == root1);
1749627f7eb2Smrg
1750627f7eb2Smrg symtree2 = gfc_new_symtree (&root2, sym->name);
1751627f7eb2Smrg symtree2->n.sym = &init_val_sym;
1752627f7eb2Smrg gcc_assert (symtree2 == root2);
1753627f7eb2Smrg
1754627f7eb2Smrg symtree3 = gfc_new_symtree (&root3, sym->name);
1755627f7eb2Smrg symtree3->n.sym = &outer_sym;
1756627f7eb2Smrg gcc_assert (symtree3 == root3);
1757627f7eb2Smrg
1758627f7eb2Smrg memset (omp_var_copy, 0, sizeof omp_var_copy);
1759627f7eb2Smrg if (udr)
1760627f7eb2Smrg {
1761627f7eb2Smrg omp_var_copy[0] = *udr->omp_out;
1762627f7eb2Smrg omp_var_copy[1] = *udr->omp_in;
1763627f7eb2Smrg *udr->omp_out = outer_sym;
1764627f7eb2Smrg *udr->omp_in = *sym;
1765627f7eb2Smrg if (udr->initializer_ns)
1766627f7eb2Smrg {
1767627f7eb2Smrg omp_var_copy[2] = *udr->omp_priv;
1768627f7eb2Smrg omp_var_copy[3] = *udr->omp_orig;
1769627f7eb2Smrg *udr->omp_priv = *sym;
1770627f7eb2Smrg *udr->omp_orig = outer_sym;
1771627f7eb2Smrg }
1772627f7eb2Smrg }
1773627f7eb2Smrg
1774627f7eb2Smrg /* Create expressions. */
1775627f7eb2Smrg e1 = gfc_get_expr ();
1776627f7eb2Smrg e1->expr_type = EXPR_VARIABLE;
1777627f7eb2Smrg e1->where = where;
1778627f7eb2Smrg e1->symtree = symtree1;
1779627f7eb2Smrg e1->ts = sym->ts;
1780627f7eb2Smrg if (sym->attr.dimension)
1781627f7eb2Smrg {
1782627f7eb2Smrg e1->ref = ref = gfc_get_ref ();
1783627f7eb2Smrg ref->type = REF_ARRAY;
1784627f7eb2Smrg ref->u.ar.where = where;
1785627f7eb2Smrg ref->u.ar.as = sym->as;
1786627f7eb2Smrg ref->u.ar.type = AR_FULL;
1787627f7eb2Smrg ref->u.ar.dimen = 0;
1788627f7eb2Smrg }
1789627f7eb2Smrg t = gfc_resolve_expr (e1);
1790627f7eb2Smrg gcc_assert (t);
1791627f7eb2Smrg
1792627f7eb2Smrg e2 = NULL;
1793627f7eb2Smrg if (backend_decl != NULL_TREE)
1794627f7eb2Smrg {
1795627f7eb2Smrg e2 = gfc_get_expr ();
1796627f7eb2Smrg e2->expr_type = EXPR_VARIABLE;
1797627f7eb2Smrg e2->where = where;
1798627f7eb2Smrg e2->symtree = symtree2;
1799627f7eb2Smrg e2->ts = sym->ts;
1800627f7eb2Smrg t = gfc_resolve_expr (e2);
1801627f7eb2Smrg gcc_assert (t);
1802627f7eb2Smrg }
1803627f7eb2Smrg else if (udr->initializer_ns == NULL)
1804627f7eb2Smrg {
1805627f7eb2Smrg gcc_assert (sym->ts.type == BT_DERIVED);
1806627f7eb2Smrg e2 = gfc_default_initializer (&sym->ts);
1807627f7eb2Smrg gcc_assert (e2);
1808627f7eb2Smrg t = gfc_resolve_expr (e2);
1809627f7eb2Smrg gcc_assert (t);
1810627f7eb2Smrg }
1811627f7eb2Smrg else if (n->udr->initializer->op == EXEC_ASSIGN)
1812627f7eb2Smrg {
1813627f7eb2Smrg e2 = gfc_copy_expr (n->udr->initializer->expr2);
1814627f7eb2Smrg t = gfc_resolve_expr (e2);
1815627f7eb2Smrg gcc_assert (t);
1816627f7eb2Smrg }
1817627f7eb2Smrg if (udr && udr->initializer_ns)
1818627f7eb2Smrg {
1819627f7eb2Smrg struct omp_udr_find_orig_data cd;
1820627f7eb2Smrg cd.omp_udr = udr;
1821627f7eb2Smrg cd.omp_orig_seen = false;
1822627f7eb2Smrg gfc_code_walker (&n->udr->initializer,
1823627f7eb2Smrg gfc_dummy_code_callback, omp_udr_find_orig, &cd);
1824627f7eb2Smrg if (cd.omp_orig_seen)
1825627f7eb2Smrg OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
1826627f7eb2Smrg }
1827627f7eb2Smrg
1828627f7eb2Smrg e3 = gfc_copy_expr (e1);
1829627f7eb2Smrg e3->symtree = symtree3;
1830627f7eb2Smrg t = gfc_resolve_expr (e3);
1831627f7eb2Smrg gcc_assert (t);
1832627f7eb2Smrg
1833627f7eb2Smrg iname = NULL;
1834627f7eb2Smrg e4 = NULL;
1835627f7eb2Smrg switch (OMP_CLAUSE_REDUCTION_CODE (c))
1836627f7eb2Smrg {
1837627f7eb2Smrg case PLUS_EXPR:
1838627f7eb2Smrg case MINUS_EXPR:
1839627f7eb2Smrg e4 = gfc_add (e3, e1);
1840627f7eb2Smrg break;
1841627f7eb2Smrg case MULT_EXPR:
1842627f7eb2Smrg e4 = gfc_multiply (e3, e1);
1843627f7eb2Smrg break;
1844627f7eb2Smrg case TRUTH_ANDIF_EXPR:
1845627f7eb2Smrg e4 = gfc_and (e3, e1);
1846627f7eb2Smrg break;
1847627f7eb2Smrg case TRUTH_ORIF_EXPR:
1848627f7eb2Smrg e4 = gfc_or (e3, e1);
1849627f7eb2Smrg break;
1850627f7eb2Smrg case EQ_EXPR:
1851627f7eb2Smrg e4 = gfc_eqv (e3, e1);
1852627f7eb2Smrg break;
1853627f7eb2Smrg case NE_EXPR:
1854627f7eb2Smrg e4 = gfc_neqv (e3, e1);
1855627f7eb2Smrg break;
1856627f7eb2Smrg case MIN_EXPR:
1857627f7eb2Smrg iname = "min";
1858627f7eb2Smrg break;
1859627f7eb2Smrg case MAX_EXPR:
1860627f7eb2Smrg iname = "max";
1861627f7eb2Smrg break;
1862627f7eb2Smrg case BIT_AND_EXPR:
1863627f7eb2Smrg iname = "iand";
1864627f7eb2Smrg break;
1865627f7eb2Smrg case BIT_IOR_EXPR:
1866627f7eb2Smrg iname = "ior";
1867627f7eb2Smrg break;
1868627f7eb2Smrg case BIT_XOR_EXPR:
1869627f7eb2Smrg iname = "ieor";
1870627f7eb2Smrg break;
1871627f7eb2Smrg case ERROR_MARK:
1872627f7eb2Smrg if (n->udr->combiner->op == EXEC_ASSIGN)
1873627f7eb2Smrg {
1874627f7eb2Smrg gfc_free_expr (e3);
1875627f7eb2Smrg e3 = gfc_copy_expr (n->udr->combiner->expr1);
1876627f7eb2Smrg e4 = gfc_copy_expr (n->udr->combiner->expr2);
1877627f7eb2Smrg t = gfc_resolve_expr (e3);
1878627f7eb2Smrg gcc_assert (t);
1879627f7eb2Smrg t = gfc_resolve_expr (e4);
1880627f7eb2Smrg gcc_assert (t);
1881627f7eb2Smrg }
1882627f7eb2Smrg break;
1883627f7eb2Smrg default:
1884627f7eb2Smrg gcc_unreachable ();
1885627f7eb2Smrg }
1886627f7eb2Smrg if (iname != NULL)
1887627f7eb2Smrg {
1888627f7eb2Smrg memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
1889627f7eb2Smrg intrinsic_sym.ns = sym->ns;
1890627f7eb2Smrg intrinsic_sym.name = iname;
1891627f7eb2Smrg intrinsic_sym.ts = sym->ts;
1892627f7eb2Smrg intrinsic_sym.attr.referenced = 1;
1893627f7eb2Smrg intrinsic_sym.attr.intrinsic = 1;
1894627f7eb2Smrg intrinsic_sym.attr.function = 1;
1895627f7eb2Smrg intrinsic_sym.attr.implicit_type = 1;
1896627f7eb2Smrg intrinsic_sym.result = &intrinsic_sym;
1897627f7eb2Smrg intrinsic_sym.declared_at = where;
1898627f7eb2Smrg
1899627f7eb2Smrg symtree4 = gfc_new_symtree (&root4, iname);
1900627f7eb2Smrg symtree4->n.sym = &intrinsic_sym;
1901627f7eb2Smrg gcc_assert (symtree4 == root4);
1902627f7eb2Smrg
1903627f7eb2Smrg e4 = gfc_get_expr ();
1904627f7eb2Smrg e4->expr_type = EXPR_FUNCTION;
1905627f7eb2Smrg e4->where = where;
1906627f7eb2Smrg e4->symtree = symtree4;
1907627f7eb2Smrg e4->value.function.actual = gfc_get_actual_arglist ();
1908627f7eb2Smrg e4->value.function.actual->expr = e3;
1909627f7eb2Smrg e4->value.function.actual->next = gfc_get_actual_arglist ();
1910627f7eb2Smrg e4->value.function.actual->next->expr = e1;
1911627f7eb2Smrg }
1912627f7eb2Smrg if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
1913627f7eb2Smrg {
1914627f7eb2Smrg /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
1915627f7eb2Smrg e1 = gfc_copy_expr (e1);
1916627f7eb2Smrg e3 = gfc_copy_expr (e3);
1917627f7eb2Smrg t = gfc_resolve_expr (e4);
1918627f7eb2Smrg gcc_assert (t);
1919627f7eb2Smrg }
1920627f7eb2Smrg
1921627f7eb2Smrg /* Create the init statement list. */
1922627f7eb2Smrg pushlevel ();
1923627f7eb2Smrg if (e2)
1924627f7eb2Smrg stmt = gfc_trans_assignment (e1, e2, false, false);
1925627f7eb2Smrg else
1926627f7eb2Smrg stmt = gfc_trans_call (n->udr->initializer, false,
1927627f7eb2Smrg NULL_TREE, NULL_TREE, false);
1928627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
1929627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1930627f7eb2Smrg else
1931627f7eb2Smrg poplevel (0, 0);
1932627f7eb2Smrg OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
1933627f7eb2Smrg
1934627f7eb2Smrg /* Create the merge statement list. */
1935627f7eb2Smrg pushlevel ();
1936627f7eb2Smrg if (e4)
1937627f7eb2Smrg stmt = gfc_trans_assignment (e3, e4, false, true);
1938627f7eb2Smrg else
1939627f7eb2Smrg stmt = gfc_trans_call (n->udr->combiner, false,
1940627f7eb2Smrg NULL_TREE, NULL_TREE, false);
1941627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
1942627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
1943627f7eb2Smrg else
1944627f7eb2Smrg poplevel (0, 0);
1945627f7eb2Smrg OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
1946627f7eb2Smrg
1947627f7eb2Smrg /* And stick the placeholder VAR_DECL into the clause as well. */
1948627f7eb2Smrg OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
1949627f7eb2Smrg
1950627f7eb2Smrg gfc_current_locus = old_loc;
1951627f7eb2Smrg
1952627f7eb2Smrg gfc_free_expr (e1);
1953627f7eb2Smrg if (e2)
1954627f7eb2Smrg gfc_free_expr (e2);
1955627f7eb2Smrg gfc_free_expr (e3);
1956627f7eb2Smrg if (e4)
1957627f7eb2Smrg gfc_free_expr (e4);
1958627f7eb2Smrg free (symtree1);
1959627f7eb2Smrg free (symtree2);
1960627f7eb2Smrg free (symtree3);
1961627f7eb2Smrg free (symtree4);
1962627f7eb2Smrg if (outer_sym.as)
1963627f7eb2Smrg gfc_free_array_spec (outer_sym.as);
1964627f7eb2Smrg
1965627f7eb2Smrg if (udr)
1966627f7eb2Smrg {
1967627f7eb2Smrg *udr->omp_out = omp_var_copy[0];
1968627f7eb2Smrg *udr->omp_in = omp_var_copy[1];
1969627f7eb2Smrg if (udr->initializer_ns)
1970627f7eb2Smrg {
1971627f7eb2Smrg *udr->omp_priv = omp_var_copy[2];
1972627f7eb2Smrg *udr->omp_orig = omp_var_copy[3];
1973627f7eb2Smrg }
1974627f7eb2Smrg }
1975627f7eb2Smrg }
1976627f7eb2Smrg
1977627f7eb2Smrg static tree
gfc_trans_omp_reduction_list(gfc_omp_namelist * namelist,tree list,locus where,bool mark_addressable)1978627f7eb2Smrg gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
1979627f7eb2Smrg locus where, bool mark_addressable)
1980627f7eb2Smrg {
1981627f7eb2Smrg for (; namelist != NULL; namelist = namelist->next)
1982627f7eb2Smrg if (namelist->sym->attr.referenced)
1983627f7eb2Smrg {
1984627f7eb2Smrg tree t = gfc_trans_omp_variable (namelist->sym, false);
1985627f7eb2Smrg if (t != error_mark_node)
1986627f7eb2Smrg {
1987*4c3eb207Smrg tree node = build_omp_clause (gfc_get_location (&namelist->where),
1988627f7eb2Smrg OMP_CLAUSE_REDUCTION);
1989627f7eb2Smrg OMP_CLAUSE_DECL (node) = t;
1990627f7eb2Smrg if (mark_addressable)
1991627f7eb2Smrg TREE_ADDRESSABLE (t) = 1;
1992627f7eb2Smrg switch (namelist->u.reduction_op)
1993627f7eb2Smrg {
1994627f7eb2Smrg case OMP_REDUCTION_PLUS:
1995627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
1996627f7eb2Smrg break;
1997627f7eb2Smrg case OMP_REDUCTION_MINUS:
1998627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
1999627f7eb2Smrg break;
2000627f7eb2Smrg case OMP_REDUCTION_TIMES:
2001627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
2002627f7eb2Smrg break;
2003627f7eb2Smrg case OMP_REDUCTION_AND:
2004627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
2005627f7eb2Smrg break;
2006627f7eb2Smrg case OMP_REDUCTION_OR:
2007627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
2008627f7eb2Smrg break;
2009627f7eb2Smrg case OMP_REDUCTION_EQV:
2010627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
2011627f7eb2Smrg break;
2012627f7eb2Smrg case OMP_REDUCTION_NEQV:
2013627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
2014627f7eb2Smrg break;
2015627f7eb2Smrg case OMP_REDUCTION_MAX:
2016627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
2017627f7eb2Smrg break;
2018627f7eb2Smrg case OMP_REDUCTION_MIN:
2019627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
2020627f7eb2Smrg break;
2021627f7eb2Smrg case OMP_REDUCTION_IAND:
2022627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
2023627f7eb2Smrg break;
2024627f7eb2Smrg case OMP_REDUCTION_IOR:
2025627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
2026627f7eb2Smrg break;
2027627f7eb2Smrg case OMP_REDUCTION_IEOR:
2028627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
2029627f7eb2Smrg break;
2030627f7eb2Smrg case OMP_REDUCTION_USER:
2031627f7eb2Smrg OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
2032627f7eb2Smrg break;
2033627f7eb2Smrg default:
2034627f7eb2Smrg gcc_unreachable ();
2035627f7eb2Smrg }
2036627f7eb2Smrg if (namelist->sym->attr.dimension
2037627f7eb2Smrg || namelist->u.reduction_op == OMP_REDUCTION_USER
2038627f7eb2Smrg || namelist->sym->attr.allocatable)
2039627f7eb2Smrg gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
2040627f7eb2Smrg list = gfc_trans_add_clause (node, list);
2041627f7eb2Smrg }
2042627f7eb2Smrg }
2043627f7eb2Smrg return list;
2044627f7eb2Smrg }
2045627f7eb2Smrg
2046627f7eb2Smrg static inline tree
gfc_convert_expr_to_tree(stmtblock_t * block,gfc_expr * expr)2047627f7eb2Smrg gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
2048627f7eb2Smrg {
2049627f7eb2Smrg gfc_se se;
2050627f7eb2Smrg tree result;
2051627f7eb2Smrg
2052627f7eb2Smrg gfc_init_se (&se, NULL );
2053627f7eb2Smrg gfc_conv_expr (&se, expr);
2054627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2055627f7eb2Smrg result = gfc_evaluate_now (se.expr, block);
2056627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
2057627f7eb2Smrg
2058627f7eb2Smrg return result;
2059627f7eb2Smrg }
2060627f7eb2Smrg
2061627f7eb2Smrg static vec<tree, va_heap, vl_embed> *doacross_steps;
2062627f7eb2Smrg
2063*4c3eb207Smrg
2064*4c3eb207Smrg /* Translate an array section or array element. */
2065*4c3eb207Smrg
2066*4c3eb207Smrg 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)2067*4c3eb207Smrg gfc_trans_omp_array_section (stmtblock_t *block, gfc_omp_namelist *n,
2068*4c3eb207Smrg tree decl, bool element, gomp_map_kind ptr_kind,
2069*4c3eb207Smrg tree node, tree &node2, tree &node3, tree &node4)
2070*4c3eb207Smrg {
2071*4c3eb207Smrg gfc_se se;
2072*4c3eb207Smrg tree ptr, ptr2;
2073*4c3eb207Smrg
2074*4c3eb207Smrg gfc_init_se (&se, NULL);
2075*4c3eb207Smrg
2076*4c3eb207Smrg if (element)
2077*4c3eb207Smrg {
2078*4c3eb207Smrg gfc_conv_expr_reference (&se, n->expr);
2079*4c3eb207Smrg gfc_add_block_to_block (block, &se.pre);
2080*4c3eb207Smrg ptr = se.expr;
2081*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2082*4c3eb207Smrg }
2083*4c3eb207Smrg else
2084*4c3eb207Smrg {
2085*4c3eb207Smrg gfc_conv_expr_descriptor (&se, n->expr);
2086*4c3eb207Smrg ptr = gfc_conv_array_data (se.expr);
2087*4c3eb207Smrg tree type = TREE_TYPE (se.expr);
2088*4c3eb207Smrg gfc_add_block_to_block (block, &se.pre);
2089*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr,
2090*4c3eb207Smrg GFC_TYPE_ARRAY_RANK (type));
2091*4c3eb207Smrg tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2092*4c3eb207Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
2093*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type,
2094*4c3eb207Smrg OMP_CLAUSE_SIZE (node), elemsz);
2095*4c3eb207Smrg }
2096*4c3eb207Smrg gfc_add_block_to_block (block, &se.post);
2097*4c3eb207Smrg ptr = fold_convert (build_pointer_type (char_type_node), ptr);
2098*4c3eb207Smrg OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2099*4c3eb207Smrg
2100*4c3eb207Smrg if (POINTER_TYPE_P (TREE_TYPE (decl))
2101*4c3eb207Smrg && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2102*4c3eb207Smrg && ptr_kind == GOMP_MAP_POINTER)
2103*4c3eb207Smrg {
2104*4c3eb207Smrg node4 = build_omp_clause (input_location,
2105*4c3eb207Smrg OMP_CLAUSE_MAP);
2106*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2107*4c3eb207Smrg OMP_CLAUSE_DECL (node4) = decl;
2108*4c3eb207Smrg OMP_CLAUSE_SIZE (node4) = size_int (0);
2109*4c3eb207Smrg decl = build_fold_indirect_ref (decl);
2110*4c3eb207Smrg }
2111*4c3eb207Smrg ptr = fold_convert (sizetype, ptr);
2112*4c3eb207Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2113*4c3eb207Smrg {
2114*4c3eb207Smrg tree type = TREE_TYPE (decl);
2115*4c3eb207Smrg ptr2 = gfc_conv_descriptor_data_get (decl);
2116*4c3eb207Smrg node2 = build_omp_clause (input_location,
2117*4c3eb207Smrg OMP_CLAUSE_MAP);
2118*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2119*4c3eb207Smrg OMP_CLAUSE_DECL (node2) = decl;
2120*4c3eb207Smrg OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2121*4c3eb207Smrg node3 = build_omp_clause (input_location,
2122*4c3eb207Smrg OMP_CLAUSE_MAP);
2123*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2124*4c3eb207Smrg OMP_CLAUSE_DECL (node3)
2125*4c3eb207Smrg = gfc_conv_descriptor_data_get (decl);
2126*4c3eb207Smrg if (ptr_kind == GOMP_MAP_ATTACH_DETACH)
2127*4c3eb207Smrg STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2128*4c3eb207Smrg }
2129*4c3eb207Smrg else
2130*4c3eb207Smrg {
2131*4c3eb207Smrg if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2132*4c3eb207Smrg ptr2 = build_fold_addr_expr (decl);
2133*4c3eb207Smrg else
2134*4c3eb207Smrg {
2135*4c3eb207Smrg gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
2136*4c3eb207Smrg ptr2 = decl;
2137*4c3eb207Smrg }
2138*4c3eb207Smrg node3 = build_omp_clause (input_location,
2139*4c3eb207Smrg OMP_CLAUSE_MAP);
2140*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind);
2141*4c3eb207Smrg OMP_CLAUSE_DECL (node3) = decl;
2142*4c3eb207Smrg }
2143*4c3eb207Smrg ptr2 = fold_convert (sizetype, ptr2);
2144*4c3eb207Smrg OMP_CLAUSE_SIZE (node3)
2145*4c3eb207Smrg = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
2146*4c3eb207Smrg }
2147*4c3eb207Smrg
2148627f7eb2Smrg static tree
2149627f7eb2Smrg gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
2150627f7eb2Smrg locus where, bool declare_simd = false)
2151627f7eb2Smrg {
2152627f7eb2Smrg tree omp_clauses = NULL_TREE, chunk_size, c;
2153627f7eb2Smrg int list, ifc;
2154627f7eb2Smrg enum omp_clause_code clause_code;
2155627f7eb2Smrg gfc_se se;
2156627f7eb2Smrg
2157627f7eb2Smrg if (clauses == NULL)
2158627f7eb2Smrg return NULL_TREE;
2159627f7eb2Smrg
2160627f7eb2Smrg for (list = 0; list < OMP_LIST_NUM; list++)
2161627f7eb2Smrg {
2162627f7eb2Smrg gfc_omp_namelist *n = clauses->lists[list];
2163627f7eb2Smrg
2164627f7eb2Smrg if (n == NULL)
2165627f7eb2Smrg continue;
2166627f7eb2Smrg switch (list)
2167627f7eb2Smrg {
2168627f7eb2Smrg case OMP_LIST_REDUCTION:
2169627f7eb2Smrg /* An OpenACC async clause indicates the need to set reduction
2170627f7eb2Smrg arguments addressable, to allow asynchronous copy-out. */
2171627f7eb2Smrg omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where,
2172627f7eb2Smrg clauses->async);
2173627f7eb2Smrg break;
2174627f7eb2Smrg case OMP_LIST_PRIVATE:
2175627f7eb2Smrg clause_code = OMP_CLAUSE_PRIVATE;
2176627f7eb2Smrg goto add_clause;
2177627f7eb2Smrg case OMP_LIST_SHARED:
2178627f7eb2Smrg clause_code = OMP_CLAUSE_SHARED;
2179627f7eb2Smrg goto add_clause;
2180627f7eb2Smrg case OMP_LIST_FIRSTPRIVATE:
2181627f7eb2Smrg clause_code = OMP_CLAUSE_FIRSTPRIVATE;
2182627f7eb2Smrg goto add_clause;
2183627f7eb2Smrg case OMP_LIST_LASTPRIVATE:
2184627f7eb2Smrg clause_code = OMP_CLAUSE_LASTPRIVATE;
2185627f7eb2Smrg goto add_clause;
2186627f7eb2Smrg case OMP_LIST_COPYIN:
2187627f7eb2Smrg clause_code = OMP_CLAUSE_COPYIN;
2188627f7eb2Smrg goto add_clause;
2189627f7eb2Smrg case OMP_LIST_COPYPRIVATE:
2190627f7eb2Smrg clause_code = OMP_CLAUSE_COPYPRIVATE;
2191627f7eb2Smrg goto add_clause;
2192627f7eb2Smrg case OMP_LIST_UNIFORM:
2193627f7eb2Smrg clause_code = OMP_CLAUSE_UNIFORM;
2194627f7eb2Smrg goto add_clause;
2195627f7eb2Smrg case OMP_LIST_USE_DEVICE:
2196627f7eb2Smrg case OMP_LIST_USE_DEVICE_PTR:
2197627f7eb2Smrg clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
2198627f7eb2Smrg goto add_clause;
2199*4c3eb207Smrg case OMP_LIST_USE_DEVICE_ADDR:
2200*4c3eb207Smrg clause_code = OMP_CLAUSE_USE_DEVICE_ADDR;
2201*4c3eb207Smrg goto add_clause;
2202627f7eb2Smrg case OMP_LIST_IS_DEVICE_PTR:
2203627f7eb2Smrg clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
2204627f7eb2Smrg goto add_clause;
2205627f7eb2Smrg
2206627f7eb2Smrg add_clause:
2207627f7eb2Smrg omp_clauses
2208627f7eb2Smrg = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
2209627f7eb2Smrg declare_simd);
2210627f7eb2Smrg break;
2211627f7eb2Smrg case OMP_LIST_ALIGNED:
2212627f7eb2Smrg for (; n != NULL; n = n->next)
2213627f7eb2Smrg if (n->sym->attr.referenced || declare_simd)
2214627f7eb2Smrg {
2215627f7eb2Smrg tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2216627f7eb2Smrg if (t != error_mark_node)
2217627f7eb2Smrg {
2218627f7eb2Smrg tree node = build_omp_clause (input_location,
2219627f7eb2Smrg OMP_CLAUSE_ALIGNED);
2220627f7eb2Smrg OMP_CLAUSE_DECL (node) = t;
2221627f7eb2Smrg if (n->expr)
2222627f7eb2Smrg {
2223627f7eb2Smrg tree alignment_var;
2224627f7eb2Smrg
2225627f7eb2Smrg if (declare_simd)
2226627f7eb2Smrg alignment_var = gfc_conv_constant_to_tree (n->expr);
2227627f7eb2Smrg else
2228627f7eb2Smrg {
2229627f7eb2Smrg gfc_init_se (&se, NULL);
2230627f7eb2Smrg gfc_conv_expr (&se, n->expr);
2231627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2232627f7eb2Smrg alignment_var = gfc_evaluate_now (se.expr, block);
2233627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
2234627f7eb2Smrg }
2235627f7eb2Smrg OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
2236627f7eb2Smrg }
2237627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2238627f7eb2Smrg }
2239627f7eb2Smrg }
2240627f7eb2Smrg break;
2241627f7eb2Smrg case OMP_LIST_LINEAR:
2242627f7eb2Smrg {
2243627f7eb2Smrg gfc_expr *last_step_expr = NULL;
2244627f7eb2Smrg tree last_step = NULL_TREE;
2245627f7eb2Smrg bool last_step_parm = false;
2246627f7eb2Smrg
2247627f7eb2Smrg for (; n != NULL; n = n->next)
2248627f7eb2Smrg {
2249627f7eb2Smrg if (n->expr)
2250627f7eb2Smrg {
2251627f7eb2Smrg last_step_expr = n->expr;
2252627f7eb2Smrg last_step = NULL_TREE;
2253627f7eb2Smrg last_step_parm = false;
2254627f7eb2Smrg }
2255627f7eb2Smrg if (n->sym->attr.referenced || declare_simd)
2256627f7eb2Smrg {
2257627f7eb2Smrg tree t = gfc_trans_omp_variable (n->sym, declare_simd);
2258627f7eb2Smrg if (t != error_mark_node)
2259627f7eb2Smrg {
2260627f7eb2Smrg tree node = build_omp_clause (input_location,
2261627f7eb2Smrg OMP_CLAUSE_LINEAR);
2262627f7eb2Smrg OMP_CLAUSE_DECL (node) = t;
2263627f7eb2Smrg omp_clause_linear_kind kind;
2264627f7eb2Smrg switch (n->u.linear_op)
2265627f7eb2Smrg {
2266627f7eb2Smrg case OMP_LINEAR_DEFAULT:
2267627f7eb2Smrg kind = OMP_CLAUSE_LINEAR_DEFAULT;
2268627f7eb2Smrg break;
2269627f7eb2Smrg case OMP_LINEAR_REF:
2270627f7eb2Smrg kind = OMP_CLAUSE_LINEAR_REF;
2271627f7eb2Smrg break;
2272627f7eb2Smrg case OMP_LINEAR_VAL:
2273627f7eb2Smrg kind = OMP_CLAUSE_LINEAR_VAL;
2274627f7eb2Smrg break;
2275627f7eb2Smrg case OMP_LINEAR_UVAL:
2276627f7eb2Smrg kind = OMP_CLAUSE_LINEAR_UVAL;
2277627f7eb2Smrg break;
2278627f7eb2Smrg default:
2279627f7eb2Smrg gcc_unreachable ();
2280627f7eb2Smrg }
2281627f7eb2Smrg OMP_CLAUSE_LINEAR_KIND (node) = kind;
2282627f7eb2Smrg if (last_step_expr && last_step == NULL_TREE)
2283627f7eb2Smrg {
2284627f7eb2Smrg if (!declare_simd)
2285627f7eb2Smrg {
2286627f7eb2Smrg gfc_init_se (&se, NULL);
2287627f7eb2Smrg gfc_conv_expr (&se, last_step_expr);
2288627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2289627f7eb2Smrg last_step = gfc_evaluate_now (se.expr, block);
2290627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
2291627f7eb2Smrg }
2292627f7eb2Smrg else if (last_step_expr->expr_type == EXPR_VARIABLE)
2293627f7eb2Smrg {
2294627f7eb2Smrg gfc_symbol *s = last_step_expr->symtree->n.sym;
2295627f7eb2Smrg last_step = gfc_trans_omp_variable (s, true);
2296627f7eb2Smrg last_step_parm = true;
2297627f7eb2Smrg }
2298627f7eb2Smrg else
2299627f7eb2Smrg last_step
2300627f7eb2Smrg = gfc_conv_constant_to_tree (last_step_expr);
2301627f7eb2Smrg }
2302627f7eb2Smrg if (last_step_parm)
2303627f7eb2Smrg {
2304627f7eb2Smrg OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
2305627f7eb2Smrg OMP_CLAUSE_LINEAR_STEP (node) = last_step;
2306627f7eb2Smrg }
2307627f7eb2Smrg else
2308627f7eb2Smrg {
2309627f7eb2Smrg if (kind == OMP_CLAUSE_LINEAR_REF)
2310627f7eb2Smrg {
2311627f7eb2Smrg tree type;
2312627f7eb2Smrg if (n->sym->attr.flavor == FL_PROCEDURE)
2313627f7eb2Smrg {
2314627f7eb2Smrg type = gfc_get_function_type (n->sym);
2315627f7eb2Smrg type = build_pointer_type (type);
2316627f7eb2Smrg }
2317627f7eb2Smrg else
2318627f7eb2Smrg type = gfc_sym_type (n->sym);
2319627f7eb2Smrg if (POINTER_TYPE_P (type))
2320627f7eb2Smrg type = TREE_TYPE (type);
2321627f7eb2Smrg /* Otherwise to be determined what exactly
2322627f7eb2Smrg should be done. */
2323627f7eb2Smrg tree t = fold_convert (sizetype, last_step);
2324627f7eb2Smrg t = size_binop (MULT_EXPR, t,
2325627f7eb2Smrg TYPE_SIZE_UNIT (type));
2326627f7eb2Smrg OMP_CLAUSE_LINEAR_STEP (node) = t;
2327627f7eb2Smrg }
2328627f7eb2Smrg else
2329627f7eb2Smrg {
2330627f7eb2Smrg tree type
2331627f7eb2Smrg = gfc_typenode_for_spec (&n->sym->ts);
2332627f7eb2Smrg OMP_CLAUSE_LINEAR_STEP (node)
2333627f7eb2Smrg = fold_convert (type, last_step);
2334627f7eb2Smrg }
2335627f7eb2Smrg }
2336627f7eb2Smrg if (n->sym->attr.dimension || n->sym->attr.allocatable)
2337627f7eb2Smrg OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
2338627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2339627f7eb2Smrg }
2340627f7eb2Smrg }
2341627f7eb2Smrg }
2342627f7eb2Smrg }
2343627f7eb2Smrg break;
2344627f7eb2Smrg case OMP_LIST_DEPEND:
2345627f7eb2Smrg for (; n != NULL; n = n->next)
2346627f7eb2Smrg {
2347627f7eb2Smrg if (n->u.depend_op == OMP_DEPEND_SINK_FIRST)
2348627f7eb2Smrg {
2349627f7eb2Smrg tree vec = NULL_TREE;
2350627f7eb2Smrg unsigned int i;
2351627f7eb2Smrg for (i = 0; ; i++)
2352627f7eb2Smrg {
2353627f7eb2Smrg tree addend = integer_zero_node, t;
2354627f7eb2Smrg bool neg = false;
2355627f7eb2Smrg if (n->expr)
2356627f7eb2Smrg {
2357627f7eb2Smrg addend = gfc_conv_constant_to_tree (n->expr);
2358627f7eb2Smrg if (TREE_CODE (addend) == INTEGER_CST
2359627f7eb2Smrg && tree_int_cst_sgn (addend) == -1)
2360627f7eb2Smrg {
2361627f7eb2Smrg neg = true;
2362627f7eb2Smrg addend = const_unop (NEGATE_EXPR,
2363627f7eb2Smrg TREE_TYPE (addend), addend);
2364627f7eb2Smrg }
2365627f7eb2Smrg }
2366627f7eb2Smrg t = gfc_trans_omp_variable (n->sym, false);
2367627f7eb2Smrg if (t != error_mark_node)
2368627f7eb2Smrg {
2369627f7eb2Smrg if (i < vec_safe_length (doacross_steps)
2370627f7eb2Smrg && !integer_zerop (addend)
2371627f7eb2Smrg && (*doacross_steps)[i])
2372627f7eb2Smrg {
2373627f7eb2Smrg tree step = (*doacross_steps)[i];
2374627f7eb2Smrg addend = fold_convert (TREE_TYPE (step), addend);
2375627f7eb2Smrg addend = build2 (TRUNC_DIV_EXPR,
2376627f7eb2Smrg TREE_TYPE (step), addend, step);
2377627f7eb2Smrg }
2378627f7eb2Smrg vec = tree_cons (addend, t, vec);
2379627f7eb2Smrg if (neg)
2380627f7eb2Smrg OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
2381627f7eb2Smrg }
2382627f7eb2Smrg if (n->next == NULL
2383627f7eb2Smrg || n->next->u.depend_op != OMP_DEPEND_SINK)
2384627f7eb2Smrg break;
2385627f7eb2Smrg n = n->next;
2386627f7eb2Smrg }
2387627f7eb2Smrg if (vec == NULL_TREE)
2388627f7eb2Smrg continue;
2389627f7eb2Smrg
2390627f7eb2Smrg tree node = build_omp_clause (input_location,
2391627f7eb2Smrg OMP_CLAUSE_DEPEND);
2392627f7eb2Smrg OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
2393627f7eb2Smrg OMP_CLAUSE_DECL (node) = nreverse (vec);
2394627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2395627f7eb2Smrg continue;
2396627f7eb2Smrg }
2397627f7eb2Smrg
2398627f7eb2Smrg if (!n->sym->attr.referenced)
2399627f7eb2Smrg continue;
2400627f7eb2Smrg
2401627f7eb2Smrg tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
2402627f7eb2Smrg if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2403627f7eb2Smrg {
2404*4c3eb207Smrg tree decl = gfc_trans_omp_variable (n->sym, false);
2405627f7eb2Smrg if (gfc_omp_privatize_by_reference (decl))
2406627f7eb2Smrg decl = build_fold_indirect_ref (decl);
2407627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2408627f7eb2Smrg {
2409627f7eb2Smrg decl = gfc_conv_descriptor_data_get (decl);
2410627f7eb2Smrg decl = fold_convert (build_pointer_type (char_type_node),
2411627f7eb2Smrg decl);
2412627f7eb2Smrg decl = build_fold_indirect_ref (decl);
2413627f7eb2Smrg }
2414627f7eb2Smrg else if (DECL_P (decl))
2415627f7eb2Smrg TREE_ADDRESSABLE (decl) = 1;
2416627f7eb2Smrg OMP_CLAUSE_DECL (node) = decl;
2417627f7eb2Smrg }
2418627f7eb2Smrg else
2419627f7eb2Smrg {
2420627f7eb2Smrg tree ptr;
2421627f7eb2Smrg gfc_init_se (&se, NULL);
2422627f7eb2Smrg if (n->expr->ref->u.ar.type == AR_ELEMENT)
2423627f7eb2Smrg {
2424627f7eb2Smrg gfc_conv_expr_reference (&se, n->expr);
2425627f7eb2Smrg ptr = se.expr;
2426627f7eb2Smrg }
2427627f7eb2Smrg else
2428627f7eb2Smrg {
2429627f7eb2Smrg gfc_conv_expr_descriptor (&se, n->expr);
2430627f7eb2Smrg ptr = gfc_conv_array_data (se.expr);
2431627f7eb2Smrg }
2432627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2433627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
2434627f7eb2Smrg ptr = fold_convert (build_pointer_type (char_type_node),
2435627f7eb2Smrg ptr);
2436627f7eb2Smrg OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2437627f7eb2Smrg }
2438627f7eb2Smrg switch (n->u.depend_op)
2439627f7eb2Smrg {
2440627f7eb2Smrg case OMP_DEPEND_IN:
2441627f7eb2Smrg OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
2442627f7eb2Smrg break;
2443627f7eb2Smrg case OMP_DEPEND_OUT:
2444627f7eb2Smrg OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
2445627f7eb2Smrg break;
2446627f7eb2Smrg case OMP_DEPEND_INOUT:
2447627f7eb2Smrg OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
2448627f7eb2Smrg break;
2449627f7eb2Smrg default:
2450627f7eb2Smrg gcc_unreachable ();
2451627f7eb2Smrg }
2452627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2453627f7eb2Smrg }
2454627f7eb2Smrg break;
2455627f7eb2Smrg case OMP_LIST_MAP:
2456627f7eb2Smrg for (; n != NULL; n = n->next)
2457627f7eb2Smrg {
2458627f7eb2Smrg if (!n->sym->attr.referenced)
2459627f7eb2Smrg continue;
2460627f7eb2Smrg
2461627f7eb2Smrg tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2462627f7eb2Smrg tree node2 = NULL_TREE;
2463627f7eb2Smrg tree node3 = NULL_TREE;
2464627f7eb2Smrg tree node4 = NULL_TREE;
2465*4c3eb207Smrg tree decl = gfc_trans_omp_variable (n->sym, false);
2466627f7eb2Smrg if (DECL_P (decl))
2467627f7eb2Smrg TREE_ADDRESSABLE (decl) = 1;
2468*4c3eb207Smrg if (n->expr == NULL
2469*4c3eb207Smrg || (n->expr->ref->type == REF_ARRAY
2470*4c3eb207Smrg && n->expr->ref->u.ar.type == AR_FULL))
2471627f7eb2Smrg {
2472*4c3eb207Smrg tree present = gfc_omp_check_optional_argument (decl, true);
2473*4c3eb207Smrg if (n->sym->ts.type == BT_CLASS)
2474627f7eb2Smrg {
2475*4c3eb207Smrg tree type = TREE_TYPE (decl);
2476*4c3eb207Smrg if (n->sym->attr.optional)
2477*4c3eb207Smrg sorry ("optional class parameter");
2478*4c3eb207Smrg if (POINTER_TYPE_P (type))
2479*4c3eb207Smrg {
2480627f7eb2Smrg node4 = build_omp_clause (input_location,
2481627f7eb2Smrg OMP_CLAUSE_MAP);
2482627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2483627f7eb2Smrg OMP_CLAUSE_DECL (node4) = decl;
2484627f7eb2Smrg OMP_CLAUSE_SIZE (node4) = size_int (0);
2485627f7eb2Smrg decl = build_fold_indirect_ref (decl);
2486*4c3eb207Smrg }
2487*4c3eb207Smrg tree ptr = gfc_class_data_get (decl);
2488*4c3eb207Smrg ptr = build_fold_indirect_ref (ptr);
2489*4c3eb207Smrg OMP_CLAUSE_DECL (node) = ptr;
2490*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl);
2491*4c3eb207Smrg node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2492*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2493*4c3eb207Smrg OMP_CLAUSE_DECL (node2) = decl;
2494*4c3eb207Smrg OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2495*4c3eb207Smrg node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
2496*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH_DETACH);
2497*4c3eb207Smrg OMP_CLAUSE_DECL (node3) = gfc_class_data_get (decl);
2498*4c3eb207Smrg OMP_CLAUSE_SIZE (node3) = size_int (0);
2499*4c3eb207Smrg goto finalize_map_clause;
2500*4c3eb207Smrg }
2501*4c3eb207Smrg else if (POINTER_TYPE_P (TREE_TYPE (decl))
2502*4c3eb207Smrg && (gfc_omp_privatize_by_reference (decl)
2503*4c3eb207Smrg || GFC_DECL_GET_SCALAR_POINTER (decl)
2504*4c3eb207Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
2505*4c3eb207Smrg || GFC_DECL_CRAY_POINTEE (decl)
2506*4c3eb207Smrg || GFC_DESCRIPTOR_TYPE_P
2507*4c3eb207Smrg (TREE_TYPE (TREE_TYPE (decl)))
2508*4c3eb207Smrg || n->sym->ts.type == BT_DERIVED))
2509*4c3eb207Smrg {
2510*4c3eb207Smrg tree orig_decl = decl;
2511*4c3eb207Smrg
2512*4c3eb207Smrg /* For nonallocatable, nonpointer arrays, a temporary
2513*4c3eb207Smrg variable is generated, but this one is only defined if
2514*4c3eb207Smrg the variable is present; hence, we now set it to NULL
2515*4c3eb207Smrg to avoid accessing undefined variables. We cannot use
2516*4c3eb207Smrg a temporary variable here as otherwise the replacement
2517*4c3eb207Smrg of the variables in omp-low.c will not work. */
2518*4c3eb207Smrg if (present && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)))
2519*4c3eb207Smrg {
2520*4c3eb207Smrg tree tmp = fold_build2_loc (input_location,
2521*4c3eb207Smrg MODIFY_EXPR,
2522*4c3eb207Smrg void_type_node, decl,
2523*4c3eb207Smrg null_pointer_node);
2524*4c3eb207Smrg tree cond = fold_build1_loc (input_location,
2525*4c3eb207Smrg TRUTH_NOT_EXPR,
2526*4c3eb207Smrg boolean_type_node,
2527*4c3eb207Smrg present);
2528*4c3eb207Smrg gfc_add_expr_to_block (block,
2529*4c3eb207Smrg build3_loc (input_location,
2530*4c3eb207Smrg COND_EXPR,
2531*4c3eb207Smrg void_type_node,
2532*4c3eb207Smrg cond, tmp,
2533*4c3eb207Smrg NULL_TREE));
2534*4c3eb207Smrg }
2535*4c3eb207Smrg node4 = build_omp_clause (input_location,
2536*4c3eb207Smrg OMP_CLAUSE_MAP);
2537*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
2538*4c3eb207Smrg OMP_CLAUSE_DECL (node4) = decl;
2539*4c3eb207Smrg OMP_CLAUSE_SIZE (node4) = size_int (0);
2540*4c3eb207Smrg decl = build_fold_indirect_ref (decl);
2541*4c3eb207Smrg if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
2542*4c3eb207Smrg || gfc_omp_is_optional_argument (orig_decl))
2543627f7eb2Smrg && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
2544627f7eb2Smrg || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
2545627f7eb2Smrg {
2546627f7eb2Smrg node3 = build_omp_clause (input_location,
2547627f7eb2Smrg OMP_CLAUSE_MAP);
2548627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2549627f7eb2Smrg OMP_CLAUSE_DECL (node3) = decl;
2550627f7eb2Smrg OMP_CLAUSE_SIZE (node3) = size_int (0);
2551627f7eb2Smrg decl = build_fold_indirect_ref (decl);
2552627f7eb2Smrg }
2553627f7eb2Smrg }
2554*4c3eb207Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))
2555*4c3eb207Smrg && n->u.map_op != OMP_MAP_ATTACH
2556*4c3eb207Smrg && n->u.map_op != OMP_MAP_DETACH)
2557627f7eb2Smrg {
2558627f7eb2Smrg tree type = TREE_TYPE (decl);
2559627f7eb2Smrg tree ptr = gfc_conv_descriptor_data_get (decl);
2560*4c3eb207Smrg if (present)
2561*4c3eb207Smrg ptr = gfc_build_cond_assign_expr (block, present, ptr,
2562*4c3eb207Smrg null_pointer_node);
2563627f7eb2Smrg ptr = fold_convert (build_pointer_type (char_type_node),
2564627f7eb2Smrg ptr);
2565627f7eb2Smrg ptr = build_fold_indirect_ref (ptr);
2566627f7eb2Smrg OMP_CLAUSE_DECL (node) = ptr;
2567627f7eb2Smrg node2 = build_omp_clause (input_location,
2568627f7eb2Smrg OMP_CLAUSE_MAP);
2569627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2570627f7eb2Smrg OMP_CLAUSE_DECL (node2) = decl;
2571627f7eb2Smrg OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2572627f7eb2Smrg node3 = build_omp_clause (input_location,
2573627f7eb2Smrg OMP_CLAUSE_MAP);
2574627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
2575*4c3eb207Smrg if (present)
2576*4c3eb207Smrg {
2577*4c3eb207Smrg ptr = gfc_conv_descriptor_data_get (decl);
2578*4c3eb207Smrg ptr = gfc_build_addr_expr (NULL, ptr);
2579*4c3eb207Smrg ptr = gfc_build_cond_assign_expr (block, present, ptr,
2580*4c3eb207Smrg null_pointer_node);
2581*4c3eb207Smrg ptr = build_fold_indirect_ref (ptr);
2582*4c3eb207Smrg OMP_CLAUSE_DECL (node3) = ptr;
2583*4c3eb207Smrg }
2584*4c3eb207Smrg else
2585627f7eb2Smrg OMP_CLAUSE_DECL (node3)
2586627f7eb2Smrg = gfc_conv_descriptor_data_get (decl);
2587627f7eb2Smrg OMP_CLAUSE_SIZE (node3) = size_int (0);
2588627f7eb2Smrg
2589627f7eb2Smrg /* We have to check for n->sym->attr.dimension because
2590627f7eb2Smrg of scalar coarrays. */
2591627f7eb2Smrg if (n->sym->attr.pointer && n->sym->attr.dimension)
2592627f7eb2Smrg {
2593627f7eb2Smrg stmtblock_t cond_block;
2594627f7eb2Smrg tree size
2595627f7eb2Smrg = gfc_create_var (gfc_array_index_type, NULL);
2596627f7eb2Smrg tree tem, then_b, else_b, zero, cond;
2597627f7eb2Smrg
2598627f7eb2Smrg gfc_init_block (&cond_block);
2599627f7eb2Smrg tem
2600627f7eb2Smrg = gfc_full_array_size (&cond_block, decl,
2601627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
2602627f7eb2Smrg gfc_add_modify (&cond_block, size, tem);
2603627f7eb2Smrg then_b = gfc_finish_block (&cond_block);
2604627f7eb2Smrg gfc_init_block (&cond_block);
2605627f7eb2Smrg zero = build_int_cst (gfc_array_index_type, 0);
2606627f7eb2Smrg gfc_add_modify (&cond_block, size, zero);
2607627f7eb2Smrg else_b = gfc_finish_block (&cond_block);
2608627f7eb2Smrg tem = gfc_conv_descriptor_data_get (decl);
2609627f7eb2Smrg tem = fold_convert (pvoid_type_node, tem);
2610627f7eb2Smrg cond = fold_build2_loc (input_location, NE_EXPR,
2611*4c3eb207Smrg boolean_type_node,
2612627f7eb2Smrg tem, null_pointer_node);
2613*4c3eb207Smrg if (present)
2614*4c3eb207Smrg cond = fold_build2_loc (input_location,
2615*4c3eb207Smrg TRUTH_ANDIF_EXPR,
2616*4c3eb207Smrg boolean_type_node,
2617*4c3eb207Smrg present, cond);
2618627f7eb2Smrg gfc_add_expr_to_block (block,
2619627f7eb2Smrg build3_loc (input_location,
2620627f7eb2Smrg COND_EXPR,
2621627f7eb2Smrg void_type_node,
2622627f7eb2Smrg cond, then_b,
2623627f7eb2Smrg else_b));
2624627f7eb2Smrg OMP_CLAUSE_SIZE (node) = size;
2625627f7eb2Smrg }
2626627f7eb2Smrg else if (n->sym->attr.dimension)
2627*4c3eb207Smrg {
2628*4c3eb207Smrg stmtblock_t cond_block;
2629*4c3eb207Smrg gfc_init_block (&cond_block);
2630*4c3eb207Smrg tree size = gfc_full_array_size (&cond_block, decl,
2631627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
2632*4c3eb207Smrg if (present)
2633*4c3eb207Smrg {
2634*4c3eb207Smrg tree var = gfc_create_var (gfc_array_index_type,
2635*4c3eb207Smrg NULL);
2636*4c3eb207Smrg gfc_add_modify (&cond_block, var, size);
2637*4c3eb207Smrg tree cond_body = gfc_finish_block (&cond_block);
2638*4c3eb207Smrg tree cond = build3_loc (input_location, COND_EXPR,
2639*4c3eb207Smrg void_type_node, present,
2640*4c3eb207Smrg cond_body, NULL_TREE);
2641*4c3eb207Smrg gfc_add_expr_to_block (block, cond);
2642*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = var;
2643*4c3eb207Smrg }
2644*4c3eb207Smrg else
2645*4c3eb207Smrg {
2646*4c3eb207Smrg gfc_add_block_to_block (block, &cond_block);
2647*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = size;
2648*4c3eb207Smrg }
2649*4c3eb207Smrg }
2650627f7eb2Smrg if (n->sym->attr.dimension)
2651627f7eb2Smrg {
2652627f7eb2Smrg tree elemsz
2653627f7eb2Smrg = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2654627f7eb2Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
2655627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2656627f7eb2Smrg = fold_build2 (MULT_EXPR, gfc_array_index_type,
2657627f7eb2Smrg OMP_CLAUSE_SIZE (node), elemsz);
2658627f7eb2Smrg }
2659627f7eb2Smrg }
2660*4c3eb207Smrg else if (present
2661*4c3eb207Smrg && TREE_CODE (decl) == INDIRECT_REF
2662*4c3eb207Smrg && (TREE_CODE (TREE_OPERAND (decl, 0))
2663*4c3eb207Smrg == INDIRECT_REF))
2664*4c3eb207Smrg {
2665*4c3eb207Smrg /* A single indirectref is handled by the middle end. */
2666*4c3eb207Smrg gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
2667*4c3eb207Smrg decl = TREE_OPERAND (decl, 0);
2668*4c3eb207Smrg decl = gfc_build_cond_assign_expr (block, present, decl,
2669*4c3eb207Smrg null_pointer_node);
2670*4c3eb207Smrg OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl);
2671*4c3eb207Smrg }
2672627f7eb2Smrg else
2673627f7eb2Smrg OMP_CLAUSE_DECL (node) = decl;
2674627f7eb2Smrg }
2675*4c3eb207Smrg else if (n->expr
2676*4c3eb207Smrg && n->expr->expr_type == EXPR_VARIABLE
2677*4c3eb207Smrg && n->expr->ref->type == REF_COMPONENT)
2678*4c3eb207Smrg {
2679*4c3eb207Smrg gfc_ref *lastcomp;
2680*4c3eb207Smrg
2681*4c3eb207Smrg for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
2682*4c3eb207Smrg if (ref->type == REF_COMPONENT)
2683*4c3eb207Smrg lastcomp = ref;
2684*4c3eb207Smrg
2685*4c3eb207Smrg symbol_attribute sym_attr;
2686*4c3eb207Smrg
2687*4c3eb207Smrg if (lastcomp->u.c.component->ts.type == BT_CLASS)
2688*4c3eb207Smrg sym_attr = CLASS_DATA (lastcomp->u.c.component)->attr;
2689627f7eb2Smrg else
2690*4c3eb207Smrg sym_attr = lastcomp->u.c.component->attr;
2691*4c3eb207Smrg
2692627f7eb2Smrg gfc_init_se (&se, NULL);
2693*4c3eb207Smrg
2694*4c3eb207Smrg if (!sym_attr.dimension
2695*4c3eb207Smrg && lastcomp->u.c.component->ts.type != BT_CLASS
2696*4c3eb207Smrg && lastcomp->u.c.component->ts.type != BT_DERIVED)
2697627f7eb2Smrg {
2698*4c3eb207Smrg /* Last component is a scalar. */
2699*4c3eb207Smrg gfc_conv_expr (&se, n->expr);
2700627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2701*4c3eb207Smrg OMP_CLAUSE_DECL (node) = se.expr;
2702*4c3eb207Smrg gfc_add_block_to_block (block, &se.post);
2703*4c3eb207Smrg goto finalize_map_clause;
2704*4c3eb207Smrg }
2705*4c3eb207Smrg
2706*4c3eb207Smrg se.expr = gfc_maybe_dereference_var (n->sym, decl);
2707*4c3eb207Smrg
2708*4c3eb207Smrg for (gfc_ref *ref = n->expr->ref;
2709*4c3eb207Smrg ref && ref != lastcomp->next;
2710*4c3eb207Smrg ref = ref->next)
2711*4c3eb207Smrg {
2712*4c3eb207Smrg if (ref->type == REF_COMPONENT)
2713*4c3eb207Smrg {
2714*4c3eb207Smrg if (ref->u.c.sym->attr.extension)
2715*4c3eb207Smrg conv_parent_component_references (&se, ref);
2716*4c3eb207Smrg
2717*4c3eb207Smrg gfc_conv_component_ref (&se, ref);
2718*4c3eb207Smrg }
2719*4c3eb207Smrg else
2720*4c3eb207Smrg sorry ("unhandled derived-type component");
2721*4c3eb207Smrg }
2722*4c3eb207Smrg
2723*4c3eb207Smrg tree inner = se.expr;
2724*4c3eb207Smrg
2725*4c3eb207Smrg /* Last component is a derived type or class pointer. */
2726*4c3eb207Smrg if (lastcomp->u.c.component->ts.type == BT_DERIVED
2727*4c3eb207Smrg || lastcomp->u.c.component->ts.type == BT_CLASS)
2728*4c3eb207Smrg {
2729*4c3eb207Smrg if (sym_attr.allocatable || sym_attr.pointer)
2730*4c3eb207Smrg {
2731*4c3eb207Smrg tree data, size;
2732*4c3eb207Smrg
2733*4c3eb207Smrg if (lastcomp->u.c.component->ts.type == BT_CLASS)
2734*4c3eb207Smrg {
2735*4c3eb207Smrg data = gfc_class_data_get (inner);
2736*4c3eb207Smrg size = gfc_class_vtab_size_get (inner);
2737*4c3eb207Smrg }
2738*4c3eb207Smrg else /* BT_DERIVED. */
2739*4c3eb207Smrg {
2740*4c3eb207Smrg data = inner;
2741*4c3eb207Smrg size = TYPE_SIZE_UNIT (TREE_TYPE (inner));
2742*4c3eb207Smrg }
2743*4c3eb207Smrg
2744*4c3eb207Smrg OMP_CLAUSE_DECL (node)
2745*4c3eb207Smrg = build_fold_indirect_ref (data);
2746*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = size;
2747*4c3eb207Smrg node2 = build_omp_clause (input_location,
2748*4c3eb207Smrg OMP_CLAUSE_MAP);
2749*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node2,
2750*4c3eb207Smrg GOMP_MAP_ATTACH_DETACH);
2751*4c3eb207Smrg OMP_CLAUSE_DECL (node2) = data;
2752*4c3eb207Smrg OMP_CLAUSE_SIZE (node2) = size_int (0);
2753627f7eb2Smrg }
2754627f7eb2Smrg else
2755627f7eb2Smrg {
2756*4c3eb207Smrg OMP_CLAUSE_DECL (node) = inner;
2757627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2758*4c3eb207Smrg = TYPE_SIZE_UNIT (TREE_TYPE (inner));
2759*4c3eb207Smrg }
2760*4c3eb207Smrg }
2761*4c3eb207Smrg else if (lastcomp->next
2762*4c3eb207Smrg && lastcomp->next->type == REF_ARRAY
2763*4c3eb207Smrg && lastcomp->next->u.ar.type == AR_FULL)
2764*4c3eb207Smrg {
2765*4c3eb207Smrg /* Just pass the (auto-dereferenced) decl through for
2766*4c3eb207Smrg bare attach and detach clauses. */
2767*4c3eb207Smrg if (n->u.map_op == OMP_MAP_ATTACH
2768*4c3eb207Smrg || n->u.map_op == OMP_MAP_DETACH)
2769*4c3eb207Smrg {
2770*4c3eb207Smrg OMP_CLAUSE_DECL (node) = inner;
2771*4c3eb207Smrg OMP_CLAUSE_SIZE (node) = size_zero_node;
2772*4c3eb207Smrg goto finalize_map_clause;
2773*4c3eb207Smrg }
2774*4c3eb207Smrg
2775*4c3eb207Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))
2776*4c3eb207Smrg {
2777*4c3eb207Smrg tree type = TREE_TYPE (inner);
2778*4c3eb207Smrg tree ptr = gfc_conv_descriptor_data_get (inner);
2779*4c3eb207Smrg ptr = build_fold_indirect_ref (ptr);
2780*4c3eb207Smrg OMP_CLAUSE_DECL (node) = ptr;
2781*4c3eb207Smrg node2 = build_omp_clause (input_location,
2782*4c3eb207Smrg OMP_CLAUSE_MAP);
2783*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
2784*4c3eb207Smrg OMP_CLAUSE_DECL (node2) = inner;
2785*4c3eb207Smrg OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
2786*4c3eb207Smrg node3 = build_omp_clause (input_location,
2787*4c3eb207Smrg OMP_CLAUSE_MAP);
2788*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node3,
2789*4c3eb207Smrg GOMP_MAP_ATTACH_DETACH);
2790*4c3eb207Smrg OMP_CLAUSE_DECL (node3)
2791*4c3eb207Smrg = gfc_conv_descriptor_data_get (inner);
2792*4c3eb207Smrg STRIP_NOPS (OMP_CLAUSE_DECL (node3));
2793*4c3eb207Smrg OMP_CLAUSE_SIZE (node3) = size_int (0);
2794*4c3eb207Smrg int rank = GFC_TYPE_ARRAY_RANK (type);
2795*4c3eb207Smrg OMP_CLAUSE_SIZE (node)
2796*4c3eb207Smrg = gfc_full_array_size (block, inner, rank);
2797627f7eb2Smrg tree elemsz
2798627f7eb2Smrg = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2799627f7eb2Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
2800627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2801627f7eb2Smrg = fold_build2 (MULT_EXPR, gfc_array_index_type,
2802627f7eb2Smrg OMP_CLAUSE_SIZE (node), elemsz);
2803627f7eb2Smrg }
2804*4c3eb207Smrg else
2805*4c3eb207Smrg OMP_CLAUSE_DECL (node) = inner;
2806*4c3eb207Smrg }
2807*4c3eb207Smrg else /* An array element or section. */
2808*4c3eb207Smrg {
2809*4c3eb207Smrg bool element
2810*4c3eb207Smrg = (lastcomp->next
2811*4c3eb207Smrg && lastcomp->next->type == REF_ARRAY
2812*4c3eb207Smrg && lastcomp->next->u.ar.type == AR_ELEMENT);
2813627f7eb2Smrg
2814*4c3eb207Smrg gfc_trans_omp_array_section (block, n, inner, element,
2815*4c3eb207Smrg GOMP_MAP_ATTACH_DETACH,
2816*4c3eb207Smrg node, node2, node3, node4);
2817*4c3eb207Smrg }
2818*4c3eb207Smrg }
2819*4c3eb207Smrg else /* An array element or array section. */
2820627f7eb2Smrg {
2821*4c3eb207Smrg bool element = n->expr->ref->u.ar.type == AR_ELEMENT;
2822*4c3eb207Smrg gfc_trans_omp_array_section (block, n, decl, element,
2823*4c3eb207Smrg GOMP_MAP_POINTER, node, node2,
2824*4c3eb207Smrg node3, node4);
2825627f7eb2Smrg }
2826*4c3eb207Smrg
2827*4c3eb207Smrg finalize_map_clause:
2828627f7eb2Smrg switch (n->u.map_op)
2829627f7eb2Smrg {
2830627f7eb2Smrg case OMP_MAP_ALLOC:
2831627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
2832627f7eb2Smrg break;
2833*4c3eb207Smrg case OMP_MAP_IF_PRESENT:
2834*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT);
2835*4c3eb207Smrg break;
2836*4c3eb207Smrg case OMP_MAP_ATTACH:
2837*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH);
2838*4c3eb207Smrg break;
2839627f7eb2Smrg case OMP_MAP_TO:
2840627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
2841627f7eb2Smrg break;
2842627f7eb2Smrg case OMP_MAP_FROM:
2843627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
2844627f7eb2Smrg break;
2845627f7eb2Smrg case OMP_MAP_TOFROM:
2846627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
2847627f7eb2Smrg break;
2848627f7eb2Smrg case OMP_MAP_ALWAYS_TO:
2849627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
2850627f7eb2Smrg break;
2851627f7eb2Smrg case OMP_MAP_ALWAYS_FROM:
2852627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
2853627f7eb2Smrg break;
2854627f7eb2Smrg case OMP_MAP_ALWAYS_TOFROM:
2855627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
2856627f7eb2Smrg break;
2857627f7eb2Smrg case OMP_MAP_RELEASE:
2858627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
2859627f7eb2Smrg break;
2860627f7eb2Smrg case OMP_MAP_DELETE:
2861627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
2862627f7eb2Smrg break;
2863*4c3eb207Smrg case OMP_MAP_DETACH:
2864*4c3eb207Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH);
2865*4c3eb207Smrg break;
2866627f7eb2Smrg case OMP_MAP_FORCE_ALLOC:
2867627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
2868627f7eb2Smrg break;
2869627f7eb2Smrg case OMP_MAP_FORCE_TO:
2870627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
2871627f7eb2Smrg break;
2872627f7eb2Smrg case OMP_MAP_FORCE_FROM:
2873627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
2874627f7eb2Smrg break;
2875627f7eb2Smrg case OMP_MAP_FORCE_TOFROM:
2876627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
2877627f7eb2Smrg break;
2878627f7eb2Smrg case OMP_MAP_FORCE_PRESENT:
2879627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
2880627f7eb2Smrg break;
2881627f7eb2Smrg case OMP_MAP_FORCE_DEVICEPTR:
2882627f7eb2Smrg OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
2883627f7eb2Smrg break;
2884627f7eb2Smrg default:
2885627f7eb2Smrg gcc_unreachable ();
2886627f7eb2Smrg }
2887627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2888627f7eb2Smrg if (node2)
2889627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
2890627f7eb2Smrg if (node3)
2891627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
2892627f7eb2Smrg if (node4)
2893627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
2894627f7eb2Smrg }
2895627f7eb2Smrg break;
2896627f7eb2Smrg case OMP_LIST_TO:
2897627f7eb2Smrg case OMP_LIST_FROM:
2898627f7eb2Smrg case OMP_LIST_CACHE:
2899627f7eb2Smrg for (; n != NULL; n = n->next)
2900627f7eb2Smrg {
2901627f7eb2Smrg if (!n->sym->attr.referenced)
2902627f7eb2Smrg continue;
2903627f7eb2Smrg
2904627f7eb2Smrg switch (list)
2905627f7eb2Smrg {
2906627f7eb2Smrg case OMP_LIST_TO:
2907627f7eb2Smrg clause_code = OMP_CLAUSE_TO;
2908627f7eb2Smrg break;
2909627f7eb2Smrg case OMP_LIST_FROM:
2910627f7eb2Smrg clause_code = OMP_CLAUSE_FROM;
2911627f7eb2Smrg break;
2912627f7eb2Smrg case OMP_LIST_CACHE:
2913627f7eb2Smrg clause_code = OMP_CLAUSE__CACHE_;
2914627f7eb2Smrg break;
2915627f7eb2Smrg default:
2916627f7eb2Smrg gcc_unreachable ();
2917627f7eb2Smrg }
2918627f7eb2Smrg tree node = build_omp_clause (input_location, clause_code);
2919627f7eb2Smrg if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
2920627f7eb2Smrg {
2921*4c3eb207Smrg tree decl = gfc_trans_omp_variable (n->sym, false);
2922627f7eb2Smrg if (gfc_omp_privatize_by_reference (decl))
2923*4c3eb207Smrg {
2924*4c3eb207Smrg if (gfc_omp_is_allocatable_or_ptr (decl))
2925627f7eb2Smrg decl = build_fold_indirect_ref (decl);
2926*4c3eb207Smrg decl = build_fold_indirect_ref (decl);
2927*4c3eb207Smrg }
2928627f7eb2Smrg else if (DECL_P (decl))
2929627f7eb2Smrg TREE_ADDRESSABLE (decl) = 1;
2930627f7eb2Smrg if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
2931627f7eb2Smrg {
2932627f7eb2Smrg tree type = TREE_TYPE (decl);
2933627f7eb2Smrg tree ptr = gfc_conv_descriptor_data_get (decl);
2934627f7eb2Smrg ptr = fold_convert (build_pointer_type (char_type_node),
2935627f7eb2Smrg ptr);
2936627f7eb2Smrg ptr = build_fold_indirect_ref (ptr);
2937627f7eb2Smrg OMP_CLAUSE_DECL (node) = ptr;
2938627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2939627f7eb2Smrg = gfc_full_array_size (block, decl,
2940627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
2941627f7eb2Smrg tree elemsz
2942627f7eb2Smrg = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2943627f7eb2Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
2944627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2945627f7eb2Smrg = fold_build2 (MULT_EXPR, gfc_array_index_type,
2946627f7eb2Smrg OMP_CLAUSE_SIZE (node), elemsz);
2947627f7eb2Smrg }
2948627f7eb2Smrg else
2949*4c3eb207Smrg {
2950627f7eb2Smrg OMP_CLAUSE_DECL (node) = decl;
2951*4c3eb207Smrg if (gfc_omp_is_allocatable_or_ptr (decl))
2952*4c3eb207Smrg OMP_CLAUSE_SIZE (node)
2953*4c3eb207Smrg = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
2954*4c3eb207Smrg }
2955627f7eb2Smrg }
2956627f7eb2Smrg else
2957627f7eb2Smrg {
2958627f7eb2Smrg tree ptr;
2959627f7eb2Smrg gfc_init_se (&se, NULL);
2960627f7eb2Smrg if (n->expr->ref->u.ar.type == AR_ELEMENT)
2961627f7eb2Smrg {
2962627f7eb2Smrg gfc_conv_expr_reference (&se, n->expr);
2963627f7eb2Smrg ptr = se.expr;
2964627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2965627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2966627f7eb2Smrg = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
2967627f7eb2Smrg }
2968627f7eb2Smrg else
2969627f7eb2Smrg {
2970627f7eb2Smrg gfc_conv_expr_descriptor (&se, n->expr);
2971627f7eb2Smrg ptr = gfc_conv_array_data (se.expr);
2972627f7eb2Smrg tree type = TREE_TYPE (se.expr);
2973627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
2974627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2975627f7eb2Smrg = gfc_full_array_size (block, se.expr,
2976627f7eb2Smrg GFC_TYPE_ARRAY_RANK (type));
2977627f7eb2Smrg tree elemsz
2978627f7eb2Smrg = TYPE_SIZE_UNIT (gfc_get_element_type (type));
2979627f7eb2Smrg elemsz = fold_convert (gfc_array_index_type, elemsz);
2980627f7eb2Smrg OMP_CLAUSE_SIZE (node)
2981627f7eb2Smrg = fold_build2 (MULT_EXPR, gfc_array_index_type,
2982627f7eb2Smrg OMP_CLAUSE_SIZE (node), elemsz);
2983627f7eb2Smrg }
2984627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
2985627f7eb2Smrg ptr = fold_convert (build_pointer_type (char_type_node),
2986627f7eb2Smrg ptr);
2987627f7eb2Smrg OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
2988627f7eb2Smrg }
2989627f7eb2Smrg omp_clauses = gfc_trans_add_clause (node, omp_clauses);
2990627f7eb2Smrg }
2991627f7eb2Smrg break;
2992627f7eb2Smrg default:
2993627f7eb2Smrg break;
2994627f7eb2Smrg }
2995627f7eb2Smrg }
2996627f7eb2Smrg
2997627f7eb2Smrg if (clauses->if_expr)
2998627f7eb2Smrg {
2999627f7eb2Smrg tree if_var;
3000627f7eb2Smrg
3001627f7eb2Smrg gfc_init_se (&se, NULL);
3002627f7eb2Smrg gfc_conv_expr (&se, clauses->if_expr);
3003627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3004627f7eb2Smrg if_var = gfc_evaluate_now (se.expr, block);
3005627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3006627f7eb2Smrg
3007*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3008627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK;
3009627f7eb2Smrg OMP_CLAUSE_IF_EXPR (c) = if_var;
3010627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3011627f7eb2Smrg }
3012627f7eb2Smrg for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
3013627f7eb2Smrg if (clauses->if_exprs[ifc])
3014627f7eb2Smrg {
3015627f7eb2Smrg tree if_var;
3016627f7eb2Smrg
3017627f7eb2Smrg gfc_init_se (&se, NULL);
3018627f7eb2Smrg gfc_conv_expr (&se, clauses->if_exprs[ifc]);
3019627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3020627f7eb2Smrg if_var = gfc_evaluate_now (se.expr, block);
3021627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3022627f7eb2Smrg
3023*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF);
3024627f7eb2Smrg switch (ifc)
3025627f7eb2Smrg {
3026627f7eb2Smrg case OMP_IF_PARALLEL:
3027627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
3028627f7eb2Smrg break;
3029627f7eb2Smrg case OMP_IF_TASK:
3030627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
3031627f7eb2Smrg break;
3032627f7eb2Smrg case OMP_IF_TASKLOOP:
3033627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
3034627f7eb2Smrg break;
3035627f7eb2Smrg case OMP_IF_TARGET:
3036627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
3037627f7eb2Smrg break;
3038627f7eb2Smrg case OMP_IF_TARGET_DATA:
3039627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
3040627f7eb2Smrg break;
3041627f7eb2Smrg case OMP_IF_TARGET_UPDATE:
3042627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
3043627f7eb2Smrg break;
3044627f7eb2Smrg case OMP_IF_TARGET_ENTER_DATA:
3045627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
3046627f7eb2Smrg break;
3047627f7eb2Smrg case OMP_IF_TARGET_EXIT_DATA:
3048627f7eb2Smrg OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
3049627f7eb2Smrg break;
3050627f7eb2Smrg default:
3051627f7eb2Smrg gcc_unreachable ();
3052627f7eb2Smrg }
3053627f7eb2Smrg OMP_CLAUSE_IF_EXPR (c) = if_var;
3054627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3055627f7eb2Smrg }
3056627f7eb2Smrg
3057627f7eb2Smrg if (clauses->final_expr)
3058627f7eb2Smrg {
3059627f7eb2Smrg tree final_var;
3060627f7eb2Smrg
3061627f7eb2Smrg gfc_init_se (&se, NULL);
3062627f7eb2Smrg gfc_conv_expr (&se, clauses->final_expr);
3063627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3064627f7eb2Smrg final_var = gfc_evaluate_now (se.expr, block);
3065627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3066627f7eb2Smrg
3067*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL);
3068627f7eb2Smrg OMP_CLAUSE_FINAL_EXPR (c) = final_var;
3069627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3070627f7eb2Smrg }
3071627f7eb2Smrg
3072627f7eb2Smrg if (clauses->num_threads)
3073627f7eb2Smrg {
3074627f7eb2Smrg tree num_threads;
3075627f7eb2Smrg
3076627f7eb2Smrg gfc_init_se (&se, NULL);
3077627f7eb2Smrg gfc_conv_expr (&se, clauses->num_threads);
3078627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3079627f7eb2Smrg num_threads = gfc_evaluate_now (se.expr, block);
3080627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3081627f7eb2Smrg
3082*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS);
3083627f7eb2Smrg OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
3084627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3085627f7eb2Smrg }
3086627f7eb2Smrg
3087627f7eb2Smrg chunk_size = NULL_TREE;
3088627f7eb2Smrg if (clauses->chunk_size)
3089627f7eb2Smrg {
3090627f7eb2Smrg gfc_init_se (&se, NULL);
3091627f7eb2Smrg gfc_conv_expr (&se, clauses->chunk_size);
3092627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3093627f7eb2Smrg chunk_size = gfc_evaluate_now (se.expr, block);
3094627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3095627f7eb2Smrg }
3096627f7eb2Smrg
3097627f7eb2Smrg if (clauses->sched_kind != OMP_SCHED_NONE)
3098627f7eb2Smrg {
3099*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE);
3100627f7eb2Smrg OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3101627f7eb2Smrg switch (clauses->sched_kind)
3102627f7eb2Smrg {
3103627f7eb2Smrg case OMP_SCHED_STATIC:
3104627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
3105627f7eb2Smrg break;
3106627f7eb2Smrg case OMP_SCHED_DYNAMIC:
3107627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
3108627f7eb2Smrg break;
3109627f7eb2Smrg case OMP_SCHED_GUIDED:
3110627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
3111627f7eb2Smrg break;
3112627f7eb2Smrg case OMP_SCHED_RUNTIME:
3113627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
3114627f7eb2Smrg break;
3115627f7eb2Smrg case OMP_SCHED_AUTO:
3116627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
3117627f7eb2Smrg break;
3118627f7eb2Smrg default:
3119627f7eb2Smrg gcc_unreachable ();
3120627f7eb2Smrg }
3121627f7eb2Smrg if (clauses->sched_monotonic)
3122627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c)
3123627f7eb2Smrg = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3124627f7eb2Smrg | OMP_CLAUSE_SCHEDULE_MONOTONIC);
3125627f7eb2Smrg else if (clauses->sched_nonmonotonic)
3126627f7eb2Smrg OMP_CLAUSE_SCHEDULE_KIND (c)
3127627f7eb2Smrg = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
3128627f7eb2Smrg | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
3129627f7eb2Smrg if (clauses->sched_simd)
3130627f7eb2Smrg OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
3131627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3132627f7eb2Smrg }
3133627f7eb2Smrg
3134627f7eb2Smrg if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
3135627f7eb2Smrg {
3136*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT);
3137627f7eb2Smrg switch (clauses->default_sharing)
3138627f7eb2Smrg {
3139627f7eb2Smrg case OMP_DEFAULT_NONE:
3140627f7eb2Smrg OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
3141627f7eb2Smrg break;
3142627f7eb2Smrg case OMP_DEFAULT_SHARED:
3143627f7eb2Smrg OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
3144627f7eb2Smrg break;
3145627f7eb2Smrg case OMP_DEFAULT_PRIVATE:
3146627f7eb2Smrg OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
3147627f7eb2Smrg break;
3148627f7eb2Smrg case OMP_DEFAULT_FIRSTPRIVATE:
3149627f7eb2Smrg OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
3150627f7eb2Smrg break;
3151627f7eb2Smrg case OMP_DEFAULT_PRESENT:
3152627f7eb2Smrg OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT;
3153627f7eb2Smrg break;
3154627f7eb2Smrg default:
3155627f7eb2Smrg gcc_unreachable ();
3156627f7eb2Smrg }
3157627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3158627f7eb2Smrg }
3159627f7eb2Smrg
3160627f7eb2Smrg if (clauses->nowait)
3161627f7eb2Smrg {
3162*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT);
3163627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3164627f7eb2Smrg }
3165627f7eb2Smrg
3166627f7eb2Smrg if (clauses->ordered)
3167627f7eb2Smrg {
3168*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED);
3169627f7eb2Smrg OMP_CLAUSE_ORDERED_EXPR (c)
3170627f7eb2Smrg = clauses->orderedc ? build_int_cst (integer_type_node,
3171627f7eb2Smrg clauses->orderedc) : NULL_TREE;
3172627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3173627f7eb2Smrg }
3174627f7eb2Smrg
3175627f7eb2Smrg if (clauses->untied)
3176627f7eb2Smrg {
3177*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED);
3178627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3179627f7eb2Smrg }
3180627f7eb2Smrg
3181627f7eb2Smrg if (clauses->mergeable)
3182627f7eb2Smrg {
3183*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE);
3184627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3185627f7eb2Smrg }
3186627f7eb2Smrg
3187627f7eb2Smrg if (clauses->collapse)
3188627f7eb2Smrg {
3189*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE);
3190627f7eb2Smrg OMP_CLAUSE_COLLAPSE_EXPR (c)
3191627f7eb2Smrg = build_int_cst (integer_type_node, clauses->collapse);
3192627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3193627f7eb2Smrg }
3194627f7eb2Smrg
3195627f7eb2Smrg if (clauses->inbranch)
3196627f7eb2Smrg {
3197*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH);
3198627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3199627f7eb2Smrg }
3200627f7eb2Smrg
3201627f7eb2Smrg if (clauses->notinbranch)
3202627f7eb2Smrg {
3203*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH);
3204627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3205627f7eb2Smrg }
3206627f7eb2Smrg
3207627f7eb2Smrg switch (clauses->cancel)
3208627f7eb2Smrg {
3209627f7eb2Smrg case OMP_CANCEL_UNKNOWN:
3210627f7eb2Smrg break;
3211627f7eb2Smrg case OMP_CANCEL_PARALLEL:
3212*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL);
3213627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3214627f7eb2Smrg break;
3215627f7eb2Smrg case OMP_CANCEL_SECTIONS:
3216*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS);
3217627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3218627f7eb2Smrg break;
3219627f7eb2Smrg case OMP_CANCEL_DO:
3220*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR);
3221627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3222627f7eb2Smrg break;
3223627f7eb2Smrg case OMP_CANCEL_TASKGROUP:
3224*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP);
3225627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3226627f7eb2Smrg break;
3227627f7eb2Smrg }
3228627f7eb2Smrg
3229627f7eb2Smrg if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
3230627f7eb2Smrg {
3231*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND);
3232627f7eb2Smrg switch (clauses->proc_bind)
3233627f7eb2Smrg {
3234627f7eb2Smrg case OMP_PROC_BIND_MASTER:
3235627f7eb2Smrg OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
3236627f7eb2Smrg break;
3237627f7eb2Smrg case OMP_PROC_BIND_SPREAD:
3238627f7eb2Smrg OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
3239627f7eb2Smrg break;
3240627f7eb2Smrg case OMP_PROC_BIND_CLOSE:
3241627f7eb2Smrg OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
3242627f7eb2Smrg break;
3243627f7eb2Smrg default:
3244627f7eb2Smrg gcc_unreachable ();
3245627f7eb2Smrg }
3246627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3247627f7eb2Smrg }
3248627f7eb2Smrg
3249627f7eb2Smrg if (clauses->safelen_expr)
3250627f7eb2Smrg {
3251627f7eb2Smrg tree safelen_var;
3252627f7eb2Smrg
3253627f7eb2Smrg gfc_init_se (&se, NULL);
3254627f7eb2Smrg gfc_conv_expr (&se, clauses->safelen_expr);
3255627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3256627f7eb2Smrg safelen_var = gfc_evaluate_now (se.expr, block);
3257627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3258627f7eb2Smrg
3259*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN);
3260627f7eb2Smrg OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
3261627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3262627f7eb2Smrg }
3263627f7eb2Smrg
3264627f7eb2Smrg if (clauses->simdlen_expr)
3265627f7eb2Smrg {
3266627f7eb2Smrg if (declare_simd)
3267627f7eb2Smrg {
3268*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3269627f7eb2Smrg OMP_CLAUSE_SIMDLEN_EXPR (c)
3270627f7eb2Smrg = gfc_conv_constant_to_tree (clauses->simdlen_expr);
3271627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3272627f7eb2Smrg }
3273627f7eb2Smrg else
3274627f7eb2Smrg {
3275627f7eb2Smrg tree simdlen_var;
3276627f7eb2Smrg
3277627f7eb2Smrg gfc_init_se (&se, NULL);
3278627f7eb2Smrg gfc_conv_expr (&se, clauses->simdlen_expr);
3279627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3280627f7eb2Smrg simdlen_var = gfc_evaluate_now (se.expr, block);
3281627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3282627f7eb2Smrg
3283*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN);
3284627f7eb2Smrg OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
3285627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3286627f7eb2Smrg }
3287627f7eb2Smrg }
3288627f7eb2Smrg
3289627f7eb2Smrg if (clauses->num_teams)
3290627f7eb2Smrg {
3291627f7eb2Smrg tree num_teams;
3292627f7eb2Smrg
3293627f7eb2Smrg gfc_init_se (&se, NULL);
3294627f7eb2Smrg gfc_conv_expr (&se, clauses->num_teams);
3295627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3296627f7eb2Smrg num_teams = gfc_evaluate_now (se.expr, block);
3297627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3298627f7eb2Smrg
3299*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS);
3300627f7eb2Smrg OMP_CLAUSE_NUM_TEAMS_EXPR (c) = num_teams;
3301627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3302627f7eb2Smrg }
3303627f7eb2Smrg
3304627f7eb2Smrg if (clauses->device)
3305627f7eb2Smrg {
3306627f7eb2Smrg tree device;
3307627f7eb2Smrg
3308627f7eb2Smrg gfc_init_se (&se, NULL);
3309627f7eb2Smrg gfc_conv_expr (&se, clauses->device);
3310627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3311627f7eb2Smrg device = gfc_evaluate_now (se.expr, block);
3312627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3313627f7eb2Smrg
3314*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE);
3315627f7eb2Smrg OMP_CLAUSE_DEVICE_ID (c) = device;
3316627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3317627f7eb2Smrg }
3318627f7eb2Smrg
3319627f7eb2Smrg if (clauses->thread_limit)
3320627f7eb2Smrg {
3321627f7eb2Smrg tree thread_limit;
3322627f7eb2Smrg
3323627f7eb2Smrg gfc_init_se (&se, NULL);
3324627f7eb2Smrg gfc_conv_expr (&se, clauses->thread_limit);
3325627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3326627f7eb2Smrg thread_limit = gfc_evaluate_now (se.expr, block);
3327627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3328627f7eb2Smrg
3329*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT);
3330627f7eb2Smrg OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
3331627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3332627f7eb2Smrg }
3333627f7eb2Smrg
3334627f7eb2Smrg chunk_size = NULL_TREE;
3335627f7eb2Smrg if (clauses->dist_chunk_size)
3336627f7eb2Smrg {
3337627f7eb2Smrg gfc_init_se (&se, NULL);
3338627f7eb2Smrg gfc_conv_expr (&se, clauses->dist_chunk_size);
3339627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3340627f7eb2Smrg chunk_size = gfc_evaluate_now (se.expr, block);
3341627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3342627f7eb2Smrg }
3343627f7eb2Smrg
3344627f7eb2Smrg if (clauses->dist_sched_kind != OMP_SCHED_NONE)
3345627f7eb2Smrg {
3346*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where),
3347*4c3eb207Smrg OMP_CLAUSE_DIST_SCHEDULE);
3348627f7eb2Smrg OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
3349627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3350627f7eb2Smrg }
3351627f7eb2Smrg
3352627f7eb2Smrg if (clauses->grainsize)
3353627f7eb2Smrg {
3354627f7eb2Smrg tree grainsize;
3355627f7eb2Smrg
3356627f7eb2Smrg gfc_init_se (&se, NULL);
3357627f7eb2Smrg gfc_conv_expr (&se, clauses->grainsize);
3358627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3359627f7eb2Smrg grainsize = gfc_evaluate_now (se.expr, block);
3360627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3361627f7eb2Smrg
3362*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE);
3363627f7eb2Smrg OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
3364627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3365627f7eb2Smrg }
3366627f7eb2Smrg
3367627f7eb2Smrg if (clauses->num_tasks)
3368627f7eb2Smrg {
3369627f7eb2Smrg tree num_tasks;
3370627f7eb2Smrg
3371627f7eb2Smrg gfc_init_se (&se, NULL);
3372627f7eb2Smrg gfc_conv_expr (&se, clauses->num_tasks);
3373627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3374627f7eb2Smrg num_tasks = gfc_evaluate_now (se.expr, block);
3375627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3376627f7eb2Smrg
3377*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS);
3378627f7eb2Smrg OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
3379627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3380627f7eb2Smrg }
3381627f7eb2Smrg
3382627f7eb2Smrg if (clauses->priority)
3383627f7eb2Smrg {
3384627f7eb2Smrg tree priority;
3385627f7eb2Smrg
3386627f7eb2Smrg gfc_init_se (&se, NULL);
3387627f7eb2Smrg gfc_conv_expr (&se, clauses->priority);
3388627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3389627f7eb2Smrg priority = gfc_evaluate_now (se.expr, block);
3390627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3391627f7eb2Smrg
3392*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY);
3393627f7eb2Smrg OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
3394627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3395627f7eb2Smrg }
3396627f7eb2Smrg
3397627f7eb2Smrg if (clauses->hint)
3398627f7eb2Smrg {
3399627f7eb2Smrg tree hint;
3400627f7eb2Smrg
3401627f7eb2Smrg gfc_init_se (&se, NULL);
3402627f7eb2Smrg gfc_conv_expr (&se, clauses->hint);
3403627f7eb2Smrg gfc_add_block_to_block (block, &se.pre);
3404627f7eb2Smrg hint = gfc_evaluate_now (se.expr, block);
3405627f7eb2Smrg gfc_add_block_to_block (block, &se.post);
3406627f7eb2Smrg
3407*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT);
3408627f7eb2Smrg OMP_CLAUSE_HINT_EXPR (c) = hint;
3409627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3410627f7eb2Smrg }
3411627f7eb2Smrg
3412627f7eb2Smrg if (clauses->simd)
3413627f7eb2Smrg {
3414*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD);
3415627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3416627f7eb2Smrg }
3417627f7eb2Smrg if (clauses->threads)
3418627f7eb2Smrg {
3419*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS);
3420627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3421627f7eb2Smrg }
3422627f7eb2Smrg if (clauses->nogroup)
3423627f7eb2Smrg {
3424*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP);
3425627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3426627f7eb2Smrg }
3427627f7eb2Smrg if (clauses->defaultmap)
3428627f7eb2Smrg {
3429*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP);
3430627f7eb2Smrg OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, OMP_CLAUSE_DEFAULTMAP_TOFROM,
3431627f7eb2Smrg OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR);
3432627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3433627f7eb2Smrg }
3434627f7eb2Smrg if (clauses->depend_source)
3435627f7eb2Smrg {
3436*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEPEND);
3437627f7eb2Smrg OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
3438627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3439627f7eb2Smrg }
3440627f7eb2Smrg
3441627f7eb2Smrg if (clauses->async)
3442627f7eb2Smrg {
3443*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC);
3444627f7eb2Smrg if (clauses->async_expr)
3445627f7eb2Smrg OMP_CLAUSE_ASYNC_EXPR (c)
3446627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->async_expr);
3447627f7eb2Smrg else
3448627f7eb2Smrg OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
3449627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3450627f7eb2Smrg }
3451627f7eb2Smrg if (clauses->seq)
3452627f7eb2Smrg {
3453*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ);
3454627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3455627f7eb2Smrg }
3456627f7eb2Smrg if (clauses->par_auto)
3457627f7eb2Smrg {
3458*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO);
3459627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3460627f7eb2Smrg }
3461627f7eb2Smrg if (clauses->if_present)
3462627f7eb2Smrg {
3463*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT);
3464627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3465627f7eb2Smrg }
3466627f7eb2Smrg if (clauses->finalize)
3467627f7eb2Smrg {
3468*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE);
3469627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3470627f7eb2Smrg }
3471627f7eb2Smrg if (clauses->independent)
3472627f7eb2Smrg {
3473*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT);
3474627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3475627f7eb2Smrg }
3476627f7eb2Smrg if (clauses->wait_list)
3477627f7eb2Smrg {
3478627f7eb2Smrg gfc_expr_list *el;
3479627f7eb2Smrg
3480627f7eb2Smrg for (el = clauses->wait_list; el; el = el->next)
3481627f7eb2Smrg {
3482*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT);
3483627f7eb2Smrg OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
3484627f7eb2Smrg OMP_CLAUSE_CHAIN (c) = omp_clauses;
3485627f7eb2Smrg omp_clauses = c;
3486627f7eb2Smrg }
3487627f7eb2Smrg }
3488627f7eb2Smrg if (clauses->num_gangs_expr)
3489627f7eb2Smrg {
3490627f7eb2Smrg tree num_gangs_var
3491627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
3492*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS);
3493627f7eb2Smrg OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
3494627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3495627f7eb2Smrg }
3496627f7eb2Smrg if (clauses->num_workers_expr)
3497627f7eb2Smrg {
3498627f7eb2Smrg tree num_workers_var
3499627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
3500*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS);
3501627f7eb2Smrg OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
3502627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3503627f7eb2Smrg }
3504627f7eb2Smrg if (clauses->vector_length_expr)
3505627f7eb2Smrg {
3506627f7eb2Smrg tree vector_length_var
3507627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
3508*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH);
3509627f7eb2Smrg OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
3510627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3511627f7eb2Smrg }
3512627f7eb2Smrg if (clauses->tile_list)
3513627f7eb2Smrg {
3514627f7eb2Smrg vec<tree, va_gc> *tvec;
3515627f7eb2Smrg gfc_expr_list *el;
3516627f7eb2Smrg
3517627f7eb2Smrg vec_alloc (tvec, 4);
3518627f7eb2Smrg
3519627f7eb2Smrg for (el = clauses->tile_list; el; el = el->next)
3520627f7eb2Smrg vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr));
3521627f7eb2Smrg
3522*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE);
3523627f7eb2Smrg OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec);
3524627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3525627f7eb2Smrg tvec->truncate (0);
3526627f7eb2Smrg }
3527627f7eb2Smrg if (clauses->vector)
3528627f7eb2Smrg {
3529*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR);
3530*4c3eb207Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3531*4c3eb207Smrg
3532627f7eb2Smrg if (clauses->vector_expr)
3533627f7eb2Smrg {
3534627f7eb2Smrg tree vector_var
3535627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->vector_expr);
3536627f7eb2Smrg OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
3537*4c3eb207Smrg
3538*4c3eb207Smrg /* TODO: We're not capturing location information for individual
3539*4c3eb207Smrg clauses. However, if we have an expression attached to the
3540*4c3eb207Smrg clause, that one provides better location information. */
3541*4c3eb207Smrg OMP_CLAUSE_LOCATION (c)
3542*4c3eb207Smrg = gfc_get_location (&clauses->vector_expr->where);
3543627f7eb2Smrg }
3544627f7eb2Smrg }
3545627f7eb2Smrg if (clauses->worker)
3546627f7eb2Smrg {
3547*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER);
3548*4c3eb207Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3549*4c3eb207Smrg
3550627f7eb2Smrg if (clauses->worker_expr)
3551627f7eb2Smrg {
3552627f7eb2Smrg tree worker_var
3553627f7eb2Smrg = gfc_convert_expr_to_tree (block, clauses->worker_expr);
3554627f7eb2Smrg OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
3555*4c3eb207Smrg
3556*4c3eb207Smrg /* TODO: We're not capturing location information for individual
3557*4c3eb207Smrg clauses. However, if we have an expression attached to the
3558*4c3eb207Smrg clause, that one provides better location information. */
3559*4c3eb207Smrg OMP_CLAUSE_LOCATION (c)
3560*4c3eb207Smrg = gfc_get_location (&clauses->worker_expr->where);
3561627f7eb2Smrg }
3562627f7eb2Smrg }
3563627f7eb2Smrg if (clauses->gang)
3564627f7eb2Smrg {
3565627f7eb2Smrg tree arg;
3566*4c3eb207Smrg c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG);
3567627f7eb2Smrg omp_clauses = gfc_trans_add_clause (c, omp_clauses);
3568*4c3eb207Smrg
3569627f7eb2Smrg if (clauses->gang_num_expr)
3570627f7eb2Smrg {
3571627f7eb2Smrg arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr);
3572627f7eb2Smrg OMP_CLAUSE_GANG_EXPR (c) = arg;
3573*4c3eb207Smrg
3574*4c3eb207Smrg /* TODO: We're not capturing location information for individual
3575*4c3eb207Smrg clauses. However, if we have an expression attached to the
3576*4c3eb207Smrg clause, that one provides better location information. */
3577*4c3eb207Smrg OMP_CLAUSE_LOCATION (c)
3578*4c3eb207Smrg = gfc_get_location (&clauses->gang_num_expr->where);
3579627f7eb2Smrg }
3580*4c3eb207Smrg
3581627f7eb2Smrg if (clauses->gang_static)
3582627f7eb2Smrg {
3583627f7eb2Smrg arg = clauses->gang_static_expr
3584627f7eb2Smrg ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr)
3585627f7eb2Smrg : integer_minus_one_node;
3586627f7eb2Smrg OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg;
3587627f7eb2Smrg }
3588627f7eb2Smrg }
3589627f7eb2Smrg
3590627f7eb2Smrg return nreverse (omp_clauses);
3591627f7eb2Smrg }
3592627f7eb2Smrg
3593627f7eb2Smrg /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
3594627f7eb2Smrg
3595627f7eb2Smrg static tree
gfc_trans_omp_code(gfc_code * code,bool force_empty)3596627f7eb2Smrg gfc_trans_omp_code (gfc_code *code, bool force_empty)
3597627f7eb2Smrg {
3598627f7eb2Smrg tree stmt;
3599627f7eb2Smrg
3600627f7eb2Smrg pushlevel ();
3601627f7eb2Smrg stmt = gfc_trans_code (code);
3602627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
3603627f7eb2Smrg {
3604627f7eb2Smrg if (!IS_EMPTY_STMT (stmt) || force_empty)
3605627f7eb2Smrg {
3606627f7eb2Smrg tree block = poplevel (1, 0);
3607627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, block);
3608627f7eb2Smrg }
3609627f7eb2Smrg else
3610627f7eb2Smrg poplevel (0, 0);
3611627f7eb2Smrg }
3612627f7eb2Smrg else
3613627f7eb2Smrg poplevel (0, 0);
3614627f7eb2Smrg return stmt;
3615627f7eb2Smrg }
3616627f7eb2Smrg
3617*4c3eb207Smrg /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data'
3618*4c3eb207Smrg construct. */
3619*4c3eb207Smrg
3620627f7eb2Smrg static tree
gfc_trans_oacc_construct(gfc_code * code)3621627f7eb2Smrg gfc_trans_oacc_construct (gfc_code *code)
3622627f7eb2Smrg {
3623627f7eb2Smrg stmtblock_t block;
3624627f7eb2Smrg tree stmt, oacc_clauses;
3625627f7eb2Smrg enum tree_code construct_code;
3626627f7eb2Smrg
3627627f7eb2Smrg switch (code->op)
3628627f7eb2Smrg {
3629627f7eb2Smrg case EXEC_OACC_PARALLEL:
3630627f7eb2Smrg construct_code = OACC_PARALLEL;
3631627f7eb2Smrg break;
3632627f7eb2Smrg case EXEC_OACC_KERNELS:
3633627f7eb2Smrg construct_code = OACC_KERNELS;
3634627f7eb2Smrg break;
3635*4c3eb207Smrg case EXEC_OACC_SERIAL:
3636*4c3eb207Smrg construct_code = OACC_SERIAL;
3637*4c3eb207Smrg break;
3638627f7eb2Smrg case EXEC_OACC_DATA:
3639627f7eb2Smrg construct_code = OACC_DATA;
3640627f7eb2Smrg break;
3641627f7eb2Smrg case EXEC_OACC_HOST_DATA:
3642627f7eb2Smrg construct_code = OACC_HOST_DATA;
3643627f7eb2Smrg break;
3644627f7eb2Smrg default:
3645627f7eb2Smrg gcc_unreachable ();
3646627f7eb2Smrg }
3647627f7eb2Smrg
3648627f7eb2Smrg gfc_start_block (&block);
3649627f7eb2Smrg oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3650627f7eb2Smrg code->loc);
3651627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
3652*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), construct_code,
3653*4c3eb207Smrg void_type_node, stmt, oacc_clauses);
3654627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
3655627f7eb2Smrg return gfc_finish_block (&block);
3656627f7eb2Smrg }
3657627f7eb2Smrg
3658627f7eb2Smrg /* update, enter_data, exit_data, cache. */
3659627f7eb2Smrg static tree
gfc_trans_oacc_executable_directive(gfc_code * code)3660627f7eb2Smrg gfc_trans_oacc_executable_directive (gfc_code *code)
3661627f7eb2Smrg {
3662627f7eb2Smrg stmtblock_t block;
3663627f7eb2Smrg tree stmt, oacc_clauses;
3664627f7eb2Smrg enum tree_code construct_code;
3665627f7eb2Smrg
3666627f7eb2Smrg switch (code->op)
3667627f7eb2Smrg {
3668627f7eb2Smrg case EXEC_OACC_UPDATE:
3669627f7eb2Smrg construct_code = OACC_UPDATE;
3670627f7eb2Smrg break;
3671627f7eb2Smrg case EXEC_OACC_ENTER_DATA:
3672627f7eb2Smrg construct_code = OACC_ENTER_DATA;
3673627f7eb2Smrg break;
3674627f7eb2Smrg case EXEC_OACC_EXIT_DATA:
3675627f7eb2Smrg construct_code = OACC_EXIT_DATA;
3676627f7eb2Smrg break;
3677627f7eb2Smrg case EXEC_OACC_CACHE:
3678627f7eb2Smrg construct_code = OACC_CACHE;
3679627f7eb2Smrg break;
3680627f7eb2Smrg default:
3681627f7eb2Smrg gcc_unreachable ();
3682627f7eb2Smrg }
3683627f7eb2Smrg
3684627f7eb2Smrg gfc_start_block (&block);
3685627f7eb2Smrg oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
3686627f7eb2Smrg code->loc);
3687627f7eb2Smrg stmt = build1_loc (input_location, construct_code, void_type_node,
3688627f7eb2Smrg oacc_clauses);
3689627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
3690627f7eb2Smrg return gfc_finish_block (&block);
3691627f7eb2Smrg }
3692627f7eb2Smrg
3693627f7eb2Smrg static tree
gfc_trans_oacc_wait_directive(gfc_code * code)3694627f7eb2Smrg gfc_trans_oacc_wait_directive (gfc_code *code)
3695627f7eb2Smrg {
3696627f7eb2Smrg stmtblock_t block;
3697627f7eb2Smrg tree stmt, t;
3698627f7eb2Smrg vec<tree, va_gc> *args;
3699627f7eb2Smrg int nparms = 0;
3700627f7eb2Smrg gfc_expr_list *el;
3701627f7eb2Smrg gfc_omp_clauses *clauses = code->ext.omp_clauses;
3702627f7eb2Smrg location_t loc = input_location;
3703627f7eb2Smrg
3704627f7eb2Smrg for (el = clauses->wait_list; el; el = el->next)
3705627f7eb2Smrg nparms++;
3706627f7eb2Smrg
3707627f7eb2Smrg vec_alloc (args, nparms + 2);
3708627f7eb2Smrg stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
3709627f7eb2Smrg
3710627f7eb2Smrg gfc_start_block (&block);
3711627f7eb2Smrg
3712627f7eb2Smrg if (clauses->async_expr)
3713627f7eb2Smrg t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
3714627f7eb2Smrg else
3715627f7eb2Smrg t = build_int_cst (integer_type_node, -2);
3716627f7eb2Smrg
3717627f7eb2Smrg args->quick_push (t);
3718627f7eb2Smrg args->quick_push (build_int_cst (integer_type_node, nparms));
3719627f7eb2Smrg
3720627f7eb2Smrg for (el = clauses->wait_list; el; el = el->next)
3721627f7eb2Smrg args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
3722627f7eb2Smrg
3723627f7eb2Smrg stmt = build_call_expr_loc_vec (loc, stmt, args);
3724627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
3725627f7eb2Smrg
3726627f7eb2Smrg vec_free (args);
3727627f7eb2Smrg
3728627f7eb2Smrg return gfc_finish_block (&block);
3729627f7eb2Smrg }
3730627f7eb2Smrg
3731627f7eb2Smrg static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
3732627f7eb2Smrg static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
3733627f7eb2Smrg
3734627f7eb2Smrg static tree
gfc_trans_omp_atomic(gfc_code * code)3735627f7eb2Smrg gfc_trans_omp_atomic (gfc_code *code)
3736627f7eb2Smrg {
3737627f7eb2Smrg gfc_code *atomic_code = code;
3738627f7eb2Smrg gfc_se lse;
3739627f7eb2Smrg gfc_se rse;
3740627f7eb2Smrg gfc_se vse;
3741627f7eb2Smrg gfc_expr *expr2, *e;
3742627f7eb2Smrg gfc_symbol *var;
3743627f7eb2Smrg stmtblock_t block;
3744627f7eb2Smrg tree lhsaddr, type, rhs, x;
3745627f7eb2Smrg enum tree_code op = ERROR_MARK;
3746627f7eb2Smrg enum tree_code aop = OMP_ATOMIC;
3747627f7eb2Smrg bool var_on_left = false;
3748627f7eb2Smrg enum omp_memory_order mo
3749627f7eb2Smrg = ((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST)
3750627f7eb2Smrg ? OMP_MEMORY_ORDER_SEQ_CST : OMP_MEMORY_ORDER_RELAXED);
3751627f7eb2Smrg
3752627f7eb2Smrg code = code->block->next;
3753627f7eb2Smrg gcc_assert (code->op == EXEC_ASSIGN);
3754627f7eb2Smrg var = code->expr1->symtree->n.sym;
3755627f7eb2Smrg
3756627f7eb2Smrg gfc_init_se (&lse, NULL);
3757627f7eb2Smrg gfc_init_se (&rse, NULL);
3758627f7eb2Smrg gfc_init_se (&vse, NULL);
3759627f7eb2Smrg gfc_start_block (&block);
3760627f7eb2Smrg
3761627f7eb2Smrg expr2 = code->expr2;
3762627f7eb2Smrg if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3763627f7eb2Smrg != GFC_OMP_ATOMIC_WRITE)
3764627f7eb2Smrg && expr2->expr_type == EXPR_FUNCTION
3765627f7eb2Smrg && expr2->value.function.isym
3766627f7eb2Smrg && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3767627f7eb2Smrg expr2 = expr2->value.function.actual->expr;
3768627f7eb2Smrg
3769627f7eb2Smrg switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3770627f7eb2Smrg {
3771627f7eb2Smrg case GFC_OMP_ATOMIC_READ:
3772627f7eb2Smrg gfc_conv_expr (&vse, code->expr1);
3773627f7eb2Smrg gfc_add_block_to_block (&block, &vse.pre);
3774627f7eb2Smrg
3775627f7eb2Smrg gfc_conv_expr (&lse, expr2);
3776627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
3777627f7eb2Smrg type = TREE_TYPE (lse.expr);
3778627f7eb2Smrg lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
3779627f7eb2Smrg
3780627f7eb2Smrg x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
3781627f7eb2Smrg OMP_ATOMIC_MEMORY_ORDER (x) = mo;
3782627f7eb2Smrg x = convert (TREE_TYPE (vse.expr), x);
3783627f7eb2Smrg gfc_add_modify (&block, vse.expr, x);
3784627f7eb2Smrg
3785627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
3786627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3787627f7eb2Smrg
3788627f7eb2Smrg return gfc_finish_block (&block);
3789627f7eb2Smrg case GFC_OMP_ATOMIC_CAPTURE:
3790627f7eb2Smrg aop = OMP_ATOMIC_CAPTURE_NEW;
3791627f7eb2Smrg if (expr2->expr_type == EXPR_VARIABLE)
3792627f7eb2Smrg {
3793627f7eb2Smrg aop = OMP_ATOMIC_CAPTURE_OLD;
3794627f7eb2Smrg gfc_conv_expr (&vse, code->expr1);
3795627f7eb2Smrg gfc_add_block_to_block (&block, &vse.pre);
3796627f7eb2Smrg
3797627f7eb2Smrg gfc_conv_expr (&lse, expr2);
3798627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
3799627f7eb2Smrg gfc_init_se (&lse, NULL);
3800627f7eb2Smrg code = code->next;
3801627f7eb2Smrg var = code->expr1->symtree->n.sym;
3802627f7eb2Smrg expr2 = code->expr2;
3803627f7eb2Smrg if (expr2->expr_type == EXPR_FUNCTION
3804627f7eb2Smrg && expr2->value.function.isym
3805627f7eb2Smrg && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3806627f7eb2Smrg expr2 = expr2->value.function.actual->expr;
3807627f7eb2Smrg }
3808627f7eb2Smrg break;
3809627f7eb2Smrg default:
3810627f7eb2Smrg break;
3811627f7eb2Smrg }
3812627f7eb2Smrg
3813627f7eb2Smrg gfc_conv_expr (&lse, code->expr1);
3814627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
3815627f7eb2Smrg type = TREE_TYPE (lse.expr);
3816627f7eb2Smrg lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
3817627f7eb2Smrg
3818627f7eb2Smrg if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3819627f7eb2Smrg == GFC_OMP_ATOMIC_WRITE)
3820627f7eb2Smrg || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
3821627f7eb2Smrg {
3822627f7eb2Smrg gfc_conv_expr (&rse, expr2);
3823627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3824627f7eb2Smrg }
3825627f7eb2Smrg else if (expr2->expr_type == EXPR_OP)
3826627f7eb2Smrg {
3827627f7eb2Smrg gfc_expr *e;
3828627f7eb2Smrg switch (expr2->value.op.op)
3829627f7eb2Smrg {
3830627f7eb2Smrg case INTRINSIC_PLUS:
3831627f7eb2Smrg op = PLUS_EXPR;
3832627f7eb2Smrg break;
3833627f7eb2Smrg case INTRINSIC_TIMES:
3834627f7eb2Smrg op = MULT_EXPR;
3835627f7eb2Smrg break;
3836627f7eb2Smrg case INTRINSIC_MINUS:
3837627f7eb2Smrg op = MINUS_EXPR;
3838627f7eb2Smrg break;
3839627f7eb2Smrg case INTRINSIC_DIVIDE:
3840627f7eb2Smrg if (expr2->ts.type == BT_INTEGER)
3841627f7eb2Smrg op = TRUNC_DIV_EXPR;
3842627f7eb2Smrg else
3843627f7eb2Smrg op = RDIV_EXPR;
3844627f7eb2Smrg break;
3845627f7eb2Smrg case INTRINSIC_AND:
3846627f7eb2Smrg op = TRUTH_ANDIF_EXPR;
3847627f7eb2Smrg break;
3848627f7eb2Smrg case INTRINSIC_OR:
3849627f7eb2Smrg op = TRUTH_ORIF_EXPR;
3850627f7eb2Smrg break;
3851627f7eb2Smrg case INTRINSIC_EQV:
3852627f7eb2Smrg op = EQ_EXPR;
3853627f7eb2Smrg break;
3854627f7eb2Smrg case INTRINSIC_NEQV:
3855627f7eb2Smrg op = NE_EXPR;
3856627f7eb2Smrg break;
3857627f7eb2Smrg default:
3858627f7eb2Smrg gcc_unreachable ();
3859627f7eb2Smrg }
3860627f7eb2Smrg e = expr2->value.op.op1;
3861627f7eb2Smrg if (e->expr_type == EXPR_FUNCTION
3862627f7eb2Smrg && e->value.function.isym
3863627f7eb2Smrg && e->value.function.isym->id == GFC_ISYM_CONVERSION)
3864627f7eb2Smrg e = e->value.function.actual->expr;
3865627f7eb2Smrg if (e->expr_type == EXPR_VARIABLE
3866627f7eb2Smrg && e->symtree != NULL
3867627f7eb2Smrg && e->symtree->n.sym == var)
3868627f7eb2Smrg {
3869627f7eb2Smrg expr2 = expr2->value.op.op2;
3870627f7eb2Smrg var_on_left = true;
3871627f7eb2Smrg }
3872627f7eb2Smrg else
3873627f7eb2Smrg {
3874627f7eb2Smrg e = expr2->value.op.op2;
3875627f7eb2Smrg if (e->expr_type == EXPR_FUNCTION
3876627f7eb2Smrg && e->value.function.isym
3877627f7eb2Smrg && e->value.function.isym->id == GFC_ISYM_CONVERSION)
3878627f7eb2Smrg e = e->value.function.actual->expr;
3879627f7eb2Smrg gcc_assert (e->expr_type == EXPR_VARIABLE
3880627f7eb2Smrg && e->symtree != NULL
3881627f7eb2Smrg && e->symtree->n.sym == var);
3882627f7eb2Smrg expr2 = expr2->value.op.op1;
3883627f7eb2Smrg var_on_left = false;
3884627f7eb2Smrg }
3885627f7eb2Smrg gfc_conv_expr (&rse, expr2);
3886627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3887627f7eb2Smrg }
3888627f7eb2Smrg else
3889627f7eb2Smrg {
3890627f7eb2Smrg gcc_assert (expr2->expr_type == EXPR_FUNCTION);
3891627f7eb2Smrg switch (expr2->value.function.isym->id)
3892627f7eb2Smrg {
3893627f7eb2Smrg case GFC_ISYM_MIN:
3894627f7eb2Smrg op = MIN_EXPR;
3895627f7eb2Smrg break;
3896627f7eb2Smrg case GFC_ISYM_MAX:
3897627f7eb2Smrg op = MAX_EXPR;
3898627f7eb2Smrg break;
3899627f7eb2Smrg case GFC_ISYM_IAND:
3900627f7eb2Smrg op = BIT_AND_EXPR;
3901627f7eb2Smrg break;
3902627f7eb2Smrg case GFC_ISYM_IOR:
3903627f7eb2Smrg op = BIT_IOR_EXPR;
3904627f7eb2Smrg break;
3905627f7eb2Smrg case GFC_ISYM_IEOR:
3906627f7eb2Smrg op = BIT_XOR_EXPR;
3907627f7eb2Smrg break;
3908627f7eb2Smrg default:
3909627f7eb2Smrg gcc_unreachable ();
3910627f7eb2Smrg }
3911627f7eb2Smrg e = expr2->value.function.actual->expr;
3912627f7eb2Smrg gcc_assert (e->expr_type == EXPR_VARIABLE
3913627f7eb2Smrg && e->symtree != NULL
3914627f7eb2Smrg && e->symtree->n.sym == var);
3915627f7eb2Smrg
3916627f7eb2Smrg gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
3917627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3918627f7eb2Smrg if (expr2->value.function.actual->next->next != NULL)
3919627f7eb2Smrg {
3920627f7eb2Smrg tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
3921627f7eb2Smrg gfc_actual_arglist *arg;
3922627f7eb2Smrg
3923627f7eb2Smrg gfc_add_modify (&block, accum, rse.expr);
3924627f7eb2Smrg for (arg = expr2->value.function.actual->next->next; arg;
3925627f7eb2Smrg arg = arg->next)
3926627f7eb2Smrg {
3927627f7eb2Smrg gfc_init_block (&rse.pre);
3928627f7eb2Smrg gfc_conv_expr (&rse, arg->expr);
3929627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3930627f7eb2Smrg x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
3931627f7eb2Smrg accum, rse.expr);
3932627f7eb2Smrg gfc_add_modify (&block, accum, x);
3933627f7eb2Smrg }
3934627f7eb2Smrg
3935627f7eb2Smrg rse.expr = accum;
3936627f7eb2Smrg }
3937627f7eb2Smrg
3938627f7eb2Smrg expr2 = expr2->value.function.actual->next->expr;
3939627f7eb2Smrg }
3940627f7eb2Smrg
3941627f7eb2Smrg lhsaddr = save_expr (lhsaddr);
3942627f7eb2Smrg if (TREE_CODE (lhsaddr) != SAVE_EXPR
3943627f7eb2Smrg && (TREE_CODE (lhsaddr) != ADDR_EXPR
3944627f7eb2Smrg || !VAR_P (TREE_OPERAND (lhsaddr, 0))))
3945627f7eb2Smrg {
3946627f7eb2Smrg /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
3947627f7eb2Smrg it even after unsharing function body. */
3948627f7eb2Smrg tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
3949627f7eb2Smrg DECL_CONTEXT (var) = current_function_decl;
3950627f7eb2Smrg lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
3951627f7eb2Smrg NULL_TREE, NULL_TREE);
3952627f7eb2Smrg }
3953627f7eb2Smrg
3954627f7eb2Smrg rhs = gfc_evaluate_now (rse.expr, &block);
3955627f7eb2Smrg
3956627f7eb2Smrg if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
3957627f7eb2Smrg == GFC_OMP_ATOMIC_WRITE)
3958627f7eb2Smrg || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
3959627f7eb2Smrg x = rhs;
3960627f7eb2Smrg else
3961627f7eb2Smrg {
3962627f7eb2Smrg x = convert (TREE_TYPE (rhs),
3963627f7eb2Smrg build_fold_indirect_ref_loc (input_location, lhsaddr));
3964627f7eb2Smrg if (var_on_left)
3965627f7eb2Smrg x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
3966627f7eb2Smrg else
3967627f7eb2Smrg x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
3968627f7eb2Smrg }
3969627f7eb2Smrg
3970627f7eb2Smrg if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
3971627f7eb2Smrg && TREE_CODE (type) != COMPLEX_TYPE)
3972627f7eb2Smrg x = fold_build1_loc (input_location, REALPART_EXPR,
3973627f7eb2Smrg TREE_TYPE (TREE_TYPE (rhs)), x);
3974627f7eb2Smrg
3975627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
3976627f7eb2Smrg gfc_add_block_to_block (&block, &rse.pre);
3977627f7eb2Smrg
3978627f7eb2Smrg if (aop == OMP_ATOMIC)
3979627f7eb2Smrg {
3980627f7eb2Smrg x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
3981627f7eb2Smrg OMP_ATOMIC_MEMORY_ORDER (x) = mo;
3982627f7eb2Smrg gfc_add_expr_to_block (&block, x);
3983627f7eb2Smrg }
3984627f7eb2Smrg else
3985627f7eb2Smrg {
3986627f7eb2Smrg if (aop == OMP_ATOMIC_CAPTURE_NEW)
3987627f7eb2Smrg {
3988627f7eb2Smrg code = code->next;
3989627f7eb2Smrg expr2 = code->expr2;
3990627f7eb2Smrg if (expr2->expr_type == EXPR_FUNCTION
3991627f7eb2Smrg && expr2->value.function.isym
3992627f7eb2Smrg && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
3993627f7eb2Smrg expr2 = expr2->value.function.actual->expr;
3994627f7eb2Smrg
3995627f7eb2Smrg gcc_assert (expr2->expr_type == EXPR_VARIABLE);
3996627f7eb2Smrg gfc_conv_expr (&vse, code->expr1);
3997627f7eb2Smrg gfc_add_block_to_block (&block, &vse.pre);
3998627f7eb2Smrg
3999627f7eb2Smrg gfc_init_se (&lse, NULL);
4000627f7eb2Smrg gfc_conv_expr (&lse, expr2);
4001627f7eb2Smrg gfc_add_block_to_block (&block, &lse.pre);
4002627f7eb2Smrg }
4003627f7eb2Smrg x = build2 (aop, type, lhsaddr, convert (type, x));
4004627f7eb2Smrg OMP_ATOMIC_MEMORY_ORDER (x) = mo;
4005627f7eb2Smrg x = convert (TREE_TYPE (vse.expr), x);
4006627f7eb2Smrg gfc_add_modify (&block, vse.expr, x);
4007627f7eb2Smrg }
4008627f7eb2Smrg
4009627f7eb2Smrg return gfc_finish_block (&block);
4010627f7eb2Smrg }
4011627f7eb2Smrg
4012627f7eb2Smrg static tree
gfc_trans_omp_barrier(void)4013627f7eb2Smrg gfc_trans_omp_barrier (void)
4014627f7eb2Smrg {
4015627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
4016627f7eb2Smrg return build_call_expr_loc (input_location, decl, 0);
4017627f7eb2Smrg }
4018627f7eb2Smrg
4019627f7eb2Smrg static tree
gfc_trans_omp_cancel(gfc_code * code)4020627f7eb2Smrg gfc_trans_omp_cancel (gfc_code *code)
4021627f7eb2Smrg {
4022627f7eb2Smrg int mask = 0;
4023627f7eb2Smrg tree ifc = boolean_true_node;
4024627f7eb2Smrg stmtblock_t block;
4025627f7eb2Smrg switch (code->ext.omp_clauses->cancel)
4026627f7eb2Smrg {
4027627f7eb2Smrg case OMP_CANCEL_PARALLEL: mask = 1; break;
4028627f7eb2Smrg case OMP_CANCEL_DO: mask = 2; break;
4029627f7eb2Smrg case OMP_CANCEL_SECTIONS: mask = 4; break;
4030627f7eb2Smrg case OMP_CANCEL_TASKGROUP: mask = 8; break;
4031627f7eb2Smrg default: gcc_unreachable ();
4032627f7eb2Smrg }
4033627f7eb2Smrg gfc_start_block (&block);
4034627f7eb2Smrg if (code->ext.omp_clauses->if_expr)
4035627f7eb2Smrg {
4036627f7eb2Smrg gfc_se se;
4037627f7eb2Smrg tree if_var;
4038627f7eb2Smrg
4039627f7eb2Smrg gfc_init_se (&se, NULL);
4040627f7eb2Smrg gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
4041627f7eb2Smrg gfc_add_block_to_block (&block, &se.pre);
4042627f7eb2Smrg if_var = gfc_evaluate_now (se.expr, &block);
4043627f7eb2Smrg gfc_add_block_to_block (&block, &se.post);
4044627f7eb2Smrg tree type = TREE_TYPE (if_var);
4045627f7eb2Smrg ifc = fold_build2_loc (input_location, NE_EXPR,
4046627f7eb2Smrg boolean_type_node, if_var,
4047627f7eb2Smrg build_zero_cst (type));
4048627f7eb2Smrg }
4049627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
4050627f7eb2Smrg tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
4051627f7eb2Smrg ifc = fold_convert (c_bool_type, ifc);
4052627f7eb2Smrg gfc_add_expr_to_block (&block,
4053627f7eb2Smrg build_call_expr_loc (input_location, decl, 2,
4054627f7eb2Smrg build_int_cst (integer_type_node,
4055627f7eb2Smrg mask), ifc));
4056627f7eb2Smrg return gfc_finish_block (&block);
4057627f7eb2Smrg }
4058627f7eb2Smrg
4059627f7eb2Smrg static tree
gfc_trans_omp_cancellation_point(gfc_code * code)4060627f7eb2Smrg gfc_trans_omp_cancellation_point (gfc_code *code)
4061627f7eb2Smrg {
4062627f7eb2Smrg int mask = 0;
4063627f7eb2Smrg switch (code->ext.omp_clauses->cancel)
4064627f7eb2Smrg {
4065627f7eb2Smrg case OMP_CANCEL_PARALLEL: mask = 1; break;
4066627f7eb2Smrg case OMP_CANCEL_DO: mask = 2; break;
4067627f7eb2Smrg case OMP_CANCEL_SECTIONS: mask = 4; break;
4068627f7eb2Smrg case OMP_CANCEL_TASKGROUP: mask = 8; break;
4069627f7eb2Smrg default: gcc_unreachable ();
4070627f7eb2Smrg }
4071627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
4072627f7eb2Smrg return build_call_expr_loc (input_location, decl, 1,
4073627f7eb2Smrg build_int_cst (integer_type_node, mask));
4074627f7eb2Smrg }
4075627f7eb2Smrg
4076627f7eb2Smrg static tree
gfc_trans_omp_critical(gfc_code * code)4077627f7eb2Smrg gfc_trans_omp_critical (gfc_code *code)
4078627f7eb2Smrg {
4079627f7eb2Smrg tree name = NULL_TREE, stmt;
4080627f7eb2Smrg if (code->ext.omp_clauses != NULL)
4081627f7eb2Smrg name = get_identifier (code->ext.omp_clauses->critical_name);
4082627f7eb2Smrg stmt = gfc_trans_code (code->block->next);
4083627f7eb2Smrg return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
4084627f7eb2Smrg NULL_TREE, name);
4085627f7eb2Smrg }
4086627f7eb2Smrg
4087627f7eb2Smrg typedef struct dovar_init_d {
4088627f7eb2Smrg tree var;
4089627f7eb2Smrg tree init;
4090627f7eb2Smrg } dovar_init;
4091627f7eb2Smrg
4092627f7eb2Smrg
4093627f7eb2Smrg static tree
gfc_trans_omp_do(gfc_code * code,gfc_exec_op op,stmtblock_t * pblock,gfc_omp_clauses * do_clauses,tree par_clauses)4094627f7eb2Smrg gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
4095627f7eb2Smrg gfc_omp_clauses *do_clauses, tree par_clauses)
4096627f7eb2Smrg {
4097627f7eb2Smrg gfc_se se;
4098627f7eb2Smrg tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
4099627f7eb2Smrg tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
4100627f7eb2Smrg stmtblock_t block;
4101627f7eb2Smrg stmtblock_t body;
4102627f7eb2Smrg gfc_omp_clauses *clauses = code->ext.omp_clauses;
4103627f7eb2Smrg int i, collapse = clauses->collapse;
4104627f7eb2Smrg vec<dovar_init> inits = vNULL;
4105627f7eb2Smrg dovar_init *di;
4106627f7eb2Smrg unsigned ix;
4107627f7eb2Smrg vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
4108627f7eb2Smrg gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list;
4109627f7eb2Smrg
4110627f7eb2Smrg /* Both collapsed and tiled loops are lowered the same way. In
4111627f7eb2Smrg OpenACC, those clauses are not compatible, so prioritize the tile
4112627f7eb2Smrg clause, if present. */
4113627f7eb2Smrg if (tile)
4114627f7eb2Smrg {
4115627f7eb2Smrg collapse = 0;
4116627f7eb2Smrg for (gfc_expr_list *el = tile; el; el = el->next)
4117627f7eb2Smrg collapse++;
4118627f7eb2Smrg }
4119627f7eb2Smrg
4120627f7eb2Smrg doacross_steps = NULL;
4121627f7eb2Smrg if (clauses->orderedc)
4122627f7eb2Smrg collapse = clauses->orderedc;
4123627f7eb2Smrg if (collapse <= 0)
4124627f7eb2Smrg collapse = 1;
4125627f7eb2Smrg
4126627f7eb2Smrg code = code->block->next;
4127627f7eb2Smrg gcc_assert (code->op == EXEC_DO);
4128627f7eb2Smrg
4129627f7eb2Smrg init = make_tree_vec (collapse);
4130627f7eb2Smrg cond = make_tree_vec (collapse);
4131627f7eb2Smrg incr = make_tree_vec (collapse);
4132627f7eb2Smrg orig_decls = clauses->orderedc ? make_tree_vec (collapse) : NULL_TREE;
4133627f7eb2Smrg
4134627f7eb2Smrg if (pblock == NULL)
4135627f7eb2Smrg {
4136627f7eb2Smrg gfc_start_block (&block);
4137627f7eb2Smrg pblock = █
4138627f7eb2Smrg }
4139627f7eb2Smrg
4140627f7eb2Smrg /* simd schedule modifier is only useful for composite do simd and other
4141627f7eb2Smrg constructs including that, where gfc_trans_omp_do is only called
4142627f7eb2Smrg on the simd construct and DO's clauses are translated elsewhere. */
4143627f7eb2Smrg do_clauses->sched_simd = false;
4144627f7eb2Smrg
4145627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
4146627f7eb2Smrg
4147627f7eb2Smrg for (i = 0; i < collapse; i++)
4148627f7eb2Smrg {
4149627f7eb2Smrg int simple = 0;
4150627f7eb2Smrg int dovar_found = 0;
4151627f7eb2Smrg tree dovar_decl;
4152627f7eb2Smrg
4153627f7eb2Smrg if (clauses)
4154627f7eb2Smrg {
4155627f7eb2Smrg gfc_omp_namelist *n = NULL;
4156627f7eb2Smrg if (op != EXEC_OMP_DISTRIBUTE)
4157627f7eb2Smrg for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
4158627f7eb2Smrg ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
4159627f7eb2Smrg n != NULL; n = n->next)
4160627f7eb2Smrg if (code->ext.iterator->var->symtree->n.sym == n->sym)
4161627f7eb2Smrg break;
4162627f7eb2Smrg if (n != NULL)
4163627f7eb2Smrg dovar_found = 1;
4164627f7eb2Smrg else if (n == NULL && op != EXEC_OMP_SIMD)
4165627f7eb2Smrg for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
4166627f7eb2Smrg if (code->ext.iterator->var->symtree->n.sym == n->sym)
4167627f7eb2Smrg break;
4168627f7eb2Smrg if (n != NULL)
4169627f7eb2Smrg dovar_found++;
4170627f7eb2Smrg }
4171627f7eb2Smrg
4172627f7eb2Smrg /* Evaluate all the expressions in the iterator. */
4173627f7eb2Smrg gfc_init_se (&se, NULL);
4174627f7eb2Smrg gfc_conv_expr_lhs (&se, code->ext.iterator->var);
4175627f7eb2Smrg gfc_add_block_to_block (pblock, &se.pre);
4176627f7eb2Smrg dovar = se.expr;
4177627f7eb2Smrg type = TREE_TYPE (dovar);
4178627f7eb2Smrg gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
4179627f7eb2Smrg
4180627f7eb2Smrg gfc_init_se (&se, NULL);
4181627f7eb2Smrg gfc_conv_expr_val (&se, code->ext.iterator->start);
4182627f7eb2Smrg gfc_add_block_to_block (pblock, &se.pre);
4183627f7eb2Smrg from = gfc_evaluate_now (se.expr, pblock);
4184627f7eb2Smrg
4185627f7eb2Smrg gfc_init_se (&se, NULL);
4186627f7eb2Smrg gfc_conv_expr_val (&se, code->ext.iterator->end);
4187627f7eb2Smrg gfc_add_block_to_block (pblock, &se.pre);
4188627f7eb2Smrg to = gfc_evaluate_now (se.expr, pblock);
4189627f7eb2Smrg
4190627f7eb2Smrg gfc_init_se (&se, NULL);
4191627f7eb2Smrg gfc_conv_expr_val (&se, code->ext.iterator->step);
4192627f7eb2Smrg gfc_add_block_to_block (pblock, &se.pre);
4193627f7eb2Smrg step = gfc_evaluate_now (se.expr, pblock);
4194627f7eb2Smrg dovar_decl = dovar;
4195627f7eb2Smrg
4196627f7eb2Smrg /* Special case simple loops. */
4197627f7eb2Smrg if (VAR_P (dovar))
4198627f7eb2Smrg {
4199627f7eb2Smrg if (integer_onep (step))
4200627f7eb2Smrg simple = 1;
4201627f7eb2Smrg else if (tree_int_cst_equal (step, integer_minus_one_node))
4202627f7eb2Smrg simple = -1;
4203627f7eb2Smrg }
4204627f7eb2Smrg else
4205627f7eb2Smrg dovar_decl
4206627f7eb2Smrg = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
4207627f7eb2Smrg false);
4208627f7eb2Smrg
4209627f7eb2Smrg /* Loop body. */
4210627f7eb2Smrg if (simple)
4211627f7eb2Smrg {
4212627f7eb2Smrg TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
4213627f7eb2Smrg /* The condition should not be folded. */
4214627f7eb2Smrg TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
4215627f7eb2Smrg ? LE_EXPR : GE_EXPR,
4216627f7eb2Smrg logical_type_node, dovar, to);
4217627f7eb2Smrg TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
4218627f7eb2Smrg type, dovar, step);
4219627f7eb2Smrg TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
4220627f7eb2Smrg MODIFY_EXPR,
4221627f7eb2Smrg type, dovar,
4222627f7eb2Smrg TREE_VEC_ELT (incr, i));
4223627f7eb2Smrg }
4224627f7eb2Smrg else
4225627f7eb2Smrg {
4226627f7eb2Smrg /* STEP is not 1 or -1. Use:
4227627f7eb2Smrg for (count = 0; count < (to + step - from) / step; count++)
4228627f7eb2Smrg {
4229627f7eb2Smrg dovar = from + count * step;
4230627f7eb2Smrg body;
4231627f7eb2Smrg cycle_label:;
4232627f7eb2Smrg } */
4233627f7eb2Smrg tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
4234627f7eb2Smrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
4235627f7eb2Smrg tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
4236627f7eb2Smrg step);
4237627f7eb2Smrg tmp = gfc_evaluate_now (tmp, pblock);
4238627f7eb2Smrg count = gfc_create_var (type, "count");
4239627f7eb2Smrg TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
4240627f7eb2Smrg build_int_cst (type, 0));
4241627f7eb2Smrg /* The condition should not be folded. */
4242627f7eb2Smrg TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
4243627f7eb2Smrg logical_type_node,
4244627f7eb2Smrg count, tmp);
4245627f7eb2Smrg TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
4246627f7eb2Smrg type, count,
4247627f7eb2Smrg build_int_cst (type, 1));
4248627f7eb2Smrg TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
4249627f7eb2Smrg MODIFY_EXPR, type, count,
4250627f7eb2Smrg TREE_VEC_ELT (incr, i));
4251627f7eb2Smrg
4252627f7eb2Smrg /* Initialize DOVAR. */
4253627f7eb2Smrg tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
4254627f7eb2Smrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
4255627f7eb2Smrg dovar_init e = {dovar, tmp};
4256627f7eb2Smrg inits.safe_push (e);
4257627f7eb2Smrg if (clauses->orderedc)
4258627f7eb2Smrg {
4259627f7eb2Smrg if (doacross_steps == NULL)
4260627f7eb2Smrg vec_safe_grow_cleared (doacross_steps, clauses->orderedc);
4261627f7eb2Smrg (*doacross_steps)[i] = step;
4262627f7eb2Smrg }
4263627f7eb2Smrg }
4264627f7eb2Smrg if (orig_decls)
4265627f7eb2Smrg TREE_VEC_ELT (orig_decls, i) = dovar_decl;
4266627f7eb2Smrg
4267627f7eb2Smrg if (dovar_found == 2
4268627f7eb2Smrg && op == EXEC_OMP_SIMD
4269627f7eb2Smrg && collapse == 1
4270627f7eb2Smrg && !simple)
4271627f7eb2Smrg {
4272627f7eb2Smrg for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
4273627f7eb2Smrg if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
4274627f7eb2Smrg && OMP_CLAUSE_DECL (tmp) == dovar)
4275627f7eb2Smrg {
4276627f7eb2Smrg OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4277627f7eb2Smrg break;
4278627f7eb2Smrg }
4279627f7eb2Smrg }
4280627f7eb2Smrg if (!dovar_found)
4281627f7eb2Smrg {
4282627f7eb2Smrg if (op == EXEC_OMP_SIMD)
4283627f7eb2Smrg {
4284627f7eb2Smrg if (collapse == 1)
4285627f7eb2Smrg {
4286627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
4287627f7eb2Smrg OMP_CLAUSE_LINEAR_STEP (tmp) = step;
4288627f7eb2Smrg OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4289627f7eb2Smrg }
4290627f7eb2Smrg else
4291627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
4292627f7eb2Smrg if (!simple)
4293627f7eb2Smrg dovar_found = 2;
4294627f7eb2Smrg }
4295627f7eb2Smrg else
4296627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
4297627f7eb2Smrg OMP_CLAUSE_DECL (tmp) = dovar_decl;
4298627f7eb2Smrg omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
4299627f7eb2Smrg }
4300627f7eb2Smrg if (dovar_found == 2)
4301627f7eb2Smrg {
4302627f7eb2Smrg tree c = NULL;
4303627f7eb2Smrg
4304627f7eb2Smrg tmp = NULL;
4305627f7eb2Smrg if (!simple)
4306627f7eb2Smrg {
4307627f7eb2Smrg /* If dovar is lastprivate, but different counter is used,
4308627f7eb2Smrg dovar += step needs to be added to
4309627f7eb2Smrg OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
4310627f7eb2Smrg will have the value on entry of the last loop, rather
4311627f7eb2Smrg than value after iterator increment. */
4312627f7eb2Smrg if (clauses->orderedc)
4313627f7eb2Smrg {
4314627f7eb2Smrg if (clauses->collapse <= 1 || i >= clauses->collapse)
4315627f7eb2Smrg tmp = count;
4316627f7eb2Smrg else
4317627f7eb2Smrg tmp = fold_build2_loc (input_location, PLUS_EXPR,
4318627f7eb2Smrg type, count, build_one_cst (type));
4319627f7eb2Smrg tmp = fold_build2_loc (input_location, MULT_EXPR, type,
4320627f7eb2Smrg tmp, step);
4321627f7eb2Smrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
4322627f7eb2Smrg from, tmp);
4323627f7eb2Smrg }
4324627f7eb2Smrg else
4325627f7eb2Smrg {
4326627f7eb2Smrg tmp = gfc_evaluate_now (step, pblock);
4327627f7eb2Smrg tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
4328627f7eb2Smrg dovar, tmp);
4329627f7eb2Smrg }
4330627f7eb2Smrg tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
4331627f7eb2Smrg dovar, tmp);
4332627f7eb2Smrg for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4333627f7eb2Smrg if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4334627f7eb2Smrg && OMP_CLAUSE_DECL (c) == dovar_decl)
4335627f7eb2Smrg {
4336627f7eb2Smrg OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
4337627f7eb2Smrg break;
4338627f7eb2Smrg }
4339627f7eb2Smrg else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4340627f7eb2Smrg && OMP_CLAUSE_DECL (c) == dovar_decl)
4341627f7eb2Smrg {
4342627f7eb2Smrg OMP_CLAUSE_LINEAR_STMT (c) = tmp;
4343627f7eb2Smrg break;
4344627f7eb2Smrg }
4345627f7eb2Smrg }
4346627f7eb2Smrg if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
4347627f7eb2Smrg {
4348627f7eb2Smrg for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4349627f7eb2Smrg if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4350627f7eb2Smrg && OMP_CLAUSE_DECL (c) == dovar_decl)
4351627f7eb2Smrg {
4352627f7eb2Smrg tree l = build_omp_clause (input_location,
4353627f7eb2Smrg OMP_CLAUSE_LASTPRIVATE);
4354627f7eb2Smrg OMP_CLAUSE_DECL (l) = dovar_decl;
4355627f7eb2Smrg OMP_CLAUSE_CHAIN (l) = omp_clauses;
4356627f7eb2Smrg OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
4357627f7eb2Smrg omp_clauses = l;
4358627f7eb2Smrg OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
4359627f7eb2Smrg break;
4360627f7eb2Smrg }
4361627f7eb2Smrg }
4362627f7eb2Smrg gcc_assert (simple || c != NULL);
4363627f7eb2Smrg }
4364627f7eb2Smrg if (!simple)
4365627f7eb2Smrg {
4366627f7eb2Smrg if (op != EXEC_OMP_SIMD)
4367627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
4368627f7eb2Smrg else if (collapse == 1)
4369627f7eb2Smrg {
4370627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
4371627f7eb2Smrg OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
4372627f7eb2Smrg OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
4373627f7eb2Smrg OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
4374627f7eb2Smrg }
4375627f7eb2Smrg else
4376627f7eb2Smrg tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
4377627f7eb2Smrg OMP_CLAUSE_DECL (tmp) = count;
4378627f7eb2Smrg omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
4379627f7eb2Smrg }
4380627f7eb2Smrg
4381627f7eb2Smrg if (i + 1 < collapse)
4382627f7eb2Smrg code = code->block->next;
4383627f7eb2Smrg }
4384627f7eb2Smrg
4385627f7eb2Smrg if (pblock != &block)
4386627f7eb2Smrg {
4387627f7eb2Smrg pushlevel ();
4388627f7eb2Smrg gfc_start_block (&block);
4389627f7eb2Smrg }
4390627f7eb2Smrg
4391627f7eb2Smrg gfc_start_block (&body);
4392627f7eb2Smrg
4393627f7eb2Smrg FOR_EACH_VEC_ELT (inits, ix, di)
4394627f7eb2Smrg gfc_add_modify (&body, di->var, di->init);
4395627f7eb2Smrg inits.release ();
4396627f7eb2Smrg
4397627f7eb2Smrg /* Cycle statement is implemented with a goto. Exit statement must not be
4398627f7eb2Smrg present for this loop. */
4399627f7eb2Smrg cycle_label = gfc_build_label_decl (NULL_TREE);
4400627f7eb2Smrg
4401627f7eb2Smrg /* Put these labels where they can be found later. */
4402627f7eb2Smrg
4403627f7eb2Smrg code->cycle_label = cycle_label;
4404627f7eb2Smrg code->exit_label = NULL_TREE;
4405627f7eb2Smrg
4406627f7eb2Smrg /* Main loop body. */
4407627f7eb2Smrg tmp = gfc_trans_omp_code (code->block->next, true);
4408627f7eb2Smrg gfc_add_expr_to_block (&body, tmp);
4409627f7eb2Smrg
4410627f7eb2Smrg /* Label for cycle statements (if needed). */
4411627f7eb2Smrg if (TREE_USED (cycle_label))
4412627f7eb2Smrg {
4413627f7eb2Smrg tmp = build1_v (LABEL_EXPR, cycle_label);
4414627f7eb2Smrg gfc_add_expr_to_block (&body, tmp);
4415627f7eb2Smrg }
4416627f7eb2Smrg
4417627f7eb2Smrg /* End of loop body. */
4418627f7eb2Smrg switch (op)
4419627f7eb2Smrg {
4420627f7eb2Smrg case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
4421627f7eb2Smrg case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
4422627f7eb2Smrg case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
4423627f7eb2Smrg case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
4424627f7eb2Smrg case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
4425627f7eb2Smrg default: gcc_unreachable ();
4426627f7eb2Smrg }
4427627f7eb2Smrg
4428627f7eb2Smrg TREE_TYPE (stmt) = void_type_node;
4429627f7eb2Smrg OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
4430627f7eb2Smrg OMP_FOR_CLAUSES (stmt) = omp_clauses;
4431627f7eb2Smrg OMP_FOR_INIT (stmt) = init;
4432627f7eb2Smrg OMP_FOR_COND (stmt) = cond;
4433627f7eb2Smrg OMP_FOR_INCR (stmt) = incr;
4434627f7eb2Smrg if (orig_decls)
4435627f7eb2Smrg OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
4436627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
4437627f7eb2Smrg
4438627f7eb2Smrg vec_free (doacross_steps);
4439627f7eb2Smrg doacross_steps = saved_doacross_steps;
4440627f7eb2Smrg
4441627f7eb2Smrg return gfc_finish_block (&block);
4442627f7eb2Smrg }
4443627f7eb2Smrg
4444*4c3eb207Smrg /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop'
4445*4c3eb207Smrg construct. */
4446*4c3eb207Smrg
4447627f7eb2Smrg static tree
gfc_trans_oacc_combined_directive(gfc_code * code)4448627f7eb2Smrg gfc_trans_oacc_combined_directive (gfc_code *code)
4449627f7eb2Smrg {
4450627f7eb2Smrg stmtblock_t block, *pblock = NULL;
4451627f7eb2Smrg gfc_omp_clauses construct_clauses, loop_clauses;
4452627f7eb2Smrg tree stmt, oacc_clauses = NULL_TREE;
4453627f7eb2Smrg enum tree_code construct_code;
4454627f7eb2Smrg location_t loc = input_location;
4455627f7eb2Smrg
4456627f7eb2Smrg switch (code->op)
4457627f7eb2Smrg {
4458627f7eb2Smrg case EXEC_OACC_PARALLEL_LOOP:
4459627f7eb2Smrg construct_code = OACC_PARALLEL;
4460627f7eb2Smrg break;
4461627f7eb2Smrg case EXEC_OACC_KERNELS_LOOP:
4462627f7eb2Smrg construct_code = OACC_KERNELS;
4463627f7eb2Smrg break;
4464*4c3eb207Smrg case EXEC_OACC_SERIAL_LOOP:
4465*4c3eb207Smrg construct_code = OACC_SERIAL;
4466*4c3eb207Smrg break;
4467627f7eb2Smrg default:
4468627f7eb2Smrg gcc_unreachable ();
4469627f7eb2Smrg }
4470627f7eb2Smrg
4471627f7eb2Smrg gfc_start_block (&block);
4472627f7eb2Smrg
4473627f7eb2Smrg memset (&loop_clauses, 0, sizeof (loop_clauses));
4474627f7eb2Smrg if (code->ext.omp_clauses != NULL)
4475627f7eb2Smrg {
4476627f7eb2Smrg memcpy (&construct_clauses, code->ext.omp_clauses,
4477627f7eb2Smrg sizeof (construct_clauses));
4478627f7eb2Smrg loop_clauses.collapse = construct_clauses.collapse;
4479627f7eb2Smrg loop_clauses.gang = construct_clauses.gang;
4480627f7eb2Smrg loop_clauses.gang_static = construct_clauses.gang_static;
4481627f7eb2Smrg loop_clauses.gang_num_expr = construct_clauses.gang_num_expr;
4482627f7eb2Smrg loop_clauses.gang_static_expr = construct_clauses.gang_static_expr;
4483627f7eb2Smrg loop_clauses.vector = construct_clauses.vector;
4484627f7eb2Smrg loop_clauses.vector_expr = construct_clauses.vector_expr;
4485627f7eb2Smrg loop_clauses.worker = construct_clauses.worker;
4486627f7eb2Smrg loop_clauses.worker_expr = construct_clauses.worker_expr;
4487627f7eb2Smrg loop_clauses.seq = construct_clauses.seq;
4488627f7eb2Smrg loop_clauses.par_auto = construct_clauses.par_auto;
4489627f7eb2Smrg loop_clauses.independent = construct_clauses.independent;
4490627f7eb2Smrg loop_clauses.tile_list = construct_clauses.tile_list;
4491627f7eb2Smrg loop_clauses.lists[OMP_LIST_PRIVATE]
4492627f7eb2Smrg = construct_clauses.lists[OMP_LIST_PRIVATE];
4493627f7eb2Smrg loop_clauses.lists[OMP_LIST_REDUCTION]
4494627f7eb2Smrg = construct_clauses.lists[OMP_LIST_REDUCTION];
4495627f7eb2Smrg construct_clauses.gang = false;
4496627f7eb2Smrg construct_clauses.gang_static = false;
4497627f7eb2Smrg construct_clauses.gang_num_expr = NULL;
4498627f7eb2Smrg construct_clauses.gang_static_expr = NULL;
4499627f7eb2Smrg construct_clauses.vector = false;
4500627f7eb2Smrg construct_clauses.vector_expr = NULL;
4501627f7eb2Smrg construct_clauses.worker = false;
4502627f7eb2Smrg construct_clauses.worker_expr = NULL;
4503627f7eb2Smrg construct_clauses.seq = false;
4504627f7eb2Smrg construct_clauses.par_auto = false;
4505627f7eb2Smrg construct_clauses.independent = false;
4506627f7eb2Smrg construct_clauses.independent = false;
4507627f7eb2Smrg construct_clauses.tile_list = NULL;
4508627f7eb2Smrg construct_clauses.lists[OMP_LIST_PRIVATE] = NULL;
4509627f7eb2Smrg if (construct_code == OACC_KERNELS)
4510627f7eb2Smrg construct_clauses.lists[OMP_LIST_REDUCTION] = NULL;
4511627f7eb2Smrg oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
4512627f7eb2Smrg code->loc);
4513627f7eb2Smrg }
4514627f7eb2Smrg if (!loop_clauses.seq)
4515627f7eb2Smrg pblock = █
4516627f7eb2Smrg else
4517627f7eb2Smrg pushlevel ();
4518627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
4519627f7eb2Smrg protected_set_expr_location (stmt, loc);
4520627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
4521627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4522627f7eb2Smrg else
4523627f7eb2Smrg poplevel (0, 0);
4524627f7eb2Smrg stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses);
4525627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
4526627f7eb2Smrg return gfc_finish_block (&block);
4527627f7eb2Smrg }
4528627f7eb2Smrg
4529627f7eb2Smrg static tree
gfc_trans_omp_flush(void)4530627f7eb2Smrg gfc_trans_omp_flush (void)
4531627f7eb2Smrg {
4532627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
4533627f7eb2Smrg return build_call_expr_loc (input_location, decl, 0);
4534627f7eb2Smrg }
4535627f7eb2Smrg
4536627f7eb2Smrg static tree
gfc_trans_omp_master(gfc_code * code)4537627f7eb2Smrg gfc_trans_omp_master (gfc_code *code)
4538627f7eb2Smrg {
4539627f7eb2Smrg tree stmt = gfc_trans_code (code->block->next);
4540627f7eb2Smrg if (IS_EMPTY_STMT (stmt))
4541627f7eb2Smrg return stmt;
4542627f7eb2Smrg return build1_v (OMP_MASTER, stmt);
4543627f7eb2Smrg }
4544627f7eb2Smrg
4545627f7eb2Smrg static tree
gfc_trans_omp_ordered(gfc_code * code)4546627f7eb2Smrg gfc_trans_omp_ordered (gfc_code *code)
4547627f7eb2Smrg {
4548627f7eb2Smrg if (!flag_openmp)
4549627f7eb2Smrg {
4550627f7eb2Smrg if (!code->ext.omp_clauses->simd)
4551627f7eb2Smrg return gfc_trans_code (code->block ? code->block->next : NULL);
4552627f7eb2Smrg code->ext.omp_clauses->threads = 0;
4553627f7eb2Smrg }
4554627f7eb2Smrg tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
4555627f7eb2Smrg code->loc);
4556627f7eb2Smrg return build2_loc (input_location, OMP_ORDERED, void_type_node,
4557627f7eb2Smrg code->block ? gfc_trans_code (code->block->next)
4558627f7eb2Smrg : NULL_TREE, omp_clauses);
4559627f7eb2Smrg }
4560627f7eb2Smrg
4561627f7eb2Smrg static tree
gfc_trans_omp_parallel(gfc_code * code)4562627f7eb2Smrg gfc_trans_omp_parallel (gfc_code *code)
4563627f7eb2Smrg {
4564627f7eb2Smrg stmtblock_t block;
4565627f7eb2Smrg tree stmt, omp_clauses;
4566627f7eb2Smrg
4567627f7eb2Smrg gfc_start_block (&block);
4568627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
4569627f7eb2Smrg code->loc);
4570627f7eb2Smrg pushlevel ();
4571627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
4572627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
4573627f7eb2Smrg stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
4574627f7eb2Smrg omp_clauses);
4575627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
4576627f7eb2Smrg return gfc_finish_block (&block);
4577627f7eb2Smrg }
4578627f7eb2Smrg
4579627f7eb2Smrg enum
4580627f7eb2Smrg {
4581627f7eb2Smrg GFC_OMP_SPLIT_SIMD,
4582627f7eb2Smrg GFC_OMP_SPLIT_DO,
4583627f7eb2Smrg GFC_OMP_SPLIT_PARALLEL,
4584627f7eb2Smrg GFC_OMP_SPLIT_DISTRIBUTE,
4585627f7eb2Smrg GFC_OMP_SPLIT_TEAMS,
4586627f7eb2Smrg GFC_OMP_SPLIT_TARGET,
4587627f7eb2Smrg GFC_OMP_SPLIT_TASKLOOP,
4588627f7eb2Smrg GFC_OMP_SPLIT_NUM
4589627f7eb2Smrg };
4590627f7eb2Smrg
4591627f7eb2Smrg enum
4592627f7eb2Smrg {
4593627f7eb2Smrg GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
4594627f7eb2Smrg GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
4595627f7eb2Smrg GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
4596627f7eb2Smrg GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
4597627f7eb2Smrg GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
4598627f7eb2Smrg GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
4599627f7eb2Smrg GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP)
4600627f7eb2Smrg };
4601627f7eb2Smrg
4602627f7eb2Smrg static void
gfc_split_omp_clauses(gfc_code * code,gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])4603627f7eb2Smrg gfc_split_omp_clauses (gfc_code *code,
4604627f7eb2Smrg gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
4605627f7eb2Smrg {
4606627f7eb2Smrg int mask = 0, innermost = 0;
4607627f7eb2Smrg memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
4608627f7eb2Smrg switch (code->op)
4609627f7eb2Smrg {
4610627f7eb2Smrg case EXEC_OMP_DISTRIBUTE:
4611627f7eb2Smrg innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4612627f7eb2Smrg break;
4613627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4614627f7eb2Smrg mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4615627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4616627f7eb2Smrg break;
4617627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4618627f7eb2Smrg mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
4619627f7eb2Smrg | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4620627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4621627f7eb2Smrg break;
4622627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_SIMD:
4623627f7eb2Smrg mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4624627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4625627f7eb2Smrg break;
4626627f7eb2Smrg case EXEC_OMP_DO:
4627627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4628627f7eb2Smrg break;
4629627f7eb2Smrg case EXEC_OMP_DO_SIMD:
4630627f7eb2Smrg mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4631627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4632627f7eb2Smrg break;
4633627f7eb2Smrg case EXEC_OMP_PARALLEL:
4634627f7eb2Smrg innermost = GFC_OMP_SPLIT_PARALLEL;
4635627f7eb2Smrg break;
4636627f7eb2Smrg case EXEC_OMP_PARALLEL_DO:
4637627f7eb2Smrg mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4638627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4639627f7eb2Smrg break;
4640627f7eb2Smrg case EXEC_OMP_PARALLEL_DO_SIMD:
4641627f7eb2Smrg mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4642627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4643627f7eb2Smrg break;
4644627f7eb2Smrg case EXEC_OMP_SIMD:
4645627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4646627f7eb2Smrg break;
4647627f7eb2Smrg case EXEC_OMP_TARGET:
4648627f7eb2Smrg innermost = GFC_OMP_SPLIT_TARGET;
4649627f7eb2Smrg break;
4650627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL:
4651627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
4652627f7eb2Smrg innermost = GFC_OMP_SPLIT_PARALLEL;
4653627f7eb2Smrg break;
4654627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL_DO:
4655627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4656627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4657627f7eb2Smrg break;
4658627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4659627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
4660627f7eb2Smrg | GFC_OMP_MASK_SIMD;
4661627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4662627f7eb2Smrg break;
4663627f7eb2Smrg case EXEC_OMP_TARGET_SIMD:
4664627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
4665627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4666627f7eb2Smrg break;
4667627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS:
4668627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
4669627f7eb2Smrg innermost = GFC_OMP_SPLIT_TEAMS;
4670627f7eb2Smrg break;
4671627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4672627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
4673627f7eb2Smrg | GFC_OMP_MASK_DISTRIBUTE;
4674627f7eb2Smrg innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4675627f7eb2Smrg break;
4676627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4677627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4678627f7eb2Smrg | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4679627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4680627f7eb2Smrg break;
4681627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4682627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4683627f7eb2Smrg | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4684627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4685627f7eb2Smrg break;
4686627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4687627f7eb2Smrg mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
4688627f7eb2Smrg | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4689627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4690627f7eb2Smrg break;
4691627f7eb2Smrg case EXEC_OMP_TASKLOOP:
4692627f7eb2Smrg innermost = GFC_OMP_SPLIT_TASKLOOP;
4693627f7eb2Smrg break;
4694627f7eb2Smrg case EXEC_OMP_TASKLOOP_SIMD:
4695627f7eb2Smrg mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
4696627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4697627f7eb2Smrg break;
4698627f7eb2Smrg case EXEC_OMP_TEAMS:
4699627f7eb2Smrg innermost = GFC_OMP_SPLIT_TEAMS;
4700627f7eb2Smrg break;
4701627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE:
4702627f7eb2Smrg mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
4703627f7eb2Smrg innermost = GFC_OMP_SPLIT_DISTRIBUTE;
4704627f7eb2Smrg break;
4705627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4706627f7eb2Smrg mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4707627f7eb2Smrg | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
4708627f7eb2Smrg innermost = GFC_OMP_SPLIT_DO;
4709627f7eb2Smrg break;
4710627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4711627f7eb2Smrg mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
4712627f7eb2Smrg | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
4713627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4714627f7eb2Smrg break;
4715627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4716627f7eb2Smrg mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
4717627f7eb2Smrg innermost = GFC_OMP_SPLIT_SIMD;
4718627f7eb2Smrg break;
4719627f7eb2Smrg default:
4720627f7eb2Smrg gcc_unreachable ();
4721627f7eb2Smrg }
4722627f7eb2Smrg if (mask == 0)
4723627f7eb2Smrg {
4724627f7eb2Smrg clausesa[innermost] = *code->ext.omp_clauses;
4725627f7eb2Smrg return;
4726627f7eb2Smrg }
4727627f7eb2Smrg if (code->ext.omp_clauses != NULL)
4728627f7eb2Smrg {
4729627f7eb2Smrg if (mask & GFC_OMP_MASK_TARGET)
4730627f7eb2Smrg {
4731627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4732627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
4733627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_MAP];
4734627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
4735627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
4736627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].device
4737627f7eb2Smrg = code->ext.omp_clauses->device;
4738627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].defaultmap
4739627f7eb2Smrg = code->ext.omp_clauses->defaultmap;
4740627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
4741627f7eb2Smrg = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
4742627f7eb2Smrg /* And this is copied to all. */
4743627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
4744627f7eb2Smrg = code->ext.omp_clauses->if_expr;
4745627f7eb2Smrg }
4746627f7eb2Smrg if (mask & GFC_OMP_MASK_TEAMS)
4747627f7eb2Smrg {
4748627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4749627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
4750627f7eb2Smrg = code->ext.omp_clauses->num_teams;
4751627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
4752627f7eb2Smrg = code->ext.omp_clauses->thread_limit;
4753627f7eb2Smrg /* Shared and default clauses are allowed on parallel, teams
4754627f7eb2Smrg and taskloop. */
4755627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
4756627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4757627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
4758627f7eb2Smrg = code->ext.omp_clauses->default_sharing;
4759627f7eb2Smrg }
4760627f7eb2Smrg if (mask & GFC_OMP_MASK_DISTRIBUTE)
4761627f7eb2Smrg {
4762627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4763627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
4764627f7eb2Smrg = code->ext.omp_clauses->dist_sched_kind;
4765627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
4766627f7eb2Smrg = code->ext.omp_clauses->dist_chunk_size;
4767627f7eb2Smrg /* Duplicate collapse. */
4768627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
4769627f7eb2Smrg = code->ext.omp_clauses->collapse;
4770627f7eb2Smrg }
4771627f7eb2Smrg if (mask & GFC_OMP_MASK_PARALLEL)
4772627f7eb2Smrg {
4773627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4774627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
4775627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
4776627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
4777627f7eb2Smrg = code->ext.omp_clauses->num_threads;
4778627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
4779627f7eb2Smrg = code->ext.omp_clauses->proc_bind;
4780627f7eb2Smrg /* Shared and default clauses are allowed on parallel, teams
4781627f7eb2Smrg and taskloop. */
4782627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
4783627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4784627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
4785627f7eb2Smrg = code->ext.omp_clauses->default_sharing;
4786627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
4787627f7eb2Smrg = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
4788627f7eb2Smrg /* And this is copied to all. */
4789627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
4790627f7eb2Smrg = code->ext.omp_clauses->if_expr;
4791627f7eb2Smrg }
4792627f7eb2Smrg if (mask & GFC_OMP_MASK_DO)
4793627f7eb2Smrg {
4794627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4795627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].ordered
4796627f7eb2Smrg = code->ext.omp_clauses->ordered;
4797627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].orderedc
4798627f7eb2Smrg = code->ext.omp_clauses->orderedc;
4799627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].sched_kind
4800627f7eb2Smrg = code->ext.omp_clauses->sched_kind;
4801627f7eb2Smrg if (innermost == GFC_OMP_SPLIT_SIMD)
4802627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].sched_simd
4803627f7eb2Smrg = code->ext.omp_clauses->sched_simd;
4804627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
4805627f7eb2Smrg = code->ext.omp_clauses->sched_monotonic;
4806627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
4807627f7eb2Smrg = code->ext.omp_clauses->sched_nonmonotonic;
4808627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].chunk_size
4809627f7eb2Smrg = code->ext.omp_clauses->chunk_size;
4810627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].nowait
4811627f7eb2Smrg = code->ext.omp_clauses->nowait;
4812627f7eb2Smrg /* Duplicate collapse. */
4813627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].collapse
4814627f7eb2Smrg = code->ext.omp_clauses->collapse;
4815627f7eb2Smrg }
4816627f7eb2Smrg if (mask & GFC_OMP_MASK_SIMD)
4817627f7eb2Smrg {
4818627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
4819627f7eb2Smrg = code->ext.omp_clauses->safelen_expr;
4820627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
4821627f7eb2Smrg = code->ext.omp_clauses->simdlen_expr;
4822627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
4823627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
4824627f7eb2Smrg /* Duplicate collapse. */
4825627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].collapse
4826627f7eb2Smrg = code->ext.omp_clauses->collapse;
4827627f7eb2Smrg }
4828627f7eb2Smrg if (mask & GFC_OMP_MASK_TASKLOOP)
4829627f7eb2Smrg {
4830627f7eb2Smrg /* First the clauses that are unique to some constructs. */
4831627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
4832627f7eb2Smrg = code->ext.omp_clauses->nogroup;
4833627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
4834627f7eb2Smrg = code->ext.omp_clauses->grainsize;
4835627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
4836627f7eb2Smrg = code->ext.omp_clauses->num_tasks;
4837627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
4838627f7eb2Smrg = code->ext.omp_clauses->priority;
4839627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
4840627f7eb2Smrg = code->ext.omp_clauses->final_expr;
4841627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
4842627f7eb2Smrg = code->ext.omp_clauses->untied;
4843627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
4844627f7eb2Smrg = code->ext.omp_clauses->mergeable;
4845627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
4846627f7eb2Smrg = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
4847627f7eb2Smrg /* And this is copied to all. */
4848627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
4849627f7eb2Smrg = code->ext.omp_clauses->if_expr;
4850627f7eb2Smrg /* Shared and default clauses are allowed on parallel, teams
4851627f7eb2Smrg and taskloop. */
4852627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
4853627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
4854627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
4855627f7eb2Smrg = code->ext.omp_clauses->default_sharing;
4856627f7eb2Smrg /* Duplicate collapse. */
4857627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
4858627f7eb2Smrg = code->ext.omp_clauses->collapse;
4859627f7eb2Smrg }
4860627f7eb2Smrg /* Private clause is supported on all constructs,
4861627f7eb2Smrg it is enough to put it on the innermost one. For
4862627f7eb2Smrg !$ omp parallel do put it on parallel though,
4863627f7eb2Smrg as that's what we did for OpenMP 3.1. */
4864627f7eb2Smrg clausesa[innermost == GFC_OMP_SPLIT_DO
4865627f7eb2Smrg ? (int) GFC_OMP_SPLIT_PARALLEL
4866627f7eb2Smrg : innermost].lists[OMP_LIST_PRIVATE]
4867627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
4868627f7eb2Smrg /* Firstprivate clause is supported on all constructs but
4869627f7eb2Smrg simd. Put it on the outermost of those and duplicate
4870627f7eb2Smrg on parallel and teams. */
4871627f7eb2Smrg if (mask & GFC_OMP_MASK_TARGET)
4872627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
4873627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4874627f7eb2Smrg if (mask & GFC_OMP_MASK_TEAMS)
4875627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
4876627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4877627f7eb2Smrg else if (mask & GFC_OMP_MASK_DISTRIBUTE)
4878627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
4879627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4880627f7eb2Smrg if (mask & GFC_OMP_MASK_PARALLEL)
4881627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
4882627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4883627f7eb2Smrg else if (mask & GFC_OMP_MASK_DO)
4884627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
4885627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
4886627f7eb2Smrg /* Lastprivate is allowed on distribute, do and simd.
4887627f7eb2Smrg In parallel do{, simd} we actually want to put it on
4888627f7eb2Smrg parallel rather than do. */
4889627f7eb2Smrg if (mask & GFC_OMP_MASK_DISTRIBUTE)
4890627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
4891627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4892627f7eb2Smrg if (mask & GFC_OMP_MASK_PARALLEL)
4893627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
4894627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4895627f7eb2Smrg else if (mask & GFC_OMP_MASK_DO)
4896627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
4897627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4898627f7eb2Smrg if (mask & GFC_OMP_MASK_SIMD)
4899627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
4900627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
4901627f7eb2Smrg /* Reduction is allowed on simd, do, parallel and teams.
4902627f7eb2Smrg Duplicate it on all of them, but omit on do if
4903627f7eb2Smrg parallel is present. */
4904627f7eb2Smrg if (mask & GFC_OMP_MASK_TEAMS)
4905627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
4906627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4907627f7eb2Smrg if (mask & GFC_OMP_MASK_PARALLEL)
4908627f7eb2Smrg clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
4909627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4910627f7eb2Smrg else if (mask & GFC_OMP_MASK_DO)
4911627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
4912627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4913627f7eb2Smrg if (mask & GFC_OMP_MASK_SIMD)
4914627f7eb2Smrg clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
4915627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
4916627f7eb2Smrg /* Linear clause is supported on do and simd,
4917627f7eb2Smrg put it on the innermost one. */
4918627f7eb2Smrg clausesa[innermost].lists[OMP_LIST_LINEAR]
4919627f7eb2Smrg = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
4920627f7eb2Smrg }
4921627f7eb2Smrg if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
4922627f7eb2Smrg == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
4923627f7eb2Smrg clausesa[GFC_OMP_SPLIT_DO].nowait = true;
4924627f7eb2Smrg }
4925627f7eb2Smrg
4926627f7eb2Smrg static tree
gfc_trans_omp_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa,tree omp_clauses)4927627f7eb2Smrg gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
4928627f7eb2Smrg gfc_omp_clauses *clausesa, tree omp_clauses)
4929627f7eb2Smrg {
4930627f7eb2Smrg stmtblock_t block;
4931627f7eb2Smrg gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4932627f7eb2Smrg tree stmt, body, omp_do_clauses = NULL_TREE;
4933627f7eb2Smrg
4934627f7eb2Smrg if (pblock == NULL)
4935627f7eb2Smrg gfc_start_block (&block);
4936627f7eb2Smrg else
4937627f7eb2Smrg gfc_init_block (&block);
4938627f7eb2Smrg
4939627f7eb2Smrg if (clausesa == NULL)
4940627f7eb2Smrg {
4941627f7eb2Smrg clausesa = clausesa_buf;
4942627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
4943627f7eb2Smrg }
4944627f7eb2Smrg if (flag_openmp)
4945627f7eb2Smrg omp_do_clauses
4946627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
4947627f7eb2Smrg body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
4948627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
4949627f7eb2Smrg if (pblock == NULL)
4950627f7eb2Smrg {
4951627f7eb2Smrg if (TREE_CODE (body) != BIND_EXPR)
4952627f7eb2Smrg body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
4953627f7eb2Smrg else
4954627f7eb2Smrg poplevel (0, 0);
4955627f7eb2Smrg }
4956627f7eb2Smrg else if (TREE_CODE (body) != BIND_EXPR)
4957627f7eb2Smrg body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
4958627f7eb2Smrg if (flag_openmp)
4959627f7eb2Smrg {
4960627f7eb2Smrg stmt = make_node (OMP_FOR);
4961627f7eb2Smrg TREE_TYPE (stmt) = void_type_node;
4962627f7eb2Smrg OMP_FOR_BODY (stmt) = body;
4963627f7eb2Smrg OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
4964627f7eb2Smrg }
4965627f7eb2Smrg else
4966627f7eb2Smrg stmt = body;
4967627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
4968627f7eb2Smrg return gfc_finish_block (&block);
4969627f7eb2Smrg }
4970627f7eb2Smrg
4971627f7eb2Smrg static tree
gfc_trans_omp_parallel_do(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa)4972627f7eb2Smrg gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
4973627f7eb2Smrg gfc_omp_clauses *clausesa)
4974627f7eb2Smrg {
4975627f7eb2Smrg stmtblock_t block, *new_pblock = pblock;
4976627f7eb2Smrg gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
4977627f7eb2Smrg tree stmt, omp_clauses = NULL_TREE;
4978627f7eb2Smrg
4979627f7eb2Smrg if (pblock == NULL)
4980627f7eb2Smrg gfc_start_block (&block);
4981627f7eb2Smrg else
4982627f7eb2Smrg gfc_init_block (&block);
4983627f7eb2Smrg
4984627f7eb2Smrg if (clausesa == NULL)
4985627f7eb2Smrg {
4986627f7eb2Smrg clausesa = clausesa_buf;
4987627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
4988627f7eb2Smrg }
4989627f7eb2Smrg omp_clauses
4990627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
4991627f7eb2Smrg code->loc);
4992627f7eb2Smrg if (pblock == NULL)
4993627f7eb2Smrg {
4994627f7eb2Smrg if (!clausesa[GFC_OMP_SPLIT_DO].ordered
4995627f7eb2Smrg && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
4996627f7eb2Smrg new_pblock = █
4997627f7eb2Smrg else
4998627f7eb2Smrg pushlevel ();
4999627f7eb2Smrg }
5000627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, new_pblock,
5001627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
5002627f7eb2Smrg if (pblock == NULL)
5003627f7eb2Smrg {
5004627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5005627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5006627f7eb2Smrg else
5007627f7eb2Smrg poplevel (0, 0);
5008627f7eb2Smrg }
5009627f7eb2Smrg else if (TREE_CODE (stmt) != BIND_EXPR)
5010627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
5011*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
5012*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5013627f7eb2Smrg OMP_PARALLEL_COMBINED (stmt) = 1;
5014627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5015627f7eb2Smrg return gfc_finish_block (&block);
5016627f7eb2Smrg }
5017627f7eb2Smrg
5018627f7eb2Smrg static tree
gfc_trans_omp_parallel_do_simd(gfc_code * code,stmtblock_t * pblock,gfc_omp_clauses * clausesa)5019627f7eb2Smrg gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
5020627f7eb2Smrg gfc_omp_clauses *clausesa)
5021627f7eb2Smrg {
5022627f7eb2Smrg stmtblock_t block;
5023627f7eb2Smrg gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5024627f7eb2Smrg tree stmt, omp_clauses = NULL_TREE;
5025627f7eb2Smrg
5026627f7eb2Smrg if (pblock == NULL)
5027627f7eb2Smrg gfc_start_block (&block);
5028627f7eb2Smrg else
5029627f7eb2Smrg gfc_init_block (&block);
5030627f7eb2Smrg
5031627f7eb2Smrg if (clausesa == NULL)
5032627f7eb2Smrg {
5033627f7eb2Smrg clausesa = clausesa_buf;
5034627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
5035627f7eb2Smrg }
5036627f7eb2Smrg if (flag_openmp)
5037627f7eb2Smrg omp_clauses
5038627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
5039627f7eb2Smrg code->loc);
5040627f7eb2Smrg if (pblock == NULL)
5041627f7eb2Smrg pushlevel ();
5042627f7eb2Smrg stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
5043627f7eb2Smrg if (pblock == NULL)
5044627f7eb2Smrg {
5045627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5046627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5047627f7eb2Smrg else
5048627f7eb2Smrg poplevel (0, 0);
5049627f7eb2Smrg }
5050627f7eb2Smrg else if (TREE_CODE (stmt) != BIND_EXPR)
5051627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
5052627f7eb2Smrg if (flag_openmp)
5053627f7eb2Smrg {
5054*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
5055*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5056627f7eb2Smrg OMP_PARALLEL_COMBINED (stmt) = 1;
5057627f7eb2Smrg }
5058627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5059627f7eb2Smrg return gfc_finish_block (&block);
5060627f7eb2Smrg }
5061627f7eb2Smrg
5062627f7eb2Smrg static tree
gfc_trans_omp_parallel_sections(gfc_code * code)5063627f7eb2Smrg gfc_trans_omp_parallel_sections (gfc_code *code)
5064627f7eb2Smrg {
5065627f7eb2Smrg stmtblock_t block;
5066627f7eb2Smrg gfc_omp_clauses section_clauses;
5067627f7eb2Smrg tree stmt, omp_clauses;
5068627f7eb2Smrg
5069627f7eb2Smrg memset (§ion_clauses, 0, sizeof (section_clauses));
5070627f7eb2Smrg section_clauses.nowait = true;
5071627f7eb2Smrg
5072627f7eb2Smrg gfc_start_block (&block);
5073627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5074627f7eb2Smrg code->loc);
5075627f7eb2Smrg pushlevel ();
5076627f7eb2Smrg stmt = gfc_trans_omp_sections (code, §ion_clauses);
5077627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5078627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5079627f7eb2Smrg else
5080627f7eb2Smrg poplevel (0, 0);
5081*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
5082*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5083627f7eb2Smrg OMP_PARALLEL_COMBINED (stmt) = 1;
5084627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5085627f7eb2Smrg return gfc_finish_block (&block);
5086627f7eb2Smrg }
5087627f7eb2Smrg
5088627f7eb2Smrg static tree
gfc_trans_omp_parallel_workshare(gfc_code * code)5089627f7eb2Smrg gfc_trans_omp_parallel_workshare (gfc_code *code)
5090627f7eb2Smrg {
5091627f7eb2Smrg stmtblock_t block;
5092627f7eb2Smrg gfc_omp_clauses workshare_clauses;
5093627f7eb2Smrg tree stmt, omp_clauses;
5094627f7eb2Smrg
5095627f7eb2Smrg memset (&workshare_clauses, 0, sizeof (workshare_clauses));
5096627f7eb2Smrg workshare_clauses.nowait = true;
5097627f7eb2Smrg
5098627f7eb2Smrg gfc_start_block (&block);
5099627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5100627f7eb2Smrg code->loc);
5101627f7eb2Smrg pushlevel ();
5102627f7eb2Smrg stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
5103627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5104*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL,
5105*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5106627f7eb2Smrg OMP_PARALLEL_COMBINED (stmt) = 1;
5107627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5108627f7eb2Smrg return gfc_finish_block (&block);
5109627f7eb2Smrg }
5110627f7eb2Smrg
5111627f7eb2Smrg static tree
gfc_trans_omp_sections(gfc_code * code,gfc_omp_clauses * clauses)5112627f7eb2Smrg gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
5113627f7eb2Smrg {
5114627f7eb2Smrg stmtblock_t block, body;
5115627f7eb2Smrg tree omp_clauses, stmt;
5116627f7eb2Smrg bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
5117*4c3eb207Smrg location_t loc = gfc_get_location (&code->loc);
5118627f7eb2Smrg
5119627f7eb2Smrg gfc_start_block (&block);
5120627f7eb2Smrg
5121627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
5122627f7eb2Smrg
5123627f7eb2Smrg gfc_init_block (&body);
5124627f7eb2Smrg for (code = code->block; code; code = code->block)
5125627f7eb2Smrg {
5126627f7eb2Smrg /* Last section is special because of lastprivate, so even if it
5127627f7eb2Smrg is empty, chain it in. */
5128627f7eb2Smrg stmt = gfc_trans_omp_code (code->next,
5129627f7eb2Smrg has_lastprivate && code->block == NULL);
5130627f7eb2Smrg if (! IS_EMPTY_STMT (stmt))
5131627f7eb2Smrg {
5132627f7eb2Smrg stmt = build1_v (OMP_SECTION, stmt);
5133627f7eb2Smrg gfc_add_expr_to_block (&body, stmt);
5134627f7eb2Smrg }
5135627f7eb2Smrg }
5136627f7eb2Smrg stmt = gfc_finish_block (&body);
5137627f7eb2Smrg
5138*4c3eb207Smrg stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses);
5139627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5140627f7eb2Smrg
5141627f7eb2Smrg return gfc_finish_block (&block);
5142627f7eb2Smrg }
5143627f7eb2Smrg
5144627f7eb2Smrg static tree
gfc_trans_omp_single(gfc_code * code,gfc_omp_clauses * clauses)5145627f7eb2Smrg gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
5146627f7eb2Smrg {
5147627f7eb2Smrg tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
5148627f7eb2Smrg tree stmt = gfc_trans_omp_code (code->block->next, true);
5149*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node,
5150*4c3eb207Smrg stmt, omp_clauses);
5151627f7eb2Smrg return stmt;
5152627f7eb2Smrg }
5153627f7eb2Smrg
5154627f7eb2Smrg static tree
gfc_trans_omp_task(gfc_code * code)5155627f7eb2Smrg gfc_trans_omp_task (gfc_code *code)
5156627f7eb2Smrg {
5157627f7eb2Smrg stmtblock_t block;
5158627f7eb2Smrg tree stmt, omp_clauses;
5159627f7eb2Smrg
5160627f7eb2Smrg gfc_start_block (&block);
5161627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5162627f7eb2Smrg code->loc);
5163627f7eb2Smrg pushlevel ();
5164627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5165627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5166*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node,
5167*4c3eb207Smrg stmt, omp_clauses);
5168627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5169627f7eb2Smrg return gfc_finish_block (&block);
5170627f7eb2Smrg }
5171627f7eb2Smrg
5172627f7eb2Smrg static tree
gfc_trans_omp_taskgroup(gfc_code * code)5173627f7eb2Smrg gfc_trans_omp_taskgroup (gfc_code *code)
5174627f7eb2Smrg {
5175627f7eb2Smrg tree body = gfc_trans_code (code->block->next);
5176627f7eb2Smrg tree stmt = make_node (OMP_TASKGROUP);
5177627f7eb2Smrg TREE_TYPE (stmt) = void_type_node;
5178627f7eb2Smrg OMP_TASKGROUP_BODY (stmt) = body;
5179627f7eb2Smrg OMP_TASKGROUP_CLAUSES (stmt) = NULL_TREE;
5180627f7eb2Smrg return stmt;
5181627f7eb2Smrg }
5182627f7eb2Smrg
5183627f7eb2Smrg static tree
gfc_trans_omp_taskwait(void)5184627f7eb2Smrg gfc_trans_omp_taskwait (void)
5185627f7eb2Smrg {
5186627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
5187627f7eb2Smrg return build_call_expr_loc (input_location, decl, 0);
5188627f7eb2Smrg }
5189627f7eb2Smrg
5190627f7eb2Smrg static tree
gfc_trans_omp_taskyield(void)5191627f7eb2Smrg gfc_trans_omp_taskyield (void)
5192627f7eb2Smrg {
5193627f7eb2Smrg tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
5194627f7eb2Smrg return build_call_expr_loc (input_location, decl, 0);
5195627f7eb2Smrg }
5196627f7eb2Smrg
5197627f7eb2Smrg static tree
gfc_trans_omp_distribute(gfc_code * code,gfc_omp_clauses * clausesa)5198627f7eb2Smrg gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
5199627f7eb2Smrg {
5200627f7eb2Smrg stmtblock_t block;
5201627f7eb2Smrg gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5202627f7eb2Smrg tree stmt, omp_clauses = NULL_TREE;
5203627f7eb2Smrg
5204627f7eb2Smrg gfc_start_block (&block);
5205627f7eb2Smrg if (clausesa == NULL)
5206627f7eb2Smrg {
5207627f7eb2Smrg clausesa = clausesa_buf;
5208627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
5209627f7eb2Smrg }
5210627f7eb2Smrg if (flag_openmp)
5211627f7eb2Smrg omp_clauses
5212627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
5213627f7eb2Smrg code->loc);
5214627f7eb2Smrg switch (code->op)
5215627f7eb2Smrg {
5216627f7eb2Smrg case EXEC_OMP_DISTRIBUTE:
5217627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5218627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE:
5219627f7eb2Smrg /* This is handled in gfc_trans_omp_do. */
5220627f7eb2Smrg gcc_unreachable ();
5221627f7eb2Smrg break;
5222627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5223627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5224627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5225627f7eb2Smrg stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
5226627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5227627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5228627f7eb2Smrg else
5229627f7eb2Smrg poplevel (0, 0);
5230627f7eb2Smrg break;
5231627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5232627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5233627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5234627f7eb2Smrg stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
5235627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5236627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5237627f7eb2Smrg else
5238627f7eb2Smrg poplevel (0, 0);
5239627f7eb2Smrg break;
5240627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_SIMD:
5241627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5242627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5243627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5244627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5245627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5246627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5247627f7eb2Smrg else
5248627f7eb2Smrg poplevel (0, 0);
5249627f7eb2Smrg break;
5250627f7eb2Smrg default:
5251627f7eb2Smrg gcc_unreachable ();
5252627f7eb2Smrg }
5253627f7eb2Smrg if (flag_openmp)
5254627f7eb2Smrg {
5255627f7eb2Smrg tree distribute = make_node (OMP_DISTRIBUTE);
5256627f7eb2Smrg TREE_TYPE (distribute) = void_type_node;
5257627f7eb2Smrg OMP_FOR_BODY (distribute) = stmt;
5258627f7eb2Smrg OMP_FOR_CLAUSES (distribute) = omp_clauses;
5259627f7eb2Smrg stmt = distribute;
5260627f7eb2Smrg }
5261627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5262627f7eb2Smrg return gfc_finish_block (&block);
5263627f7eb2Smrg }
5264627f7eb2Smrg
5265627f7eb2Smrg static tree
gfc_trans_omp_teams(gfc_code * code,gfc_omp_clauses * clausesa,tree omp_clauses)5266627f7eb2Smrg gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
5267627f7eb2Smrg tree omp_clauses)
5268627f7eb2Smrg {
5269627f7eb2Smrg stmtblock_t block;
5270627f7eb2Smrg gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
5271627f7eb2Smrg tree stmt;
5272627f7eb2Smrg bool combined = true;
5273627f7eb2Smrg
5274627f7eb2Smrg gfc_start_block (&block);
5275627f7eb2Smrg if (clausesa == NULL)
5276627f7eb2Smrg {
5277627f7eb2Smrg clausesa = clausesa_buf;
5278627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
5279627f7eb2Smrg }
5280627f7eb2Smrg if (flag_openmp)
5281*4c3eb207Smrg {
5282627f7eb2Smrg omp_clauses
5283627f7eb2Smrg = chainon (omp_clauses,
5284*4c3eb207Smrg gfc_trans_omp_clauses (&block,
5285*4c3eb207Smrg &clausesa[GFC_OMP_SPLIT_TEAMS],
5286627f7eb2Smrg code->loc));
5287*4c3eb207Smrg pushlevel ();
5288*4c3eb207Smrg }
5289627f7eb2Smrg switch (code->op)
5290627f7eb2Smrg {
5291627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS:
5292627f7eb2Smrg case EXEC_OMP_TEAMS:
5293627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5294627f7eb2Smrg combined = false;
5295627f7eb2Smrg break;
5296627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5297627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE:
5298627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
5299627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
5300627f7eb2Smrg NULL);
5301627f7eb2Smrg break;
5302627f7eb2Smrg default:
5303627f7eb2Smrg stmt = gfc_trans_omp_distribute (code, clausesa);
5304627f7eb2Smrg break;
5305627f7eb2Smrg }
5306627f7eb2Smrg if (flag_openmp)
5307627f7eb2Smrg {
5308*4c3eb207Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5309*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS,
5310*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5311627f7eb2Smrg if (combined)
5312627f7eb2Smrg OMP_TEAMS_COMBINED (stmt) = 1;
5313627f7eb2Smrg }
5314627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5315627f7eb2Smrg return gfc_finish_block (&block);
5316627f7eb2Smrg }
5317627f7eb2Smrg
5318627f7eb2Smrg static tree
gfc_trans_omp_target(gfc_code * code)5319627f7eb2Smrg gfc_trans_omp_target (gfc_code *code)
5320627f7eb2Smrg {
5321627f7eb2Smrg stmtblock_t block;
5322627f7eb2Smrg gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
5323627f7eb2Smrg tree stmt, omp_clauses = NULL_TREE;
5324627f7eb2Smrg
5325627f7eb2Smrg gfc_start_block (&block);
5326627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
5327627f7eb2Smrg if (flag_openmp)
5328627f7eb2Smrg omp_clauses
5329627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
5330627f7eb2Smrg code->loc);
5331627f7eb2Smrg switch (code->op)
5332627f7eb2Smrg {
5333627f7eb2Smrg case EXEC_OMP_TARGET:
5334627f7eb2Smrg pushlevel ();
5335627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5336627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5337627f7eb2Smrg break;
5338627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL:
5339627f7eb2Smrg {
5340627f7eb2Smrg stmtblock_t iblock;
5341627f7eb2Smrg
5342627f7eb2Smrg pushlevel ();
5343627f7eb2Smrg gfc_start_block (&iblock);
5344627f7eb2Smrg tree inner_clauses
5345627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
5346627f7eb2Smrg code->loc);
5347627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5348627f7eb2Smrg stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
5349627f7eb2Smrg inner_clauses);
5350627f7eb2Smrg gfc_add_expr_to_block (&iblock, stmt);
5351627f7eb2Smrg stmt = gfc_finish_block (&iblock);
5352627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5353627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5354627f7eb2Smrg else
5355627f7eb2Smrg poplevel (0, 0);
5356627f7eb2Smrg }
5357627f7eb2Smrg break;
5358627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL_DO:
5359627f7eb2Smrg stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
5360627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5361627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5362627f7eb2Smrg else
5363627f7eb2Smrg poplevel (0, 0);
5364627f7eb2Smrg break;
5365*4c3eb207Smrg case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5366*4c3eb207Smrg stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
5367*4c3eb207Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5368*4c3eb207Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5369*4c3eb207Smrg else
5370*4c3eb207Smrg poplevel (0, 0);
5371*4c3eb207Smrg break;
5372627f7eb2Smrg case EXEC_OMP_TARGET_SIMD:
5373627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5374627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5375627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5376627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5377627f7eb2Smrg else
5378627f7eb2Smrg poplevel (0, 0);
5379627f7eb2Smrg break;
5380627f7eb2Smrg default:
5381627f7eb2Smrg if (flag_openmp
5382627f7eb2Smrg && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
5383627f7eb2Smrg || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
5384627f7eb2Smrg {
5385627f7eb2Smrg gfc_omp_clauses clausesb;
5386627f7eb2Smrg tree teams_clauses;
5387627f7eb2Smrg /* For combined !$omp target teams, the num_teams and
5388627f7eb2Smrg thread_limit clauses are evaluated before entering the
5389627f7eb2Smrg target construct. */
5390627f7eb2Smrg memset (&clausesb, '\0', sizeof (clausesb));
5391627f7eb2Smrg clausesb.num_teams = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams;
5392627f7eb2Smrg clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
5393627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].num_teams = NULL;
5394627f7eb2Smrg clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
5395627f7eb2Smrg teams_clauses
5396627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
5397627f7eb2Smrg pushlevel ();
5398627f7eb2Smrg stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
5399627f7eb2Smrg }
5400627f7eb2Smrg else
5401627f7eb2Smrg {
5402627f7eb2Smrg pushlevel ();
5403627f7eb2Smrg stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
5404627f7eb2Smrg }
5405627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5406627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5407627f7eb2Smrg else
5408627f7eb2Smrg poplevel (0, 0);
5409627f7eb2Smrg break;
5410627f7eb2Smrg }
5411627f7eb2Smrg if (flag_openmp)
5412627f7eb2Smrg {
5413*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET,
5414*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5415627f7eb2Smrg if (code->op != EXEC_OMP_TARGET)
5416627f7eb2Smrg OMP_TARGET_COMBINED (stmt) = 1;
5417627f7eb2Smrg }
5418627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5419627f7eb2Smrg return gfc_finish_block (&block);
5420627f7eb2Smrg }
5421627f7eb2Smrg
5422627f7eb2Smrg static tree
gfc_trans_omp_taskloop(gfc_code * code)5423627f7eb2Smrg gfc_trans_omp_taskloop (gfc_code *code)
5424627f7eb2Smrg {
5425627f7eb2Smrg stmtblock_t block;
5426627f7eb2Smrg gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
5427627f7eb2Smrg tree stmt, omp_clauses = NULL_TREE;
5428627f7eb2Smrg
5429627f7eb2Smrg gfc_start_block (&block);
5430627f7eb2Smrg gfc_split_omp_clauses (code, clausesa);
5431627f7eb2Smrg if (flag_openmp)
5432627f7eb2Smrg omp_clauses
5433627f7eb2Smrg = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
5434627f7eb2Smrg code->loc);
5435627f7eb2Smrg switch (code->op)
5436627f7eb2Smrg {
5437627f7eb2Smrg case EXEC_OMP_TASKLOOP:
5438627f7eb2Smrg /* This is handled in gfc_trans_omp_do. */
5439627f7eb2Smrg gcc_unreachable ();
5440627f7eb2Smrg break;
5441627f7eb2Smrg case EXEC_OMP_TASKLOOP_SIMD:
5442627f7eb2Smrg stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
5443627f7eb2Smrg &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
5444627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5445627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
5446627f7eb2Smrg else
5447627f7eb2Smrg poplevel (0, 0);
5448627f7eb2Smrg break;
5449627f7eb2Smrg default:
5450627f7eb2Smrg gcc_unreachable ();
5451627f7eb2Smrg }
5452627f7eb2Smrg if (flag_openmp)
5453627f7eb2Smrg {
5454627f7eb2Smrg tree taskloop = make_node (OMP_TASKLOOP);
5455627f7eb2Smrg TREE_TYPE (taskloop) = void_type_node;
5456627f7eb2Smrg OMP_FOR_BODY (taskloop) = stmt;
5457627f7eb2Smrg OMP_FOR_CLAUSES (taskloop) = omp_clauses;
5458627f7eb2Smrg stmt = taskloop;
5459627f7eb2Smrg }
5460627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5461627f7eb2Smrg return gfc_finish_block (&block);
5462627f7eb2Smrg }
5463627f7eb2Smrg
5464627f7eb2Smrg static tree
gfc_trans_omp_target_data(gfc_code * code)5465627f7eb2Smrg gfc_trans_omp_target_data (gfc_code *code)
5466627f7eb2Smrg {
5467627f7eb2Smrg stmtblock_t block;
5468627f7eb2Smrg tree stmt, omp_clauses;
5469627f7eb2Smrg
5470627f7eb2Smrg gfc_start_block (&block);
5471627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5472627f7eb2Smrg code->loc);
5473627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5474*4c3eb207Smrg stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA,
5475*4c3eb207Smrg void_type_node, stmt, omp_clauses);
5476627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5477627f7eb2Smrg return gfc_finish_block (&block);
5478627f7eb2Smrg }
5479627f7eb2Smrg
5480627f7eb2Smrg static tree
gfc_trans_omp_target_enter_data(gfc_code * code)5481627f7eb2Smrg gfc_trans_omp_target_enter_data (gfc_code *code)
5482627f7eb2Smrg {
5483627f7eb2Smrg stmtblock_t block;
5484627f7eb2Smrg tree stmt, omp_clauses;
5485627f7eb2Smrg
5486627f7eb2Smrg gfc_start_block (&block);
5487627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5488627f7eb2Smrg code->loc);
5489627f7eb2Smrg stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
5490627f7eb2Smrg omp_clauses);
5491627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5492627f7eb2Smrg return gfc_finish_block (&block);
5493627f7eb2Smrg }
5494627f7eb2Smrg
5495627f7eb2Smrg static tree
gfc_trans_omp_target_exit_data(gfc_code * code)5496627f7eb2Smrg gfc_trans_omp_target_exit_data (gfc_code *code)
5497627f7eb2Smrg {
5498627f7eb2Smrg stmtblock_t block;
5499627f7eb2Smrg tree stmt, omp_clauses;
5500627f7eb2Smrg
5501627f7eb2Smrg gfc_start_block (&block);
5502627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5503627f7eb2Smrg code->loc);
5504627f7eb2Smrg stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
5505627f7eb2Smrg omp_clauses);
5506627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5507627f7eb2Smrg return gfc_finish_block (&block);
5508627f7eb2Smrg }
5509627f7eb2Smrg
5510627f7eb2Smrg static tree
gfc_trans_omp_target_update(gfc_code * code)5511627f7eb2Smrg gfc_trans_omp_target_update (gfc_code *code)
5512627f7eb2Smrg {
5513627f7eb2Smrg stmtblock_t block;
5514627f7eb2Smrg tree stmt, omp_clauses;
5515627f7eb2Smrg
5516627f7eb2Smrg gfc_start_block (&block);
5517627f7eb2Smrg omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
5518627f7eb2Smrg code->loc);
5519627f7eb2Smrg stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
5520627f7eb2Smrg omp_clauses);
5521627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5522627f7eb2Smrg return gfc_finish_block (&block);
5523627f7eb2Smrg }
5524627f7eb2Smrg
5525627f7eb2Smrg static tree
gfc_trans_omp_workshare(gfc_code * code,gfc_omp_clauses * clauses)5526627f7eb2Smrg gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
5527627f7eb2Smrg {
5528627f7eb2Smrg tree res, tmp, stmt;
5529627f7eb2Smrg stmtblock_t block, *pblock = NULL;
5530627f7eb2Smrg stmtblock_t singleblock;
5531627f7eb2Smrg int saved_ompws_flags;
5532627f7eb2Smrg bool singleblock_in_progress = false;
5533627f7eb2Smrg /* True if previous gfc_code in workshare construct is not workshared. */
5534627f7eb2Smrg bool prev_singleunit;
5535*4c3eb207Smrg location_t loc = gfc_get_location (&code->loc);
5536627f7eb2Smrg
5537627f7eb2Smrg code = code->block->next;
5538627f7eb2Smrg
5539627f7eb2Smrg pushlevel ();
5540627f7eb2Smrg
5541627f7eb2Smrg gfc_start_block (&block);
5542627f7eb2Smrg pblock = █
5543627f7eb2Smrg
5544627f7eb2Smrg ompws_flags = OMPWS_WORKSHARE_FLAG;
5545627f7eb2Smrg prev_singleunit = false;
5546627f7eb2Smrg
5547627f7eb2Smrg /* Translate statements one by one to trees until we reach
5548627f7eb2Smrg the end of the workshare construct. Adjacent gfc_codes that
5549627f7eb2Smrg are a single unit of work are clustered and encapsulated in a
5550627f7eb2Smrg single OMP_SINGLE construct. */
5551627f7eb2Smrg for (; code; code = code->next)
5552627f7eb2Smrg {
5553627f7eb2Smrg if (code->here != 0)
5554627f7eb2Smrg {
5555627f7eb2Smrg res = gfc_trans_label_here (code);
5556627f7eb2Smrg gfc_add_expr_to_block (pblock, res);
5557627f7eb2Smrg }
5558627f7eb2Smrg
5559627f7eb2Smrg /* No dependence analysis, use for clauses with wait.
5560627f7eb2Smrg If this is the last gfc_code, use default omp_clauses. */
5561627f7eb2Smrg if (code->next == NULL && clauses->nowait)
5562627f7eb2Smrg ompws_flags |= OMPWS_NOWAIT;
5563627f7eb2Smrg
5564627f7eb2Smrg /* By default, every gfc_code is a single unit of work. */
5565627f7eb2Smrg ompws_flags |= OMPWS_CURR_SINGLEUNIT;
5566627f7eb2Smrg ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY);
5567627f7eb2Smrg
5568627f7eb2Smrg switch (code->op)
5569627f7eb2Smrg {
5570627f7eb2Smrg case EXEC_NOP:
5571627f7eb2Smrg res = NULL_TREE;
5572627f7eb2Smrg break;
5573627f7eb2Smrg
5574627f7eb2Smrg case EXEC_ASSIGN:
5575627f7eb2Smrg res = gfc_trans_assign (code);
5576627f7eb2Smrg break;
5577627f7eb2Smrg
5578627f7eb2Smrg case EXEC_POINTER_ASSIGN:
5579627f7eb2Smrg res = gfc_trans_pointer_assign (code);
5580627f7eb2Smrg break;
5581627f7eb2Smrg
5582627f7eb2Smrg case EXEC_INIT_ASSIGN:
5583627f7eb2Smrg res = gfc_trans_init_assign (code);
5584627f7eb2Smrg break;
5585627f7eb2Smrg
5586627f7eb2Smrg case EXEC_FORALL:
5587627f7eb2Smrg res = gfc_trans_forall (code);
5588627f7eb2Smrg break;
5589627f7eb2Smrg
5590627f7eb2Smrg case EXEC_WHERE:
5591627f7eb2Smrg res = gfc_trans_where (code);
5592627f7eb2Smrg break;
5593627f7eb2Smrg
5594627f7eb2Smrg case EXEC_OMP_ATOMIC:
5595627f7eb2Smrg res = gfc_trans_omp_directive (code);
5596627f7eb2Smrg break;
5597627f7eb2Smrg
5598627f7eb2Smrg case EXEC_OMP_PARALLEL:
5599627f7eb2Smrg case EXEC_OMP_PARALLEL_DO:
5600627f7eb2Smrg case EXEC_OMP_PARALLEL_SECTIONS:
5601627f7eb2Smrg case EXEC_OMP_PARALLEL_WORKSHARE:
5602627f7eb2Smrg case EXEC_OMP_CRITICAL:
5603627f7eb2Smrg saved_ompws_flags = ompws_flags;
5604627f7eb2Smrg ompws_flags = 0;
5605627f7eb2Smrg res = gfc_trans_omp_directive (code);
5606627f7eb2Smrg ompws_flags = saved_ompws_flags;
5607627f7eb2Smrg break;
5608627f7eb2Smrg
5609627f7eb2Smrg default:
5610627f7eb2Smrg gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
5611627f7eb2Smrg }
5612627f7eb2Smrg
5613627f7eb2Smrg gfc_set_backend_locus (&code->loc);
5614627f7eb2Smrg
5615627f7eb2Smrg if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
5616627f7eb2Smrg {
5617627f7eb2Smrg if (prev_singleunit)
5618627f7eb2Smrg {
5619627f7eb2Smrg if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
5620627f7eb2Smrg /* Add current gfc_code to single block. */
5621627f7eb2Smrg gfc_add_expr_to_block (&singleblock, res);
5622627f7eb2Smrg else
5623627f7eb2Smrg {
5624627f7eb2Smrg /* Finish single block and add it to pblock. */
5625627f7eb2Smrg tmp = gfc_finish_block (&singleblock);
5626*4c3eb207Smrg tmp = build2_loc (loc, OMP_SINGLE,
5627627f7eb2Smrg void_type_node, tmp, NULL_TREE);
5628627f7eb2Smrg gfc_add_expr_to_block (pblock, tmp);
5629627f7eb2Smrg /* Add current gfc_code to pblock. */
5630627f7eb2Smrg gfc_add_expr_to_block (pblock, res);
5631627f7eb2Smrg singleblock_in_progress = false;
5632627f7eb2Smrg }
5633627f7eb2Smrg }
5634627f7eb2Smrg else
5635627f7eb2Smrg {
5636627f7eb2Smrg if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
5637627f7eb2Smrg {
5638627f7eb2Smrg /* Start single block. */
5639627f7eb2Smrg gfc_init_block (&singleblock);
5640627f7eb2Smrg gfc_add_expr_to_block (&singleblock, res);
5641627f7eb2Smrg singleblock_in_progress = true;
5642*4c3eb207Smrg loc = gfc_get_location (&code->loc);
5643627f7eb2Smrg }
5644627f7eb2Smrg else
5645627f7eb2Smrg /* Add the new statement to the block. */
5646627f7eb2Smrg gfc_add_expr_to_block (pblock, res);
5647627f7eb2Smrg }
5648627f7eb2Smrg prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
5649627f7eb2Smrg }
5650627f7eb2Smrg }
5651627f7eb2Smrg
5652627f7eb2Smrg /* Finish remaining SINGLE block, if we were in the middle of one. */
5653627f7eb2Smrg if (singleblock_in_progress)
5654627f7eb2Smrg {
5655627f7eb2Smrg /* Finish single block and add it to pblock. */
5656627f7eb2Smrg tmp = gfc_finish_block (&singleblock);
5657*4c3eb207Smrg tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp,
5658627f7eb2Smrg clauses->nowait
5659627f7eb2Smrg ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
5660627f7eb2Smrg : NULL_TREE);
5661627f7eb2Smrg gfc_add_expr_to_block (pblock, tmp);
5662627f7eb2Smrg }
5663627f7eb2Smrg
5664627f7eb2Smrg stmt = gfc_finish_block (pblock);
5665627f7eb2Smrg if (TREE_CODE (stmt) != BIND_EXPR)
5666627f7eb2Smrg {
5667627f7eb2Smrg if (!IS_EMPTY_STMT (stmt))
5668627f7eb2Smrg {
5669627f7eb2Smrg tree bindblock = poplevel (1, 0);
5670627f7eb2Smrg stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
5671627f7eb2Smrg }
5672627f7eb2Smrg else
5673627f7eb2Smrg poplevel (0, 0);
5674627f7eb2Smrg }
5675627f7eb2Smrg else
5676627f7eb2Smrg poplevel (0, 0);
5677627f7eb2Smrg
5678627f7eb2Smrg if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
5679627f7eb2Smrg stmt = gfc_trans_omp_barrier ();
5680627f7eb2Smrg
5681627f7eb2Smrg ompws_flags = 0;
5682627f7eb2Smrg return stmt;
5683627f7eb2Smrg }
5684627f7eb2Smrg
5685627f7eb2Smrg tree
gfc_trans_oacc_declare(gfc_code * code)5686627f7eb2Smrg gfc_trans_oacc_declare (gfc_code *code)
5687627f7eb2Smrg {
5688627f7eb2Smrg stmtblock_t block;
5689627f7eb2Smrg tree stmt, oacc_clauses;
5690627f7eb2Smrg enum tree_code construct_code;
5691627f7eb2Smrg
5692627f7eb2Smrg construct_code = OACC_DATA;
5693627f7eb2Smrg
5694627f7eb2Smrg gfc_start_block (&block);
5695627f7eb2Smrg
5696627f7eb2Smrg oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses,
5697627f7eb2Smrg code->loc);
5698627f7eb2Smrg stmt = gfc_trans_omp_code (code->block->next, true);
5699627f7eb2Smrg stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
5700627f7eb2Smrg oacc_clauses);
5701627f7eb2Smrg gfc_add_expr_to_block (&block, stmt);
5702627f7eb2Smrg
5703627f7eb2Smrg return gfc_finish_block (&block);
5704627f7eb2Smrg }
5705627f7eb2Smrg
5706627f7eb2Smrg tree
gfc_trans_oacc_directive(gfc_code * code)5707627f7eb2Smrg gfc_trans_oacc_directive (gfc_code *code)
5708627f7eb2Smrg {
5709627f7eb2Smrg switch (code->op)
5710627f7eb2Smrg {
5711627f7eb2Smrg case EXEC_OACC_PARALLEL_LOOP:
5712627f7eb2Smrg case EXEC_OACC_KERNELS_LOOP:
5713*4c3eb207Smrg case EXEC_OACC_SERIAL_LOOP:
5714627f7eb2Smrg return gfc_trans_oacc_combined_directive (code);
5715627f7eb2Smrg case EXEC_OACC_PARALLEL:
5716627f7eb2Smrg case EXEC_OACC_KERNELS:
5717*4c3eb207Smrg case EXEC_OACC_SERIAL:
5718627f7eb2Smrg case EXEC_OACC_DATA:
5719627f7eb2Smrg case EXEC_OACC_HOST_DATA:
5720627f7eb2Smrg return gfc_trans_oacc_construct (code);
5721627f7eb2Smrg case EXEC_OACC_LOOP:
5722627f7eb2Smrg return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
5723627f7eb2Smrg NULL);
5724627f7eb2Smrg case EXEC_OACC_UPDATE:
5725627f7eb2Smrg case EXEC_OACC_CACHE:
5726627f7eb2Smrg case EXEC_OACC_ENTER_DATA:
5727627f7eb2Smrg case EXEC_OACC_EXIT_DATA:
5728627f7eb2Smrg return gfc_trans_oacc_executable_directive (code);
5729627f7eb2Smrg case EXEC_OACC_WAIT:
5730627f7eb2Smrg return gfc_trans_oacc_wait_directive (code);
5731627f7eb2Smrg case EXEC_OACC_ATOMIC:
5732627f7eb2Smrg return gfc_trans_omp_atomic (code);
5733627f7eb2Smrg case EXEC_OACC_DECLARE:
5734627f7eb2Smrg return gfc_trans_oacc_declare (code);
5735627f7eb2Smrg default:
5736627f7eb2Smrg gcc_unreachable ();
5737627f7eb2Smrg }
5738627f7eb2Smrg }
5739627f7eb2Smrg
5740627f7eb2Smrg tree
gfc_trans_omp_directive(gfc_code * code)5741627f7eb2Smrg gfc_trans_omp_directive (gfc_code *code)
5742627f7eb2Smrg {
5743627f7eb2Smrg switch (code->op)
5744627f7eb2Smrg {
5745627f7eb2Smrg case EXEC_OMP_ATOMIC:
5746627f7eb2Smrg return gfc_trans_omp_atomic (code);
5747627f7eb2Smrg case EXEC_OMP_BARRIER:
5748627f7eb2Smrg return gfc_trans_omp_barrier ();
5749627f7eb2Smrg case EXEC_OMP_CANCEL:
5750627f7eb2Smrg return gfc_trans_omp_cancel (code);
5751627f7eb2Smrg case EXEC_OMP_CANCELLATION_POINT:
5752627f7eb2Smrg return gfc_trans_omp_cancellation_point (code);
5753627f7eb2Smrg case EXEC_OMP_CRITICAL:
5754627f7eb2Smrg return gfc_trans_omp_critical (code);
5755627f7eb2Smrg case EXEC_OMP_DISTRIBUTE:
5756627f7eb2Smrg case EXEC_OMP_DO:
5757627f7eb2Smrg case EXEC_OMP_SIMD:
5758627f7eb2Smrg case EXEC_OMP_TASKLOOP:
5759627f7eb2Smrg return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
5760627f7eb2Smrg NULL);
5761627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5762627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5763627f7eb2Smrg case EXEC_OMP_DISTRIBUTE_SIMD:
5764627f7eb2Smrg return gfc_trans_omp_distribute (code, NULL);
5765627f7eb2Smrg case EXEC_OMP_DO_SIMD:
5766627f7eb2Smrg return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
5767627f7eb2Smrg case EXEC_OMP_FLUSH:
5768627f7eb2Smrg return gfc_trans_omp_flush ();
5769627f7eb2Smrg case EXEC_OMP_MASTER:
5770627f7eb2Smrg return gfc_trans_omp_master (code);
5771627f7eb2Smrg case EXEC_OMP_ORDERED:
5772627f7eb2Smrg return gfc_trans_omp_ordered (code);
5773627f7eb2Smrg case EXEC_OMP_PARALLEL:
5774627f7eb2Smrg return gfc_trans_omp_parallel (code);
5775627f7eb2Smrg case EXEC_OMP_PARALLEL_DO:
5776627f7eb2Smrg return gfc_trans_omp_parallel_do (code, NULL, NULL);
5777627f7eb2Smrg case EXEC_OMP_PARALLEL_DO_SIMD:
5778627f7eb2Smrg return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
5779627f7eb2Smrg case EXEC_OMP_PARALLEL_SECTIONS:
5780627f7eb2Smrg return gfc_trans_omp_parallel_sections (code);
5781627f7eb2Smrg case EXEC_OMP_PARALLEL_WORKSHARE:
5782627f7eb2Smrg return gfc_trans_omp_parallel_workshare (code);
5783627f7eb2Smrg case EXEC_OMP_SECTIONS:
5784627f7eb2Smrg return gfc_trans_omp_sections (code, code->ext.omp_clauses);
5785627f7eb2Smrg case EXEC_OMP_SINGLE:
5786627f7eb2Smrg return gfc_trans_omp_single (code, code->ext.omp_clauses);
5787627f7eb2Smrg case EXEC_OMP_TARGET:
5788627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL:
5789627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL_DO:
5790627f7eb2Smrg case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5791627f7eb2Smrg case EXEC_OMP_TARGET_SIMD:
5792627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS:
5793627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5794627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5795627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5796627f7eb2Smrg case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5797627f7eb2Smrg return gfc_trans_omp_target (code);
5798627f7eb2Smrg case EXEC_OMP_TARGET_DATA:
5799627f7eb2Smrg return gfc_trans_omp_target_data (code);
5800627f7eb2Smrg case EXEC_OMP_TARGET_ENTER_DATA:
5801627f7eb2Smrg return gfc_trans_omp_target_enter_data (code);
5802627f7eb2Smrg case EXEC_OMP_TARGET_EXIT_DATA:
5803627f7eb2Smrg return gfc_trans_omp_target_exit_data (code);
5804627f7eb2Smrg case EXEC_OMP_TARGET_UPDATE:
5805627f7eb2Smrg return gfc_trans_omp_target_update (code);
5806627f7eb2Smrg case EXEC_OMP_TASK:
5807627f7eb2Smrg return gfc_trans_omp_task (code);
5808627f7eb2Smrg case EXEC_OMP_TASKGROUP:
5809627f7eb2Smrg return gfc_trans_omp_taskgroup (code);
5810627f7eb2Smrg case EXEC_OMP_TASKLOOP_SIMD:
5811627f7eb2Smrg return gfc_trans_omp_taskloop (code);
5812627f7eb2Smrg case EXEC_OMP_TASKWAIT:
5813627f7eb2Smrg return gfc_trans_omp_taskwait ();
5814627f7eb2Smrg case EXEC_OMP_TASKYIELD:
5815627f7eb2Smrg return gfc_trans_omp_taskyield ();
5816627f7eb2Smrg case EXEC_OMP_TEAMS:
5817627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE:
5818627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5819627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5820627f7eb2Smrg case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5821627f7eb2Smrg return gfc_trans_omp_teams (code, NULL, NULL_TREE);
5822627f7eb2Smrg case EXEC_OMP_WORKSHARE:
5823627f7eb2Smrg return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
5824627f7eb2Smrg default:
5825627f7eb2Smrg gcc_unreachable ();
5826627f7eb2Smrg }
5827627f7eb2Smrg }
5828627f7eb2Smrg
5829627f7eb2Smrg void
gfc_trans_omp_declare_simd(gfc_namespace * ns)5830627f7eb2Smrg gfc_trans_omp_declare_simd (gfc_namespace *ns)
5831627f7eb2Smrg {
5832627f7eb2Smrg if (ns->entries)
5833627f7eb2Smrg return;
5834627f7eb2Smrg
5835627f7eb2Smrg gfc_omp_declare_simd *ods;
5836627f7eb2Smrg for (ods = ns->omp_declare_simd; ods; ods = ods->next)
5837627f7eb2Smrg {
5838627f7eb2Smrg tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
5839627f7eb2Smrg tree fndecl = ns->proc_name->backend_decl;
5840627f7eb2Smrg if (c != NULL_TREE)
5841627f7eb2Smrg c = tree_cons (NULL_TREE, c, NULL_TREE);
5842627f7eb2Smrg c = build_tree_list (get_identifier ("omp declare simd"), c);
5843627f7eb2Smrg TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
5844627f7eb2Smrg DECL_ATTRIBUTES (fndecl) = c;
5845627f7eb2Smrg }
5846627f7eb2Smrg }
5847