Line data Source code
1 : /* This file contains routines to construct OpenACC and OpenMP constructs,
2 : called from parsing in the C and C++ front ends.
3 :
4 : Copyright (C) 2005-2026 Free Software Foundation, Inc.
5 : Contributed by Richard Henderson <rth@redhat.com>,
6 : Diego Novillo <dnovillo@redhat.com>.
7 :
8 : This file is part of GCC.
9 :
10 : GCC is free software; you can redistribute it and/or modify it under
11 : the terms of the GNU General Public License as published by the Free
12 : Software Foundation; either version 3, or (at your option) any later
13 : version.
14 :
15 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 : for more details.
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with GCC; see the file COPYING3. If not see
22 : <http://www.gnu.org/licenses/>. */
23 :
24 : #include "config.h"
25 : #include "system.h"
26 : #include "coretypes.h"
27 : #include "options.h"
28 : #include "c-common.h"
29 : #include "gimple-expr.h"
30 : #include "c-pragma.h"
31 : #include "stringpool.h"
32 : #include "omp-general.h"
33 : #include "gomp-constants.h"
34 : #include "memmodel.h"
35 : #include "attribs.h"
36 : #include "gimplify.h"
37 : #include "langhooks.h"
38 : #include "bitmap.h"
39 : #include "tree-iterator.h"
40 :
41 :
42 : /* Complete a #pragma oacc wait construct. LOC is the location of
43 : the #pragma. */
44 :
45 : tree
46 241 : c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
47 : {
48 241 : const int nparms = list_length (parms);
49 241 : tree stmt, t;
50 241 : vec<tree, va_gc> *args;
51 :
52 241 : vec_alloc (args, nparms + 2);
53 241 : stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
54 :
55 241 : if ((t = omp_find_clause (clauses, OMP_CLAUSE_ASYNC)))
56 47 : t = OMP_CLAUSE_ASYNC_EXPR (t);
57 : else
58 194 : t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
59 :
60 241 : args->quick_push (t);
61 241 : args->quick_push (build_int_cst (integer_type_node, nparms));
62 :
63 380 : for (t = parms; t; t = TREE_CHAIN (t))
64 : {
65 139 : if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
66 42 : args->quick_push (build_int_cst (integer_type_node,
67 42 : TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t))));
68 : else
69 97 : args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
70 : }
71 :
72 241 : stmt = build_call_expr_loc_vec (loc, stmt, args);
73 :
74 241 : t = omp_find_clause (clauses, OMP_CLAUSE_IF);
75 241 : if (t)
76 24 : stmt = build3_loc (input_location, COND_EXPR, void_type_node,
77 24 : OMP_CLAUSE_IF_EXPR (t), stmt, NULL_TREE);
78 :
79 241 : vec_free (args);
80 :
81 241 : return stmt;
82 : }
83 :
84 : /* Complete a #pragma omp master construct. STMT is the structured-block
85 : that follows the pragma. LOC is the location of the #pragma. */
86 :
87 : tree
88 718 : c_finish_omp_master (location_t loc, tree stmt)
89 : {
90 718 : tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
91 718 : SET_EXPR_LOCATION (t, loc);
92 718 : return t;
93 : }
94 :
95 : /* Complete a #pragma omp masked construct. BODY is the structured-block
96 : that follows the pragma. LOC is the location of the #pragma. */
97 :
98 : tree
99 421 : c_finish_omp_masked (location_t loc, tree body, tree clauses)
100 : {
101 421 : tree stmt = make_node (OMP_MASKED);
102 421 : TREE_TYPE (stmt) = void_type_node;
103 421 : OMP_MASKED_BODY (stmt) = body;
104 421 : OMP_MASKED_CLAUSES (stmt) = clauses;
105 421 : SET_EXPR_LOCATION (stmt, loc);
106 421 : return add_stmt (stmt);
107 : }
108 :
109 : /* Complete a #pragma omp taskgroup construct. BODY is the structured-block
110 : that follows the pragma. LOC is the location of the #pragma. */
111 :
112 : tree
113 430 : c_finish_omp_taskgroup (location_t loc, tree body, tree clauses)
114 : {
115 430 : tree stmt = make_node (OMP_TASKGROUP);
116 430 : TREE_TYPE (stmt) = void_type_node;
117 430 : OMP_TASKGROUP_BODY (stmt) = body;
118 430 : OMP_TASKGROUP_CLAUSES (stmt) = clauses;
119 430 : SET_EXPR_LOCATION (stmt, loc);
120 430 : return add_stmt (stmt);
121 : }
122 :
123 : /* Complete a #pragma omp critical construct. BODY is the structured-block
124 : that follows the pragma, NAME is the identifier in the pragma, or null
125 : if it was omitted. LOC is the location of the #pragma. */
126 :
127 : tree
128 411 : c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
129 : {
130 492 : gcc_assert (!clauses || OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT);
131 411 : if (name == NULL_TREE
132 411 : && clauses != NULL_TREE
133 411 : && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (clauses)))
134 : {
135 2 : error_at (OMP_CLAUSE_LOCATION (clauses),
136 : "%<#pragma omp critical%> with %<hint%> clause requires "
137 : "a name, except when %<omp_sync_hint_none%> is used");
138 2 : return error_mark_node;
139 : }
140 :
141 409 : tree stmt = make_node (OMP_CRITICAL);
142 409 : TREE_TYPE (stmt) = void_type_node;
143 409 : OMP_CRITICAL_BODY (stmt) = body;
144 409 : OMP_CRITICAL_NAME (stmt) = name;
145 409 : OMP_CRITICAL_CLAUSES (stmt) = clauses;
146 409 : SET_EXPR_LOCATION (stmt, loc);
147 409 : return add_stmt (stmt);
148 : }
149 :
150 : /* Complete a #pragma omp ordered construct. STMT is the structured-block
151 : that follows the pragma. LOC is the location of the #pragma. */
152 :
153 : tree
154 1566 : c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
155 : {
156 1566 : tree t = make_node (OMP_ORDERED);
157 1566 : TREE_TYPE (t) = void_type_node;
158 1566 : OMP_ORDERED_BODY (t) = stmt;
159 1566 : if (!flag_openmp /* flag_openmp_simd */
160 1606 : && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
161 40 : || OMP_CLAUSE_CHAIN (clauses)))
162 4 : clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
163 1566 : OMP_ORDERED_CLAUSES (t) = clauses;
164 1566 : SET_EXPR_LOCATION (t, loc);
165 1566 : return add_stmt (t);
166 : }
167 :
168 :
169 : /* Complete a #pragma omp barrier construct. LOC is the location of
170 : the #pragma. */
171 :
172 : void
173 346 : c_finish_omp_barrier (location_t loc)
174 : {
175 346 : tree x;
176 :
177 346 : x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
178 346 : x = build_call_expr_loc (loc, x, 1,
179 : build_int_cst (integer_type_node,
180 : GOMP_BARRIER_EXPLICIT));
181 346 : add_stmt (x);
182 346 : }
183 :
184 :
185 : /* Complete a #pragma omp taskwait construct. LOC is the location of the
186 : pragma. */
187 :
188 : void
189 72 : c_finish_omp_taskwait (location_t loc)
190 : {
191 72 : tree x;
192 :
193 72 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
194 72 : x = build_call_expr_loc (loc, x, 0);
195 72 : add_stmt (x);
196 72 : }
197 :
198 :
199 : /* Complete a #pragma omp taskyield construct. LOC is the location of the
200 : pragma. */
201 :
202 : void
203 6 : c_finish_omp_taskyield (location_t loc)
204 : {
205 6 : tree x;
206 :
207 6 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
208 6 : x = build_call_expr_loc (loc, x, 0);
209 6 : add_stmt (x);
210 6 : }
211 :
212 :
213 : /* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC
214 : the expression to be implemented atomically is LHS opcode= RHS.
215 : For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
216 : opcode= RHS with the new or old content of LHS returned.
217 : LOC is the location of the atomic statement. The value returned
218 : is either error_mark_node (if the construct was erroneous) or an
219 : OMP_ATOMIC* node which should be added to the current statement
220 : tree with add_stmt. If TEST is set, avoid calling save_expr
221 : or create_tmp_var*. */
222 :
223 : tree
224 4592 : c_finish_omp_atomic (location_t loc, enum tree_code code,
225 : enum tree_code opcode, tree lhs, tree rhs,
226 : tree v, tree lhs1, tree rhs1, tree r, bool swapped,
227 : enum omp_memory_order memory_order, bool weak,
228 : bool test)
229 : {
230 4592 : tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
231 4592 : HOST_WIDE_INT bitpos = 0, bitsize = 0;
232 4592 : enum tree_code orig_opcode = opcode;
233 :
234 4592 : if (lhs == error_mark_node || rhs == error_mark_node
235 4592 : || v == error_mark_node || lhs1 == error_mark_node
236 4592 : || rhs1 == error_mark_node || r == error_mark_node)
237 : return error_mark_node;
238 :
239 : /* ??? According to one reading of the OpenMP spec, complex type are
240 : supported, but there are no atomic stores for any architecture.
241 : But at least icc 9.0 doesn't support complex types here either.
242 : And lets not even talk about vector types... */
243 4592 : type = TREE_TYPE (lhs);
244 4592 : if (!INTEGRAL_TYPE_P (type)
245 882 : && !POINTER_TYPE_P (type)
246 872 : && !SCALAR_FLOAT_TYPE_P (type))
247 : {
248 7 : error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
249 7 : return error_mark_node;
250 : }
251 4585 : if (TYPE_ATOMIC (type))
252 : {
253 8 : error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
254 8 : return error_mark_node;
255 : }
256 4577 : if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
257 : {
258 4 : error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
259 : "comparison result");
260 4 : return error_mark_node;
261 : }
262 :
263 4573 : if (opcode == RDIV_EXPR)
264 0 : opcode = TRUNC_DIV_EXPR;
265 :
266 : /* ??? Validate that rhs does not overlap lhs. */
267 4573 : tree blhs = NULL;
268 4573 : if (TREE_CODE (lhs) == COMPONENT_REF
269 69 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
270 69 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
271 4623 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
272 : {
273 50 : tree field = TREE_OPERAND (lhs, 1);
274 50 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
275 50 : if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
276 100 : && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
277 50 : bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
278 50 : - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
279 : else
280 : bitpos = 0;
281 50 : bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
282 50 : - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
283 50 : gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
284 50 : bitsize = tree_to_shwi (DECL_SIZE (field));
285 50 : blhs = lhs;
286 50 : type = TREE_TYPE (repr);
287 50 : lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
288 50 : repr, TREE_OPERAND (lhs, 2));
289 : }
290 :
291 : /* Take and save the address of the lhs. From then on we'll reference it
292 : via indirection. */
293 4573 : addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
294 4573 : if (addr == error_mark_node)
295 : return error_mark_node;
296 4564 : if (!test)
297 4351 : addr = save_expr (addr);
298 4351 : if (!test
299 4351 : && TREE_CODE (addr) != SAVE_EXPR
300 3756 : && (TREE_CODE (addr) != ADDR_EXPR
301 3577 : || !VAR_P (TREE_OPERAND (addr, 0))))
302 : {
303 : /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
304 : it even after unsharing function body. */
305 368 : tree var = create_tmp_var_raw (TREE_TYPE (addr));
306 368 : DECL_CONTEXT (var) = current_function_decl;
307 368 : addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
308 : }
309 4564 : tree orig_lhs = lhs;
310 4564 : lhs = build_indirect_ref (loc, addr, RO_NULL);
311 4564 : tree new_lhs = lhs;
312 :
313 4564 : if (code == OMP_ATOMIC_READ)
314 : {
315 750 : x = build1 (OMP_ATOMIC_READ, type, addr);
316 750 : SET_EXPR_LOCATION (x, loc);
317 750 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
318 750 : gcc_assert (!weak);
319 750 : if (blhs)
320 2 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
321 2 : bitsize_int (bitsize), bitsize_int (bitpos));
322 750 : return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
323 750 : loc, x, NULL_TREE);
324 : }
325 :
326 : /* There are lots of warnings, errors, and conversions that need to happen
327 : in the course of interpreting a statement. Use the normal mechanisms
328 : to do this, and then take it apart again. */
329 3814 : if (blhs)
330 : {
331 48 : lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
332 48 : bitsize_int (bitsize), bitsize_int (bitpos));
333 48 : if (opcode == COND_EXPR)
334 : {
335 16 : bool save = in_late_binary_op;
336 16 : in_late_binary_op = true;
337 16 : std::swap (rhs, rhs1);
338 16 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
339 16 : in_late_binary_op = save;
340 : }
341 32 : else if (swapped)
342 0 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
343 32 : else if (opcode != NOP_EXPR)
344 26 : rhs = build_binary_op (loc, opcode, lhs, rhs, true);
345 : opcode = NOP_EXPR;
346 : }
347 3766 : else if (opcode == COND_EXPR)
348 : {
349 334 : bool save = in_late_binary_op;
350 334 : in_late_binary_op = true;
351 334 : std::swap (rhs, rhs1);
352 334 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
353 334 : in_late_binary_op = save;
354 334 : opcode = NOP_EXPR;
355 : }
356 3432 : else if (swapped)
357 : {
358 124 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
359 124 : opcode = NOP_EXPR;
360 : }
361 3814 : bool save = in_late_binary_op;
362 3814 : in_late_binary_op = true;
363 3814 : if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
364 4102 : && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
365 288 : true) == error_mark_node)
366 : x = error_mark_node;
367 : else
368 7572 : x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
369 : loc, rhs, NULL_TREE);
370 3814 : in_late_binary_op = save;
371 3814 : if (x == error_mark_node)
372 : return error_mark_node;
373 3794 : if (TREE_CODE (x) == COMPOUND_EXPR)
374 : {
375 14 : pre = TREE_OPERAND (x, 0);
376 14 : gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
377 14 : x = TREE_OPERAND (x, 1);
378 : }
379 3794 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
380 3794 : rhs = TREE_OPERAND (x, 1);
381 :
382 3794 : if (blhs)
383 48 : rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
384 48 : rhs, bitsize_int (bitpos));
385 3794 : if (orig_opcode == COND_EXPR)
386 : {
387 350 : if (error_operand_p (rhs1))
388 0 : return error_mark_node;
389 350 : gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
390 350 : tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
391 350 : if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
392 : {
393 114 : bool clear_padding = false;
394 114 : HOST_WIDE_INT non_padding_start = 0;
395 114 : HOST_WIDE_INT non_padding_end = 0;
396 114 : if (BITS_PER_UNIT == 8
397 : && CHAR_BIT == 8
398 114 : && clear_padding_type_may_have_padding_p (cmptype))
399 : {
400 30 : HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
401 30 : gcc_assert (sz > 0);
402 30 : unsigned char *buf = XALLOCAVEC (unsigned char, sz);
403 30 : memset (buf, ~0, sz);
404 30 : clear_type_padding_in_mask (cmptype, buf);
405 360 : for (i = 0; i < sz; i++)
406 330 : if (buf[i] != (unsigned char) ~0)
407 : {
408 : clear_padding = true;
409 : break;
410 : }
411 30 : if (clear_padding && buf[i] == 0)
412 : {
413 : /* Try to optimize. In the common case where
414 : non-padding bits are all continuous and start
415 : and end at a byte boundary, we can just adjust
416 : the memcmp call arguments and don't need to
417 : emit __builtin_clear_padding calls. */
418 30 : if (i == 0)
419 : {
420 0 : for (i = 0; i < sz; i++)
421 0 : if (buf[i] != 0)
422 : break;
423 0 : if (i < sz && buf[i] == (unsigned char) ~0)
424 : {
425 0 : non_padding_start = i;
426 0 : for (; i < sz; i++)
427 0 : if (buf[i] != (unsigned char) ~0)
428 : break;
429 : }
430 : else
431 : i = 0;
432 : }
433 30 : if (i != 0)
434 : {
435 210 : non_padding_end = i;
436 210 : for (; i < sz; i++)
437 180 : if (buf[i] != 0)
438 : {
439 : non_padding_start = 0;
440 : non_padding_end = 0;
441 : break;
442 : }
443 : }
444 : }
445 : }
446 84 : tree inttype = NULL_TREE;
447 84 : if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
448 : {
449 84 : HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
450 84 : inttype = c_common_type_for_size (prec, 1);
451 84 : if (inttype
452 168 : && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
453 84 : TYPE_SIZE (inttype))
454 84 : || TYPE_PRECISION (inttype) != prec))
455 : inttype = NULL_TREE;
456 : }
457 84 : if (inttype)
458 : {
459 84 : TREE_OPERAND (rhs1, 0)
460 84 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
461 84 : TREE_OPERAND (rhs1, 0));
462 84 : TREE_OPERAND (rhs1, 1)
463 168 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
464 84 : TREE_OPERAND (rhs1, 1));
465 : }
466 : else
467 : {
468 30 : tree pcmptype = build_pointer_type (cmptype);
469 30 : tree tmp1 = create_tmp_var_raw (cmptype);
470 30 : TREE_ADDRESSABLE (tmp1) = 1;
471 30 : DECL_CONTEXT (tmp1) = current_function_decl;
472 30 : tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
473 30 : TREE_OPERAND (rhs1, 0), NULL, NULL);
474 30 : tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
475 30 : tree tmp2 = create_tmp_var_raw (cmptype);
476 30 : TREE_ADDRESSABLE (tmp2) = 1;
477 30 : DECL_CONTEXT (tmp2) = current_function_decl;
478 30 : tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
479 30 : TREE_OPERAND (rhs1, 1), NULL, NULL);
480 30 : tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
481 30 : if (non_padding_start)
482 : {
483 0 : tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
484 0 : size_int (non_padding_start));
485 0 : tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
486 0 : size_int (non_padding_start));
487 : }
488 30 : tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
489 60 : rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
490 : non_padding_end
491 30 : ? size_int (non_padding_end
492 : - non_padding_start)
493 0 : : TYPE_SIZE_UNIT (cmptype));
494 30 : rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
495 : integer_zero_node);
496 30 : if (clear_padding && non_padding_end == 0)
497 : {
498 0 : fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
499 0 : tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
500 0 : tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
501 0 : rhs1 = omit_two_operands_loc (loc, boolean_type_node,
502 : rhs1, cp2, cp1);
503 : }
504 : }
505 : }
506 350 : if (r && test)
507 : rtmp = rhs1;
508 325 : else if (r)
509 : {
510 118 : tree var = create_tmp_var_raw (boolean_type_node);
511 118 : DECL_CONTEXT (var) = current_function_decl;
512 118 : rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
513 : boolean_false_node, NULL, NULL);
514 118 : save = in_late_binary_op;
515 118 : in_late_binary_op = true;
516 118 : x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
517 : loc, rhs1, NULL_TREE);
518 118 : in_late_binary_op = save;
519 118 : if (x == error_mark_node)
520 : return error_mark_node;
521 118 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
522 : && TREE_OPERAND (x, 0) == var);
523 118 : TREE_OPERAND (x, 0) = rtmp;
524 118 : rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
525 : }
526 350 : rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs);
527 350 : rhs1 = NULL_TREE;
528 : }
529 :
530 : /* Punt the actual generation of atomic operations to common code. */
531 3794 : if (code == OMP_ATOMIC)
532 2524 : type = void_type_node;
533 3794 : x = build2 (code, type, addr, rhs);
534 3794 : SET_EXPR_LOCATION (x, loc);
535 3794 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
536 3794 : OMP_ATOMIC_WEAK (x) = weak;
537 :
538 : /* Generally it is hard to prove lhs1 and lhs are the same memory
539 : location, just diagnose different variables. */
540 3794 : if (rhs1
541 1031 : && VAR_P (rhs1)
542 439 : && VAR_P (orig_lhs)
543 439 : && rhs1 != orig_lhs
544 0 : && !test)
545 : {
546 0 : if (code == OMP_ATOMIC)
547 0 : error_at (loc, "%<#pragma omp atomic update%> uses two different "
548 : "variables for memory");
549 : else
550 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two different "
551 : "variables for memory");
552 0 : return error_mark_node;
553 : }
554 :
555 3794 : if (lhs1
556 3794 : && lhs1 != orig_lhs
557 325 : && TREE_CODE (lhs1) == COMPONENT_REF
558 12 : && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
559 12 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
560 3806 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
561 : {
562 12 : tree field = TREE_OPERAND (lhs1, 1);
563 12 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
564 12 : lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
565 12 : repr, TREE_OPERAND (lhs1, 2));
566 : }
567 3794 : if (rhs1
568 1031 : && rhs1 != orig_lhs
569 592 : && TREE_CODE (rhs1) == COMPONENT_REF
570 16 : && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
571 16 : && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
572 3810 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
573 : {
574 16 : tree field = TREE_OPERAND (rhs1, 1);
575 16 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
576 16 : rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
577 16 : repr, TREE_OPERAND (rhs1, 2));
578 : }
579 :
580 3794 : if (code != OMP_ATOMIC)
581 : {
582 : /* Generally it is hard to prove lhs1 and lhs are the same memory
583 : location, just diagnose different variables. */
584 1270 : if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
585 : {
586 434 : if (lhs1 != orig_lhs && !test)
587 : {
588 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two "
589 : "different variables for memory");
590 0 : return error_mark_node;
591 : }
592 : }
593 1270 : if (blhs)
594 28 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
595 28 : bitsize_int (bitsize), bitsize_int (bitpos));
596 1270 : if (r && !test)
597 : {
598 80 : vtmp = create_tmp_var_raw (TREE_TYPE (x));
599 80 : DECL_CONTEXT (vtmp) = current_function_decl;
600 : }
601 : else
602 : vtmp = v;
603 1270 : x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
604 : loc, x, NULL_TREE);
605 1270 : if (x == error_mark_node)
606 : return error_mark_node;
607 1266 : type = TREE_TYPE (x);
608 1266 : if (r && !test)
609 : {
610 80 : vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
611 80 : build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
612 80 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
613 : && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
614 80 : TREE_OPERAND (x, 0) = vtmp;
615 : }
616 1266 : if (rhs1 && rhs1 != orig_lhs)
617 : {
618 238 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
619 238 : if (rhs1addr == error_mark_node)
620 : return error_mark_node;
621 238 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
622 : }
623 1266 : if (lhs1 && lhs1 != orig_lhs)
624 : {
625 325 : tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
626 325 : if (lhs1addr == error_mark_node)
627 : return error_mark_node;
628 324 : if (code == OMP_ATOMIC_CAPTURE_OLD)
629 205 : x = omit_one_operand_loc (loc, type, x, lhs1addr);
630 : else
631 : {
632 119 : if (!test)
633 103 : x = save_expr (x);
634 119 : x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
635 : }
636 : }
637 : }
638 2524 : else if (rhs1 && rhs1 != orig_lhs)
639 : {
640 354 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
641 354 : if (rhs1addr == error_mark_node)
642 : return error_mark_node;
643 354 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
644 : }
645 :
646 3789 : if (pre)
647 14 : x = omit_one_operand_loc (loc, type, x, pre);
648 3789 : if (r && r != void_list_node)
649 : {
650 88 : in_late_binary_op = true;
651 88 : tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
652 : loc, rtmp, NULL_TREE);
653 88 : in_late_binary_op = save;
654 88 : if (x2 == error_mark_node)
655 : return error_mark_node;
656 88 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
657 : }
658 3789 : if (v && vtmp != v)
659 : {
660 80 : in_late_binary_op = true;
661 80 : tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
662 : loc, vtmp, NULL_TREE);
663 80 : in_late_binary_op = save;
664 80 : if (x2 == error_mark_node)
665 : return error_mark_node;
666 80 : x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp,
667 : void_node, x2);
668 80 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
669 : }
670 : return x;
671 : }
672 :
673 :
674 : /* Return true if TYPE is the implementation's omp_interop_t. */
675 :
676 : bool
677 1844 : c_omp_interop_t_p (tree type)
678 : {
679 1844 : if (type == error_mark_node)
680 : return false;
681 1820 : type = TYPE_MAIN_VARIANT (type);
682 1820 : return (TREE_CODE (type) == ENUMERAL_TYPE
683 1727 : && TYPE_NAME (type)
684 3454 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
685 1727 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
686 1727 : == get_identifier ("omp_interop_t"))
687 1727 : && TYPE_FILE_SCOPE_P (type)
688 1727 : && COMPLETE_TYPE_P (type)
689 1727 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
690 3547 : && !compare_tree_int (TYPE_SIZE (type),
691 1727 : tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
692 : }
693 :
694 : /* Return true if TYPE is the implementation's omp_depend_t. */
695 :
696 : bool
697 1214 : c_omp_depend_t_p (tree type)
698 : {
699 1214 : type = TYPE_MAIN_VARIANT (type);
700 1214 : return (TREE_CODE (type) == RECORD_TYPE
701 429 : && TYPE_NAME (type)
702 858 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
703 429 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
704 429 : == get_identifier ("omp_depend_t"))
705 411 : && TYPE_FILE_SCOPE_P (type)
706 411 : && COMPLETE_TYPE_P (type)
707 411 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
708 1625 : && !compare_tree_int (TYPE_SIZE (type),
709 411 : 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
710 : }
711 :
712 :
713 : /* Complete a #pragma omp depobj construct. LOC is the location of the
714 : #pragma. */
715 :
716 : void
717 355 : c_finish_omp_depobj (location_t loc, tree depobj,
718 : enum omp_clause_depend_kind kind, tree clause)
719 : {
720 355 : tree t = NULL_TREE;
721 355 : if (!error_operand_p (depobj))
722 : {
723 344 : if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
724 : {
725 42 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
726 : "type of %<depobj%> expression is not %<omp_depend_t%>");
727 21 : depobj = error_mark_node;
728 : }
729 323 : else if (TYPE_READONLY (TREE_TYPE (depobj)))
730 : {
731 14 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
732 : "%<const%> qualified %<depobj%> expression");
733 7 : depobj = error_mark_node;
734 : }
735 : }
736 : else
737 11 : depobj = error_mark_node;
738 :
739 355 : if (clause == error_mark_node)
740 355 : return;
741 :
742 317 : if (clause)
743 : {
744 169 : gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
745 169 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
746 : {
747 42 : error_at (OMP_CLAUSE_LOCATION (clause),
748 : "%<depend(%s)%> is only allowed in %<omp ordered%>",
749 14 : OMP_CLAUSE_DOACROSS_KIND (clause)
750 : == OMP_CLAUSE_DOACROSS_SOURCE
751 : ? "source" : "sink");
752 14 : return;
753 : }
754 155 : gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
755 155 : if (OMP_CLAUSE_CHAIN (clause))
756 7 : error_at (OMP_CLAUSE_LOCATION (clause),
757 : "more than one locator in %<depend%> clause on %<depobj%> "
758 : "construct");
759 155 : switch (OMP_CLAUSE_DEPEND_KIND (clause))
760 : {
761 7 : case OMP_CLAUSE_DEPEND_DEPOBJ:
762 7 : error_at (OMP_CLAUSE_LOCATION (clause),
763 : "%<depobj%> dependence type specified in %<depend%> "
764 : "clause on %<depobj%> construct");
765 7 : return;
766 148 : case OMP_CLAUSE_DEPEND_IN:
767 148 : case OMP_CLAUSE_DEPEND_OUT:
768 148 : case OMP_CLAUSE_DEPEND_INOUT:
769 148 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
770 148 : case OMP_CLAUSE_DEPEND_INOUTSET:
771 148 : kind = OMP_CLAUSE_DEPEND_KIND (clause);
772 148 : t = OMP_CLAUSE_DECL (clause);
773 148 : gcc_assert (t);
774 148 : if (OMP_ITERATOR_DECL_P (t))
775 : {
776 7 : error_at (OMP_CLAUSE_LOCATION (clause),
777 : "%<iterator%> modifier may not be specified on "
778 : "%<depobj%> construct");
779 7 : return;
780 : }
781 141 : if (TREE_CODE (t) == COMPOUND_EXPR)
782 : {
783 0 : tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
784 0 : t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
785 : t1);
786 : }
787 141 : else if (t != null_pointer_node)
788 133 : t = build_fold_addr_expr (t);
789 : break;
790 0 : default:
791 0 : gcc_unreachable ();
792 : }
793 : }
794 : else
795 148 : gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
796 :
797 289 : if (depobj == error_mark_node)
798 : return;
799 :
800 483 : depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
801 250 : tree dtype
802 250 : = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
803 : true);
804 250 : depobj = fold_convert (dtype, depobj);
805 250 : tree r;
806 250 : if (clause)
807 : {
808 127 : depobj = save_expr (depobj);
809 127 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
810 127 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
811 : }
812 250 : int k;
813 250 : switch (kind)
814 : {
815 : case OMP_CLAUSE_DEPEND_IN:
816 : k = GOMP_DEPEND_IN;
817 : break;
818 11 : case OMP_CLAUSE_DEPEND_OUT:
819 11 : k = GOMP_DEPEND_OUT;
820 11 : break;
821 45 : case OMP_CLAUSE_DEPEND_INOUT:
822 45 : k = GOMP_DEPEND_INOUT;
823 45 : break;
824 14 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
825 14 : k = GOMP_DEPEND_MUTEXINOUTSET;
826 14 : break;
827 12 : case OMP_CLAUSE_DEPEND_INOUTSET:
828 12 : k = GOMP_DEPEND_INOUTSET;
829 12 : break;
830 87 : case OMP_CLAUSE_DEPEND_LAST:
831 87 : k = -1;
832 87 : break;
833 0 : default:
834 0 : gcc_unreachable ();
835 : }
836 250 : t = build_int_cst (ptr_type_node, k);
837 250 : depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
838 250 : TYPE_SIZE_UNIT (ptr_type_node));
839 250 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
840 250 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
841 : }
842 :
843 :
844 : /* Complete a #pragma omp flush construct. We don't do anything with
845 : the variable list that the syntax allows. LOC is the location of
846 : the #pragma. */
847 :
848 : void
849 59 : c_finish_omp_flush (location_t loc, int mo)
850 : {
851 59 : tree x;
852 :
853 59 : if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
854 : {
855 41 : x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
856 41 : x = build_call_expr_loc (loc, x, 0);
857 : }
858 : else
859 : {
860 18 : x = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
861 18 : x = build_call_expr_loc (loc, x, 1,
862 18 : build_int_cst (integer_type_node, mo));
863 : }
864 59 : add_stmt (x);
865 59 : }
866 :
867 :
868 : /* Check and canonicalize OMP_FOR increment expression.
869 : Helper function for c_finish_omp_for. */
870 :
871 : static tree
872 609 : check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
873 : {
874 694 : tree t;
875 :
876 1388 : if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
877 1388 : || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
878 0 : return error_mark_node;
879 :
880 694 : if (exp == decl)
881 171 : return build_int_cst (TREE_TYPE (exp), 0);
882 :
883 523 : switch (TREE_CODE (exp))
884 : {
885 197 : CASE_CONVERT:
886 197 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
887 197 : if (t != error_mark_node)
888 165 : return fold_convert_loc (loc, TREE_TYPE (exp), t);
889 : break;
890 16 : case MINUS_EXPR:
891 16 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
892 16 : if (t != error_mark_node)
893 16 : return fold_build2_loc (loc, MINUS_EXPR,
894 32 : TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
895 : break;
896 172 : case PLUS_EXPR:
897 172 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
898 172 : if (t != error_mark_node)
899 131 : return fold_build2_loc (loc, PLUS_EXPR,
900 262 : TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
901 41 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
902 41 : if (t != error_mark_node)
903 33 : return fold_build2_loc (loc, PLUS_EXPR,
904 66 : TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
905 : break;
906 85 : case COMPOUND_EXPR:
907 85 : {
908 : /* cp_build_modify_expr forces preevaluation of the RHS to make
909 : sure that it is evaluated before the lvalue-rvalue conversion
910 : is applied to the LHS. Reconstruct the original expression. */
911 85 : tree op0 = TREE_OPERAND (exp, 0);
912 85 : if (TREE_CODE (op0) == TARGET_EXPR
913 85 : && !VOID_TYPE_P (TREE_TYPE (op0)))
914 : {
915 85 : tree op1 = TREE_OPERAND (exp, 1);
916 85 : tree temp = TARGET_EXPR_SLOT (op0);
917 85 : if (BINARY_CLASS_P (op1)
918 85 : && TREE_OPERAND (op1, 1) == temp)
919 : {
920 85 : op1 = copy_node (op1);
921 85 : TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
922 85 : return check_omp_for_incr_expr (loc, op1, decl);
923 : }
924 : }
925 : break;
926 : }
927 : default:
928 : break;
929 : }
930 :
931 93 : return error_mark_node;
932 : }
933 :
934 : /* If the OMP_FOR increment expression in INCR is of pointer type,
935 : canonicalize it into an expression handled by gimplify_omp_for()
936 : and return it. DECL is the iteration variable. */
937 :
938 : static tree
939 31984 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
940 : {
941 61961 : if (POINTER_TYPE_P (TREE_TYPE (decl))
942 31984 : && TREE_OPERAND (incr, 1))
943 : {
944 1997 : tree t = fold_convert_loc (loc,
945 1997 : sizetype, TREE_OPERAND (incr, 1));
946 :
947 1997 : if (TREE_CODE (incr) == POSTDECREMENT_EXPR
948 1954 : || TREE_CODE (incr) == PREDECREMENT_EXPR)
949 597 : t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
950 1997 : t = fold_build_pointer_plus (decl, t);
951 1997 : incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
952 : }
953 31984 : return incr;
954 : }
955 :
956 : /* Validate and generate OMP_FOR.
957 : DECLV is a vector of iteration variables, for each collapsed loop.
958 :
959 : ORIG_DECLV, if non-NULL, is a vector with the original iteration
960 : variables (prior to any transformations, by say, C++ iterators).
961 :
962 : INITV, CONDV and INCRV are vectors containing initialization
963 : expressions, controlling predicates and increment expressions.
964 : BODY is the body of the loop and PRE_BODY statements that go before
965 : the loop. */
966 :
967 : tree
968 31926 : c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
969 : tree orig_declv, tree initv, tree condv, tree incrv,
970 : tree body, tree pre_body, bool final_p)
971 : {
972 31926 : location_t elocus;
973 31926 : bool fail = false;
974 31926 : int i;
975 :
976 31926 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
977 31926 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
978 31926 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
979 73875 : for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
980 : {
981 43327 : tree decl = TREE_VEC_ELT (declv, i);
982 43327 : tree init = TREE_VEC_ELT (initv, i);
983 43327 : tree cond = TREE_VEC_ELT (condv, i);
984 43327 : tree incr = TREE_VEC_ELT (incrv, i);
985 :
986 43327 : if (init == NULL_TREE)
987 : {
988 1378 : gcc_assert (decl == NULL_TREE
989 : && cond == NULL_TREE
990 : && incr == NULL_TREE);
991 1649 : for (i++; i < TREE_VEC_LENGTH (declv); i++)
992 271 : gcc_assert (TREE_VEC_ELT (declv, i) == NULL_TREE
993 : && TREE_VEC_ELT (initv, i) == NULL_TREE
994 : && TREE_VEC_ELT (condv, i) == NULL_TREE
995 : && TREE_VEC_ELT (incrv, i) == NULL_TREE);
996 : break;
997 : }
998 :
999 41949 : elocus = locus;
1000 41949 : if (EXPR_HAS_LOCATION (init))
1001 37257 : elocus = EXPR_LOCATION (init);
1002 :
1003 : /* Validate the iteration variable. */
1004 83898 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
1005 44823 : && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
1006 : {
1007 1 : error_at (elocus, "invalid type for iteration variable %qE", decl);
1008 1 : fail = true;
1009 : }
1010 41948 : else if (TYPE_ATOMIC (TREE_TYPE (decl)))
1011 : {
1012 16 : error_at (elocus, "%<_Atomic%> iteration variable %qE", decl);
1013 16 : fail = true;
1014 : /* _Atomic iterator confuses stuff too much, so we risk ICE
1015 : trying to diagnose it further. */
1016 16 : continue;
1017 : }
1018 :
1019 : /* In the case of "for (int i = 0...)", init will be a decl. It should
1020 : have a DECL_INITIAL that we can turn into an assignment. */
1021 41933 : if (init == decl)
1022 : {
1023 4676 : elocus = DECL_SOURCE_LOCATION (decl);
1024 :
1025 4676 : init = DECL_INITIAL (decl);
1026 4676 : if (init == NULL)
1027 : {
1028 0 : error_at (elocus, "%qE is not initialized", decl);
1029 0 : init = integer_zero_node;
1030 0 : fail = true;
1031 : }
1032 4676 : DECL_INITIAL (decl) = NULL_TREE;
1033 :
1034 4676 : init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
1035 : /* FIXME diagnostics: This should
1036 : be the location of the INIT. */
1037 : elocus,
1038 : init,
1039 : NULL_TREE);
1040 : }
1041 41933 : if (init != error_mark_node)
1042 : {
1043 41933 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1044 41933 : gcc_assert (TREE_OPERAND (init, 0) == decl);
1045 : }
1046 :
1047 41933 : if (cond == NULL_TREE)
1048 : {
1049 2 : error_at (elocus, "missing controlling predicate");
1050 2 : fail = true;
1051 : }
1052 : else
1053 : {
1054 41931 : bool cond_ok = false;
1055 :
1056 : /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
1057 : evaluation of the vla VAR_DECL. We need to readd
1058 : them to the non-decl operand. See PR45784. */
1059 41931 : while (TREE_CODE (cond) == COMPOUND_EXPR)
1060 0 : cond = TREE_OPERAND (cond, 1);
1061 :
1062 41931 : if (EXPR_HAS_LOCATION (cond))
1063 41803 : elocus = EXPR_LOCATION (cond);
1064 :
1065 41931 : if (TREE_CODE (cond) == LT_EXPR
1066 : || TREE_CODE (cond) == LE_EXPR
1067 : || TREE_CODE (cond) == GT_EXPR
1068 41931 : || TREE_CODE (cond) == GE_EXPR
1069 5587 : || TREE_CODE (cond) == NE_EXPR
1070 31 : || TREE_CODE (cond) == EQ_EXPR)
1071 : {
1072 41900 : tree op0 = TREE_OPERAND (cond, 0);
1073 41900 : tree op1 = TREE_OPERAND (cond, 1);
1074 :
1075 : /* 2.5.1. The comparison in the condition is computed in
1076 : the type of DECL, otherwise the behavior is undefined.
1077 :
1078 : For example:
1079 : long n; int i;
1080 : i < n;
1081 :
1082 : according to ISO will be evaluated as:
1083 : (long)i < n;
1084 :
1085 : We want to force:
1086 : i < (int)n; */
1087 41900 : if (TREE_CODE (op0) == NOP_EXPR
1088 41900 : && decl == TREE_OPERAND (op0, 0))
1089 : {
1090 58 : TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
1091 58 : TREE_OPERAND (cond, 1)
1092 116 : = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1093 58 : TREE_OPERAND (cond, 1));
1094 : }
1095 41842 : else if (TREE_CODE (op1) == NOP_EXPR
1096 41842 : && decl == TREE_OPERAND (op1, 0))
1097 : {
1098 4 : TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
1099 4 : TREE_OPERAND (cond, 0)
1100 8 : = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1101 4 : TREE_OPERAND (cond, 0));
1102 : }
1103 :
1104 41900 : if (decl == TREE_OPERAND (cond, 0))
1105 : cond_ok = true;
1106 139 : else if (decl == TREE_OPERAND (cond, 1))
1107 : {
1108 138 : TREE_SET_CODE (cond,
1109 : swap_tree_comparison (TREE_CODE (cond)));
1110 138 : TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
1111 138 : TREE_OPERAND (cond, 0) = decl;
1112 138 : cond_ok = true;
1113 : }
1114 :
1115 41900 : if (TREE_CODE (cond) == NE_EXPR
1116 41900 : || TREE_CODE (cond) == EQ_EXPR)
1117 : {
1118 5556 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
1119 : {
1120 935 : if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1121 : cond_ok = false;
1122 : }
1123 4621 : else if (operand_equal_p (TREE_OPERAND (cond, 1),
1124 4621 : TYPE_MIN_VALUE (TREE_TYPE (decl)),
1125 : 0))
1126 221 : TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1127 : ? GT_EXPR : LE_EXPR);
1128 4400 : else if (operand_equal_p (TREE_OPERAND (cond, 1),
1129 4400 : TYPE_MAX_VALUE (TREE_TYPE (decl)),
1130 : 0))
1131 5 : TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1132 : ? LT_EXPR : GE_EXPR);
1133 4395 : else if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1134 : cond_ok = false;
1135 : }
1136 :
1137 41900 : if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
1138 : {
1139 0 : tree ce = NULL_TREE, *pce = &ce;
1140 0 : tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
1141 0 : for (tree c = TREE_VEC_ELT (condv, i); c != cond;
1142 0 : c = TREE_OPERAND (c, 1))
1143 : {
1144 0 : *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
1145 0 : TREE_OPERAND (cond, 1));
1146 0 : pce = &TREE_OPERAND (*pce, 1);
1147 : }
1148 0 : TREE_OPERAND (cond, 1) = ce;
1149 0 : TREE_VEC_ELT (condv, i) = cond;
1150 : }
1151 : }
1152 :
1153 41900 : if (!cond_ok)
1154 : {
1155 32 : error_at (elocus, "invalid controlling predicate");
1156 32 : fail = true;
1157 : }
1158 : }
1159 :
1160 41933 : if (incr == NULL_TREE)
1161 : {
1162 0 : error_at (elocus, "missing increment expression");
1163 0 : fail = true;
1164 : }
1165 : else
1166 : {
1167 41933 : bool incr_ok = false;
1168 :
1169 41933 : if (EXPR_HAS_LOCATION (incr))
1170 41053 : elocus = EXPR_LOCATION (incr);
1171 :
1172 : /* Check all the valid increment expressions: v++, v--, ++v, --v,
1173 : v = v + incr, v = incr + v and v = v - incr. */
1174 41933 : switch (TREE_CODE (incr))
1175 : {
1176 31990 : case POSTINCREMENT_EXPR:
1177 31990 : case PREINCREMENT_EXPR:
1178 31990 : case POSTDECREMENT_EXPR:
1179 31990 : case PREDECREMENT_EXPR:
1180 31990 : if (TREE_OPERAND (incr, 0) != decl)
1181 : break;
1182 :
1183 31984 : incr_ok = true;
1184 31984 : if (!fail
1185 31959 : && TREE_CODE (cond) == NE_EXPR
1186 3739 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
1187 819 : && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
1188 32803 : && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
1189 : != INTEGER_CST))
1190 : {
1191 : /* For pointer to VLA, transform != into < or >
1192 : depending on whether incr is increment or decrement. */
1193 4 : if (TREE_CODE (incr) == PREINCREMENT_EXPR
1194 4 : || TREE_CODE (incr) == POSTINCREMENT_EXPR)
1195 2 : TREE_SET_CODE (cond, LT_EXPR);
1196 : else
1197 2 : TREE_SET_CODE (cond, GT_EXPR);
1198 : }
1199 31984 : incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
1200 31984 : break;
1201 :
1202 202 : case COMPOUND_EXPR:
1203 202 : if ((TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
1204 6 : && TREE_CODE (TREE_OPERAND (incr, 0)) != TARGET_EXPR)
1205 203 : || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
1206 : break;
1207 197 : incr = TREE_OPERAND (incr, 1);
1208 : /* FALLTHRU */
1209 9927 : case MODIFY_EXPR:
1210 9927 : if (TREE_OPERAND (incr, 0) != decl)
1211 : break;
1212 9927 : if (TREE_OPERAND (incr, 1) == decl)
1213 : break;
1214 9927 : if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
1215 9927 : && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
1216 286 : || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
1217 : incr_ok = true;
1218 2072 : else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
1219 1045 : || (TREE_CODE (TREE_OPERAND (incr, 1))
1220 : == POINTER_PLUS_EXPR))
1221 2937 : && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
1222 : incr_ok = true;
1223 : else
1224 : {
1225 183 : tree t = check_omp_for_incr_expr (elocus,
1226 183 : TREE_OPERAND (incr, 1),
1227 : decl);
1228 183 : if (t != error_mark_node)
1229 : {
1230 171 : incr_ok = true;
1231 171 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
1232 171 : incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
1233 : }
1234 : }
1235 9927 : if (!fail
1236 9927 : && incr_ok
1237 9909 : && TREE_CODE (cond) == NE_EXPR)
1238 : {
1239 1591 : tree i = TREE_OPERAND (incr, 1);
1240 1591 : i = TREE_OPERAND (i, TREE_OPERAND (i, 0) == decl);
1241 1591 : i = c_fully_fold (i, false, NULL);
1242 1591 : if (!final_p
1243 4 : && TREE_CODE (i) != INTEGER_CST)
1244 : ;
1245 1591 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
1246 : {
1247 116 : tree unit
1248 116 : = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
1249 116 : if (unit)
1250 : {
1251 116 : enum tree_code ccode = GT_EXPR;
1252 116 : unit = c_fully_fold (unit, false, NULL);
1253 116 : i = fold_convert (TREE_TYPE (unit), i);
1254 116 : if (operand_equal_p (unit, i, 0))
1255 : ccode = LT_EXPR;
1256 90 : if (ccode == GT_EXPR)
1257 : {
1258 90 : i = fold_unary (NEGATE_EXPR, TREE_TYPE (i), i);
1259 90 : if (i == NULL_TREE
1260 90 : || !operand_equal_p (unit, i, 0))
1261 : {
1262 72 : error_at (elocus,
1263 : "increment is not constant 1 or "
1264 : "-1 for %<!=%> condition");
1265 72 : fail = true;
1266 : }
1267 : }
1268 116 : if (TREE_CODE (unit) != INTEGER_CST)
1269 : /* For pointer to VLA, transform != into < or >
1270 : depending on whether the pointer is
1271 : incremented or decremented in each
1272 : iteration. */
1273 60 : TREE_SET_CODE (cond, ccode);
1274 : }
1275 : }
1276 : else
1277 : {
1278 1475 : if (!integer_onep (i) && !integer_minus_onep (i))
1279 : {
1280 132 : error_at (elocus,
1281 : "increment is not constant 1 or -1 for"
1282 : " %<!=%> condition");
1283 132 : fail = true;
1284 : }
1285 : }
1286 : }
1287 : break;
1288 :
1289 : default:
1290 : break;
1291 : }
1292 41911 : if (!incr_ok)
1293 : {
1294 34 : error_at (elocus, "invalid increment expression");
1295 34 : fail = true;
1296 : }
1297 : }
1298 :
1299 41933 : TREE_VEC_ELT (initv, i) = init;
1300 41933 : TREE_VEC_ELT (incrv, i) = incr;
1301 : }
1302 :
1303 31926 : if (fail)
1304 : return NULL;
1305 : else
1306 : {
1307 31641 : tree t = make_node (code);
1308 :
1309 31641 : TREE_TYPE (t) = void_type_node;
1310 31641 : OMP_FOR_INIT (t) = initv;
1311 31641 : OMP_FOR_COND (t) = condv;
1312 31641 : OMP_FOR_INCR (t) = incrv;
1313 31641 : OMP_FOR_BODY (t) = body;
1314 31641 : OMP_FOR_PRE_BODY (t) = pre_body;
1315 31641 : OMP_FOR_ORIG_DECLS (t) = orig_declv;
1316 :
1317 31641 : SET_EXPR_LOCATION (t, locus);
1318 31641 : return t;
1319 : }
1320 : }
1321 :
1322 : /* Type for passing data in between c_omp_check_loop_iv and
1323 : c_omp_check_loop_iv_r. */
1324 :
1325 : struct c_omp_check_loop_iv_data
1326 : {
1327 : tree declv;
1328 : bool fail;
1329 : bool maybe_nonrect;
1330 : location_t stmt_loc;
1331 : location_t expr_loc;
1332 : int kind;
1333 : int idx;
1334 : walk_tree_lh lh;
1335 : hash_set<tree> *ppset;
1336 : };
1337 :
1338 : /* Return -1 if DECL is not a loop iterator in loop nest D, otherwise
1339 : return the index of the loop in which it is an iterator.
1340 : Return TREE_VEC_LENGTH (d->declv) if it is a C++ range for iterator. */
1341 :
1342 : static int
1343 42142 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1344 : {
1345 133421 : for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1346 105815 : if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
1347 253 : continue;
1348 105562 : else if (decl == TREE_VEC_ELT (d->declv, i)
1349 105562 : || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1350 2292 : && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i))))
1351 : return i;
1352 91107 : else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1353 2223 : && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1354 92146 : && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
1355 : == TREE_VEC))
1356 1461 : for (int j = 2;
1357 2500 : j < TREE_VEC_LENGTH (TREE_CHAIN (TREE_VEC_ELT (d->declv, i))); j++)
1358 1542 : if (decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)), j))
1359 : return TREE_VEC_LENGTH (d->declv);
1360 : return -1;
1361 : }
1362 :
1363 : /* Helper function called via walk_tree, to diagnose uses
1364 : of associated loop IVs inside of lb, b and incr expressions
1365 : of OpenMP loops. */
1366 :
1367 : static tree
1368 169995 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1369 : {
1370 169995 : struct c_omp_check_loop_iv_data *d
1371 : = (struct c_omp_check_loop_iv_data *) data;
1372 169995 : if (DECL_P (*tp))
1373 : {
1374 28643 : int idx = c_omp_is_loop_iterator (*tp, d);
1375 28643 : if (idx == -1)
1376 : return NULL_TREE;
1377 :
1378 1441 : if ((d->kind & 4) && idx < d->idx)
1379 : {
1380 787 : d->maybe_nonrect = true;
1381 787 : return NULL_TREE;
1382 : }
1383 :
1384 654 : if (d->ppset->add (*tp))
1385 : return NULL_TREE;
1386 :
1387 636 : location_t loc = d->expr_loc;
1388 636 : if (loc == UNKNOWN_LOCATION)
1389 181 : loc = d->stmt_loc;
1390 :
1391 636 : switch (d->kind & 3)
1392 : {
1393 206 : case 0:
1394 206 : error_at (loc, "initializer expression refers to "
1395 : "iteration variable %qD", *tp);
1396 206 : break;
1397 201 : case 1:
1398 201 : error_at (loc, "condition expression refers to "
1399 : "iteration variable %qD", *tp);
1400 201 : break;
1401 229 : case 2:
1402 229 : error_at (loc, "increment expression refers to "
1403 : "iteration variable %qD", *tp);
1404 229 : break;
1405 : }
1406 636 : d->fail = true;
1407 : }
1408 141352 : else if ((d->kind & 4)
1409 : && TREE_CODE (*tp) != TREE_VEC
1410 : && TREE_CODE (*tp) != PLUS_EXPR
1411 : && TREE_CODE (*tp) != MINUS_EXPR
1412 : && TREE_CODE (*tp) != MULT_EXPR
1413 : && TREE_CODE (*tp) != POINTER_PLUS_EXPR
1414 : && !CONVERT_EXPR_P (*tp))
1415 : {
1416 17170 : *walk_subtrees = 0;
1417 17170 : d->kind &= 3;
1418 17170 : walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
1419 17170 : d->kind |= 4;
1420 17170 : return NULL_TREE;
1421 : }
1422 124182 : else if (d->ppset->add (*tp))
1423 17893 : *walk_subtrees = 0;
1424 : /* Don't walk dtors added by C++ wrap_cleanups_r. */
1425 106289 : else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1426 106289 : && TRY_CATCH_IS_CLEANUP (*tp))
1427 : {
1428 0 : *walk_subtrees = 0;
1429 0 : return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
1430 0 : NULL, d->lh);
1431 : }
1432 :
1433 : return NULL_TREE;
1434 : }
1435 :
1436 : /* Check the allowed expressions for non-rectangular loop nest lb and b
1437 : expressions. Return the outer var decl referenced in the expression. */
1438 :
1439 : static tree
1440 744 : c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d,
1441 : walk_tree_lh lh)
1442 : {
1443 744 : d->maybe_nonrect = false;
1444 744 : if (d->fail)
1445 : return NULL_TREE;
1446 :
1447 728 : hash_set<tree> pset;
1448 728 : hash_set<tree> *ppset = d->ppset;
1449 728 : d->ppset = &pset;
1450 :
1451 728 : tree t = *tp;
1452 728 : if (TREE_CODE (t) == TREE_VEC
1453 24 : && TREE_VEC_LENGTH (t) == 3
1454 24 : && DECL_P (TREE_VEC_ELT (t, 0))
1455 752 : && c_omp_is_loop_iterator (TREE_VEC_ELT (t, 0), d) >= 0)
1456 : {
1457 24 : d->kind &= 3;
1458 24 : walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1459 24 : walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1460 24 : d->ppset = ppset;
1461 24 : return d->fail ? NULL_TREE : TREE_VEC_ELT (t, 0);
1462 : }
1463 :
1464 716 : while (CONVERT_EXPR_P (t))
1465 12 : t = TREE_OPERAND (t, 0);
1466 :
1467 704 : tree a1 = t, a2 = integer_zero_node;
1468 704 : bool neg_a1 = false, neg_a2 = false;
1469 704 : switch (TREE_CODE (t))
1470 : {
1471 298 : case PLUS_EXPR:
1472 298 : case MINUS_EXPR:
1473 298 : a1 = TREE_OPERAND (t, 0);
1474 298 : a2 = TREE_OPERAND (t, 1);
1475 350 : while (CONVERT_EXPR_P (a1))
1476 52 : a1 = TREE_OPERAND (a1, 0);
1477 386 : while (CONVERT_EXPR_P (a2))
1478 88 : a2 = TREE_OPERAND (a2, 0);
1479 298 : if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
1480 : {
1481 64 : a2 = TREE_OPERAND (t, 1);
1482 64 : if (TREE_CODE (t) == MINUS_EXPR)
1483 19 : neg_a2 = true;
1484 64 : t = a1;
1485 64 : break;
1486 : }
1487 234 : if (DECL_P (a2) && c_omp_is_loop_iterator (a2, d) >= 0)
1488 : {
1489 0 : a1 = TREE_OPERAND (t, 0);
1490 0 : if (TREE_CODE (t) == MINUS_EXPR)
1491 0 : neg_a1 = true;
1492 0 : t = a2;
1493 0 : a2 = a1;
1494 0 : break;
1495 : }
1496 234 : if (TREE_CODE (a1) == MULT_EXPR && TREE_CODE (a2) == MULT_EXPR)
1497 : {
1498 0 : tree o1 = TREE_OPERAND (a1, 0);
1499 0 : tree o2 = TREE_OPERAND (a1, 1);
1500 0 : while (CONVERT_EXPR_P (o1))
1501 0 : o1 = TREE_OPERAND (o1, 0);
1502 0 : while (CONVERT_EXPR_P (o2))
1503 0 : o2 = TREE_OPERAND (o2, 0);
1504 0 : if ((DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
1505 0 : || (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0))
1506 : {
1507 0 : a2 = TREE_OPERAND (t, 1);
1508 0 : if (TREE_CODE (t) == MINUS_EXPR)
1509 0 : neg_a2 = true;
1510 0 : t = a1;
1511 0 : break;
1512 : }
1513 : }
1514 234 : if (TREE_CODE (a2) == MULT_EXPR)
1515 : {
1516 60 : a1 = TREE_OPERAND (t, 0);
1517 60 : if (TREE_CODE (t) == MINUS_EXPR)
1518 0 : neg_a1 = true;
1519 60 : t = a2;
1520 60 : a2 = a1;
1521 60 : break;
1522 : }
1523 174 : if (TREE_CODE (a1) == MULT_EXPR)
1524 : {
1525 174 : a2 = TREE_OPERAND (t, 1);
1526 174 : if (TREE_CODE (t) == MINUS_EXPR)
1527 32 : neg_a2 = true;
1528 174 : t = a1;
1529 174 : break;
1530 : }
1531 0 : a2 = integer_zero_node;
1532 0 : break;
1533 75 : case POINTER_PLUS_EXPR:
1534 75 : a1 = TREE_OPERAND (t, 0);
1535 75 : a2 = TREE_OPERAND (t, 1);
1536 79 : while (CONVERT_EXPR_P (a1))
1537 4 : a1 = TREE_OPERAND (a1, 0);
1538 75 : if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
1539 : {
1540 71 : a2 = TREE_OPERAND (t, 1);
1541 71 : t = a1;
1542 71 : break;
1543 : }
1544 : break;
1545 : default:
1546 : break;
1547 : }
1548 :
1549 704 : a1 = integer_one_node;
1550 704 : if (TREE_CODE (t) == MULT_EXPR)
1551 : {
1552 367 : tree o1 = TREE_OPERAND (t, 0);
1553 367 : tree o2 = TREE_OPERAND (t, 1);
1554 448 : while (CONVERT_EXPR_P (o1))
1555 81 : o1 = TREE_OPERAND (o1, 0);
1556 435 : while (CONVERT_EXPR_P (o2))
1557 68 : o2 = TREE_OPERAND (o2, 0);
1558 367 : if (DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
1559 : {
1560 118 : a1 = TREE_OPERAND (t, 1);
1561 118 : t = o1;
1562 : }
1563 249 : else if (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0)
1564 : {
1565 240 : a1 = TREE_OPERAND (t, 0);
1566 240 : t = o2;
1567 : }
1568 : }
1569 :
1570 704 : d->kind &= 3;
1571 704 : tree ret = NULL_TREE;
1572 704 : if (DECL_P (t) && c_omp_is_loop_iterator (t, d) >= 0)
1573 : {
1574 691 : location_t loc = d->expr_loc;
1575 691 : if (loc == UNKNOWN_LOCATION)
1576 93 : loc = d->stmt_loc;
1577 691 : if (!lang_hooks.types_compatible_p (TREE_TYPE (*tp), TREE_TYPE (t)))
1578 : {
1579 16 : if (d->kind == 0)
1580 12 : error_at (loc, "outer iteration variable %qD used in initializer"
1581 : " expression has type other than %qT",
1582 12 : t, TREE_TYPE (*tp));
1583 : else
1584 4 : error_at (loc, "outer iteration variable %qD used in condition"
1585 : " expression has type other than %qT",
1586 4 : t, TREE_TYPE (*tp));
1587 16 : d->fail = true;
1588 : }
1589 675 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (a1)))
1590 : {
1591 0 : error_at (loc, "outer iteration variable %qD multiplier expression"
1592 : " %qE is not integral", t, a1);
1593 0 : d->fail = true;
1594 : }
1595 675 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (a2)))
1596 : {
1597 0 : error_at (loc, "outer iteration variable %qD addend expression"
1598 : " %qE is not integral", t, a2);
1599 0 : d->fail = true;
1600 : }
1601 : else
1602 : {
1603 675 : walk_tree_1 (&a1, c_omp_check_loop_iv_r, d, NULL, lh);
1604 675 : walk_tree_1 (&a2, c_omp_check_loop_iv_r, d, NULL, lh);
1605 : }
1606 691 : if (!d->fail)
1607 : {
1608 660 : a1 = fold_convert (TREE_TYPE (*tp), a1);
1609 660 : a2 = fold_convert (TREE_TYPE (*tp), a2);
1610 660 : if (neg_a1)
1611 0 : a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
1612 660 : if (neg_a2)
1613 51 : a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
1614 660 : ret = t;
1615 660 : *tp = make_tree_vec (3);
1616 660 : TREE_VEC_ELT (*tp, 0) = t;
1617 660 : TREE_VEC_ELT (*tp, 1) = a1;
1618 660 : TREE_VEC_ELT (*tp, 2) = a2;
1619 : }
1620 : }
1621 : else
1622 13 : walk_tree_1 (&t, c_omp_check_loop_iv_r, d, NULL, lh);
1623 :
1624 704 : d->ppset = ppset;
1625 704 : return ret;
1626 728 : }
1627 :
1628 : /* Callback for walk_tree to find nested loop transforming construct. */
1629 :
1630 : static tree
1631 10110 : c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *)
1632 : {
1633 10110 : *walk_subtrees = 0;
1634 10110 : switch (TREE_CODE (*tp))
1635 : {
1636 : case OMP_TILE:
1637 : case OMP_UNROLL:
1638 : return *tp;
1639 2867 : case BIND_EXPR:
1640 2867 : *walk_subtrees = 1;
1641 2867 : break;
1642 41 : case STATEMENT_LIST:
1643 41 : *walk_subtrees = 1;
1644 41 : break;
1645 46 : case TRY_FINALLY_EXPR:
1646 46 : case CLEANUP_POINT_EXPR:
1647 46 : *walk_subtrees = 1;
1648 46 : break;
1649 : default:
1650 : break;
1651 : }
1652 : return NULL;
1653 : }
1654 :
1655 : /* Find Jth loop among generated loops of STMT. */
1656 :
1657 : int
1658 1659 : c_omp_find_generated_loop (tree &stmt, int j, walk_tree_lh lh)
1659 : {
1660 2498 : stmt = walk_tree_1 (&stmt, c_find_nested_loop_xform_r,
1661 : NULL, NULL, lh);
1662 2498 : gcc_assert (stmt);
1663 2498 : switch (TREE_CODE (stmt))
1664 : {
1665 726 : case OMP_UNROLL:
1666 726 : gcc_assert (omp_find_clause (OMP_FOR_CLAUSES (stmt),
1667 : OMP_CLAUSE_PARTIAL));
1668 : /* FALLTHRU */
1669 : case OMP_TILE:
1670 : int k;
1671 : k = 0;
1672 2859 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); ++i)
1673 2859 : if (i == j)
1674 : {
1675 2498 : if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1676 : {
1677 839 : stmt = OMP_FOR_BODY (stmt);
1678 839 : return c_omp_find_generated_loop (stmt, k, lh);
1679 : }
1680 : else
1681 1659 : return i;
1682 : }
1683 361 : else if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1684 56 : ++k;
1685 0 : gcc_unreachable ();
1686 0 : default:
1687 0 : gcc_unreachable ();
1688 : }
1689 : }
1690 :
1691 : /* Diagnose invalid references to loop iterators in lb, b and incr
1692 : expressions. */
1693 :
1694 : bool
1695 31641 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1696 : {
1697 31641 : hash_set<tree> pset;
1698 31641 : struct c_omp_check_loop_iv_data data;
1699 31641 : int i, k = 0;
1700 :
1701 31641 : data.declv = declv;
1702 31641 : data.fail = false;
1703 31641 : data.maybe_nonrect = false;
1704 31641 : data.stmt_loc = EXPR_LOCATION (stmt);
1705 31641 : data.lh = lh;
1706 31641 : data.ppset = &pset;
1707 74950 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1708 : {
1709 43309 : tree this_stmt = stmt;
1710 43309 : int j = i;
1711 43309 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1712 43309 : if (init == NULL_TREE)
1713 : {
1714 1649 : if (k == 0)
1715 1378 : data.declv = copy_node (declv);
1716 1649 : this_stmt = OMP_FOR_BODY (stmt);
1717 1649 : j = c_omp_find_generated_loop (this_stmt, k++, lh);
1718 1649 : init = TREE_VEC_ELT (OMP_FOR_INIT (this_stmt), j);
1719 1649 : TREE_VEC_ELT (data.declv, i) = TREE_OPERAND (init, 0);
1720 : }
1721 43309 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1722 43309 : tree decl = TREE_OPERAND (init, 0);
1723 43309 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
1724 43309 : gcc_assert (COMPARISON_CLASS_P (cond));
1725 43309 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
1726 43309 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
1727 43309 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1728 43309 : tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1729 43309 : int kind = 0;
1730 43309 : if (i > 0
1731 43309 : && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
1732 : {
1733 24 : location_t loc = data.expr_loc;
1734 24 : if (loc == UNKNOWN_LOCATION)
1735 24 : loc = data.stmt_loc;
1736 24 : error_at (loc, "the same loop iteration variables %qD used in "
1737 : "multiple associated loops", decl);
1738 24 : data.fail = true;
1739 : }
1740 : /* Handle non-rectangular loop nests. */
1741 43309 : if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1742 43309 : kind = 4;
1743 43309 : data.kind = kind;
1744 43309 : data.idx = i;
1745 43309 : walk_tree_1 (&TREE_OPERAND (init, 1),
1746 : c_omp_check_loop_iv_r, &data, NULL, lh);
1747 43309 : if (data.maybe_nonrect)
1748 357 : vec_outer1 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (init, 1),
1749 : &data, lh);
1750 : /* Don't warn for C++ random access iterators here, the
1751 : expression then involves the subtraction and always refers
1752 : to the original value. The C++ FE needs to warn on those
1753 : earlier. */
1754 43309 : if (decl == TREE_VEC_ELT (data.declv, i)
1755 43309 : || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
1756 933 : && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
1757 : {
1758 42376 : data.expr_loc = EXPR_LOCATION (cond);
1759 42376 : data.kind = kind | 1;
1760 42376 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1761 : c_omp_check_loop_iv_r, &data, NULL, lh);
1762 42376 : if (data.maybe_nonrect)
1763 387 : vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
1764 : &data, lh);
1765 : }
1766 43309 : if (vec_outer1 && vec_outer2 && vec_outer1 != vec_outer2)
1767 : {
1768 8 : location_t loc = data.expr_loc;
1769 8 : if (loc == UNKNOWN_LOCATION)
1770 0 : loc = data.stmt_loc;
1771 8 : error_at (loc, "two different outer iteration variables %qD and %qD"
1772 : " used in a single loop", vec_outer1, vec_outer2);
1773 8 : data.fail = true;
1774 8 : }
1775 43301 : else if ((vec_outer1 || vec_outer2) && this_stmt != stmt)
1776 : {
1777 16 : location_t loc = data.expr_loc;
1778 16 : if (loc == UNKNOWN_LOCATION)
1779 0 : loc = data.stmt_loc;
1780 16 : sorry_at (loc, "non-rectangular loops from generated loops "
1781 : "unsupported");
1782 16 : data.fail = true;
1783 : }
1784 43309 : if (vec_outer1 || vec_outer2)
1785 474 : OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1786 43309 : if (TREE_CODE (incr) == MODIFY_EXPR)
1787 : {
1788 11758 : gcc_assert (TREE_OPERAND (incr, 0) == decl);
1789 11758 : incr = TREE_OPERAND (incr, 1);
1790 11758 : data.kind = 2;
1791 11758 : if (TREE_CODE (incr) == PLUS_EXPR
1792 11758 : && TREE_OPERAND (incr, 1) == decl)
1793 : {
1794 299 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
1795 299 : walk_tree_1 (&TREE_OPERAND (incr, 0),
1796 : c_omp_check_loop_iv_r, &data, NULL, lh);
1797 : }
1798 : else
1799 : {
1800 11459 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
1801 11459 : walk_tree_1 (&TREE_OPERAND (incr, 1),
1802 : c_omp_check_loop_iv_r, &data, NULL, lh);
1803 : }
1804 : }
1805 : }
1806 31641 : return !data.fail;
1807 31641 : }
1808 :
1809 : /* Similar, but allows to check the init or cond expressions individually. */
1810 :
1811 : bool
1812 1971 : c_omp_check_loop_iv_exprs (location_t stmt_loc, enum tree_code code,
1813 : tree declv, int i, tree decl, tree init, tree cond,
1814 : walk_tree_lh lh)
1815 : {
1816 1971 : hash_set<tree> pset;
1817 1971 : struct c_omp_check_loop_iv_data data;
1818 1971 : int kind = (code != OACC_LOOP && i > 0) ? 4 : 0;
1819 :
1820 1971 : data.declv = declv;
1821 1971 : data.fail = false;
1822 1971 : data.maybe_nonrect = false;
1823 1971 : data.stmt_loc = stmt_loc;
1824 1971 : data.lh = lh;
1825 1971 : data.ppset = &pset;
1826 1971 : data.idx = i;
1827 1971 : if (i > 0
1828 1971 : && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
1829 : {
1830 6 : error_at (stmt_loc, "the same loop iteration variables %qD used in "
1831 : "multiple associated loops", decl);
1832 6 : data.fail = true;
1833 : }
1834 1971 : if (init)
1835 : {
1836 1164 : data.expr_loc = EXPR_LOCATION (init);
1837 1164 : data.kind = kind;
1838 1164 : walk_tree_1 (&init,
1839 : c_omp_check_loop_iv_r, &data, NULL, lh);
1840 : }
1841 1971 : if (cond)
1842 : {
1843 807 : gcc_assert (COMPARISON_CLASS_P (cond));
1844 807 : data.expr_loc = EXPR_LOCATION (init);
1845 807 : data.kind = kind | 1;
1846 807 : if (TREE_OPERAND (cond, 0) == decl)
1847 807 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1848 : c_omp_check_loop_iv_r, &data, NULL, lh);
1849 : else
1850 0 : walk_tree_1 (&TREE_OPERAND (cond, 0),
1851 : c_omp_check_loop_iv_r, &data, NULL, lh);
1852 : }
1853 1971 : return !data.fail;
1854 1971 : }
1855 :
1856 :
1857 : /* Helper function for c_omp_check_loop_binding_exprs: look for a binding
1858 : of DECL in BODY. Only traverse things that might be containers for
1859 : intervening code in an OMP loop. Returns the BIND_EXPR or DECL_EXPR
1860 : if found, otherwise null. */
1861 :
1862 : static tree
1863 3987 : find_binding_in_body (tree decl, tree body)
1864 : {
1865 5543 : if (!body)
1866 : return NULL_TREE;
1867 :
1868 5543 : switch (TREE_CODE (body))
1869 : {
1870 447 : case BIND_EXPR:
1871 584 : for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
1872 165 : if (b == decl)
1873 : return body;
1874 419 : return find_binding_in_body (decl, BIND_EXPR_BODY (body));
1875 :
1876 257 : case DECL_EXPR:
1877 257 : if (DECL_EXPR_DECL (body) == decl)
1878 : return body;
1879 : return NULL_TREE;
1880 :
1881 1042 : case STATEMENT_LIST:
1882 4587 : for (tree_stmt_iterator si = tsi_start (body); !tsi_end_p (si);
1883 3545 : tsi_next (&si))
1884 : {
1885 3573 : tree b = find_binding_in_body (decl, tsi_stmt (si));
1886 3573 : if (b)
1887 28 : return b;
1888 : }
1889 1014 : return NULL_TREE;
1890 :
1891 1137 : case OMP_STRUCTURED_BLOCK:
1892 1137 : return find_binding_in_body (decl, OMP_BODY (body));
1893 :
1894 : default:
1895 : return NULL_TREE;
1896 : }
1897 : }
1898 :
1899 : /* Traversal function for check_loop_binding_expr, to diagnose
1900 : errors when a binding made in intervening code is referenced outside
1901 : of the loop. Returns non-null if such a reference is found. DATA points
1902 : to the tree containing the loop body. */
1903 :
1904 : static tree
1905 859 : check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1906 : void *data)
1907 : {
1908 859 : tree body = *(tree *)data;
1909 :
1910 859 : if (DECL_P (*tp) && find_binding_in_body (*tp, body))
1911 49 : return *tp;
1912 : return NULL_TREE;
1913 : }
1914 :
1915 : /* Helper macro used below. */
1916 :
1917 : #define LOCATION_OR(loc1, loc2) \
1918 : ((loc1) != UNKNOWN_LOCATION ? (loc1) : (loc2))
1919 :
1920 : enum check_loop_binding_expr_ctx {
1921 : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR,
1922 : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT,
1923 : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST,
1924 : CHECK_LOOP_BINDING_EXPR_CTX_INCR
1925 : };
1926 :
1927 : /* Check a single expression EXPR for references to variables bound in
1928 : intervening code in BODY. Return true if ok, otherwise give an error
1929 : referencing CONTEXT and return false. Use LOC for the error message
1930 : if EXPR doesn't have one. */
1931 : static bool
1932 673 : check_loop_binding_expr (tree expr, tree body, location_t loc,
1933 : check_loop_binding_expr_ctx ctx)
1934 : {
1935 673 : tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
1936 :
1937 673 : if (bad)
1938 : {
1939 49 : location_t eloc = EXPR_LOCATION (expr);
1940 49 : eloc = LOCATION_OR (eloc, loc);
1941 49 : switch (ctx)
1942 : {
1943 14 : case CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR:
1944 14 : error_at (eloc, "variable %qD used as loop variable is bound "
1945 : "in intervening code", bad);
1946 14 : break;
1947 21 : case CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT:
1948 21 : error_at (eloc, "variable %qD used in initializer is bound "
1949 : "in intervening code", bad);
1950 21 : break;
1951 7 : case CHECK_LOOP_BINDING_EXPR_CTX_END_TEST:
1952 7 : error_at (eloc, "variable %qD used in end test is bound "
1953 : "in intervening code", bad);
1954 7 : break;
1955 7 : case CHECK_LOOP_BINDING_EXPR_CTX_INCR:
1956 7 : error_at (eloc, "variable %qD used in increment expression is bound "
1957 : "in intervening code", bad);
1958 7 : break;
1959 : }
1960 49 : return false;
1961 : }
1962 : return true;
1963 : }
1964 :
1965 : /* STMT is an OMP_FOR construct. Check all of the iteration variable,
1966 : initializer, end condition, and increment for bindings inside the
1967 : loop body. If ORIG_INITS is provided, check those elements too.
1968 : Return true if OK, false otherwise. */
1969 : bool
1970 190 : c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
1971 : {
1972 190 : bool ok = true;
1973 190 : location_t loc = EXPR_LOCATION (stmt);
1974 190 : tree body = OMP_FOR_BODY (stmt);
1975 338 : int orig_init_length = orig_inits ? orig_inits->length () : 0;
1976 :
1977 410 : for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1978 : {
1979 220 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1980 220 : if (init == NULL_TREE)
1981 : {
1982 16 : sorry_at (loc, "imperfectly nested loop using generated loops");
1983 16 : ok = false;
1984 16 : continue;
1985 : }
1986 204 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1987 204 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1988 204 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1989 204 : tree decl = TREE_OPERAND (init, 0);
1990 204 : tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
1991 204 : tree e;
1992 204 : location_t eloc;
1993 :
1994 204 : e = TREE_OPERAND (init, 1);
1995 204 : eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
1996 204 : if (!check_loop_binding_expr (decl, body, eloc,
1997 : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR))
1998 14 : ok = false;
1999 204 : if (!check_loop_binding_expr (e, body, eloc,
2000 : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
2001 15 : ok = false;
2002 204 : if (orig_init
2003 204 : && !check_loop_binding_expr (orig_init, body, eloc,
2004 : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
2005 : ok = false;
2006 :
2007 : /* INCR and/or COND may be null if this is a template with a
2008 : class iterator. */
2009 204 : if (cond)
2010 : {
2011 204 : eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
2012 204 : if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
2013 202 : e = TREE_OPERAND (cond, 1);
2014 2 : else if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 1) == decl)
2015 0 : e = TREE_OPERAND (cond, 0);
2016 : else
2017 : e = cond;
2018 204 : if (!check_loop_binding_expr (e, body, eloc,
2019 : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST))
2020 204 : ok = false;
2021 : }
2022 :
2023 204 : if (incr)
2024 : {
2025 202 : eloc = LOCATION_OR (EXPR_LOCATION (incr), loc);
2026 : /* INCR should be either a MODIFY_EXPR or pre/post
2027 : increment/decrement. We don't have to check the latter
2028 : since there are no operands besides the iteration variable. */
2029 202 : if (TREE_CODE (incr) == MODIFY_EXPR
2030 202 : && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body, eloc,
2031 : CHECK_LOOP_BINDING_EXPR_CTX_INCR))
2032 : ok = false;
2033 : }
2034 : }
2035 :
2036 190 : return ok;
2037 : }
2038 :
2039 : /* This function splits clauses for OpenACC combined loop
2040 : constructs. OpenACC combined loop constructs are:
2041 : #pragma acc kernels loop
2042 : #pragma acc parallel loop */
2043 :
2044 : tree
2045 1830 : c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
2046 : bool is_parallel)
2047 : {
2048 1830 : tree next, loop_clauses, nc;
2049 :
2050 1830 : loop_clauses = *not_loop_clauses = NULL_TREE;
2051 3613 : for (; clauses ; clauses = next)
2052 : {
2053 1783 : next = OMP_CLAUSE_CHAIN (clauses);
2054 :
2055 1783 : switch (OMP_CLAUSE_CODE (clauses))
2056 : {
2057 : /* Loop clauses. */
2058 1174 : case OMP_CLAUSE_COLLAPSE:
2059 1174 : case OMP_CLAUSE_TILE:
2060 1174 : case OMP_CLAUSE_GANG:
2061 1174 : case OMP_CLAUSE_WORKER:
2062 1174 : case OMP_CLAUSE_VECTOR:
2063 1174 : case OMP_CLAUSE_AUTO:
2064 1174 : case OMP_CLAUSE_SEQ:
2065 1174 : case OMP_CLAUSE_INDEPENDENT:
2066 1174 : case OMP_CLAUSE_PRIVATE:
2067 1174 : OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
2068 1174 : loop_clauses = clauses;
2069 1174 : break;
2070 :
2071 : /* Reductions must be duplicated on both constructs. */
2072 114 : case OMP_CLAUSE_REDUCTION:
2073 114 : if (is_parallel)
2074 : {
2075 83 : nc = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2076 : OMP_CLAUSE_REDUCTION);
2077 83 : OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (clauses);
2078 166 : OMP_CLAUSE_REDUCTION_CODE (nc)
2079 83 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2080 83 : OMP_CLAUSE_CHAIN (nc) = *not_loop_clauses;
2081 83 : *not_loop_clauses = nc;
2082 : }
2083 :
2084 114 : OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
2085 114 : loop_clauses = clauses;
2086 114 : break;
2087 :
2088 : /* Parallel/kernels clauses. */
2089 495 : default:
2090 495 : OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
2091 495 : *not_loop_clauses = clauses;
2092 495 : break;
2093 : }
2094 : }
2095 :
2096 1830 : return loop_clauses;
2097 : }
2098 :
2099 : /* This function attempts to split or duplicate clauses for OpenMP
2100 : combined/composite constructs. Right now there are 30 different
2101 : constructs. CODE is the innermost construct in the combined construct,
2102 : and MASK allows to determine which constructs are combined together,
2103 : as every construct has at least one clause that no other construct
2104 : has (except for OMP_SECTIONS, but that can be only combined with parallel,
2105 : and OMP_MASTER, which doesn't have any clauses at all).
2106 : OpenMP combined/composite constructs are:
2107 : #pragma omp distribute parallel for
2108 : #pragma omp distribute parallel for simd
2109 : #pragma omp distribute simd
2110 : #pragma omp for simd
2111 : #pragma omp masked taskloop
2112 : #pragma omp masked taskloop simd
2113 : #pragma omp master taskloop
2114 : #pragma omp master taskloop simd
2115 : #pragma omp parallel for
2116 : #pragma omp parallel for simd
2117 : #pragma omp parallel loop
2118 : #pragma omp parallel masked
2119 : #pragma omp parallel masked taskloop
2120 : #pragma omp parallel masked taskloop simd
2121 : #pragma omp parallel master
2122 : #pragma omp parallel master taskloop
2123 : #pragma omp parallel master taskloop simd
2124 : #pragma omp parallel sections
2125 : #pragma omp target parallel
2126 : #pragma omp target parallel for
2127 : #pragma omp target parallel for simd
2128 : #pragma omp target parallel loop
2129 : #pragma omp target teams
2130 : #pragma omp target teams distribute
2131 : #pragma omp target teams distribute parallel for
2132 : #pragma omp target teams distribute parallel for simd
2133 : #pragma omp target teams distribute simd
2134 : #pragma omp target teams loop
2135 : #pragma omp target simd
2136 : #pragma omp taskloop simd
2137 : #pragma omp teams distribute
2138 : #pragma omp teams distribute parallel for
2139 : #pragma omp teams distribute parallel for simd
2140 : #pragma omp teams distribute simd
2141 : #pragma omp teams loop */
2142 :
2143 : void
2144 15819 : c_omp_split_clauses (location_t loc, enum tree_code code,
2145 : omp_clause_mask mask, tree clauses, tree *cclauses)
2146 : {
2147 15819 : tree next, c;
2148 15819 : enum c_omp_clause_split s;
2149 15819 : int i;
2150 15819 : bool has_dup_allocate = false;
2151 :
2152 110733 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2153 94914 : cclauses[i] = NULL;
2154 : /* Add implicit nowait clause on
2155 : #pragma omp parallel {for,for simd,sections}. */
2156 15819 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2157 10915 : switch (code)
2158 : {
2159 10255 : case OMP_FOR:
2160 10255 : case OMP_SIMD:
2161 25892 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2162 10073 : cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2163 10073 : = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2164 : break;
2165 155 : case OMP_SECTIONS:
2166 155 : cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
2167 155 : = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2168 155 : break;
2169 : default:
2170 : break;
2171 : }
2172 :
2173 55734 : for (; clauses ; clauses = next)
2174 : {
2175 39915 : next = OMP_CLAUSE_CHAIN (clauses);
2176 :
2177 39915 : switch (OMP_CLAUSE_CODE (clauses))
2178 : {
2179 : /* First the clauses that are unique to some constructs. */
2180 : case OMP_CLAUSE_DEVICE:
2181 : case OMP_CLAUSE_DEVICE_TYPE:
2182 : case OMP_CLAUSE_DEFAULTMAP:
2183 : case OMP_CLAUSE_DEPEND:
2184 : case OMP_CLAUSE_DYN_GROUPPRIVATE:
2185 : case OMP_CLAUSE_IS_DEVICE_PTR:
2186 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
2187 : case OMP_CLAUSE_MAP:
2188 : case OMP_CLAUSE_USES_ALLOCATORS:
2189 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2190 : break;
2191 4 : case OMP_CLAUSE_DOACROSS:
2192 : /* This can happen with invalid depend(source) or
2193 : depend(sink:vec) on target combined with other constructs. */
2194 4 : gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
2195 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2196 : break;
2197 : case OMP_CLAUSE_NUM_TEAMS:
2198 2454 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2199 : break;
2200 : case OMP_CLAUSE_DIST_SCHEDULE:
2201 6933 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2202 : break;
2203 : case OMP_CLAUSE_COPYIN:
2204 : case OMP_CLAUSE_NUM_THREADS:
2205 : case OMP_CLAUSE_PROC_BIND:
2206 7710 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2207 : break;
2208 : case OMP_CLAUSE_ORDERED:
2209 13148 : s = C_OMP_CLAUSE_SPLIT_FOR;
2210 : break;
2211 6079 : case OMP_CLAUSE_SCHEDULE:
2212 6079 : s = C_OMP_CLAUSE_SPLIT_FOR;
2213 6079 : if (code != OMP_SIMD)
2214 3080 : OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
2215 : break;
2216 : case OMP_CLAUSE_SAFELEN:
2217 : case OMP_CLAUSE_SIMDLEN:
2218 : case OMP_CLAUSE_ALIGNED:
2219 : case OMP_CLAUSE_NONTEMPORAL:
2220 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2221 : break;
2222 : case OMP_CLAUSE_GRAINSIZE:
2223 : case OMP_CLAUSE_NUM_TASKS:
2224 : case OMP_CLAUSE_FINAL:
2225 : case OMP_CLAUSE_UNTIED:
2226 : case OMP_CLAUSE_MERGEABLE:
2227 : case OMP_CLAUSE_NOGROUP:
2228 : case OMP_CLAUSE_PRIORITY:
2229 13148 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2230 : break;
2231 : case OMP_CLAUSE_BIND:
2232 13148 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2233 : break;
2234 : case OMP_CLAUSE_FILTER:
2235 6933 : s = C_OMP_CLAUSE_SPLIT_MASKED;
2236 : break;
2237 : /* Duplicate this to all of taskloop, distribute, for, simd and
2238 : loop. */
2239 5077 : case OMP_CLAUSE_COLLAPSE:
2240 5077 : if (code == OMP_SIMD)
2241 : {
2242 2579 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2243 2579 : | (OMP_CLAUSE_MASK_1
2244 2579 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2245 2579 : | (OMP_CLAUSE_MASK_1
2246 2579 : << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
2247 : {
2248 2531 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2249 : OMP_CLAUSE_COLLAPSE);
2250 2531 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2251 2531 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2252 2531 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2253 2531 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2254 : }
2255 : else
2256 : {
2257 : /* This must be #pragma omp target simd */
2258 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2259 : break;
2260 : }
2261 : }
2262 5029 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2263 : {
2264 3925 : if ((mask & (OMP_CLAUSE_MASK_1
2265 3925 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2266 : {
2267 2625 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2268 : OMP_CLAUSE_COLLAPSE);
2269 2625 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2270 2625 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2271 2625 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2272 2625 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2273 2625 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2274 : }
2275 : else
2276 : s = C_OMP_CLAUSE_SPLIT_FOR;
2277 : }
2278 1104 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2279 13834 : != 0)
2280 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2281 686 : else if (code == OMP_LOOP)
2282 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2283 : else
2284 6933 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2285 : break;
2286 : /* Private clause is supported on all constructs but master/masked,
2287 : it is enough to put it on the innermost one other than
2288 : master/masked. For #pragma omp {for,sections} put it on parallel
2289 : though, as that's what we did for OpenMP 3.1. */
2290 1301 : case OMP_CLAUSE_PRIVATE:
2291 1301 : switch (code)
2292 : {
2293 : case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2294 : case OMP_FOR: case OMP_SECTIONS:
2295 7710 : case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2296 6933 : case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2297 2454 : case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2298 7710 : case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2299 7710 : case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2300 13148 : case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2301 13148 : case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
2302 0 : default: gcc_unreachable ();
2303 : }
2304 : break;
2305 : /* Firstprivate clause is supported on all constructs but
2306 : simd, master, masked and loop. Put it on the outermost of those
2307 : and duplicate on teams and parallel. */
2308 1743 : case OMP_CLAUSE_FIRSTPRIVATE:
2309 1743 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2310 2103 : != 0)
2311 : {
2312 388 : if (code == OMP_SIMD
2313 388 : && (mask & ((OMP_CLAUSE_MASK_1
2314 134 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2315 134 : | (OMP_CLAUSE_MASK_1
2316 134 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
2317 : {
2318 : /* This must be #pragma omp target simd. */
2319 28 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2320 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
2321 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
2322 28 : break;
2323 : }
2324 360 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2325 : OMP_CLAUSE_FIRSTPRIVATE);
2326 : /* firstprivate should not be applied to target if it is
2327 : also lastprivate or on the combined/composite construct,
2328 : or if it is mentioned in map clause. OMP_CLAUSE_DECLs
2329 : may need to go through FE handling though (instantiation,
2330 : C++ non-static data members, array section lowering), so
2331 : add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
2332 : let *finish_omp_clauses and the gimplifier handle it
2333 : right. */
2334 360 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
2335 360 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2336 360 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2337 360 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2338 : }
2339 1715 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2340 1715 : != 0)
2341 : {
2342 1103 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2343 1103 : | (OMP_CLAUSE_MASK_1
2344 1103 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2345 : {
2346 463 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2347 : OMP_CLAUSE_FIRSTPRIVATE);
2348 463 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2349 463 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2350 463 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2351 463 : if ((mask & (OMP_CLAUSE_MASK_1
2352 463 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2353 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2354 : else
2355 6933 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2356 : }
2357 640 : else if ((mask & (OMP_CLAUSE_MASK_1
2358 640 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2359 : /* This must be
2360 : #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
2361 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2362 : else
2363 : /* This must be
2364 : #pragma omp parallel{, for{, simd}, sections,loop}
2365 : or
2366 : #pragma omp target parallel. */
2367 7710 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2368 : }
2369 612 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2370 612 : != 0)
2371 : {
2372 : /* This must be one of
2373 : #pragma omp {,target }teams {distribute,loop}
2374 : #pragma omp target teams
2375 : #pragma omp {,target }teams distribute simd. */
2376 276 : gcc_assert (code == OMP_DISTRIBUTE
2377 : || code == OMP_LOOP
2378 : || code == OMP_TEAMS
2379 : || code == OMP_SIMD);
2380 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2381 : }
2382 336 : else if ((mask & (OMP_CLAUSE_MASK_1
2383 336 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2384 : {
2385 : /* This must be #pragma omp distribute simd. */
2386 76 : gcc_assert (code == OMP_SIMD);
2387 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2388 : }
2389 260 : else if ((mask & (OMP_CLAUSE_MASK_1
2390 260 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2391 : {
2392 : /* This must be
2393 : #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
2394 : or
2395 : #pragma omp {,parallel }mas{ked,ter} taskloop. */
2396 232 : gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
2397 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2398 : }
2399 : else
2400 : {
2401 : /* This must be #pragma omp for simd. */
2402 28 : gcc_assert (code == OMP_SIMD);
2403 : s = C_OMP_CLAUSE_SPLIT_FOR;
2404 : }
2405 : break;
2406 : /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
2407 : and simd. In parallel {for{, simd},sections} we actually want to
2408 : put it on parallel rather than for or sections. */
2409 1959 : case OMP_CLAUSE_LASTPRIVATE:
2410 1959 : if (code == OMP_DISTRIBUTE)
2411 : {
2412 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2413 : break;
2414 : }
2415 1951 : if ((mask & (OMP_CLAUSE_MASK_1
2416 1951 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2417 : {
2418 548 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2419 : OMP_CLAUSE_LASTPRIVATE);
2420 548 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2421 548 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2422 1096 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2423 548 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2424 548 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2425 : }
2426 1951 : if (code == OMP_FOR || code == OMP_SECTIONS)
2427 : {
2428 823 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2429 20858 : != 0)
2430 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2431 : else
2432 13148 : s = C_OMP_CLAUSE_SPLIT_FOR;
2433 : break;
2434 : }
2435 : if (code == OMP_TASKLOOP)
2436 : {
2437 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2438 : break;
2439 : }
2440 : if (code == OMP_LOOP)
2441 : {
2442 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2443 : break;
2444 : }
2445 0 : gcc_assert (code == OMP_SIMD);
2446 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2447 : {
2448 423 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2449 : OMP_CLAUSE_LASTPRIVATE);
2450 423 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2451 846 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2452 423 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2453 423 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2454 498 : != 0)
2455 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2456 : else
2457 75 : s = C_OMP_CLAUSE_SPLIT_FOR;
2458 423 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2459 423 : cclauses[s] = c;
2460 : }
2461 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2462 : {
2463 253 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2464 : OMP_CLAUSE_LASTPRIVATE);
2465 253 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2466 506 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2467 253 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2468 253 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2469 253 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2470 : }
2471 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2472 : break;
2473 : /* Shared and default clauses are allowed on parallel, teams and
2474 : taskloop. */
2475 3567 : case OMP_CLAUSE_SHARED:
2476 3567 : case OMP_CLAUSE_DEFAULT:
2477 3567 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2478 3567 : != 0)
2479 : {
2480 898 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2481 13504 : != 0)
2482 : {
2483 712 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2484 356 : OMP_CLAUSE_CODE (clauses));
2485 356 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2486 128 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2487 : else
2488 456 : OMP_CLAUSE_DEFAULT_KIND (c)
2489 228 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2490 356 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2491 356 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2492 : }
2493 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2494 : break;
2495 : }
2496 2669 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2497 9005 : != 0)
2498 : {
2499 1295 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2500 3062 : == 0)
2501 : {
2502 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2503 : break;
2504 : }
2505 1216 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2506 608 : OMP_CLAUSE_CODE (clauses));
2507 608 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2508 284 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2509 : else
2510 648 : OMP_CLAUSE_DEFAULT_KIND (c)
2511 324 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2512 608 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2513 608 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2514 : }
2515 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2516 : break;
2517 : /* order clauses are allowed on distribute, for, simd and loop. */
2518 880 : case OMP_CLAUSE_ORDER:
2519 880 : if ((mask & (OMP_CLAUSE_MASK_1
2520 880 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2521 : {
2522 332 : if (code == OMP_DISTRIBUTE)
2523 : {
2524 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2525 : break;
2526 : }
2527 288 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2528 : OMP_CLAUSE_ORDER);
2529 576 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2530 288 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2531 576 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2532 288 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2533 288 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2534 288 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2535 : }
2536 836 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2537 : {
2538 465 : if (code == OMP_SIMD)
2539 : {
2540 317 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2541 : OMP_CLAUSE_ORDER);
2542 634 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2543 317 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2544 634 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2545 317 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2546 317 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2547 317 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2548 317 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2549 : }
2550 : else
2551 : s = C_OMP_CLAUSE_SPLIT_FOR;
2552 : }
2553 371 : else if (code == OMP_LOOP)
2554 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2555 : else
2556 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2557 : break;
2558 : /* Reduction is allowed on simd, for, parallel, sections, taskloop,
2559 : teams and loop. Duplicate it on all of them, but omit on for or
2560 : sections if parallel is present (unless inscan, in that case
2561 : omit on parallel). If taskloop or loop is combined with
2562 : parallel, omit it on parallel. */
2563 2883 : case OMP_CLAUSE_REDUCTION:
2564 2883 : if (OMP_CLAUSE_REDUCTION_TASK (clauses))
2565 : {
2566 56 : if (code == OMP_SIMD || code == OMP_LOOP)
2567 : {
2568 16 : error_at (OMP_CLAUSE_LOCATION (clauses),
2569 : "invalid %<task%> reduction modifier on construct "
2570 : "combined with %<simd%> or %<loop%>");
2571 16 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2572 : }
2573 40 : else if (code != OMP_SECTIONS
2574 34 : && (mask & (OMP_CLAUSE_MASK_1
2575 34 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
2576 40 : && (mask & (OMP_CLAUSE_MASK_1
2577 4 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
2578 : {
2579 4 : error_at (OMP_CLAUSE_LOCATION (clauses),
2580 : "invalid %<task%> reduction modifier on construct "
2581 : "not combined with %<parallel%>, %<for%> or "
2582 : "%<sections%>");
2583 4 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2584 : }
2585 : }
2586 2883 : if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2587 2883 : && ((mask & ((OMP_CLAUSE_MASK_1
2588 196 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2589 196 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2590 2895 : != 0))
2591 : {
2592 12 : error_at (OMP_CLAUSE_LOCATION (clauses),
2593 : "%<inscan%> %<reduction%> clause on construct other "
2594 : "than %<for%>, %<simd%>, %<for simd%>, "
2595 : "%<parallel for%>, %<parallel for simd%>");
2596 12 : OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
2597 : }
2598 2883 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2599 : {
2600 567 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2601 : OMP_CLAUSE_MAP);
2602 567 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2603 567 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
2604 567 : OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
2605 567 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2606 567 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2607 : }
2608 2883 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2609 : {
2610 1722 : if (code == OMP_SIMD)
2611 : {
2612 561 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2613 : OMP_CLAUSE_REDUCTION);
2614 561 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2615 1122 : OMP_CLAUSE_REDUCTION_CODE (c)
2616 561 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2617 561 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2618 561 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2619 561 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2620 561 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2621 1122 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2622 561 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2623 561 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2624 561 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2625 : }
2626 1722 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2627 1722 : != 0)
2628 : {
2629 431 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2630 : OMP_CLAUSE_REDUCTION);
2631 431 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2632 862 : OMP_CLAUSE_REDUCTION_CODE (c)
2633 431 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2634 431 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2635 431 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2636 431 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2637 431 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2638 862 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2639 431 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2640 431 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2641 431 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2642 431 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2643 : }
2644 1291 : else if ((mask & (OMP_CLAUSE_MASK_1
2645 1291 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2646 1202 : && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2647 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2648 : else
2649 13148 : s = C_OMP_CLAUSE_SPLIT_FOR;
2650 : }
2651 1161 : else if (code == OMP_SECTIONS
2652 1161 : || code == OMP_PARALLEL
2653 : || code == OMP_MASTER
2654 : || code == OMP_MASKED)
2655 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2656 : else if (code == OMP_TASKLOOP)
2657 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2658 : else if (code == OMP_LOOP)
2659 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2660 : else if (code == OMP_SIMD)
2661 : {
2662 437 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2663 437 : != 0)
2664 : {
2665 247 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2666 : OMP_CLAUSE_REDUCTION);
2667 247 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2668 494 : OMP_CLAUSE_REDUCTION_CODE (c)
2669 247 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2670 247 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2671 247 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2672 247 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2673 247 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2674 494 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2675 247 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2676 247 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2677 247 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2678 : }
2679 190 : else if ((mask & (OMP_CLAUSE_MASK_1
2680 190 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2681 : {
2682 90 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2683 : OMP_CLAUSE_REDUCTION);
2684 90 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2685 180 : OMP_CLAUSE_REDUCTION_CODE (c)
2686 90 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2687 90 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2688 90 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2689 90 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2690 90 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2691 180 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2692 90 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2693 90 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2694 90 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2695 : }
2696 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2697 : }
2698 : else
2699 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2700 : break;
2701 400 : case OMP_CLAUSE_IN_REDUCTION:
2702 400 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2703 : {
2704 : /* When on target, map(always, tofrom: item) is added as
2705 : well. For non-combined target it is added in the FEs. */
2706 228 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2707 : OMP_CLAUSE_MAP);
2708 228 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2709 228 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
2710 228 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2711 228 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2712 228 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2713 228 : break;
2714 : }
2715 : /* in_reduction on taskloop simd becomes reduction on the simd
2716 : and keeps being in_reduction on taskloop. */
2717 172 : if (code == OMP_SIMD)
2718 : {
2719 108 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2720 : OMP_CLAUSE_REDUCTION);
2721 108 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2722 216 : OMP_CLAUSE_REDUCTION_CODE (c)
2723 108 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2724 108 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2725 108 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2726 108 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2727 108 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2728 108 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2729 108 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2730 : }
2731 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2732 : break;
2733 1617 : case OMP_CLAUSE_IF:
2734 1617 : if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
2735 : {
2736 1188 : s = C_OMP_CLAUSE_SPLIT_COUNT;
2737 1188 : switch (OMP_CLAUSE_IF_MODIFIER (clauses))
2738 : {
2739 510 : case OMP_PARALLEL:
2740 510 : if ((mask & (OMP_CLAUSE_MASK_1
2741 510 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2742 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2743 : break;
2744 280 : case OMP_SIMD:
2745 280 : if (code == OMP_SIMD)
2746 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2747 : break;
2748 168 : case OMP_TASKLOOP:
2749 168 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2750 13156 : != 0)
2751 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2752 : break;
2753 222 : case OMP_TARGET:
2754 222 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2755 3218 : != 0)
2756 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2757 : break;
2758 : default:
2759 : break;
2760 : }
2761 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2762 : break;
2763 : /* Error-recovery here, invalid if-modifier specified, add the
2764 : clause to just one construct. */
2765 8 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2766 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2767 4 : else if ((mask & (OMP_CLAUSE_MASK_1
2768 4 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2769 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2770 0 : else if ((mask & (OMP_CLAUSE_MASK_1
2771 0 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2772 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2773 0 : else if (code == OMP_SIMD)
2774 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2775 : else
2776 0 : gcc_unreachable ();
2777 : break;
2778 : }
2779 : /* Otherwise, duplicate if clause to all constructs. */
2780 429 : if (code == OMP_SIMD)
2781 : {
2782 266 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
2783 266 : | (OMP_CLAUSE_MASK_1
2784 266 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2785 266 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
2786 5337 : != 0)
2787 : {
2788 176 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2789 : OMP_CLAUSE_IF);
2790 352 : OMP_CLAUSE_IF_MODIFIER (c)
2791 176 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2792 176 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2793 176 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2794 176 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2795 : }
2796 : else
2797 : {
2798 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2799 : break;
2800 : }
2801 : }
2802 339 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2803 339 : != 0)
2804 : {
2805 148 : if ((mask & (OMP_CLAUSE_MASK_1
2806 148 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2807 : {
2808 64 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2809 : OMP_CLAUSE_IF);
2810 128 : OMP_CLAUSE_IF_MODIFIER (c)
2811 64 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2812 64 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2813 64 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2814 64 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2815 64 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2816 : }
2817 : else
2818 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2819 : }
2820 191 : else if ((mask & (OMP_CLAUSE_MASK_1
2821 191 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2822 : {
2823 119 : if ((mask & (OMP_CLAUSE_MASK_1
2824 7730 : << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2825 : {
2826 20 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2827 : OMP_CLAUSE_IF);
2828 40 : OMP_CLAUSE_IF_MODIFIER (c)
2829 20 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2830 20 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2831 20 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2832 20 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2833 20 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2834 : }
2835 : else
2836 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2837 : }
2838 : else
2839 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2840 : break;
2841 800 : case OMP_CLAUSE_LINEAR:
2842 : /* Linear clause is allowed on simd and for. Put it on the
2843 : innermost construct. */
2844 800 : if (code == OMP_SIMD)
2845 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2846 : else
2847 13148 : s = C_OMP_CLAUSE_SPLIT_FOR;
2848 : break;
2849 247 : case OMP_CLAUSE_NOWAIT:
2850 : /* Nowait clause is allowed on target, for and sections, but
2851 : is not allowed on parallel for or parallel sections. Therefore,
2852 : put it on target construct if present, because that can only
2853 : be combined with parallel for{, simd} and not with for{, simd},
2854 : otherwise to the worksharing construct. */
2855 247 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2856 16358 : != 0)
2857 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2858 : else
2859 13148 : s = C_OMP_CLAUSE_SPLIT_FOR;
2860 : break;
2861 : /* thread_limit is allowed on target and teams. Distribute it
2862 : to all. */
2863 444 : case OMP_CLAUSE_THREAD_LIMIT:
2864 444 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2865 2454 : != 0)
2866 : {
2867 232 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2868 3210 : != 0)
2869 : {
2870 230 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2871 : OMP_CLAUSE_THREAD_LIMIT);
2872 230 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
2873 230 : = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
2874 230 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2875 230 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2876 : }
2877 : else
2878 : {
2879 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2880 : break;
2881 : }
2882 : }
2883 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2884 : break;
2885 : /* Allocate clause is allowed on target, teams, distribute, parallel,
2886 : for, sections and taskloop. Distribute it to all. */
2887 : case OMP_CLAUSE_ALLOCATE:
2888 : s = C_OMP_CLAUSE_SPLIT_COUNT;
2889 7861 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2890 : {
2891 6738 : switch (i)
2892 : {
2893 1123 : case C_OMP_CLAUSE_SPLIT_TARGET:
2894 1986 : if ((mask & (OMP_CLAUSE_MASK_1
2895 1123 : << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2896 863 : continue;
2897 : break;
2898 1123 : case C_OMP_CLAUSE_SPLIT_TEAMS:
2899 1842 : if ((mask & (OMP_CLAUSE_MASK_1
2900 1123 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2901 719 : continue;
2902 : break;
2903 1123 : case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2904 1794 : if ((mask & (OMP_CLAUSE_MASK_1
2905 1123 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2906 671 : continue;
2907 : break;
2908 1123 : case C_OMP_CLAUSE_SPLIT_PARALLEL:
2909 1495 : if ((mask & (OMP_CLAUSE_MASK_1
2910 1123 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2911 372 : continue;
2912 : break;
2913 1123 : case C_OMP_CLAUSE_SPLIT_FOR:
2914 1123 : STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
2915 : == C_OMP_CLAUSE_SPLIT_FOR
2916 : && (C_OMP_CLAUSE_SPLIT_TASKLOOP
2917 : == C_OMP_CLAUSE_SPLIT_FOR)
2918 : && (C_OMP_CLAUSE_SPLIT_LOOP
2919 : == C_OMP_CLAUSE_SPLIT_FOR));
2920 1123 : if (code == OMP_SECTIONS)
2921 : break;
2922 1107 : if ((mask & (OMP_CLAUSE_MASK_1
2923 1107 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2924 : break;
2925 602 : if ((mask & (OMP_CLAUSE_MASK_1
2926 602 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2927 : break;
2928 322 : continue;
2929 1123 : case C_OMP_CLAUSE_SPLIT_SIMD:
2930 1123 : continue;
2931 : default:
2932 : gcc_unreachable ();
2933 : }
2934 2668 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2935 : {
2936 1545 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2937 : OMP_CLAUSE_ALLOCATE);
2938 3090 : OMP_CLAUSE_DECL (c)
2939 1545 : = OMP_CLAUSE_DECL (clauses);
2940 1545 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2941 1545 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2942 1545 : OMP_CLAUSE_ALLOCATE_ALIGN (c)
2943 1545 : = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2944 1545 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2945 1545 : cclauses[s] = c;
2946 1545 : has_dup_allocate = true;
2947 : }
2948 2668 : s = (enum c_omp_clause_split) i;
2949 : }
2950 1123 : gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2951 : break;
2952 0 : default:
2953 0 : gcc_unreachable ();
2954 : }
2955 39915 : OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2956 39915 : cclauses[s] = clauses;
2957 : }
2958 :
2959 15819 : if (has_dup_allocate)
2960 : {
2961 753 : bool need_prune = false;
2962 753 : bitmap_obstack_initialize (NULL);
2963 8588 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2964 3701 : if (cclauses[i])
2965 : {
2966 2230 : bitmap_head allocate_head;
2967 2230 : bitmap_initialize (&allocate_head, &bitmap_default_obstack);
2968 17416 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2969 15186 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2970 15186 : && DECL_P (OMP_CLAUSE_DECL (c)))
2971 4716 : bitmap_set_bit (&allocate_head,
2972 2358 : DECL_UID (OMP_CLAUSE_DECL (c)));
2973 17416 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2974 15186 : switch (OMP_CLAUSE_CODE (c))
2975 : {
2976 1103 : case OMP_CLAUSE_REDUCTION:
2977 1103 : case OMP_CLAUSE_IN_REDUCTION:
2978 1103 : case OMP_CLAUSE_TASK_REDUCTION:
2979 1103 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
2980 : {
2981 0 : tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
2982 0 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
2983 0 : t = TREE_OPERAND (t, 0);
2984 0 : if (TREE_CODE (t) == ADDR_EXPR
2985 0 : || INDIRECT_REF_P (t))
2986 0 : t = TREE_OPERAND (t, 0);
2987 0 : if (DECL_P (t))
2988 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2989 : break;
2990 : }
2991 1103 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
2992 : {
2993 : /* TODO: This can go away once we transition all uses of
2994 : TREE_LIST for representing OMP array sections to
2995 : OMP_ARRAY_SECTION. */
2996 0 : tree t;
2997 0 : for (t = OMP_CLAUSE_DECL (c);
2998 0 : TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
2999 : ;
3000 0 : if (DECL_P (t))
3001 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3002 : break;
3003 : }
3004 1103 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
3005 : {
3006 112 : tree t;
3007 112 : for (t = OMP_CLAUSE_DECL (c);
3008 224 : TREE_CODE (t) == OMP_ARRAY_SECTION;
3009 112 : t = TREE_OPERAND (t, 0))
3010 : ;
3011 112 : if (DECL_P (t))
3012 112 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3013 : break;
3014 : }
3015 : /* FALLTHRU */
3016 3241 : case OMP_CLAUSE_PRIVATE:
3017 3241 : case OMP_CLAUSE_FIRSTPRIVATE:
3018 3241 : case OMP_CLAUSE_LASTPRIVATE:
3019 3241 : case OMP_CLAUSE_LINEAR:
3020 3241 : if (DECL_P (OMP_CLAUSE_DECL (c)))
3021 6482 : bitmap_clear_bit (&allocate_head,
3022 3241 : DECL_UID (OMP_CLAUSE_DECL (c)));
3023 : break;
3024 : default:
3025 : break;
3026 : }
3027 17416 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
3028 15186 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
3029 2358 : && DECL_P (OMP_CLAUSE_DECL (c))
3030 17544 : && bitmap_bit_p (&allocate_head,
3031 2358 : DECL_UID (OMP_CLAUSE_DECL (c))))
3032 : {
3033 : /* Mark allocate clauses which don't have corresponding
3034 : explicit data sharing clause. */
3035 1029 : OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
3036 1029 : need_prune = true;
3037 : }
3038 : }
3039 753 : bitmap_obstack_release (NULL);
3040 753 : if (need_prune)
3041 : {
3042 : /* At least one allocate clause has been marked. Walk all the
3043 : duplicated allocate clauses in sync. If it is marked in all
3044 : constituent constructs, diagnose it as invalid and remove
3045 : them. Otherwise, remove all marked inner clauses inside
3046 : a construct that doesn't have them marked. Keep the outer
3047 : marked ones, because some clause duplication is done only
3048 : during gimplification. */
3049 : tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
3050 4599 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3051 3942 : if (cclauses[i] == NULL_TREE
3052 2298 : || i == C_OMP_CLAUSE_SPLIT_SIMD
3053 2038 : || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
3054 1904 : p[i] = NULL;
3055 : else
3056 2038 : p[i] = &cclauses[i];
3057 1310 : do
3058 : {
3059 1310 : int j = -1;
3060 1310 : tree seen = NULL_TREE;
3061 6173 : for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
3062 5520 : if (p[i])
3063 : {
3064 13457 : while (*p[i]
3065 13457 : && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
3066 10634 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3067 2823 : if (*p[i] == NULL_TREE)
3068 : {
3069 : i = C_OMP_CLAUSE_SPLIT_COUNT;
3070 : break;
3071 : }
3072 2166 : if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
3073 4863 : j = i;
3074 : seen = *p[i];
3075 : }
3076 1310 : if (i == C_OMP_CLAUSE_SPLIT_COUNT)
3077 : break;
3078 653 : if (j == -1)
3079 8 : error_at (OMP_CLAUSE_LOCATION (seen),
3080 : "%qD specified in %<allocate%> clause but not in "
3081 : "an explicit privatization clause",
3082 4 : OMP_CLAUSE_DECL (seen));
3083 4571 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3084 3918 : if (p[i])
3085 : {
3086 2038 : if (i > j)
3087 : /* Remove. */
3088 580 : *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
3089 : else
3090 : /* Keep. */
3091 1458 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3092 : }
3093 : }
3094 : while (1);
3095 : }
3096 : }
3097 :
3098 15819 : if (!flag_checking)
3099 : return;
3100 :
3101 15819 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
3102 10634 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
3103 15819 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
3104 8979 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
3105 15819 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
3106 8553 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
3107 8303 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
3108 15819 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
3109 4904 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
3110 15819 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
3111 15819 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
3112 4117 : && code != OMP_SECTIONS
3113 4117 : && code != OMP_LOOP)
3114 3667 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
3115 15819 : if (code != OMP_SIMD)
3116 9308 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
3117 : }
3118 :
3119 :
3120 : /* qsort callback to compare #pragma omp declare simd clauses. */
3121 :
3122 : static int
3123 12200 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
3124 : {
3125 12200 : tree a = *(const tree *) p;
3126 12200 : tree b = *(const tree *) q;
3127 12200 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
3128 : {
3129 10725 : if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
3130 : return -1;
3131 4480 : return 1;
3132 : }
3133 1475 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
3134 : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
3135 : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
3136 : {
3137 1451 : int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
3138 1451 : int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
3139 1451 : if (c < d)
3140 : return 1;
3141 670 : if (c > d)
3142 670 : return -1;
3143 : }
3144 : return 0;
3145 : }
3146 :
3147 : /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
3148 : CLAUSES on FNDECL into argument indexes and sort them. */
3149 :
3150 : tree
3151 1427 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
3152 : {
3153 1427 : tree c;
3154 1427 : vec<tree> clvec = vNULL;
3155 :
3156 4507 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3157 : {
3158 3080 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3159 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3160 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3161 : {
3162 1712 : tree decl = OMP_CLAUSE_DECL (c);
3163 1712 : tree arg;
3164 1712 : int idx;
3165 3815 : for (arg = parms, idx = 0; arg;
3166 2103 : arg = TREE_CHAIN (arg), idx++)
3167 3815 : if (arg == decl)
3168 : break;
3169 1712 : if (arg == NULL_TREE)
3170 : {
3171 0 : error_at (OMP_CLAUSE_LOCATION (c),
3172 : "%qD is not a function argument", decl);
3173 3080 : continue;
3174 : }
3175 1712 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3176 1712 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3177 1712 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3178 : {
3179 43 : decl = OMP_CLAUSE_LINEAR_STEP (c);
3180 121 : for (arg = parms, idx = 0; arg;
3181 78 : arg = TREE_CHAIN (arg), idx++)
3182 121 : if (arg == decl)
3183 : break;
3184 43 : if (arg == NULL_TREE)
3185 : {
3186 0 : error_at (OMP_CLAUSE_LOCATION (c),
3187 : "%qD is not a function argument", decl);
3188 0 : continue;
3189 : }
3190 43 : OMP_CLAUSE_LINEAR_STEP (c)
3191 86 : = build_int_cst (integer_type_node, idx);
3192 : }
3193 : }
3194 3080 : clvec.safe_push (c);
3195 : }
3196 1427 : if (!clvec.is_empty ())
3197 : {
3198 1314 : unsigned int len = clvec.length (), i;
3199 1314 : clvec.qsort (c_omp_declare_simd_clause_cmp);
3200 1314 : clauses = clvec[0];
3201 4394 : for (i = 0; i < len; i++)
3202 3080 : OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3203 : }
3204 : else
3205 : clauses = NULL_TREE;
3206 1427 : clvec.release ();
3207 1427 : return clauses;
3208 : }
3209 :
3210 : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3211 :
3212 : void
3213 105 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3214 : {
3215 105 : tree c;
3216 :
3217 393 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3218 288 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3219 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3220 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3221 : {
3222 189 : int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3223 189 : tree arg;
3224 369 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3225 180 : arg = TREE_CHAIN (arg), i++)
3226 369 : if (i == idx)
3227 : break;
3228 0 : gcc_assert (arg);
3229 189 : OMP_CLAUSE_DECL (c) = arg;
3230 189 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3231 189 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3232 : {
3233 0 : idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3234 0 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3235 0 : arg = TREE_CHAIN (arg), i++)
3236 0 : if (i == idx)
3237 : break;
3238 0 : gcc_assert (arg);
3239 0 : OMP_CLAUSE_LINEAR_STEP (c) = arg;
3240 : }
3241 : }
3242 105 : }
3243 :
3244 : /* Return true for __func__ and similar function-local predefined
3245 : variables (which are in OpenMP predetermined shared, allowed in
3246 : shared/firstprivate clauses). */
3247 :
3248 : bool
3249 65281 : c_omp_predefined_variable (tree decl)
3250 : {
3251 65281 : if (VAR_P (decl)
3252 34324 : && DECL_ARTIFICIAL (decl)
3253 309 : && TREE_STATIC (decl)
3254 65575 : && DECL_NAME (decl))
3255 : {
3256 294 : if (TREE_READONLY (decl)
3257 294 : && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3258 226 : || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3259 182 : || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3260 : return true;
3261 : /* For UBSan handle the same also ubsan_create_data created
3262 : variables. There is no magic flag for those, but user variables
3263 : shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3264 : such names. */
3265 142 : if ((flag_sanitize & (SANITIZE_UNDEFINED
3266 : | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3267 39 : && DECL_IGNORED_P (decl)
3268 39 : && !TREE_READONLY (decl)
3269 30 : && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3270 30 : && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3271 30 : && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3272 30 : && TYPE_NAME (TREE_TYPE (decl))
3273 30 : && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3274 30 : && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3275 172 : && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3276 : == IDENTIFIER_NODE))
3277 : {
3278 30 : tree id1 = DECL_NAME (decl);
3279 30 : tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3280 30 : if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3281 30 : && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3282 30 : && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
3283 : sizeof ("__ubsan_") - 1)
3284 30 : && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3285 30 : - sizeof ("_data") + 1, "_data",
3286 : sizeof ("_data") - 1)
3287 60 : && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
3288 30 : return true;
3289 : }
3290 : }
3291 : return false;
3292 : }
3293 :
3294 : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3295 : is predetermined. */
3296 :
3297 : enum omp_clause_default_kind
3298 28029 : c_omp_predetermined_sharing (tree decl)
3299 : {
3300 : /* Predetermine artificial variables holding integral values, those
3301 : are usually result of gimplify_one_sizepos or SAVE_EXPR
3302 : gimplification. */
3303 28029 : if (VAR_P (decl)
3304 17249 : && DECL_ARTIFICIAL (decl)
3305 28668 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3306 : return OMP_CLAUSE_DEFAULT_SHARED;
3307 :
3308 27481 : if (c_omp_predefined_variable (decl))
3309 : return OMP_CLAUSE_DEFAULT_SHARED;
3310 :
3311 : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3312 : }
3313 :
3314 : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3315 : of DECL is predetermined. */
3316 :
3317 : enum omp_clause_defaultmap_kind
3318 5150 : c_omp_predetermined_mapping (tree decl)
3319 : {
3320 : /* Predetermine artificial variables holding integral values, those
3321 : are usually result of gimplify_one_sizepos or SAVE_EXPR
3322 : gimplification. */
3323 5150 : if (VAR_P (decl)
3324 939 : && DECL_ARTIFICIAL (decl)
3325 5182 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3326 : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3327 :
3328 5122 : if (c_omp_predefined_variable (decl))
3329 2 : return OMP_CLAUSE_DEFAULTMAP_TO;
3330 :
3331 : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3332 : }
3333 :
3334 :
3335 : /* Used to merge map clause information in c_omp_adjust_map_clauses. */
3336 : struct map_clause
3337 : {
3338 : tree clause;
3339 : bool firstprivate_ptr_p;
3340 : bool decl_mapped;
3341 : bool omp_declare_target;
3342 3552 : map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3343 3552 : decl_mapped (false), omp_declare_target (false) { }
3344 : };
3345 :
3346 : /* Adjust map clauses after normal clause parsing, mainly to mark specific
3347 : base-pointer map cases addressable that may be turned into attach/detach
3348 : operations during gimplification. */
3349 : void
3350 12771 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
3351 : {
3352 12771 : if (!is_target)
3353 : {
3354 : /* If this is not a target construct, just turn firstprivate pointers
3355 : into attach/detach, the runtime will check and do the rest. */
3356 :
3357 4506 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3358 3056 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3359 2579 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3360 0 : && DECL_P (OMP_CLAUSE_DECL (c))
3361 3056 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3362 : {
3363 0 : tree ptr = OMP_CLAUSE_DECL (c);
3364 0 : c_common_mark_addressable_vec (ptr);
3365 : }
3366 1450 : return;
3367 : }
3368 :
3369 11321 : hash_map<tree, map_clause> maps;
3370 :
3371 24617 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3372 13296 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3373 13296 : && DECL_P (OMP_CLAUSE_DECL (c)))
3374 : {
3375 : /* If this is for a target construct, the firstprivate pointer
3376 : is marked addressable if either is true:
3377 : (1) the base-pointer is mapped in this same construct, or
3378 : (2) the base-pointer is a variable place on the device by
3379 : "declare target" directives.
3380 :
3381 : Here we iterate through all map clauses collecting these cases,
3382 : and merge them with a hash_map to process below. */
3383 :
3384 4192 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3385 4192 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3386 : {
3387 341 : tree ptr = OMP_CLAUSE_DECL (c);
3388 341 : map_clause &mc = maps.get_or_insert (ptr);
3389 341 : if (mc.clause == NULL_TREE)
3390 341 : mc.clause = c;
3391 341 : mc.firstprivate_ptr_p = true;
3392 :
3393 341 : if (is_global_var (ptr)
3394 389 : && lookup_attribute ("omp declare target",
3395 48 : DECL_ATTRIBUTES (ptr)))
3396 0 : mc.omp_declare_target = true;
3397 : }
3398 3851 : else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3399 3764 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3400 3261 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3401 2259 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3402 1049 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3403 979 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3404 4821 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3405 : {
3406 3242 : map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3407 3242 : mc.decl_mapped = true;
3408 : }
3409 : }
3410 :
3411 14873 : for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3412 29746 : i != maps.end (); ++i)
3413 : {
3414 3552 : map_clause &mc = (*i).second;
3415 :
3416 3552 : if (mc.firstprivate_ptr_p
3417 341 : && (mc.decl_mapped || mc.omp_declare_target))
3418 23 : c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3419 : }
3420 11321 : }
3421 :
3422 : /* Maybe strip off an indirection from a "converted" reference, then find the
3423 : origin of a pointer (i.e. without any offset). */
3424 :
3425 : tree
3426 70919 : c_omp_address_inspector::unconverted_ref_origin ()
3427 : {
3428 70919 : tree t = orig;
3429 :
3430 : /* We may have a reference-typed component access at the outermost level
3431 : that has had convert_from_reference called on it. Get the un-dereferenced
3432 : reference itself. */
3433 70919 : t = maybe_unconvert_ref (t);
3434 :
3435 : /* Find base pointer for POINTER_PLUS_EXPR, etc. */
3436 70919 : t = get_origin (t);
3437 :
3438 70919 : return t;
3439 : }
3440 :
3441 : /* Return TRUE if the address is a component access. */
3442 :
3443 : bool
3444 12245 : c_omp_address_inspector::component_access_p ()
3445 : {
3446 12245 : tree t = maybe_unconvert_ref (orig);
3447 :
3448 12245 : t = get_origin (t);
3449 :
3450 12245 : return TREE_CODE (t) == COMPONENT_REF;
3451 : }
3452 :
3453 : /* Perform various checks on the address, as described by clause CLAUSE (we
3454 : only use its code and location here). */
3455 :
3456 : bool
3457 33153 : c_omp_address_inspector::check_clause (tree clause)
3458 : {
3459 33153 : tree t = unconverted_ref_origin ();
3460 :
3461 33153 : if (TREE_CODE (t) != COMPONENT_REF)
3462 : return true;
3463 :
3464 4869 : if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
3465 4869 : && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
3466 : {
3467 24 : error_at (OMP_CLAUSE_LOCATION (clause),
3468 : "bit-field %qE in %qs clause",
3469 24 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3470 24 : return false;
3471 : }
3472 4845 : else if (!processing_template_decl_p ()
3473 4845 : && !omp_mappable_type (TREE_TYPE (t)))
3474 : {
3475 0 : error_at (OMP_CLAUSE_LOCATION (clause),
3476 : "%qE does not have a mappable type in %qs clause",
3477 0 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3478 0 : emit_unmappable_type_notes (TREE_TYPE (t));
3479 0 : return false;
3480 : }
3481 4845 : else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
3482 : {
3483 2 : error_at (OMP_CLAUSE_LOCATION (clause),
3484 : "%<_Atomic%> %qE in %qs clause", t,
3485 2 : omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3486 2 : return false;
3487 : }
3488 :
3489 : return true;
3490 : }
3491 :
3492 : /* Find the "root term" for the address. This is the innermost decl, etc.
3493 : of the access. */
3494 :
3495 : tree
3496 1691 : c_omp_address_inspector::get_root_term (bool checking)
3497 : {
3498 1691 : if (root_term && !checking)
3499 : return root_term;
3500 :
3501 1691 : tree t = unconverted_ref_origin ();
3502 :
3503 5737 : while (TREE_CODE (t) == COMPONENT_REF)
3504 : {
3505 2355 : if (checking
3506 2355 : && TREE_TYPE (TREE_OPERAND (t, 0))
3507 4522 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
3508 : {
3509 0 : error_at (loc, "%qE is a member of a union", t);
3510 0 : return error_mark_node;
3511 : }
3512 2355 : t = TREE_OPERAND (t, 0);
3513 2355 : while (TREE_CODE (t) == MEM_REF
3514 3774 : || TREE_CODE (t) == INDIRECT_REF
3515 3774 : || TREE_CODE (t) == ARRAY_REF)
3516 : {
3517 1419 : if (TREE_CODE (t) == MEM_REF
3518 : || TREE_CODE (t) == INDIRECT_REF)
3519 1275 : indirections = true;
3520 1419 : t = TREE_OPERAND (t, 0);
3521 1419 : STRIP_NOPS (t);
3522 1419 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
3523 102 : t = TREE_OPERAND (t, 0);
3524 : }
3525 : }
3526 :
3527 1691 : root_term = t;
3528 :
3529 1691 : return t;
3530 : }
3531 :
3532 : /* Return TRUE if the address is supported in mapping clauses. At present,
3533 : this means that the innermost expression is a DECL_P, but could be extended
3534 : to other types of expression in the future. */
3535 :
3536 : bool
3537 25521 : c_omp_address_inspector::map_supported_p ()
3538 : {
3539 : /* If we've already decided if the mapped address is supported, return
3540 : that. */
3541 25521 : if (map_supported != -1)
3542 0 : return map_supported;
3543 :
3544 25521 : tree t = unconverted_ref_origin ();
3545 :
3546 25521 : STRIP_NOPS (t);
3547 :
3548 25521 : while (TREE_CODE (t) == INDIRECT_REF
3549 41622 : || TREE_CODE (t) == MEM_REF
3550 : || TREE_CODE (t) == ARRAY_REF
3551 : || TREE_CODE (t) == COMPONENT_REF
3552 : || TREE_CODE (t) == COMPOUND_EXPR
3553 : || TREE_CODE (t) == SAVE_EXPR
3554 : || TREE_CODE (t) == POINTER_PLUS_EXPR
3555 : || TREE_CODE (t) == NON_LVALUE_EXPR
3556 : || TREE_CODE (t) == OMP_ARRAY_SECTION
3557 41622 : || TREE_CODE (t) == NOP_EXPR)
3558 16101 : if (TREE_CODE (t) == COMPOUND_EXPR)
3559 27 : t = TREE_OPERAND (t, 1);
3560 : else
3561 16074 : t = TREE_OPERAND (t, 0);
3562 :
3563 25521 : STRIP_NOPS (t);
3564 :
3565 25521 : map_supported = DECL_P (t);
3566 :
3567 25521 : return map_supported;
3568 : }
3569 :
3570 : /* Get the origin of an address T, stripping off offsets and some other
3571 : bits. */
3572 :
3573 : tree
3574 83164 : c_omp_address_inspector::get_origin (tree t)
3575 : {
3576 83713 : while (1)
3577 : {
3578 83713 : if (TREE_CODE (t) == COMPOUND_EXPR)
3579 : {
3580 10 : t = TREE_OPERAND (t, 1);
3581 10 : STRIP_NOPS (t);
3582 : }
3583 83703 : else if (TREE_CODE (t) == POINTER_PLUS_EXPR
3584 83703 : || TREE_CODE (t) == SAVE_EXPR)
3585 512 : t = TREE_OPERAND (t, 0);
3586 83191 : else if (!processing_template_decl_p ()
3587 76444 : && TREE_CODE (t) == INDIRECT_REF
3588 85790 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3589 27 : t = TREE_OPERAND (t, 0);
3590 : else
3591 : break;
3592 : }
3593 83164 : STRIP_NOPS (t);
3594 83164 : return t;
3595 : }
3596 :
3597 : /* For an address T that might be a reference that has had
3598 : "convert_from_reference" called on it, return the actual reference without
3599 : any indirection. */
3600 :
3601 : tree
3602 92437 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
3603 : {
3604 : /* Be careful not to dereference the type if we're processing a
3605 : template decl, else it might be NULL. */
3606 92437 : if (!processing_template_decl_p ()
3607 83694 : && TREE_CODE (t) == INDIRECT_REF
3608 95557 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3609 587 : return TREE_OPERAND (t, 0);
3610 :
3611 : return t;
3612 : }
3613 :
3614 : /* Return TRUE if CLAUSE might describe a zero-length array section. */
3615 :
3616 : bool
3617 5452 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
3618 : {
3619 5452 : switch (OMP_CLAUSE_MAP_KIND (clause))
3620 : {
3621 : case GOMP_MAP_ALLOC:
3622 : case GOMP_MAP_IF_PRESENT:
3623 : case GOMP_MAP_TO:
3624 : case GOMP_MAP_FROM:
3625 : case GOMP_MAP_TOFROM:
3626 : case GOMP_MAP_ALWAYS_TO:
3627 : case GOMP_MAP_ALWAYS_FROM:
3628 : case GOMP_MAP_ALWAYS_TOFROM:
3629 : case GOMP_MAP_PRESENT_ALLOC:
3630 : case GOMP_MAP_PRESENT_TO:
3631 : case GOMP_MAP_PRESENT_FROM:
3632 : case GOMP_MAP_PRESENT_TOFROM:
3633 : case GOMP_MAP_ALWAYS_PRESENT_TO:
3634 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
3635 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
3636 : case GOMP_MAP_RELEASE:
3637 : case GOMP_MAP_DELETE:
3638 : case GOMP_MAP_FORCE_TO:
3639 : case GOMP_MAP_FORCE_FROM:
3640 : case GOMP_MAP_FORCE_TOFROM:
3641 : case GOMP_MAP_FORCE_PRESENT:
3642 : return true;
3643 28 : default:
3644 28 : return false;
3645 : }
3646 : }
3647 :
3648 : /* Expand a chained access. We only expect to see a quite limited range of
3649 : expression types here, because e.g. you can't have an array of
3650 : references. */
3651 :
3652 : static tree
3653 75 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
3654 : unsigned *idx, c_omp_region_type ort)
3655 : {
3656 83 : using namespace omp_addr_tokenizer;
3657 83 : location_t loc = OMP_CLAUSE_LOCATION (c);
3658 83 : unsigned i = *idx;
3659 83 : tree c2 = NULL_TREE;
3660 83 : gomp_map_kind kind;
3661 :
3662 83 : if ((ort & C_ORT_EXIT_DATA) != 0
3663 71 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
3664 154 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3665 71 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3666 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
3667 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
3668 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3669 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
3670 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
3671 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
3672 : kind = GOMP_MAP_DETACH;
3673 : else
3674 : kind = GOMP_MAP_ATTACH;
3675 :
3676 83 : switch (addr_tokens[i]->u.access_kind)
3677 : {
3678 83 : case ACCESS_POINTER:
3679 83 : case ACCESS_POINTER_OFFSET:
3680 83 : {
3681 83 : tree virtual_origin
3682 83 : = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
3683 83 : tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
3684 83 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3685 83 : OMP_CLAUSE_SET_MAP_KIND (c2, kind);
3686 83 : OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
3687 83 : OMP_CLAUSE_SIZE (c2)
3688 83 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3689 : fold_convert_loc (loc, ptrdiff_type_node,
3690 : data_addr),
3691 : virtual_origin);
3692 : }
3693 83 : break;
3694 :
3695 : case ACCESS_INDEXED_ARRAY:
3696 : break;
3697 :
3698 0 : default:
3699 0 : return error_mark_node;
3700 : }
3701 :
3702 83 : if (c2)
3703 : {
3704 83 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
3705 83 : OMP_CLAUSE_CHAIN (c) = c2;
3706 83 : c = c2;
3707 : }
3708 :
3709 83 : *idx = ++i;
3710 :
3711 83 : if (i < addr_tokens.length ()
3712 91 : && addr_tokens[i]->type == ACCESS_METHOD)
3713 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
3714 :
3715 : return c;
3716 : }
3717 :
3718 : /* Translate "array_base_decl access_method" to OMP mapping clauses. */
3719 :
3720 : tree
3721 18237 : c_omp_address_inspector::expand_array_base (tree c,
3722 : vec<omp_addr_token *> &addr_tokens,
3723 : tree expr, unsigned *idx,
3724 : c_omp_region_type ort)
3725 : {
3726 18237 : using namespace omp_addr_tokenizer;
3727 18237 : location_t loc = OMP_CLAUSE_LOCATION (c);
3728 18237 : int i = *idx;
3729 18237 : tree decl = addr_tokens[i + 1]->expr;
3730 18237 : bool decl_p = DECL_P (decl);
3731 18237 : bool declare_target_p = (decl_p
3732 18228 : && is_global_var (decl)
3733 25736 : && lookup_attribute ("omp declare target",
3734 7499 : DECL_ATTRIBUTES (decl)));
3735 18237 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
3736 18237 : bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
3737 18237 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
3738 18237 : tree c2 = NULL_TREE, c3 = NULL_TREE;
3739 18237 : unsigned consume_tokens = 2;
3740 18237 : bool target_p = (ort & C_ORT_TARGET) != 0;
3741 18237 : bool openmp_p = (ort & C_ORT_OMP) != 0;
3742 :
3743 18237 : gcc_assert (i == 0);
3744 :
3745 18237 : if (!openmp_p
3746 18237 : && map_p
3747 18237 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
3748 6745 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
3749 : {
3750 28 : i += 2;
3751 28 : *idx = i;
3752 28 : return c;
3753 : }
3754 :
3755 18209 : switch (addr_tokens[i + 1]->u.access_kind)
3756 : {
3757 13938 : case ACCESS_DIRECT:
3758 13938 : if (decl_p && !target_p)
3759 8630 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3760 : break;
3761 :
3762 154 : case ACCESS_REF:
3763 154 : {
3764 : /* Copy the referenced object. Note that we do this even for !MAP_P
3765 : clauses. */
3766 154 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
3767 154 : if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
3768 : /* We have a ref to array: add a [0] element as the ME expects. */
3769 47 : OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
3770 : else
3771 107 : OMP_CLAUSE_DECL (c) = obj;
3772 154 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
3773 :
3774 154 : if (!map_p)
3775 : {
3776 6 : if (decl_p)
3777 6 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3778 : break;
3779 : }
3780 :
3781 148 : if (!target_p)
3782 : break;
3783 :
3784 : /* If we have a reference to a pointer, avoid using
3785 : FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
3786 : offload region (we can only do that if the pointer does not point
3787 : to a mapped block). We could avoid doing this if we don't have a
3788 : FROM mapping... */
3789 88 : bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
3790 :
3791 88 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3792 88 : if (!ref_to_ptr
3793 88 : && !declare_target_p
3794 54 : && decl_p)
3795 54 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3796 : else
3797 : {
3798 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3799 34 : if (decl_p)
3800 34 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3801 : }
3802 88 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3803 88 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
3804 :
3805 88 : if (ref_to_ptr)
3806 : {
3807 34 : c3 = c2;
3808 34 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3809 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
3810 34 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3811 68 : OMP_CLAUSE_SIZE (c2)
3812 34 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
3813 : }
3814 : }
3815 : break;
3816 :
3817 83 : case ACCESS_INDEXED_REF_TO_ARRAY:
3818 83 : {
3819 83 : if (!map_p)
3820 : {
3821 0 : if (decl_p)
3822 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3823 : break;
3824 : }
3825 :
3826 83 : if (!target_p)
3827 : break;
3828 :
3829 64 : tree virtual_origin
3830 64 : = convert_from_reference (addr_tokens[i + 1]->expr);
3831 64 : virtual_origin = build_fold_addr_expr (virtual_origin);
3832 64 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3833 : virtual_origin);
3834 64 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3835 64 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3836 64 : if (decl_p && target_p && !declare_target_p)
3837 : {
3838 : /* It appears that omp-low.cc mishandles cases where we have a
3839 : [reference to an] array of pointers such as:
3840 :
3841 : int *arr[N]; (or "int *(&arr)[N] = ...")
3842 : #pragma omp target map(arr[a][b:c])
3843 : { ... }
3844 :
3845 : in such cases chain_p will be true. For now, fall back to
3846 : GOMP_MAP_POINTER. */
3847 61 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3848 : : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
3849 61 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3850 61 : }
3851 : else
3852 : {
3853 3 : if (decl_p)
3854 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3855 3 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3856 : }
3857 64 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3858 64 : OMP_CLAUSE_SIZE (c2)
3859 64 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3860 : fold_convert_loc (loc, ptrdiff_type_node,
3861 : data_addr),
3862 : virtual_origin);
3863 : }
3864 64 : break;
3865 :
3866 1328 : case ACCESS_INDEXED_ARRAY:
3867 1328 : {
3868 1328 : if (!map_p)
3869 : {
3870 0 : if (decl_p)
3871 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3872 : break;
3873 : }
3874 :
3875 : /* The code handling "firstprivatize_array_bases" in gimplify.cc is
3876 : relevant here. What do we need to create for arrays at this
3877 : stage? (This condition doesn't feel quite right. FIXME?) */
3878 1328 : if (!target_p
3879 1328 : && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
3880 : == ARRAY_TYPE))
3881 : break;
3882 :
3883 683 : tree virtual_origin
3884 683 : = build_fold_addr_expr (addr_tokens[i + 1]->expr);
3885 683 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3886 : virtual_origin);
3887 683 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3888 683 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3889 683 : if (decl_p && target_p)
3890 : {
3891 : /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above. */
3892 683 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3893 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
3894 683 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3895 : }
3896 : else
3897 : {
3898 0 : if (decl_p)
3899 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3900 0 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3901 : }
3902 683 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3903 683 : OMP_CLAUSE_SIZE (c2)
3904 683 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3905 : fold_convert_loc (loc, ptrdiff_type_node,
3906 : data_addr),
3907 : virtual_origin);
3908 : }
3909 683 : break;
3910 :
3911 2632 : case ACCESS_POINTER:
3912 2632 : case ACCESS_POINTER_OFFSET:
3913 2632 : {
3914 2632 : if (!map_p)
3915 : {
3916 0 : if (decl_p)
3917 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3918 : break;
3919 : }
3920 :
3921 2632 : unsigned last_access = i + 1;
3922 2632 : tree virtual_origin;
3923 :
3924 2632 : if (chain_p
3925 149 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3926 2781 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3927 : {
3928 : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3929 115 : consume_tokens = 3;
3930 115 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3931 115 : last_access = i + 2;
3932 115 : virtual_origin
3933 115 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3934 : integer_zero_node);
3935 115 : virtual_origin = build_fold_addr_expr (virtual_origin);
3936 115 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3937 : virtual_origin);
3938 : }
3939 : else
3940 2517 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3941 2517 : addr_tokens[last_access]->expr);
3942 2632 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3943 2632 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3944 : /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
3945 : regions (e.g. "acc data" constructs). It'll be removed anyway in
3946 : gimplify.cc, but doing it this way maintains diagnostic
3947 : behaviour. */
3948 2632 : if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
3949 2434 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
3950 : else
3951 : {
3952 195 : if (decl_p)
3953 195 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3954 198 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3955 : }
3956 2632 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3957 2632 : OMP_CLAUSE_SIZE (c2)
3958 2632 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3959 : fold_convert_loc (loc, ptrdiff_type_node,
3960 : data_addr),
3961 : virtual_origin);
3962 : }
3963 2632 : break;
3964 :
3965 74 : case ACCESS_REF_TO_POINTER:
3966 74 : case ACCESS_REF_TO_POINTER_OFFSET:
3967 74 : {
3968 74 : if (!map_p)
3969 : {
3970 0 : if (decl_p)
3971 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3972 : break;
3973 : }
3974 :
3975 74 : unsigned last_access = i + 1;
3976 74 : tree virtual_origin;
3977 :
3978 74 : if (chain_p
3979 6 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3980 80 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3981 : {
3982 : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3983 2 : consume_tokens = 3;
3984 2 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3985 2 : last_access = i + 2;
3986 2 : virtual_origin
3987 2 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3988 : integer_zero_node);
3989 2 : virtual_origin = build_fold_addr_expr (virtual_origin);
3990 2 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3991 : virtual_origin);
3992 : }
3993 : else
3994 : {
3995 72 : virtual_origin
3996 72 : = convert_from_reference (addr_tokens[last_access]->expr);
3997 72 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3998 : virtual_origin);
3999 : }
4000 :
4001 74 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
4002 74 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4003 74 : if (decl_p && target_p && !chain_p && !declare_target_p)
4004 : {
4005 58 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
4006 58 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4007 : }
4008 : else
4009 : {
4010 16 : if (decl_p)
4011 16 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4012 16 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4013 16 : OMP_CLAUSE_DECL (c2)
4014 32 : = convert_from_reference (addr_tokens[i + 1]->expr);
4015 : }
4016 74 : OMP_CLAUSE_SIZE (c2)
4017 74 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4018 : fold_convert_loc (loc, ptrdiff_type_node,
4019 : data_addr),
4020 : virtual_origin);
4021 : }
4022 74 : break;
4023 :
4024 0 : default:
4025 0 : *idx = i + consume_tokens;
4026 0 : return error_mark_node;
4027 : }
4028 :
4029 12089 : if (c3)
4030 : {
4031 34 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4032 34 : OMP_CLAUSE_CHAIN (c2) = c3;
4033 34 : OMP_CLAUSE_CHAIN (c) = c2;
4034 34 : if (implicit_p)
4035 : {
4036 0 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4037 0 : OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
4038 : }
4039 : c = c3;
4040 : }
4041 18175 : else if (c2)
4042 : {
4043 3507 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4044 3507 : OMP_CLAUSE_CHAIN (c) = c2;
4045 3507 : if (implicit_p)
4046 116 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4047 : c = c2;
4048 : }
4049 :
4050 18209 : i += consume_tokens;
4051 18209 : *idx = i;
4052 :
4053 18209 : if (chain_p && map_p)
4054 53 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4055 :
4056 : return c;
4057 : }
4058 :
4059 : /* Translate "component_selector access_method" to OMP mapping clauses. */
4060 :
4061 : tree
4062 3226 : c_omp_address_inspector::expand_component_selector (tree c,
4063 : vec<omp_addr_token *>
4064 : &addr_tokens,
4065 : tree expr, unsigned *idx,
4066 : c_omp_region_type ort)
4067 : {
4068 3226 : using namespace omp_addr_tokenizer;
4069 3226 : location_t loc = OMP_CLAUSE_LOCATION (c);
4070 3226 : unsigned i = *idx;
4071 3226 : tree c2 = NULL_TREE, c3 = NULL_TREE;
4072 3226 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
4073 3226 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
4074 :
4075 3226 : switch (addr_tokens[i + 1]->u.access_kind)
4076 : {
4077 : case ACCESS_DIRECT:
4078 : case ACCESS_INDEXED_ARRAY:
4079 : break;
4080 :
4081 479 : case ACCESS_REF:
4082 479 : {
4083 : /* Copy the referenced object. Note that we also do this for !MAP_P
4084 : clauses. */
4085 479 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
4086 479 : OMP_CLAUSE_DECL (c) = obj;
4087 479 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
4088 :
4089 479 : if (!map_p)
4090 : break;
4091 :
4092 461 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4093 461 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4094 461 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4095 461 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
4096 : }
4097 461 : break;
4098 :
4099 92 : case ACCESS_INDEXED_REF_TO_ARRAY:
4100 92 : {
4101 92 : if (!map_p)
4102 : break;
4103 :
4104 92 : tree virtual_origin
4105 92 : = convert_from_reference (addr_tokens[i + 1]->expr);
4106 92 : virtual_origin = build_fold_addr_expr (virtual_origin);
4107 92 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4108 : virtual_origin);
4109 92 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4110 :
4111 92 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4112 92 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4113 92 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4114 92 : OMP_CLAUSE_SIZE (c2)
4115 92 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4116 : fold_convert_loc (loc, ptrdiff_type_node,
4117 : data_addr),
4118 : virtual_origin);
4119 : }
4120 92 : break;
4121 :
4122 778 : case ACCESS_POINTER:
4123 778 : case ACCESS_POINTER_OFFSET:
4124 778 : {
4125 778 : if (!map_p)
4126 : break;
4127 :
4128 778 : tree virtual_origin
4129 1556 : = fold_convert_loc (loc, ptrdiff_type_node,
4130 778 : addr_tokens[i + 1]->expr);
4131 778 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4132 :
4133 778 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4134 778 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4135 778 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4136 778 : OMP_CLAUSE_SIZE (c2)
4137 778 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4138 : fold_convert_loc (loc, ptrdiff_type_node,
4139 : data_addr),
4140 : virtual_origin);
4141 : }
4142 778 : break;
4143 :
4144 185 : case ACCESS_REF_TO_POINTER:
4145 185 : case ACCESS_REF_TO_POINTER_OFFSET:
4146 185 : {
4147 185 : if (!map_p)
4148 : break;
4149 :
4150 185 : tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
4151 185 : tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4152 : ptr);
4153 185 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4154 :
4155 : /* Attach the pointer... */
4156 185 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4157 185 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4158 185 : OMP_CLAUSE_DECL (c2) = ptr;
4159 185 : OMP_CLAUSE_SIZE (c2)
4160 185 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4161 : fold_convert_loc (loc, ptrdiff_type_node,
4162 : data_addr),
4163 : virtual_origin);
4164 :
4165 : /* ...and also the reference. */
4166 185 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4167 185 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
4168 185 : OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
4169 185 : OMP_CLAUSE_SIZE (c3) = size_zero_node;
4170 : }
4171 185 : break;
4172 :
4173 0 : default:
4174 0 : *idx = i + 2;
4175 0 : return error_mark_node;
4176 : }
4177 :
4178 1331 : if (c3)
4179 : {
4180 185 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4181 185 : OMP_CLAUSE_CHAIN (c2) = c3;
4182 185 : OMP_CLAUSE_CHAIN (c) = c2;
4183 185 : c = c3;
4184 : }
4185 3041 : else if (c2)
4186 : {
4187 1331 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4188 1331 : OMP_CLAUSE_CHAIN (c) = c2;
4189 1331 : c = c2;
4190 : }
4191 :
4192 3226 : i += 2;
4193 3226 : *idx = i;
4194 :
4195 3226 : if (chain_p && map_p)
4196 22 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4197 :
4198 : return c;
4199 : }
4200 :
4201 : /* Expand a map clause into a group of mapping clauses, creating nodes to
4202 : attach/detach pointers and so forth as necessary. */
4203 :
4204 : tree
4205 21463 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
4206 : vec<omp_addr_token *> &addr_tokens,
4207 : c_omp_region_type ort)
4208 : {
4209 21463 : using namespace omp_addr_tokenizer;
4210 21463 : unsigned i, length = addr_tokens.length ();
4211 :
4212 46847 : for (i = 0; i < length;)
4213 : {
4214 25384 : int remaining = length - i;
4215 :
4216 25384 : if (remaining >= 2
4217 25384 : && addr_tokens[i]->type == ARRAY_BASE
4218 18237 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4219 43612 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4220 : {
4221 18228 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4222 18228 : if (c == error_mark_node)
4223 : return error_mark_node;
4224 : }
4225 7156 : else if (remaining >= 2
4226 7156 : && addr_tokens[i]->type == ARRAY_BASE
4227 9 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4228 7165 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4229 : {
4230 9 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4231 9 : if (c == error_mark_node)
4232 : return error_mark_node;
4233 : }
4234 7147 : else if (remaining >= 2
4235 7147 : && addr_tokens[i]->type == STRUCTURE_BASE
4236 3226 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4237 10370 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4238 : {
4239 3223 : if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
4240 1754 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4241 3223 : i += 2;
4242 3383 : while (addr_tokens[i]->type == ACCESS_METHOD)
4243 160 : i++;
4244 : }
4245 3924 : else if (remaining >= 2
4246 3924 : && addr_tokens[i]->type == STRUCTURE_BASE
4247 3 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4248 3927 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4249 : {
4250 3 : switch (addr_tokens[i + 1]->u.access_kind)
4251 : {
4252 3 : case ACCESS_DIRECT:
4253 3 : case ACCESS_POINTER:
4254 3 : i += 2;
4255 3 : while (addr_tokens[i]->type == ACCESS_METHOD)
4256 0 : i++;
4257 : break;
4258 0 : default:
4259 0 : return error_mark_node;
4260 : }
4261 : }
4262 3921 : else if (remaining >= 2
4263 3921 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4264 7842 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4265 : {
4266 3226 : c = expand_component_selector (c, addr_tokens, expr, &i, ort);
4267 : /* We used 'expr', so these must have been the last tokens. */
4268 3226 : gcc_assert (i == length);
4269 3226 : if (c == error_mark_node)
4270 : return error_mark_node;
4271 : }
4272 695 : else if (remaining >= 3
4273 695 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4274 695 : && addr_tokens[i + 1]->type == STRUCTURE_BASE
4275 695 : && (addr_tokens[i + 1]->u.structure_base_kind
4276 : == BASE_COMPONENT_EXPR)
4277 1390 : && addr_tokens[i + 2]->type == ACCESS_METHOD)
4278 : {
4279 695 : i += 3;
4280 719 : while (addr_tokens[i]->type == ACCESS_METHOD)
4281 24 : i++;
4282 : }
4283 : else
4284 : break;
4285 : }
4286 :
4287 21463 : if (i == length)
4288 : return c;
4289 :
4290 0 : return error_mark_node;
4291 : }
4292 :
4293 : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
4294 : for that mapper, and if any of those should use a (named or unnamed) mapper
4295 : themselves, add it to MLIST. */
4296 :
4297 : void
4298 140 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
4299 : {
4300 140 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4301 140 : tree mapper_name = NULL_TREE;
4302 :
4303 140 : if (mapper == error_mark_node)
4304 : return;
4305 :
4306 140 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
4307 :
4308 454 : for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4309 454 : clause;
4310 314 : clause = OMP_CLAUSE_CHAIN (clause))
4311 : {
4312 314 : tree expr = OMP_CLAUSE_DECL (clause);
4313 314 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
4314 314 : tree elem_type;
4315 :
4316 314 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4317 : {
4318 0 : mapper_name = expr;
4319 0 : continue;
4320 : }
4321 314 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4322 : {
4323 0 : mapper_name = NULL_TREE;
4324 0 : continue;
4325 : }
4326 :
4327 314 : gcc_assert (TREE_CODE (expr) != TREE_LIST);
4328 314 : if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4329 : {
4330 220 : while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4331 110 : expr = TREE_OPERAND (expr, 0);
4332 :
4333 110 : elem_type = TREE_TYPE (expr);
4334 : }
4335 : else
4336 204 : elem_type = TREE_TYPE (expr);
4337 :
4338 : /* This might be too much... or not enough? */
4339 512 : while (TREE_CODE (elem_type) == ARRAY_TYPE
4340 506 : || TREE_CODE (elem_type) == POINTER_TYPE
4341 826 : || TREE_CODE (elem_type) == REFERENCE_TYPE)
4342 198 : elem_type = TREE_TYPE (elem_type);
4343 :
4344 314 : elem_type = TYPE_MAIN_VARIANT (elem_type);
4345 :
4346 314 : if (RECORD_OR_UNION_TYPE_P (elem_type)
4347 314 : && !mlist->contains (mapper_name, elem_type))
4348 : {
4349 5 : tree nested_mapper_fn
4350 5 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
4351 :
4352 5 : if (nested_mapper_fn)
4353 : {
4354 5 : mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
4355 5 : c_omp_find_nested_mappers (mlist, nested_mapper_fn);
4356 : }
4357 0 : else if (mapper_name)
4358 : {
4359 0 : error ("mapper %qE not found for type %qT", mapper_name,
4360 : elem_type);
4361 0 : continue;
4362 : }
4363 : }
4364 : }
4365 : }
4366 :
4367 : struct remap_mapper_decl_info
4368 : {
4369 : tree dummy_var;
4370 : tree expr;
4371 : };
4372 :
4373 : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
4374 :
4375 : static tree
4376 4044 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
4377 : {
4378 4044 : remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
4379 :
4380 4044 : if (operand_equal_p (*tp, map_info->dummy_var))
4381 : {
4382 1001 : *tp = map_info->expr;
4383 1001 : *walk_subtrees = 0;
4384 : }
4385 :
4386 4044 : return NULL_TREE;
4387 : }
4388 :
4389 : static enum gomp_map_kind
4390 946 : omp_split_map_kind (enum gomp_map_kind op, bool *force_p, bool *always_p,
4391 : bool *present_p)
4392 : {
4393 946 : *force_p = *always_p = *present_p = false;
4394 :
4395 946 : switch (op)
4396 : {
4397 0 : case GOMP_MAP_FORCE_ALLOC:
4398 0 : case GOMP_MAP_FORCE_TO:
4399 0 : case GOMP_MAP_FORCE_FROM:
4400 0 : case GOMP_MAP_FORCE_TOFROM:
4401 0 : case GOMP_MAP_FORCE_PRESENT:
4402 0 : *force_p = true;
4403 0 : break;
4404 54 : case GOMP_MAP_ALWAYS_TO:
4405 54 : case GOMP_MAP_ALWAYS_FROM:
4406 54 : case GOMP_MAP_ALWAYS_TOFROM:
4407 54 : *always_p = true;
4408 54 : break;
4409 32 : case GOMP_MAP_ALWAYS_PRESENT_TO:
4410 32 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
4411 32 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
4412 32 : *always_p = true;
4413 : /* Fallthrough. */
4414 132 : case GOMP_MAP_PRESENT_ALLOC:
4415 132 : case GOMP_MAP_PRESENT_TO:
4416 132 : case GOMP_MAP_PRESENT_FROM:
4417 132 : case GOMP_MAP_PRESENT_TOFROM:
4418 132 : *present_p = true;
4419 132 : break;
4420 946 : default:
4421 946 : ;
4422 : }
4423 :
4424 946 : switch (op)
4425 : {
4426 : case GOMP_MAP_ALLOC:
4427 : case GOMP_MAP_FORCE_ALLOC:
4428 : case GOMP_MAP_PRESENT_ALLOC:
4429 : return GOMP_MAP_ALLOC;
4430 283 : case GOMP_MAP_TO:
4431 283 : case GOMP_MAP_FORCE_TO:
4432 283 : case GOMP_MAP_ALWAYS_TO:
4433 283 : case GOMP_MAP_PRESENT_TO:
4434 283 : case GOMP_MAP_ALWAYS_PRESENT_TO:
4435 283 : return GOMP_MAP_TO;
4436 212 : case GOMP_MAP_FROM:
4437 212 : case GOMP_MAP_FORCE_FROM:
4438 212 : case GOMP_MAP_ALWAYS_FROM:
4439 212 : case GOMP_MAP_PRESENT_FROM:
4440 212 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
4441 212 : return GOMP_MAP_FROM;
4442 210 : case GOMP_MAP_TOFROM:
4443 210 : case GOMP_MAP_FORCE_TOFROM:
4444 210 : case GOMP_MAP_ALWAYS_TOFROM:
4445 210 : case GOMP_MAP_PRESENT_TOFROM:
4446 210 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
4447 210 : return GOMP_MAP_TOFROM;
4448 128 : default:
4449 128 : ;
4450 : }
4451 :
4452 128 : return op;
4453 : }
4454 :
4455 : static enum gomp_map_kind
4456 416 : omp_join_map_kind (enum gomp_map_kind op, bool force_p, bool always_p,
4457 : bool present_p)
4458 : {
4459 416 : gcc_assert (!force_p || !(always_p || present_p));
4460 :
4461 416 : switch (op)
4462 : {
4463 89 : case GOMP_MAP_ALLOC:
4464 89 : if (force_p)
4465 : return GOMP_MAP_FORCE_ALLOC;
4466 89 : else if (present_p)
4467 16 : return GOMP_MAP_PRESENT_ALLOC;
4468 : break;
4469 :
4470 127 : case GOMP_MAP_TO:
4471 127 : if (force_p)
4472 : return GOMP_MAP_FORCE_TO;
4473 127 : else if (always_p && present_p)
4474 : return GOMP_MAP_ALWAYS_PRESENT_TO;
4475 115 : else if (always_p)
4476 : return GOMP_MAP_ALWAYS_TO;
4477 93 : else if (present_p)
4478 24 : return GOMP_MAP_PRESENT_TO;
4479 : break;
4480 :
4481 76 : case GOMP_MAP_FROM:
4482 76 : if (force_p)
4483 : return GOMP_MAP_FORCE_FROM;
4484 76 : else if (always_p && present_p)
4485 : return GOMP_MAP_ALWAYS_PRESENT_FROM;
4486 68 : else if (always_p)
4487 : return GOMP_MAP_ALWAYS_FROM;
4488 60 : else if (present_p)
4489 24 : return GOMP_MAP_PRESENT_FROM;
4490 : break;
4491 :
4492 80 : case GOMP_MAP_TOFROM:
4493 80 : if (force_p)
4494 : return GOMP_MAP_FORCE_TOFROM;
4495 80 : else if (always_p && present_p)
4496 : return GOMP_MAP_ALWAYS_PRESENT_TOFROM;
4497 80 : else if (always_p)
4498 : return GOMP_MAP_ALWAYS_TOFROM;
4499 80 : else if (present_p)
4500 0 : return GOMP_MAP_PRESENT_TOFROM;
4501 : break;
4502 :
4503 : default:
4504 : ;
4505 : }
4506 :
4507 : return op;
4508 : }
4509 :
4510 : /* Map kind decay (OpenMP 5.2, 5.8.8 "declare mapper Directive"). Return the
4511 : map kind to use given MAPPER_KIND specified in the mapper and INVOKED_AS
4512 : specified on the clause that invokes the mapper. See also
4513 : fortran/trans-openmp.cc:omp_map_decayed_kind. */
4514 :
4515 : static enum gomp_map_kind
4516 432 : omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
4517 : enum gomp_map_kind invoked_as, bool exit_p)
4518 : {
4519 432 : if (invoked_as == GOMP_MAP_RELEASE || invoked_as == GOMP_MAP_DELETE)
4520 : return invoked_as;
4521 :
4522 416 : bool m_force_p, m_always_p, m_present_p;
4523 416 : bool force_p, always_p, present_p;
4524 :
4525 416 : mapper_kind = omp_split_map_kind (mapper_kind, &m_force_p, &m_always_p, &m_present_p);
4526 416 : invoked_as = omp_split_map_kind (invoked_as, &force_p, &always_p, &present_p);
4527 416 : gomp_map_kind decay_to;
4528 :
4529 416 : switch (mapper_kind)
4530 : {
4531 53 : case GOMP_MAP_ALLOC:
4532 53 : if (exit_p && invoked_as == GOMP_MAP_FROM)
4533 : decay_to = GOMP_MAP_RELEASE;
4534 : else
4535 77 : decay_to = GOMP_MAP_ALLOC;
4536 : break;
4537 :
4538 115 : case GOMP_MAP_TO:
4539 115 : if (invoked_as == GOMP_MAP_FROM)
4540 101 : decay_to = exit_p ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
4541 91 : else if (invoked_as == GOMP_MAP_ALLOC)
4542 : decay_to = GOMP_MAP_ALLOC;
4543 : else
4544 416 : decay_to = GOMP_MAP_TO;
4545 : break;
4546 :
4547 52 : case GOMP_MAP_FROM:
4548 52 : if (invoked_as == GOMP_MAP_ALLOC || invoked_as == GOMP_MAP_TO)
4549 : decay_to = GOMP_MAP_ALLOC;
4550 : else
4551 416 : decay_to = GOMP_MAP_FROM;
4552 : break;
4553 :
4554 : case GOMP_MAP_TOFROM:
4555 : case GOMP_MAP_UNSET:
4556 : decay_to = invoked_as;
4557 : break;
4558 :
4559 0 : default:
4560 0 : gcc_unreachable ();
4561 : }
4562 :
4563 416 : return omp_join_map_kind (decay_to, m_force_p | force_p,
4564 416 : m_always_p | always_p, m_present_p | present_p);
4565 : }
4566 :
4567 : /* Return a name to use for a "basic" map kind, e.g. as output from
4568 : omp_split_map_kind above. */
4569 :
4570 : static const char *
4571 16 : omp_basic_map_kind_name (enum gomp_map_kind kind)
4572 : {
4573 16 : switch (kind)
4574 : {
4575 : case GOMP_MAP_ALLOC:
4576 : return "alloc";
4577 4 : case GOMP_MAP_TO:
4578 4 : return "to";
4579 4 : case GOMP_MAP_FROM:
4580 4 : return "from";
4581 0 : case GOMP_MAP_TOFROM:
4582 0 : return "tofrom";
4583 0 : case GOMP_MAP_RELEASE:
4584 0 : return "release";
4585 0 : case GOMP_MAP_DELETE:
4586 0 : return "delete";
4587 0 : default:
4588 0 : gcc_unreachable ();
4589 : }
4590 : }
4591 :
4592 : /* Instantiate a mapper MAPPER for expression EXPR at location LOC,
4593 : adding new clauses to OUTLIST. OUTER_KIND is the mapping kind
4594 : to use if not already specified in the mapper declaration; ORT
4595 : denotes the directive that uses the mapper.
4596 : The resulting OUTLIST is also returned by the function. */
4597 :
4598 : static tree *
4599 142 : omp_instantiate_mapper (location_t loc, tree *outlist, tree mapper, tree expr,
4600 : enum gomp_map_kind outer_kind,
4601 : enum c_omp_region_type ort)
4602 : {
4603 142 : tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4604 142 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
4605 142 : tree mapper_name = NULL_TREE;
4606 :
4607 142 : remap_mapper_decl_info map_info;
4608 142 : map_info.dummy_var = dummy_var;
4609 142 : map_info.expr = expr;
4610 :
4611 574 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4612 : {
4613 432 : tree unshared = unshare_expr (c);
4614 432 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
4615 432 : tree t = OMP_CLAUSE_DECL (unshared);
4616 432 : tree type = NULL_TREE;
4617 432 : bool nonunit_array_with_mapper = false;
4618 :
4619 432 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4620 : {
4621 0 : mapper_name = t;
4622 2 : continue;
4623 : }
4624 432 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4625 : {
4626 0 : mapper_name = NULL_TREE;
4627 0 : continue;
4628 : }
4629 :
4630 432 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4631 : {
4632 43 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4633 :
4634 43 : if (t2 == t)
4635 : {
4636 42 : nonunit_array_with_mapper = true;
4637 : /* We'd want use the mapper for the element type if this worked:
4638 : look that one up. */
4639 42 : type = TREE_TYPE (TREE_TYPE (t));
4640 : }
4641 : else
4642 : {
4643 1 : t = t2;
4644 1 : type = TREE_TYPE (t);
4645 : }
4646 : }
4647 : else
4648 389 : type = TREE_TYPE (t);
4649 :
4650 432 : gcc_assert (type);
4651 :
4652 432 : if (type == error_mark_node)
4653 0 : continue;
4654 :
4655 432 : walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
4656 :
4657 432 : OMP_CLAUSE_LOCATION (unshared) = loc;
4658 :
4659 432 : enum gomp_map_kind decayed_kind
4660 432 : = omp_map_decayed_kind (clause_kind, outer_kind,
4661 : (ort & C_ORT_EXIT_DATA) != 0
4662 432 : || (outer_kind == GOMP_MAP_FROM
4663 32 : && (ort & C_ORT_UPDATE) != 0));
4664 432 : OMP_CLAUSE_SET_MAP_KIND (unshared, decayed_kind);
4665 :
4666 432 : type = TYPE_MAIN_VARIANT (type);
4667 :
4668 432 : tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4669 :
4670 432 : if (mapper_fn && nonunit_array_with_mapper)
4671 : {
4672 0 : sorry ("user-defined mapper with non-unit length array section");
4673 0 : continue;
4674 : }
4675 432 : else if (mapper_fn)
4676 : {
4677 27 : tree nested_mapper
4678 27 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4679 27 : if (nested_mapper != mapper)
4680 : {
4681 2 : outlist = omp_instantiate_mapper (loc, outlist, nested_mapper,
4682 : t, outer_kind, ort);
4683 2 : continue;
4684 : }
4685 : }
4686 405 : else if (mapper_name)
4687 : {
4688 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4689 0 : continue;
4690 : }
4691 :
4692 430 : if (ort & C_ORT_UPDATE)
4693 : {
4694 98 : bool force_p, always_p, present_p;
4695 98 : decayed_kind
4696 98 : = omp_split_map_kind (decayed_kind, &force_p, &always_p,
4697 : &present_p);
4698 : /* We don't expect to see these flags here. */
4699 98 : gcc_assert (!force_p && !always_p);
4700 : /* For a "target update" operation, we want to turn the map node
4701 : expanded from the mapper back into a OMP_CLAUSE_TO or
4702 : OMP_CLAUSE_FROM node. If we can do neither, emit a warning and
4703 : drop the clause. */
4704 98 : switch (decayed_kind)
4705 : {
4706 82 : case GOMP_MAP_TO:
4707 82 : case GOMP_MAP_FROM:
4708 82 : {
4709 82 : tree xfer
4710 122 : = build_omp_clause (loc, (decayed_kind == GOMP_MAP_TO
4711 : ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM));
4712 82 : OMP_CLAUSE_DECL (xfer) = OMP_CLAUSE_DECL (unshared);
4713 82 : OMP_CLAUSE_SIZE (xfer) = OMP_CLAUSE_SIZE (unshared);
4714 : /* For FROM/TO clauses, "present" is represented by a flag.
4715 : Set it for the expanded clause here. */
4716 82 : if (present_p)
4717 32 : OMP_CLAUSE_MOTION_PRESENT (xfer) = 1;
4718 82 : *outlist = xfer;
4719 82 : outlist = &OMP_CLAUSE_CHAIN (xfer);
4720 : }
4721 82 : break;
4722 16 : default:
4723 16 : clause_kind
4724 16 : = omp_split_map_kind (clause_kind, &force_p, &always_p,
4725 : &present_p);
4726 16 : warning_at (loc, OPT_Wopenmp,
4727 : "dropping %qs clause during mapper expansion "
4728 : "in %<#pragma omp target update%>",
4729 : omp_basic_map_kind_name (clause_kind));
4730 16 : inform (OMP_CLAUSE_LOCATION (c), "for map clause here");
4731 : }
4732 : }
4733 : else
4734 : {
4735 332 : *outlist = unshared;
4736 332 : outlist = &OMP_CLAUSE_CHAIN (unshared);
4737 : }
4738 : }
4739 :
4740 142 : return outlist;
4741 : }
4742 :
4743 : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
4744 : appropriate to the type of the data in that clause, if such a mapper is
4745 : visible in the current parsing context. */
4746 :
4747 : tree
4748 16513 : c_omp_instantiate_mappers (tree clauses, enum c_omp_region_type ort)
4749 : {
4750 16513 : tree c, *pc, mapper_name = NULL_TREE;
4751 :
4752 35965 : for (pc = &clauses, c = clauses; c; c = *pc)
4753 : {
4754 19452 : bool using_mapper = false;
4755 19452 : bool update_p = false, update_present_p = false;
4756 :
4757 19452 : switch (OMP_CLAUSE_CODE (c))
4758 : {
4759 5987 : case OMP_CLAUSE_TO:
4760 5987 : case OMP_CLAUSE_FROM:
4761 5987 : update_p = true;
4762 5987 : if (OMP_CLAUSE_MOTION_PRESENT (c))
4763 58 : update_present_p = true;
4764 : /* Fallthrough. */
4765 13128 : case OMP_CLAUSE_MAP:
4766 13128 : {
4767 13128 : tree t = OMP_CLAUSE_DECL (c);
4768 13128 : tree type = NULL_TREE;
4769 13128 : bool nonunit_array_with_mapper = false;
4770 :
4771 13202 : if (!update_p
4772 13128 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
4773 7104 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME))
4774 : {
4775 74 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
4776 37 : mapper_name = OMP_CLAUSE_DECL (c);
4777 : else
4778 : mapper_name = NULL_TREE;
4779 74 : pc = &OMP_CLAUSE_CHAIN (c);
4780 74 : continue;
4781 : }
4782 :
4783 13054 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4784 : {
4785 2376 : location_t loc = OMP_CLAUSE_LOCATION (c);
4786 2376 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4787 :
4788 2376 : if (t2 == t)
4789 : {
4790 : /* !!! Array sections of size >1 with mappers for elements
4791 : are hard to support. Do something here. */
4792 1999 : nonunit_array_with_mapper = true;
4793 1999 : type = TREE_TYPE (TREE_TYPE (t));
4794 : }
4795 : else
4796 : {
4797 377 : t = t2;
4798 377 : type = TREE_TYPE (t);
4799 : }
4800 : }
4801 : else
4802 10678 : type = TREE_TYPE (t);
4803 :
4804 13054 : if (type == NULL_TREE || type == error_mark_node)
4805 : {
4806 58 : pc = &OMP_CLAUSE_CHAIN (c);
4807 58 : continue;
4808 : }
4809 :
4810 12996 : enum gomp_map_kind kind;
4811 12996 : if (update_p)
4812 : {
4813 5987 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
4814 983 : kind = update_present_p ? GOMP_MAP_PRESENT_TO
4815 : : GOMP_MAP_TO;
4816 : else
4817 5004 : kind = update_present_p ? GOMP_MAP_PRESENT_FROM
4818 : : GOMP_MAP_FROM;
4819 : }
4820 : else
4821 : {
4822 7009 : kind = OMP_CLAUSE_MAP_KIND (c);
4823 7009 : if (kind == GOMP_MAP_UNSET)
4824 0 : kind = GOMP_MAP_TOFROM;
4825 : }
4826 :
4827 12996 : type = TYPE_MAIN_VARIANT (type);
4828 :
4829 12996 : tree mapper_fn
4830 12996 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4831 :
4832 12996 : if (mapper_fn && nonunit_array_with_mapper)
4833 : {
4834 0 : sorry ("user-defined mapper with non-unit length "
4835 : "array section");
4836 0 : using_mapper = true;
4837 : }
4838 12996 : else if (mapper_fn)
4839 : {
4840 140 : tree mapper
4841 140 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4842 140 : pc = omp_instantiate_mapper (OMP_CLAUSE_LOCATION (c),
4843 : pc, mapper, t, kind, ort);
4844 140 : using_mapper = true;
4845 : }
4846 12856 : else if (mapper_name)
4847 : {
4848 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4849 0 : using_mapper = true;
4850 : }
4851 : }
4852 : break;
4853 :
4854 140 : default:
4855 140 : ;
4856 : }
4857 :
4858 140 : if (using_mapper)
4859 140 : *pc = OMP_CLAUSE_CHAIN (c);
4860 : else
4861 19180 : pc = &OMP_CLAUSE_CHAIN (c);
4862 : }
4863 :
4864 16513 : return clauses;
4865 : }
4866 :
4867 : const struct c_omp_directive c_omp_directives[] = {
4868 : /* Keep this alphabetically sorted by the first word. Non-null second/third
4869 : if any should precede null ones. */
4870 : { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
4871 : C_OMP_DIR_DECLARATIVE, false },
4872 : { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
4873 : C_OMP_DIR_INFORMATIONAL, false },
4874 : { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
4875 : C_OMP_DIR_INFORMATIONAL, false },
4876 : { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
4877 : C_OMP_DIR_CONSTRUCT, false },
4878 : { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
4879 : C_OMP_DIR_STANDALONE, false },
4880 : { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
4881 : C_OMP_DIR_INFORMATIONAL, false },
4882 : { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
4883 : C_OMP_DIR_DECLARATIVE, false },
4884 : { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
4885 : C_OMP_DIR_DECLARATIVE, false },
4886 : /* 'begin metadirective' is not yet implemented; however,
4887 : it is only applicable if an end-directive exists, but
4888 : metadirectives are of limited use for declarative directives. */
4889 : /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
4890 : C_OMP_DIR_META, false }, */
4891 : { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
4892 : C_OMP_DIR_STANDALONE, false },
4893 : { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
4894 : C_OMP_DIR_STANDALONE, false },
4895 : { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
4896 : C_OMP_DIR_CONSTRUCT, false },
4897 : /* { "declare", "induction", nullptr, PRAGMA_OMP_DECLARE,
4898 : C_OMP_DIR_DECLARATIVE, true }, */
4899 : { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
4900 : C_OMP_DIR_DECLARATIVE, false },
4901 : { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
4902 : C_OMP_DIR_DECLARATIVE, true },
4903 : { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
4904 : C_OMP_DIR_DECLARATIVE, true },
4905 : { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
4906 : C_OMP_DIR_DECLARATIVE, false },
4907 : { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
4908 : C_OMP_DIR_DECLARATIVE, false },
4909 : { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
4910 : C_OMP_DIR_STANDALONE, false },
4911 : { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
4912 : C_OMP_DIR_DECLARATIVE, false },
4913 : { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
4914 : C_OMP_DIR_CONSTRUCT, true },
4915 : { "end", "assumes", nullptr, PRAGMA_OMP_END,
4916 : C_OMP_DIR_INFORMATIONAL, false },
4917 : { "end", "declare", "target", PRAGMA_OMP_END,
4918 : C_OMP_DIR_DECLARATIVE, false },
4919 : { "end", "declare", "variant", PRAGMA_OMP_END,
4920 : C_OMP_DIR_DECLARATIVE, false },
4921 : /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
4922 : C_OMP_DIR_META, false }, */
4923 : /* error with at(execution) is C_OMP_DIR_STANDALONE. */
4924 : { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
4925 : C_OMP_DIR_UTILITY, false },
4926 : /* { "flatten", nullptr, nullptr, PRAGMA_OMP_FLATTEN,
4927 : C_OMP_DIR_CONSTRUCT, true }, */
4928 : { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
4929 : C_OMP_DIR_STANDALONE, false },
4930 : { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
4931 : C_OMP_DIR_CONSTRUCT, true },
4932 : /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE,
4933 : C_OMP_DIR_CONSTRUCT, true }, */
4934 : { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
4935 : C_OMP_DIR_DECLARATIVE, false },
4936 : /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE,
4937 : C_OMP_DIR_CONSTRUCT, true }, */
4938 : { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
4939 : C_OMP_DIR_STANDALONE, false },
4940 : { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
4941 : C_OMP_DIR_CONSTRUCT, true },
4942 : { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
4943 : C_OMP_DIR_CONSTRUCT, true },
4944 : { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
4945 : C_OMP_DIR_CONSTRUCT, true },
4946 : { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
4947 : C_OMP_DIR_META, false },
4948 : { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
4949 : C_OMP_DIR_UTILITY, false },
4950 : /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
4951 : { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
4952 : C_OMP_DIR_CONSTRUCT, true },
4953 : { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
4954 : C_OMP_DIR_CONSTRUCT, true },
4955 : { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
4956 : C_OMP_DIR_INFORMATIONAL, false },
4957 : { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
4958 : C_OMP_DIR_CONSTRUCT, true },
4959 : { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
4960 : C_OMP_DIR_CONSTRUCT, false },
4961 : { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
4962 : C_OMP_DIR_CONSTRUCT, false },
4963 : { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
4964 : C_OMP_DIR_CONSTRUCT, false },
4965 : { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
4966 : C_OMP_DIR_CONSTRUCT, true },
4967 : { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
4968 : C_OMP_DIR_CONSTRUCT, false },
4969 : /* { "split", nullptr, nullptr, PRAGMA_OMP_SPLIT,
4970 : C_OMP_DIR_CONSTRUCT, true }, */
4971 : /* { "stripe", nullptr, nullptr, PRAGMA_OMP_STRIPE,
4972 : C_OMP_DIR_CONSTRUCT, true }, */
4973 : { "target", "data", nullptr, PRAGMA_OMP_TARGET,
4974 : C_OMP_DIR_CONSTRUCT, false },
4975 : { "target", "enter", "data", PRAGMA_OMP_TARGET,
4976 : C_OMP_DIR_STANDALONE, false },
4977 : { "target", "exit", "data", PRAGMA_OMP_TARGET,
4978 : C_OMP_DIR_STANDALONE, false },
4979 : { "target", "update", nullptr, PRAGMA_OMP_TARGET,
4980 : C_OMP_DIR_STANDALONE, false },
4981 : { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
4982 : C_OMP_DIR_CONSTRUCT, true },
4983 : { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
4984 : C_OMP_DIR_CONSTRUCT, false },
4985 : /* { "task", "iteration", nullptr, PRAGMA_OMP_TASK_ITERATION,
4986 : C_OMP_DIR_STANDALONE, false }, */
4987 : /* { "taskgraph", nullptr, nullptr, PRAGMA_OMP_TASKGRAPH,
4988 : C_OMP_DIR_CONSTRUCT, false }, */
4989 : { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
4990 : C_OMP_DIR_CONSTRUCT, false },
4991 : { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
4992 : C_OMP_DIR_CONSTRUCT, true },
4993 : { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
4994 : C_OMP_DIR_STANDALONE, false },
4995 : { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
4996 : C_OMP_DIR_STANDALONE, false },
4997 : { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
4998 : C_OMP_DIR_CONSTRUCT, false },
4999 : { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
5000 : C_OMP_DIR_CONSTRUCT, true },
5001 : { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
5002 : C_OMP_DIR_DECLARATIVE, false },
5003 : { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
5004 : C_OMP_DIR_CONSTRUCT, false },
5005 : };
5006 :
5007 : /* Find (non-combined/composite) OpenMP directive (if any) which starts
5008 : with FIRST keyword and for multi-word directives has SECOND and
5009 : THIRD keyword after it. */
5010 :
5011 : const struct c_omp_directive *
5012 6628 : c_omp_categorize_directive (const char *first, const char *second,
5013 : const char *third)
5014 : {
5015 6628 : const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
5016 211255 : for (size_t i = 0; i < n_omp_directives; i++)
5017 : {
5018 395586 : if ((unsigned char) c_omp_directives[i].first[0]
5019 211255 : < (unsigned char) first[0])
5020 184331 : continue;
5021 26924 : if ((unsigned char) c_omp_directives[i].first[0]
5022 : > (unsigned char) first[0])
5023 : break;
5024 26837 : if (strcmp (c_omp_directives[i].first, first))
5025 16103 : continue;
5026 10734 : if (!c_omp_directives[i].second)
5027 5138 : return &c_omp_directives[i];
5028 5596 : if (!second || strcmp (c_omp_directives[i].second, second))
5029 4157 : continue;
5030 1439 : if (!c_omp_directives[i].third)
5031 1103 : return &c_omp_directives[i];
5032 336 : if (!third || strcmp (c_omp_directives[i].third, third))
5033 36 : continue;
5034 300 : return &c_omp_directives[i];
5035 : }
5036 : return NULL;
5037 : }
5038 :
5039 : /* Auxiliary helper function for c_omp_expand_variant_construct. */
5040 :
5041 : static tree
5042 388 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
5043 : hash_map<tree, tree> &body_labels,
5044 : unsigned index)
5045 : {
5046 388 : struct omp_variant &candidate = candidates[index];
5047 388 : tree if_block = push_stmt_list ();
5048 388 : if (candidate.alternative != NULL_TREE)
5049 388 : add_stmt (candidate.alternative);
5050 388 : if (candidate.body != NULL_TREE)
5051 : {
5052 118 : tree *label = body_labels.get (candidate.body);
5053 118 : if (label != NULL)
5054 0 : add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
5055 : else
5056 : {
5057 118 : tree body_label = create_artificial_label (UNKNOWN_LOCATION);
5058 118 : add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
5059 118 : add_stmt (candidate.body);
5060 118 : body_labels.put (candidate.body, body_label);
5061 : }
5062 : }
5063 388 : if_block = pop_stmt_list (if_block);
5064 :
5065 776 : if (index == candidates.length () - 1)
5066 : return if_block;
5067 :
5068 154 : tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
5069 154 : gcc_assert (cond != NULL_TREE);
5070 :
5071 154 : tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
5072 : index + 1);
5073 154 : tree ret = push_stmt_list ();
5074 154 : tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
5075 154 : add_stmt (stmt);
5076 154 : ret = pop_stmt_list (ret);
5077 :
5078 154 : return ret;
5079 : }
5080 :
5081 : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
5082 : structure. */
5083 :
5084 : tree
5085 234 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
5086 : {
5087 234 : hash_map<tree, tree> body_labels;
5088 234 : return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
5089 234 : }
|