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 21 : 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 7 : 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 250 : 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 32116 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
940 : {
941 62225 : if (POINTER_TYPE_P (TREE_TYPE (decl))
942 32116 : && 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 32116 : 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 32058 : 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 32058 : location_t elocus;
973 32058 : bool fail = false;
974 32058 : int i;
975 :
976 32058 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
977 32058 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
978 32058 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
979 74139 : for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
980 : {
981 43459 : tree decl = TREE_VEC_ELT (declv, i);
982 43459 : tree init = TREE_VEC_ELT (initv, i);
983 43459 : tree cond = TREE_VEC_ELT (condv, i);
984 43459 : tree incr = TREE_VEC_ELT (incrv, i);
985 :
986 43459 : 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 42081 : elocus = locus;
1000 42081 : if (EXPR_HAS_LOCATION (init))
1001 37373 : elocus = EXPR_LOCATION (init);
1002 :
1003 : /* Validate the iteration variable. */
1004 84162 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
1005 44955 : && 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 42080 : 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 42065 : if (init == decl)
1022 : {
1023 4692 : elocus = DECL_SOURCE_LOCATION (decl);
1024 :
1025 4692 : init = DECL_INITIAL (decl);
1026 4692 : 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 4692 : DECL_INITIAL (decl) = NULL_TREE;
1033 :
1034 4692 : 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 42065 : if (init != error_mark_node)
1042 : {
1043 42065 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1044 42065 : gcc_assert (TREE_OPERAND (init, 0) == decl);
1045 : }
1046 :
1047 42065 : if (cond == NULL_TREE)
1048 : {
1049 2 : error_at (elocus, "missing controlling predicate");
1050 2 : fail = true;
1051 : }
1052 : else
1053 : {
1054 42063 : 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 42063 : while (TREE_CODE (cond) == COMPOUND_EXPR)
1060 0 : cond = TREE_OPERAND (cond, 1);
1061 :
1062 42063 : if (EXPR_HAS_LOCATION (cond))
1063 41935 : elocus = EXPR_LOCATION (cond);
1064 :
1065 42063 : if (TREE_CODE (cond) == LT_EXPR
1066 : || TREE_CODE (cond) == LE_EXPR
1067 : || TREE_CODE (cond) == GT_EXPR
1068 42063 : || TREE_CODE (cond) == GE_EXPR
1069 5587 : || TREE_CODE (cond) == NE_EXPR
1070 31 : || TREE_CODE (cond) == EQ_EXPR)
1071 : {
1072 42032 : tree op0 = TREE_OPERAND (cond, 0);
1073 42032 : 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 42032 : if (TREE_CODE (op0) == NOP_EXPR
1088 42032 : && 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 41974 : else if (TREE_CODE (op1) == NOP_EXPR
1096 41974 : && 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 42032 : 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 42032 : if (TREE_CODE (cond) == NE_EXPR
1116 42032 : || 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 42032 : 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 42032 : if (!cond_ok)
1154 : {
1155 32 : error_at (elocus, "invalid controlling predicate");
1156 32 : fail = true;
1157 : }
1158 : }
1159 :
1160 42065 : if (incr == NULL_TREE)
1161 : {
1162 0 : error_at (elocus, "missing increment expression");
1163 0 : fail = true;
1164 : }
1165 : else
1166 : {
1167 42065 : bool incr_ok = false;
1168 :
1169 42065 : if (EXPR_HAS_LOCATION (incr))
1170 41163 : 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 42065 : switch (TREE_CODE (incr))
1175 : {
1176 32122 : case POSTINCREMENT_EXPR:
1177 32122 : case PREINCREMENT_EXPR:
1178 32122 : case POSTDECREMENT_EXPR:
1179 32122 : case PREDECREMENT_EXPR:
1180 32122 : if (TREE_OPERAND (incr, 0) != decl)
1181 : break;
1182 :
1183 32116 : incr_ok = true;
1184 32116 : if (!fail
1185 32091 : && 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 32935 : && (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 32116 : incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
1200 32116 : 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 42043 : if (!incr_ok)
1293 : {
1294 34 : error_at (elocus, "invalid increment expression");
1295 34 : fail = true;
1296 : }
1297 : }
1298 :
1299 42065 : TREE_VEC_ELT (initv, i) = init;
1300 42065 : TREE_VEC_ELT (incrv, i) = incr;
1301 : }
1302 :
1303 32058 : if (fail)
1304 : return NULL;
1305 : else
1306 : {
1307 31773 : tree t = make_node (code);
1308 :
1309 31773 : TREE_TYPE (t) = void_type_node;
1310 31773 : OMP_FOR_INIT (t) = initv;
1311 31773 : OMP_FOR_COND (t) = condv;
1312 31773 : OMP_FOR_INCR (t) = incrv;
1313 31773 : OMP_FOR_BODY (t) = body;
1314 31773 : OMP_FOR_PRE_BODY (t) = pre_body;
1315 31773 : OMP_FOR_ORIG_DECLS (t) = orig_declv;
1316 :
1317 31773 : SET_EXPR_LOCATION (t, locus);
1318 31773 : 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 42198 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1344 : {
1345 133533 : for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1346 105871 : if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
1347 253 : continue;
1348 105618 : else if (decl == TREE_VEC_ELT (d->declv, i)
1349 105618 : || (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 91163 : else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1353 2223 : && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1354 92202 : && (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 170259 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1369 : {
1370 170259 : struct c_omp_check_loop_iv_data *d
1371 : = (struct c_omp_check_loop_iv_data *) data;
1372 170259 : if (DECL_P (*tp))
1373 : {
1374 28699 : int idx = c_omp_is_loop_iterator (*tp, d);
1375 28699 : 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 141560 : 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 124390 : else if (d->ppset->add (*tp))
1423 17893 : *walk_subtrees = 0;
1424 : /* Don't walk dtors added by C++ wrap_cleanups_r. */
1425 106497 : else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1426 106497 : && 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 2498 : case OMP_TILE:
1670 2498 : int k;
1671 2498 : 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 31773 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1696 : {
1697 31773 : hash_set<tree> pset;
1698 31773 : struct c_omp_check_loop_iv_data data;
1699 31773 : int i, k = 0;
1700 :
1701 31773 : data.declv = declv;
1702 31773 : data.fail = false;
1703 31773 : data.maybe_nonrect = false;
1704 31773 : data.stmt_loc = EXPR_LOCATION (stmt);
1705 31773 : data.lh = lh;
1706 31773 : data.ppset = &pset;
1707 75214 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1708 : {
1709 43441 : tree this_stmt = stmt;
1710 43441 : int j = i;
1711 43441 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1712 43441 : 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 43441 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1722 43441 : tree decl = TREE_OPERAND (init, 0);
1723 43441 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
1724 43441 : gcc_assert (COMPARISON_CLASS_P (cond));
1725 43441 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
1726 43441 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
1727 43441 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1728 43441 : tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1729 43441 : int kind = 0;
1730 43441 : if (i > 0
1731 43441 : && (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 43441 : if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1742 43441 : kind = 4;
1743 43441 : data.kind = kind;
1744 43441 : data.idx = i;
1745 43441 : walk_tree_1 (&TREE_OPERAND (init, 1),
1746 : c_omp_check_loop_iv_r, &data, NULL, lh);
1747 43441 : 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 43441 : if (decl == TREE_VEC_ELT (data.declv, i)
1755 43441 : || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
1756 933 : && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
1757 : {
1758 42508 : data.expr_loc = EXPR_LOCATION (cond);
1759 42508 : data.kind = kind | 1;
1760 42508 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1761 : c_omp_check_loop_iv_r, &data, NULL, lh);
1762 42508 : if (data.maybe_nonrect)
1763 387 : vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
1764 : &data, lh);
1765 : }
1766 43441 : 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 43433 : 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 43441 : if (vec_outer1 || vec_outer2)
1785 474 : OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1786 43441 : 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 31773 : return !data.fail;
1807 31773 : }
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 21 : 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 : 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 15861 : c_omp_split_clauses (location_t loc, enum tree_code code,
2145 : omp_clause_mask mask, tree clauses, tree *cclauses)
2146 : {
2147 15861 : tree next, c;
2148 15861 : enum c_omp_clause_split s;
2149 15861 : int i;
2150 15861 : bool has_dup_allocate = false;
2151 :
2152 111027 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2153 95166 : cclauses[i] = NULL;
2154 : /* Add implicit nowait clause on
2155 : #pragma omp parallel {for,for simd,sections}. */
2156 15861 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2157 10957 : switch (code)
2158 : {
2159 10293 : case OMP_FOR:
2160 10293 : case OMP_SIMD:
2161 25972 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2162 10111 : cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2163 10111 : = 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 55856 : for (; clauses ; clauses = next)
2174 : {
2175 39995 : next = OMP_CLAUSE_CHAIN (clauses);
2176 :
2177 39995 : 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 2456 : 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 7742 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2207 : break;
2208 : case OMP_CLAUSE_ORDERED:
2209 13156 : 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 13156 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2230 : break;
2231 : case OMP_CLAUSE_BIND:
2232 13156 : 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 13842 : != 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 1305 : case OMP_CLAUSE_PRIVATE:
2291 1305 : switch (code)
2292 : {
2293 : case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2294 : case OMP_FOR: case OMP_SECTIONS:
2295 7742 : case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2296 6933 : case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2297 2456 : case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2298 7742 : case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2299 7742 : case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2300 13156 : case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2301 13156 : 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 1745 : case OMP_CLAUSE_FIRSTPRIVATE:
2309 1745 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2310 2105 : != 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 1717 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2340 1717 : != 0)
2341 : {
2342 1105 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2343 1105 : | (OMP_CLAUSE_MASK_1
2344 1105 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2345 : {
2346 465 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2347 : OMP_CLAUSE_FIRSTPRIVATE);
2348 465 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2349 465 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2350 465 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2351 465 : if ((mask & (OMP_CLAUSE_MASK_1
2352 465 : << 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 7742 : 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 20898 : != 0)
2430 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2431 : else
2432 13156 : 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 13512 : != 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 9037 : != 0)
2498 : {
2499 1295 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2500 3064 : == 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 2919 : case OMP_CLAUSE_REDUCTION:
2564 2919 : 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 2919 : if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2587 2919 : && ((mask & ((OMP_CLAUSE_MASK_1
2588 204 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2589 204 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2590 2931 : != 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 2919 : 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 2919 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2609 : {
2610 1758 : if (code == OMP_SIMD)
2611 : {
2612 569 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2613 : OMP_CLAUSE_REDUCTION);
2614 569 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2615 1138 : OMP_CLAUSE_REDUCTION_CODE (c)
2616 569 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2617 569 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2618 569 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2619 569 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2620 569 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2621 1138 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2622 569 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2623 569 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2624 569 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2625 : }
2626 1758 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2627 1758 : != 0)
2628 : {
2629 459 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2630 : OMP_CLAUSE_REDUCTION);
2631 459 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2632 918 : OMP_CLAUSE_REDUCTION_CODE (c)
2633 459 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2634 459 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2635 459 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2636 459 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2637 459 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2638 918 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2639 459 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2640 459 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2641 459 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2642 459 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2643 : }
2644 1299 : else if ((mask & (OMP_CLAUSE_MASK_1
2645 1299 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2646 1210 : && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2647 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2648 : else
2649 13156 : 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 13164 : != 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 40003 : != 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 7762 : << 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 13156 : 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 53151 : != 0)
2857 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2858 : else
2859 13156 : 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 2456 : != 0)
2866 : {
2867 232 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2868 40225 : != 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 8099 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2890 : {
2891 6942 : switch (i)
2892 : {
2893 1157 : case C_OMP_CLAUSE_SPLIT_TARGET:
2894 2050 : if ((mask & (OMP_CLAUSE_MASK_1
2895 1157 : << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2896 893 : continue;
2897 : break;
2898 1157 : case C_OMP_CLAUSE_SPLIT_TEAMS:
2899 1880 : if ((mask & (OMP_CLAUSE_MASK_1
2900 1157 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2901 723 : continue;
2902 : break;
2903 1157 : case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2904 1832 : if ((mask & (OMP_CLAUSE_MASK_1
2905 1157 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2906 675 : continue;
2907 : break;
2908 1157 : case C_OMP_CLAUSE_SPLIT_PARALLEL:
2909 1529 : if ((mask & (OMP_CLAUSE_MASK_1
2910 1157 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2911 372 : continue;
2912 : break;
2913 1157 : case C_OMP_CLAUSE_SPLIT_FOR:
2914 1157 : 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 1157 : if (code == OMP_SECTIONS)
2921 : break;
2922 1141 : if ((mask & (OMP_CLAUSE_MASK_1
2923 1141 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2924 : break;
2925 606 : if ((mask & (OMP_CLAUSE_MASK_1
2926 606 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2927 : break;
2928 326 : continue;
2929 1157 : case C_OMP_CLAUSE_SPLIT_SIMD:
2930 1157 : continue;
2931 : default:
2932 : gcc_unreachable ();
2933 : }
2934 2796 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2935 : {
2936 1639 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2937 : OMP_CLAUSE_ALLOCATE);
2938 3278 : OMP_CLAUSE_DECL (c)
2939 1639 : = OMP_CLAUSE_DECL (clauses);
2940 1639 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2941 1639 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2942 1639 : OMP_CLAUSE_ALLOCATE_ALIGN (c)
2943 1639 : = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2944 1639 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2945 1639 : cclauses[s] = c;
2946 1639 : has_dup_allocate = true;
2947 : }
2948 2796 : s = (enum c_omp_clause_split) i;
2949 : }
2950 1157 : gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2951 : break;
2952 0 : default:
2953 0 : gcc_unreachable ();
2954 : }
2955 39995 : OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2956 39995 : cclauses[s] = clauses;
2957 : }
2958 :
2959 15861 : if (has_dup_allocate)
2960 : {
2961 787 : bool need_prune = false;
2962 787 : bitmap_obstack_initialize (NULL);
2963 9783 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2964 3871 : if (cclauses[i])
2965 : {
2966 2358 : bitmap_head allocate_head;
2967 2358 : bitmap_initialize (&allocate_head, &bitmap_default_obstack);
2968 17770 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2969 15412 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2970 15412 : && DECL_P (OMP_CLAUSE_DECL (c)))
2971 4972 : bitmap_set_bit (&allocate_head,
2972 2486 : DECL_UID (OMP_CLAUSE_DECL (c)));
2973 17770 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2974 15412 : switch (OMP_CLAUSE_CODE (c))
2975 : {
2976 1159 : case OMP_CLAUSE_REDUCTION:
2977 1159 : case OMP_CLAUSE_IN_REDUCTION:
2978 1159 : case OMP_CLAUSE_TASK_REDUCTION:
2979 1159 : 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 1159 : 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 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
3005 : {
3006 152 : tree t;
3007 152 : for (t = OMP_CLAUSE_DECL (c);
3008 304 : TREE_CODE (t) == OMP_ARRAY_SECTION;
3009 152 : t = TREE_OPERAND (t, 0))
3010 : ;
3011 152 : if (DECL_P (t))
3012 152 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3013 : break;
3014 : }
3015 : /* FALLTHRU */
3016 3265 : case OMP_CLAUSE_PRIVATE:
3017 3265 : case OMP_CLAUSE_FIRSTPRIVATE:
3018 3265 : case OMP_CLAUSE_LASTPRIVATE:
3019 3265 : case OMP_CLAUSE_LINEAR:
3020 3265 : if (DECL_P (OMP_CLAUSE_DECL (c)))
3021 6530 : bitmap_clear_bit (&allocate_head,
3022 3265 : DECL_UID (OMP_CLAUSE_DECL (c)));
3023 : break;
3024 : default:
3025 : break;
3026 : }
3027 17770 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
3028 15412 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
3029 2486 : && DECL_P (OMP_CLAUSE_DECL (c))
3030 17898 : && bitmap_bit_p (&allocate_head,
3031 2486 : DECL_UID (OMP_CLAUSE_DECL (c))))
3032 : {
3033 : /* Mark allocate clauses which don't have corresponding
3034 : explicit data sharing clause. */
3035 1093 : OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
3036 1093 : need_prune = true;
3037 : }
3038 : }
3039 787 : bitmap_obstack_release (NULL);
3040 787 : 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 4837 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3051 4146 : if (cclauses[i] == NULL_TREE
3052 2426 : || i == C_OMP_CLAUSE_SPLIT_SIMD
3053 2166 : || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
3054 1980 : p[i] = NULL;
3055 : else
3056 2166 : p[i] = &cclauses[i];
3057 1378 : do
3058 : {
3059 1378 : int j = -1;
3060 1378 : tree seen = NULL_TREE;
3061 6483 : for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
3062 5796 : if (p[i])
3063 : {
3064 13717 : while (*p[i]
3065 13717 : && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
3066 10732 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3067 2985 : if (*p[i] == NULL_TREE)
3068 : {
3069 : i = C_OMP_CLAUSE_SPLIT_COUNT;
3070 : break;
3071 : }
3072 2294 : if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
3073 5105 : j = i;
3074 : seen = *p[i];
3075 : }
3076 1378 : if (i == C_OMP_CLAUSE_SPLIT_COUNT)
3077 : break;
3078 687 : 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 4809 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3084 4122 : if (p[i])
3085 : {
3086 2166 : if (i > j)
3087 : /* Remove. */
3088 610 : *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
3089 : else
3090 : /* Keep. */
3091 1556 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3092 : }
3093 : }
3094 : while (1);
3095 : }
3096 : }
3097 :
3098 15861 : if (!flag_checking)
3099 : return;
3100 :
3101 15861 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
3102 10672 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
3103 15861 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
3104 8991 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
3105 15861 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
3106 8565 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
3107 8315 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
3108 15861 : 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 15861 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
3111 15861 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
3112 4121 : && code != OMP_SECTIONS
3113 4121 : && code != OMP_LOOP)
3114 3671 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
3115 15861 : if (code != OMP_SIMD)
3116 9342 : 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 12204 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
3124 : {
3125 12204 : tree a = *(const tree *) p;
3126 12204 : tree b = *(const tree *) q;
3127 12204 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
3128 : {
3129 10729 : if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
3130 : return -1;
3131 4482 : 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 1493 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
3152 : {
3153 1493 : tree c;
3154 1493 : vec<tree> clvec = vNULL;
3155 :
3156 4640 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3157 : {
3158 3147 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
3159 3147 : && OMP_CLAUSE_SIMDLEN_TYPE (c))
3160 59 : sorry_at (OMP_CLAUSE_LOCATION (c),
3161 : "%<simdlen%> clause with %<scaled%> modifier");
3162 3147 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3163 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3164 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3165 : {
3166 1712 : tree decl = OMP_CLAUSE_DECL (c);
3167 1712 : tree arg;
3168 1712 : int idx;
3169 3815 : for (arg = parms, idx = 0; arg;
3170 2103 : arg = TREE_CHAIN (arg), idx++)
3171 3815 : if (arg == decl)
3172 : break;
3173 1712 : if (arg == NULL_TREE)
3174 : {
3175 0 : error_at (OMP_CLAUSE_LOCATION (c),
3176 : "%qD is not a function argument", decl);
3177 3147 : continue;
3178 : }
3179 1712 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3180 1712 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3181 1712 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3182 : {
3183 43 : decl = OMP_CLAUSE_LINEAR_STEP (c);
3184 121 : for (arg = parms, idx = 0; arg;
3185 78 : arg = TREE_CHAIN (arg), idx++)
3186 121 : if (arg == decl)
3187 : break;
3188 43 : if (arg == NULL_TREE)
3189 : {
3190 0 : error_at (OMP_CLAUSE_LOCATION (c),
3191 : "%qD is not a function argument", decl);
3192 0 : continue;
3193 : }
3194 43 : OMP_CLAUSE_LINEAR_STEP (c)
3195 86 : = build_int_cst (integer_type_node, idx);
3196 : }
3197 : }
3198 3147 : clvec.safe_push (c);
3199 : }
3200 1493 : if (!clvec.is_empty ())
3201 : {
3202 1380 : unsigned int len = clvec.length (), i;
3203 1380 : clvec.qsort (c_omp_declare_simd_clause_cmp);
3204 1380 : clauses = clvec[0];
3205 4527 : for (i = 0; i < len; i++)
3206 3147 : OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3207 : }
3208 : else
3209 : clauses = NULL_TREE;
3210 1493 : clvec.release ();
3211 1493 : return clauses;
3212 : }
3213 :
3214 : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3215 :
3216 : void
3217 123 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3218 : {
3219 123 : tree c;
3220 :
3221 429 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3222 306 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3223 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3224 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3225 : {
3226 189 : int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3227 189 : tree arg;
3228 369 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3229 180 : arg = TREE_CHAIN (arg), i++)
3230 369 : if (i == idx)
3231 : break;
3232 0 : gcc_assert (arg);
3233 189 : OMP_CLAUSE_DECL (c) = arg;
3234 189 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3235 189 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3236 : {
3237 0 : idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3238 0 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3239 0 : arg = TREE_CHAIN (arg), i++)
3240 0 : if (i == idx)
3241 : break;
3242 0 : gcc_assert (arg);
3243 0 : OMP_CLAUSE_LINEAR_STEP (c) = arg;
3244 : }
3245 : }
3246 123 : }
3247 :
3248 : /* Return true for __func__ and similar function-local predefined
3249 : variables (which are in OpenMP predetermined shared, allowed in
3250 : shared/firstprivate clauses). */
3251 :
3252 : bool
3253 65329 : c_omp_predefined_variable (tree decl)
3254 : {
3255 65329 : if (VAR_P (decl)
3256 34371 : && DECL_ARTIFICIAL (decl)
3257 309 : && TREE_STATIC (decl)
3258 65623 : && DECL_NAME (decl))
3259 : {
3260 294 : if (TREE_READONLY (decl)
3261 294 : && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3262 226 : || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3263 182 : || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3264 : return true;
3265 : /* For UBSan handle the same also ubsan_create_data created
3266 : variables. There is no magic flag for those, but user variables
3267 : shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3268 : such names. */
3269 142 : if ((flag_sanitize & (SANITIZE_UNDEFINED
3270 : | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3271 39 : && DECL_IGNORED_P (decl)
3272 39 : && !TREE_READONLY (decl)
3273 30 : && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3274 30 : && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3275 30 : && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3276 30 : && TYPE_NAME (TREE_TYPE (decl))
3277 30 : && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3278 30 : && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3279 172 : && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3280 : == IDENTIFIER_NODE))
3281 : {
3282 30 : tree id1 = DECL_NAME (decl);
3283 30 : tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3284 30 : if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3285 30 : && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3286 30 : && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
3287 : sizeof ("__ubsan_") - 1)
3288 30 : && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3289 30 : - sizeof ("_data") + 1, "_data",
3290 : sizeof ("_data") - 1)
3291 60 : && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
3292 30 : return true;
3293 : }
3294 : }
3295 : return false;
3296 : }
3297 :
3298 : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3299 : is predetermined. */
3300 :
3301 : enum omp_clause_default_kind
3302 28056 : c_omp_predetermined_sharing (tree decl)
3303 : {
3304 : /* Predetermine artificial variables holding integral values, those
3305 : are usually result of gimplify_one_sizepos or SAVE_EXPR
3306 : gimplification. */
3307 28056 : if (VAR_P (decl)
3308 17274 : && DECL_ARTIFICIAL (decl)
3309 28695 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3310 : return OMP_CLAUSE_DEFAULT_SHARED;
3311 :
3312 27508 : if (c_omp_predefined_variable (decl))
3313 91 : return OMP_CLAUSE_DEFAULT_SHARED;
3314 :
3315 : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3316 : }
3317 :
3318 : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3319 : of DECL is predetermined. */
3320 :
3321 : enum omp_clause_defaultmap_kind
3322 5175 : c_omp_predetermined_mapping (tree decl)
3323 : {
3324 : /* Predetermine artificial variables holding integral values, those
3325 : are usually result of gimplify_one_sizepos or SAVE_EXPR
3326 : gimplification. */
3327 5175 : if (VAR_P (decl)
3328 944 : && DECL_ARTIFICIAL (decl)
3329 5207 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3330 : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3331 :
3332 5147 : if (c_omp_predefined_variable (decl))
3333 2 : return OMP_CLAUSE_DEFAULTMAP_TO;
3334 :
3335 : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3336 : }
3337 :
3338 :
3339 : /* Used to merge map clause information in c_omp_adjust_map_clauses. */
3340 : struct map_clause
3341 : {
3342 : tree clause;
3343 : bool firstprivate_ptr_p;
3344 : bool decl_mapped;
3345 : bool omp_declare_target;
3346 3617 : map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3347 3617 : decl_mapped (false), omp_declare_target (false) { }
3348 : };
3349 :
3350 : /* Adjust map clauses after normal clause parsing, mainly to mark specific
3351 : base-pointer map cases addressable that may be turned into attach/detach
3352 : operations during gimplification. */
3353 : void
3354 12903 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
3355 : {
3356 12903 : if (!is_target)
3357 : {
3358 : /* If this is not a target construct, just turn firstprivate pointers
3359 : into attach/detach, the runtime will check and do the rest. */
3360 :
3361 4651 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3362 3143 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3363 2666 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3364 0 : && DECL_P (OMP_CLAUSE_DECL (c))
3365 3143 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3366 : {
3367 0 : tree ptr = OMP_CLAUSE_DECL (c);
3368 0 : c_common_mark_addressable_vec (ptr);
3369 : }
3370 1508 : return;
3371 : }
3372 :
3373 11395 : hash_map<tree, map_clause> maps;
3374 :
3375 36264 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3376 13474 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3377 13474 : && DECL_P (OMP_CLAUSE_DECL (c)))
3378 : {
3379 : /* If this is for a target construct, the firstprivate pointer
3380 : is marked addressable if either is true:
3381 : (1) the base-pointer is mapped in this same construct, or
3382 : (2) the base-pointer is a variable place on the device by
3383 : "declare target" directives.
3384 :
3385 : Here we iterate through all map clauses collecting these cases,
3386 : and merge them with a hash_map to process below. */
3387 :
3388 4283 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3389 4283 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3390 : {
3391 343 : tree ptr = OMP_CLAUSE_DECL (c);
3392 343 : map_clause &mc = maps.get_or_insert (ptr);
3393 343 : if (mc.clause == NULL_TREE)
3394 343 : mc.clause = c;
3395 343 : mc.firstprivate_ptr_p = true;
3396 :
3397 343 : if (is_global_var (ptr)
3398 391 : && lookup_attribute ("omp declare target",
3399 48 : DECL_ATTRIBUTES (ptr)))
3400 0 : mc.omp_declare_target = true;
3401 : }
3402 3940 : else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3403 3853 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3404 3339 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3405 2288 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3406 1077 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3407 1007 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3408 4938 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3409 : {
3410 3305 : map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3411 3305 : mc.decl_mapped = true;
3412 : }
3413 : }
3414 :
3415 15012 : for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3416 26407 : i != maps.end (); ++i)
3417 : {
3418 3617 : map_clause &mc = (*i).second;
3419 :
3420 3617 : if (mc.firstprivate_ptr_p
3421 343 : && (mc.decl_mapped || mc.omp_declare_target))
3422 23 : c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3423 : }
3424 11395 : }
3425 :
3426 : /* Maybe strip off an indirection from a "converted" reference, then find the
3427 : origin of a pointer (i.e. without any offset). */
3428 :
3429 : tree
3430 72247 : c_omp_address_inspector::unconverted_ref_origin ()
3431 : {
3432 72247 : tree t = orig;
3433 :
3434 : /* We may have a reference-typed component access at the outermost level
3435 : that has had convert_from_reference called on it. Get the un-dereferenced
3436 : reference itself. */
3437 72247 : t = maybe_unconvert_ref (t);
3438 :
3439 : /* Find base pointer for POINTER_PLUS_EXPR, etc. */
3440 72247 : t = get_origin (t);
3441 :
3442 72247 : return t;
3443 : }
3444 :
3445 : /* Return TRUE if the address is a component access. */
3446 :
3447 : bool
3448 12705 : c_omp_address_inspector::component_access_p ()
3449 : {
3450 12705 : tree t = maybe_unconvert_ref (orig);
3451 :
3452 12705 : t = get_origin (t);
3453 :
3454 12705 : return TREE_CODE (t) == COMPONENT_REF;
3455 : }
3456 :
3457 : /* Perform various checks on the address, as described by clause CLAUSE (we
3458 : only use its code and location here). */
3459 :
3460 : bool
3461 33775 : c_omp_address_inspector::check_clause (tree clause)
3462 : {
3463 33775 : tree t = unconverted_ref_origin ();
3464 :
3465 33775 : if (TREE_CODE (t) != COMPONENT_REF)
3466 : return true;
3467 :
3468 4875 : if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
3469 4875 : && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
3470 : {
3471 24 : error_at (OMP_CLAUSE_LOCATION (clause),
3472 : "bit-field %qE in %qs clause",
3473 24 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3474 24 : return false;
3475 : }
3476 4851 : else if (!processing_template_decl_p ()
3477 4851 : && !omp_mappable_type (TREE_TYPE (t)))
3478 : {
3479 0 : error_at (OMP_CLAUSE_LOCATION (clause),
3480 : "%qE does not have a mappable type in %qs clause",
3481 0 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3482 0 : emit_unmappable_type_notes (TREE_TYPE (t));
3483 0 : return false;
3484 : }
3485 4851 : else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
3486 : {
3487 2 : error_at (OMP_CLAUSE_LOCATION (clause),
3488 : "%<_Atomic%> %qE in %qs clause", t,
3489 2 : omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3490 2 : return false;
3491 : }
3492 :
3493 : return true;
3494 : }
3495 :
3496 : /* Find the "root term" for the address. This is the innermost decl, etc.
3497 : of the access. */
3498 :
3499 : tree
3500 1691 : c_omp_address_inspector::get_root_term (bool checking)
3501 : {
3502 1691 : if (root_term && !checking)
3503 : return root_term;
3504 :
3505 1691 : tree t = unconverted_ref_origin ();
3506 :
3507 5737 : while (TREE_CODE (t) == COMPONENT_REF)
3508 : {
3509 2355 : if (checking
3510 2355 : && TREE_TYPE (TREE_OPERAND (t, 0))
3511 4522 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
3512 : {
3513 0 : error_at (loc, "%qE is a member of a union", t);
3514 0 : return error_mark_node;
3515 : }
3516 2355 : t = TREE_OPERAND (t, 0);
3517 2355 : while (TREE_CODE (t) == MEM_REF
3518 3774 : || TREE_CODE (t) == INDIRECT_REF
3519 3774 : || TREE_CODE (t) == ARRAY_REF)
3520 : {
3521 1419 : if (TREE_CODE (t) == MEM_REF
3522 : || TREE_CODE (t) == INDIRECT_REF)
3523 1275 : indirections = true;
3524 1419 : t = TREE_OPERAND (t, 0);
3525 1419 : STRIP_NOPS (t);
3526 1419 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
3527 102 : t = TREE_OPERAND (t, 0);
3528 : }
3529 : }
3530 :
3531 1691 : root_term = t;
3532 :
3533 1691 : return t;
3534 : }
3535 :
3536 : /* Return TRUE if the address is supported in mapping clauses. At present,
3537 : this means that the innermost expression is a DECL_P, but could be extended
3538 : to other types of expression in the future. */
3539 :
3540 : bool
3541 25767 : c_omp_address_inspector::map_supported_p ()
3542 : {
3543 : /* If we've already decided if the mapped address is supported, return
3544 : that. */
3545 25767 : if (map_supported != -1)
3546 0 : return map_supported;
3547 :
3548 25767 : tree t = unconverted_ref_origin ();
3549 :
3550 25767 : STRIP_NOPS (t);
3551 :
3552 25767 : while (TREE_CODE (t) == INDIRECT_REF
3553 41922 : || TREE_CODE (t) == MEM_REF
3554 : || TREE_CODE (t) == ARRAY_REF
3555 : || TREE_CODE (t) == COMPONENT_REF
3556 : || TREE_CODE (t) == COMPOUND_EXPR
3557 : || TREE_CODE (t) == SAVE_EXPR
3558 : || TREE_CODE (t) == POINTER_PLUS_EXPR
3559 : || TREE_CODE (t) == NON_LVALUE_EXPR
3560 : || TREE_CODE (t) == OMP_ARRAY_SECTION
3561 41922 : || TREE_CODE (t) == NOP_EXPR)
3562 16155 : if (TREE_CODE (t) == COMPOUND_EXPR)
3563 27 : t = TREE_OPERAND (t, 1);
3564 : else
3565 16128 : t = TREE_OPERAND (t, 0);
3566 :
3567 25767 : STRIP_NOPS (t);
3568 :
3569 25767 : map_supported = DECL_P (t);
3570 :
3571 25767 : return map_supported;
3572 : }
3573 :
3574 : /* Get the origin of an address T, stripping off offsets and some other
3575 : bits. */
3576 :
3577 : tree
3578 84952 : c_omp_address_inspector::get_origin (tree t)
3579 : {
3580 85528 : while (1)
3581 : {
3582 85528 : if (TREE_CODE (t) == COMPOUND_EXPR)
3583 : {
3584 10 : t = TREE_OPERAND (t, 1);
3585 10 : STRIP_NOPS (t);
3586 : }
3587 85518 : else if (TREE_CODE (t) == POINTER_PLUS_EXPR
3588 85518 : || TREE_CODE (t) == SAVE_EXPR)
3589 539 : t = TREE_OPERAND (t, 0);
3590 84979 : else if (!processing_template_decl_p ()
3591 78024 : && TREE_CODE (t) == INDIRECT_REF
3592 87597 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3593 27 : t = TREE_OPERAND (t, 0);
3594 : else
3595 : break;
3596 : }
3597 84952 : STRIP_NOPS (t);
3598 84952 : return t;
3599 : }
3600 :
3601 : /* For an address T that might be a reference that has had
3602 : "convert_from_reference" called on it, return the actual reference without
3603 : any indirection. */
3604 :
3605 : tree
3606 94664 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
3607 : {
3608 : /* Be careful not to dereference the type if we're processing a
3609 : template decl, else it might be NULL. */
3610 94664 : if (!processing_template_decl_p ()
3611 85647 : && TREE_CODE (t) == INDIRECT_REF
3612 97803 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3613 587 : return TREE_OPERAND (t, 0);
3614 :
3615 : return t;
3616 : }
3617 :
3618 : /* Return TRUE if CLAUSE might describe a zero-length array section. */
3619 :
3620 : bool
3621 5517 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
3622 : {
3623 5517 : switch (OMP_CLAUSE_MAP_KIND (clause))
3624 : {
3625 : case GOMP_MAP_ALLOC:
3626 : case GOMP_MAP_IF_PRESENT:
3627 : case GOMP_MAP_TO:
3628 : case GOMP_MAP_FROM:
3629 : case GOMP_MAP_TOFROM:
3630 : case GOMP_MAP_ALWAYS_TO:
3631 : case GOMP_MAP_ALWAYS_FROM:
3632 : case GOMP_MAP_ALWAYS_TOFROM:
3633 : case GOMP_MAP_PRESENT_ALLOC:
3634 : case GOMP_MAP_PRESENT_TO:
3635 : case GOMP_MAP_PRESENT_FROM:
3636 : case GOMP_MAP_PRESENT_TOFROM:
3637 : case GOMP_MAP_ALWAYS_PRESENT_TO:
3638 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
3639 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
3640 : case GOMP_MAP_RELEASE:
3641 : case GOMP_MAP_DELETE:
3642 : case GOMP_MAP_FORCE_TO:
3643 : case GOMP_MAP_FORCE_FROM:
3644 : case GOMP_MAP_FORCE_TOFROM:
3645 : case GOMP_MAP_FORCE_PRESENT:
3646 : return true;
3647 28 : default:
3648 28 : return false;
3649 : }
3650 : }
3651 :
3652 : /* Expand a chained access. We only expect to see a quite limited range of
3653 : expression types here, because e.g. you can't have an array of
3654 : references. */
3655 :
3656 : static tree
3657 79 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
3658 : unsigned *idx, c_omp_region_type ort)
3659 : {
3660 87 : using namespace omp_addr_tokenizer;
3661 87 : location_t loc = OMP_CLAUSE_LOCATION (c);
3662 87 : unsigned i = *idx;
3663 87 : tree c2 = NULL_TREE;
3664 87 : gomp_map_kind kind;
3665 :
3666 87 : if ((ort & C_ORT_EXIT_DATA) != 0
3667 75 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
3668 162 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3669 75 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3670 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
3671 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
3672 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3673 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
3674 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
3675 75 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
3676 : kind = GOMP_MAP_DETACH;
3677 : else
3678 : kind = GOMP_MAP_ATTACH;
3679 :
3680 87 : switch (addr_tokens[i]->u.access_kind)
3681 : {
3682 87 : case ACCESS_POINTER:
3683 87 : case ACCESS_POINTER_OFFSET:
3684 87 : {
3685 87 : tree virtual_origin
3686 87 : = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
3687 87 : tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
3688 87 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3689 87 : OMP_CLAUSE_SET_MAP_KIND (c2, kind);
3690 87 : OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
3691 87 : OMP_CLAUSE_SIZE (c2)
3692 87 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3693 : fold_convert_loc (loc, ptrdiff_type_node,
3694 : data_addr),
3695 : virtual_origin);
3696 : }
3697 87 : break;
3698 :
3699 : case ACCESS_INDEXED_ARRAY:
3700 : break;
3701 :
3702 0 : default:
3703 0 : return error_mark_node;
3704 : }
3705 :
3706 87 : if (c2)
3707 : {
3708 87 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
3709 87 : OMP_CLAUSE_CHAIN (c) = c2;
3710 87 : c = c2;
3711 : }
3712 :
3713 87 : *idx = ++i;
3714 :
3715 87 : if (i < addr_tokens.length ()
3716 95 : && addr_tokens[i]->type == ACCESS_METHOD)
3717 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
3718 :
3719 : return c;
3720 : }
3721 :
3722 : /* Translate "array_base_decl access_method" to OMP mapping clauses. */
3723 :
3724 : tree
3725 18419 : c_omp_address_inspector::expand_array_base (tree c,
3726 : vec<omp_addr_token *> &addr_tokens,
3727 : tree expr, unsigned *idx,
3728 : c_omp_region_type ort)
3729 : {
3730 18419 : using namespace omp_addr_tokenizer;
3731 18419 : location_t loc = OMP_CLAUSE_LOCATION (c);
3732 18419 : int i = *idx;
3733 18419 : tree decl = addr_tokens[i + 1]->expr;
3734 18419 : bool decl_p = DECL_P (decl);
3735 18419 : bool declare_target_p = (decl_p
3736 18410 : && is_global_var (decl)
3737 25954 : && lookup_attribute ("omp declare target",
3738 7535 : DECL_ATTRIBUTES (decl)));
3739 18419 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
3740 18419 : bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
3741 18419 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
3742 18419 : tree c2 = NULL_TREE, c3 = NULL_TREE;
3743 18419 : unsigned consume_tokens = 2;
3744 18419 : bool target_p = (ort & C_ORT_TARGET) != 0;
3745 18419 : bool openmp_p = (ort & C_ORT_OMP) != 0;
3746 :
3747 18419 : gcc_assert (i == 0);
3748 :
3749 18419 : if (!openmp_p
3750 18419 : && map_p
3751 18419 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
3752 6749 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
3753 : {
3754 28 : i += 2;
3755 28 : *idx = i;
3756 28 : return c;
3757 : }
3758 :
3759 18391 : switch (addr_tokens[i + 1]->u.access_kind)
3760 : {
3761 14057 : case ACCESS_DIRECT:
3762 14057 : if (decl_p && !target_p)
3763 8684 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3764 : break;
3765 :
3766 154 : case ACCESS_REF:
3767 154 : {
3768 : /* Copy the referenced object. Note that we do this even for !MAP_P
3769 : clauses. */
3770 154 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
3771 154 : if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
3772 : /* We have a ref to array: add a [0] element as the ME expects. */
3773 47 : OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
3774 : else
3775 107 : OMP_CLAUSE_DECL (c) = obj;
3776 154 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
3777 :
3778 154 : if (!map_p)
3779 : {
3780 6 : if (decl_p)
3781 6 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3782 : break;
3783 : }
3784 :
3785 148 : if (!target_p)
3786 : break;
3787 :
3788 : /* If we have a reference to a pointer, avoid using
3789 : FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
3790 : offload region (we can only do that if the pointer does not point
3791 : to a mapped block). We could avoid doing this if we don't have a
3792 : FROM mapping... */
3793 88 : bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
3794 :
3795 88 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3796 88 : if (!ref_to_ptr
3797 88 : && !declare_target_p
3798 54 : && decl_p)
3799 54 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3800 : else
3801 : {
3802 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3803 34 : if (decl_p)
3804 34 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3805 : }
3806 88 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3807 88 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
3808 :
3809 88 : if (ref_to_ptr)
3810 : {
3811 34 : c3 = c2;
3812 34 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3813 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
3814 34 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3815 68 : OMP_CLAUSE_SIZE (c2)
3816 34 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
3817 : }
3818 : }
3819 : break;
3820 :
3821 83 : case ACCESS_INDEXED_REF_TO_ARRAY:
3822 83 : {
3823 83 : if (!map_p)
3824 : {
3825 0 : if (decl_p)
3826 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3827 : break;
3828 : }
3829 :
3830 83 : if (!target_p)
3831 : break;
3832 :
3833 64 : tree virtual_origin
3834 64 : = convert_from_reference (addr_tokens[i + 1]->expr);
3835 64 : virtual_origin = build_fold_addr_expr (virtual_origin);
3836 64 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3837 : virtual_origin);
3838 64 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3839 64 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3840 64 : if (decl_p && target_p && !declare_target_p)
3841 : {
3842 : /* It appears that omp-low.cc mishandles cases where we have a
3843 : [reference to an] array of pointers such as:
3844 :
3845 : int *arr[N]; (or "int *(&arr)[N] = ...")
3846 : #pragma omp target map(arr[a][b:c])
3847 : { ... }
3848 :
3849 : in such cases chain_p will be true. For now, fall back to
3850 : GOMP_MAP_POINTER. */
3851 61 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3852 : : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
3853 61 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3854 61 : }
3855 : else
3856 : {
3857 3 : if (decl_p)
3858 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3859 3 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3860 : }
3861 64 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3862 64 : OMP_CLAUSE_SIZE (c2)
3863 64 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3864 : fold_convert_loc (loc, ptrdiff_type_node,
3865 : data_addr),
3866 : virtual_origin);
3867 : }
3868 64 : break;
3869 :
3870 1381 : case ACCESS_INDEXED_ARRAY:
3871 1381 : {
3872 1381 : if (!map_p)
3873 : {
3874 0 : if (decl_p)
3875 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3876 : break;
3877 : }
3878 :
3879 : /* The code handling "firstprivatize_array_bases" in gimplify.cc is
3880 : relevant here. What do we need to create for arrays at this
3881 : stage? (This condition doesn't feel quite right. FIXME?) */
3882 1381 : if (!target_p
3883 1381 : && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
3884 : == ARRAY_TYPE))
3885 : break;
3886 :
3887 707 : tree virtual_origin
3888 707 : = build_fold_addr_expr (addr_tokens[i + 1]->expr);
3889 707 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3890 : virtual_origin);
3891 707 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3892 707 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3893 707 : if (decl_p && target_p)
3894 : {
3895 : /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above. */
3896 707 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3897 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
3898 707 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3899 : }
3900 : else
3901 : {
3902 0 : if (decl_p)
3903 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3904 0 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3905 : }
3906 707 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3907 707 : OMP_CLAUSE_SIZE (c2)
3908 707 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3909 : fold_convert_loc (loc, ptrdiff_type_node,
3910 : data_addr),
3911 : virtual_origin);
3912 : }
3913 707 : break;
3914 :
3915 2642 : case ACCESS_POINTER:
3916 2642 : case ACCESS_POINTER_OFFSET:
3917 2642 : {
3918 2642 : if (!map_p)
3919 : {
3920 0 : if (decl_p)
3921 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3922 : break;
3923 : }
3924 :
3925 2642 : unsigned last_access = i + 1;
3926 2642 : tree virtual_origin;
3927 :
3928 2642 : if (chain_p
3929 151 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3930 2793 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3931 : {
3932 : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3933 117 : consume_tokens = 3;
3934 117 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3935 117 : last_access = i + 2;
3936 117 : virtual_origin
3937 117 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3938 : integer_zero_node);
3939 117 : virtual_origin = build_fold_addr_expr (virtual_origin);
3940 117 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3941 : virtual_origin);
3942 : }
3943 : else
3944 2525 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3945 2525 : addr_tokens[last_access]->expr);
3946 2642 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3947 2642 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3948 : /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
3949 : regions (e.g. "acc data" constructs). It'll be removed anyway in
3950 : gimplify.cc, but doing it this way maintains diagnostic
3951 : behaviour. */
3952 2642 : if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
3953 2440 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
3954 : else
3955 : {
3956 199 : if (decl_p)
3957 199 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3958 202 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3959 : }
3960 2642 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3961 2642 : OMP_CLAUSE_SIZE (c2)
3962 2642 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3963 : fold_convert_loc (loc, ptrdiff_type_node,
3964 : data_addr),
3965 : virtual_origin);
3966 : }
3967 2642 : break;
3968 :
3969 74 : case ACCESS_REF_TO_POINTER:
3970 74 : case ACCESS_REF_TO_POINTER_OFFSET:
3971 74 : {
3972 74 : if (!map_p)
3973 : {
3974 0 : if (decl_p)
3975 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3976 : break;
3977 : }
3978 :
3979 74 : unsigned last_access = i + 1;
3980 74 : tree virtual_origin;
3981 :
3982 74 : if (chain_p
3983 6 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3984 80 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3985 : {
3986 : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3987 2 : consume_tokens = 3;
3988 2 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3989 2 : last_access = i + 2;
3990 2 : virtual_origin
3991 2 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3992 : integer_zero_node);
3993 2 : virtual_origin = build_fold_addr_expr (virtual_origin);
3994 2 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3995 : virtual_origin);
3996 : }
3997 : else
3998 : {
3999 72 : virtual_origin
4000 72 : = convert_from_reference (addr_tokens[last_access]->expr);
4001 72 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4002 : virtual_origin);
4003 : }
4004 :
4005 74 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
4006 74 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4007 74 : if (decl_p && target_p && !chain_p && !declare_target_p)
4008 : {
4009 58 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
4010 58 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4011 : }
4012 : else
4013 : {
4014 16 : if (decl_p)
4015 16 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4016 16 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4017 16 : OMP_CLAUSE_DECL (c2)
4018 32 : = convert_from_reference (addr_tokens[i + 1]->expr);
4019 : }
4020 74 : OMP_CLAUSE_SIZE (c2)
4021 74 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4022 : fold_convert_loc (loc, ptrdiff_type_node,
4023 : data_addr),
4024 : virtual_origin);
4025 : }
4026 74 : break;
4027 :
4028 0 : default:
4029 0 : *idx = i + consume_tokens;
4030 0 : return error_mark_node;
4031 : }
4032 :
4033 12177 : if (c3)
4034 : {
4035 34 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4036 34 : OMP_CLAUSE_CHAIN (c2) = c3;
4037 34 : OMP_CLAUSE_CHAIN (c) = c2;
4038 34 : if (implicit_p)
4039 : {
4040 0 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4041 0 : OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
4042 : }
4043 : c = c3;
4044 : }
4045 18357 : else if (c2)
4046 : {
4047 3541 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4048 3541 : OMP_CLAUSE_CHAIN (c) = c2;
4049 3541 : if (implicit_p)
4050 116 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4051 : c = c2;
4052 : }
4053 :
4054 18391 : i += consume_tokens;
4055 18391 : *idx = i;
4056 :
4057 18391 : if (chain_p && map_p)
4058 55 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4059 :
4060 : return c;
4061 : }
4062 :
4063 : /* Translate "component_selector access_method" to OMP mapping clauses. */
4064 :
4065 : tree
4066 3234 : c_omp_address_inspector::expand_component_selector (tree c,
4067 : vec<omp_addr_token *>
4068 : &addr_tokens,
4069 : tree expr, unsigned *idx,
4070 : c_omp_region_type ort)
4071 : {
4072 3234 : using namespace omp_addr_tokenizer;
4073 3234 : location_t loc = OMP_CLAUSE_LOCATION (c);
4074 3234 : unsigned i = *idx;
4075 3234 : tree c2 = NULL_TREE, c3 = NULL_TREE;
4076 3234 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
4077 3234 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
4078 :
4079 3234 : switch (addr_tokens[i + 1]->u.access_kind)
4080 : {
4081 : case ACCESS_DIRECT:
4082 : case ACCESS_INDEXED_ARRAY:
4083 : break;
4084 :
4085 479 : case ACCESS_REF:
4086 479 : {
4087 : /* Copy the referenced object. Note that we also do this for !MAP_P
4088 : clauses. */
4089 479 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
4090 479 : OMP_CLAUSE_DECL (c) = obj;
4091 479 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
4092 :
4093 479 : if (!map_p)
4094 : break;
4095 :
4096 461 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4097 461 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4098 461 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4099 461 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
4100 : }
4101 461 : break;
4102 :
4103 92 : case ACCESS_INDEXED_REF_TO_ARRAY:
4104 92 : {
4105 92 : if (!map_p)
4106 : break;
4107 :
4108 92 : tree virtual_origin
4109 92 : = convert_from_reference (addr_tokens[i + 1]->expr);
4110 92 : virtual_origin = build_fold_addr_expr (virtual_origin);
4111 92 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4112 : virtual_origin);
4113 92 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4114 :
4115 92 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4116 92 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4117 92 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4118 92 : OMP_CLAUSE_SIZE (c2)
4119 92 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4120 : fold_convert_loc (loc, ptrdiff_type_node,
4121 : data_addr),
4122 : virtual_origin);
4123 : }
4124 92 : break;
4125 :
4126 778 : case ACCESS_POINTER:
4127 778 : case ACCESS_POINTER_OFFSET:
4128 778 : {
4129 778 : if (!map_p)
4130 : break;
4131 :
4132 778 : tree virtual_origin
4133 1556 : = fold_convert_loc (loc, ptrdiff_type_node,
4134 778 : addr_tokens[i + 1]->expr);
4135 778 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4136 :
4137 778 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4138 778 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4139 778 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4140 778 : OMP_CLAUSE_SIZE (c2)
4141 778 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4142 : fold_convert_loc (loc, ptrdiff_type_node,
4143 : data_addr),
4144 : virtual_origin);
4145 : }
4146 778 : break;
4147 :
4148 185 : case ACCESS_REF_TO_POINTER:
4149 185 : case ACCESS_REF_TO_POINTER_OFFSET:
4150 185 : {
4151 185 : if (!map_p)
4152 : break;
4153 :
4154 185 : tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
4155 185 : tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4156 : ptr);
4157 185 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4158 :
4159 : /* Attach the pointer... */
4160 185 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4161 185 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4162 185 : OMP_CLAUSE_DECL (c2) = ptr;
4163 185 : OMP_CLAUSE_SIZE (c2)
4164 185 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4165 : fold_convert_loc (loc, ptrdiff_type_node,
4166 : data_addr),
4167 : virtual_origin);
4168 :
4169 : /* ...and also the reference. */
4170 185 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4171 185 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
4172 185 : OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
4173 185 : OMP_CLAUSE_SIZE (c3) = size_zero_node;
4174 : }
4175 185 : break;
4176 :
4177 0 : default:
4178 0 : *idx = i + 2;
4179 0 : return error_mark_node;
4180 : }
4181 :
4182 1331 : if (c3)
4183 : {
4184 185 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4185 185 : OMP_CLAUSE_CHAIN (c2) = c3;
4186 185 : OMP_CLAUSE_CHAIN (c) = c2;
4187 185 : c = c3;
4188 : }
4189 3049 : else if (c2)
4190 : {
4191 1331 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4192 1331 : OMP_CLAUSE_CHAIN (c) = c2;
4193 1331 : c = c2;
4194 : }
4195 :
4196 3234 : i += 2;
4197 3234 : *idx = i;
4198 :
4199 3234 : if (chain_p && map_p)
4200 24 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4201 :
4202 : return c;
4203 : }
4204 :
4205 : /* Expand a map clause into a group of mapping clauses, creating nodes to
4206 : attach/detach pointers and so forth as necessary. */
4207 :
4208 : tree
4209 21653 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
4210 : vec<omp_addr_token *> &addr_tokens,
4211 : c_omp_region_type ort)
4212 : {
4213 21653 : using namespace omp_addr_tokenizer;
4214 21653 : unsigned i, length = addr_tokens.length ();
4215 :
4216 47235 : for (i = 0; i < length;)
4217 : {
4218 25582 : int remaining = length - i;
4219 :
4220 25582 : if (remaining >= 2
4221 25582 : && addr_tokens[i]->type == ARRAY_BASE
4222 18419 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4223 43992 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4224 : {
4225 18410 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4226 18410 : if (c == error_mark_node)
4227 : return error_mark_node;
4228 : }
4229 7172 : else if (remaining >= 2
4230 7172 : && addr_tokens[i]->type == ARRAY_BASE
4231 9 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4232 7181 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4233 : {
4234 9 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4235 9 : if (c == error_mark_node)
4236 : return error_mark_node;
4237 : }
4238 7163 : else if (remaining >= 2
4239 7163 : && addr_tokens[i]->type == STRUCTURE_BASE
4240 3234 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4241 10394 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4242 : {
4243 3231 : if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
4244 1762 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4245 3231 : i += 2;
4246 3391 : while (addr_tokens[i]->type == ACCESS_METHOD)
4247 160 : i++;
4248 : }
4249 3932 : else if (remaining >= 2
4250 3932 : && addr_tokens[i]->type == STRUCTURE_BASE
4251 3 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4252 3935 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4253 : {
4254 3 : switch (addr_tokens[i + 1]->u.access_kind)
4255 : {
4256 3 : case ACCESS_DIRECT:
4257 3 : case ACCESS_POINTER:
4258 3 : i += 2;
4259 3 : while (addr_tokens[i]->type == ACCESS_METHOD)
4260 0 : i++;
4261 : break;
4262 0 : default:
4263 0 : return error_mark_node;
4264 : }
4265 : }
4266 3929 : else if (remaining >= 2
4267 3929 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4268 7858 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4269 : {
4270 3234 : c = expand_component_selector (c, addr_tokens, expr, &i, ort);
4271 : /* We used 'expr', so these must have been the last tokens. */
4272 3234 : gcc_assert (i == length);
4273 3234 : if (c == error_mark_node)
4274 : return error_mark_node;
4275 : }
4276 695 : else if (remaining >= 3
4277 695 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4278 695 : && addr_tokens[i + 1]->type == STRUCTURE_BASE
4279 695 : && (addr_tokens[i + 1]->u.structure_base_kind
4280 : == BASE_COMPONENT_EXPR)
4281 1390 : && addr_tokens[i + 2]->type == ACCESS_METHOD)
4282 : {
4283 695 : i += 3;
4284 719 : while (addr_tokens[i]->type == ACCESS_METHOD)
4285 24 : i++;
4286 : }
4287 : else
4288 : break;
4289 : }
4290 :
4291 21653 : if (i == length)
4292 : return c;
4293 :
4294 0 : return error_mark_node;
4295 : }
4296 :
4297 : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
4298 : for that mapper, and if any of those should use a (named or unnamed) mapper
4299 : themselves, add it to MLIST. */
4300 :
4301 : void
4302 140 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
4303 : {
4304 140 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4305 140 : tree mapper_name = NULL_TREE;
4306 :
4307 140 : if (mapper == error_mark_node)
4308 : return;
4309 :
4310 140 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
4311 :
4312 454 : for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4313 454 : clause;
4314 314 : clause = OMP_CLAUSE_CHAIN (clause))
4315 : {
4316 314 : tree expr = OMP_CLAUSE_DECL (clause);
4317 314 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
4318 314 : tree elem_type;
4319 :
4320 314 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4321 : {
4322 0 : mapper_name = expr;
4323 0 : continue;
4324 : }
4325 314 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4326 : {
4327 0 : mapper_name = NULL_TREE;
4328 0 : continue;
4329 : }
4330 :
4331 314 : gcc_assert (TREE_CODE (expr) != TREE_LIST);
4332 314 : if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4333 : {
4334 220 : while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4335 110 : expr = TREE_OPERAND (expr, 0);
4336 :
4337 110 : elem_type = TREE_TYPE (expr);
4338 : }
4339 : else
4340 204 : elem_type = TREE_TYPE (expr);
4341 :
4342 : /* This might be too much... or not enough? */
4343 512 : while (TREE_CODE (elem_type) == ARRAY_TYPE
4344 506 : || TREE_CODE (elem_type) == POINTER_TYPE
4345 826 : || TREE_CODE (elem_type) == REFERENCE_TYPE)
4346 198 : elem_type = TREE_TYPE (elem_type);
4347 :
4348 314 : elem_type = TYPE_MAIN_VARIANT (elem_type);
4349 :
4350 314 : if (RECORD_OR_UNION_TYPE_P (elem_type)
4351 314 : && !mlist->contains (mapper_name, elem_type))
4352 : {
4353 5 : tree nested_mapper_fn
4354 5 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
4355 :
4356 5 : if (nested_mapper_fn)
4357 : {
4358 5 : mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
4359 5 : c_omp_find_nested_mappers (mlist, nested_mapper_fn);
4360 : }
4361 0 : else if (mapper_name)
4362 : {
4363 0 : error ("mapper %qE not found for type %qT", mapper_name,
4364 : elem_type);
4365 0 : continue;
4366 : }
4367 : }
4368 : }
4369 : }
4370 :
4371 : struct remap_mapper_decl_info
4372 : {
4373 : tree dummy_var;
4374 : tree expr;
4375 : };
4376 :
4377 : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
4378 :
4379 : static tree
4380 4044 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
4381 : {
4382 4044 : remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
4383 :
4384 4044 : if (operand_equal_p (*tp, map_info->dummy_var))
4385 : {
4386 1001 : *tp = map_info->expr;
4387 1001 : *walk_subtrees = 0;
4388 : }
4389 :
4390 4044 : return NULL_TREE;
4391 : }
4392 :
4393 : static enum gomp_map_kind
4394 946 : omp_split_map_kind (enum gomp_map_kind op, bool *force_p, bool *always_p,
4395 : bool *present_p)
4396 : {
4397 946 : *force_p = *always_p = *present_p = false;
4398 :
4399 946 : switch (op)
4400 : {
4401 0 : case GOMP_MAP_FORCE_ALLOC:
4402 0 : case GOMP_MAP_FORCE_TO:
4403 0 : case GOMP_MAP_FORCE_FROM:
4404 0 : case GOMP_MAP_FORCE_TOFROM:
4405 0 : case GOMP_MAP_FORCE_PRESENT:
4406 0 : *force_p = true;
4407 0 : break;
4408 54 : case GOMP_MAP_ALWAYS_TO:
4409 54 : case GOMP_MAP_ALWAYS_FROM:
4410 54 : case GOMP_MAP_ALWAYS_TOFROM:
4411 54 : *always_p = true;
4412 54 : break;
4413 32 : case GOMP_MAP_ALWAYS_PRESENT_TO:
4414 32 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
4415 32 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
4416 32 : *always_p = true;
4417 : /* Fallthrough. */
4418 132 : case GOMP_MAP_PRESENT_ALLOC:
4419 132 : case GOMP_MAP_PRESENT_TO:
4420 132 : case GOMP_MAP_PRESENT_FROM:
4421 132 : case GOMP_MAP_PRESENT_TOFROM:
4422 132 : *present_p = true;
4423 132 : break;
4424 946 : default:
4425 946 : ;
4426 : }
4427 :
4428 946 : switch (op)
4429 : {
4430 : case GOMP_MAP_ALLOC:
4431 : case GOMP_MAP_FORCE_ALLOC:
4432 : case GOMP_MAP_PRESENT_ALLOC:
4433 : return GOMP_MAP_ALLOC;
4434 283 : case GOMP_MAP_TO:
4435 283 : case GOMP_MAP_FORCE_TO:
4436 283 : case GOMP_MAP_ALWAYS_TO:
4437 283 : case GOMP_MAP_PRESENT_TO:
4438 283 : case GOMP_MAP_ALWAYS_PRESENT_TO:
4439 283 : return GOMP_MAP_TO;
4440 212 : case GOMP_MAP_FROM:
4441 212 : case GOMP_MAP_FORCE_FROM:
4442 212 : case GOMP_MAP_ALWAYS_FROM:
4443 212 : case GOMP_MAP_PRESENT_FROM:
4444 212 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
4445 212 : return GOMP_MAP_FROM;
4446 210 : case GOMP_MAP_TOFROM:
4447 210 : case GOMP_MAP_FORCE_TOFROM:
4448 210 : case GOMP_MAP_ALWAYS_TOFROM:
4449 210 : case GOMP_MAP_PRESENT_TOFROM:
4450 210 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
4451 210 : return GOMP_MAP_TOFROM;
4452 128 : default:
4453 128 : ;
4454 : }
4455 :
4456 128 : return op;
4457 : }
4458 :
4459 : static enum gomp_map_kind
4460 416 : omp_join_map_kind (enum gomp_map_kind op, bool force_p, bool always_p,
4461 : bool present_p)
4462 : {
4463 416 : gcc_assert (!force_p || !(always_p || present_p));
4464 :
4465 416 : switch (op)
4466 : {
4467 89 : case GOMP_MAP_ALLOC:
4468 89 : if (force_p)
4469 : return GOMP_MAP_FORCE_ALLOC;
4470 89 : else if (present_p)
4471 16 : return GOMP_MAP_PRESENT_ALLOC;
4472 : break;
4473 :
4474 127 : case GOMP_MAP_TO:
4475 127 : if (force_p)
4476 : return GOMP_MAP_FORCE_TO;
4477 127 : else if (always_p && present_p)
4478 : return GOMP_MAP_ALWAYS_PRESENT_TO;
4479 115 : else if (always_p)
4480 : return GOMP_MAP_ALWAYS_TO;
4481 93 : else if (present_p)
4482 24 : return GOMP_MAP_PRESENT_TO;
4483 : break;
4484 :
4485 76 : case GOMP_MAP_FROM:
4486 76 : if (force_p)
4487 : return GOMP_MAP_FORCE_FROM;
4488 76 : else if (always_p && present_p)
4489 : return GOMP_MAP_ALWAYS_PRESENT_FROM;
4490 68 : else if (always_p)
4491 : return GOMP_MAP_ALWAYS_FROM;
4492 60 : else if (present_p)
4493 24 : return GOMP_MAP_PRESENT_FROM;
4494 : break;
4495 :
4496 80 : case GOMP_MAP_TOFROM:
4497 80 : if (force_p)
4498 : return GOMP_MAP_FORCE_TOFROM;
4499 80 : else if (always_p && present_p)
4500 : return GOMP_MAP_ALWAYS_PRESENT_TOFROM;
4501 80 : else if (always_p)
4502 : return GOMP_MAP_ALWAYS_TOFROM;
4503 80 : else if (present_p)
4504 0 : return GOMP_MAP_PRESENT_TOFROM;
4505 : break;
4506 :
4507 : default:
4508 : ;
4509 : }
4510 :
4511 : return op;
4512 : }
4513 :
4514 : /* Map kind decay (OpenMP 5.2, 5.8.8 "declare mapper Directive"). Return the
4515 : map kind to use given MAPPER_KIND specified in the mapper and INVOKED_AS
4516 : specified on the clause that invokes the mapper. See also
4517 : fortran/trans-openmp.cc:omp_map_decayed_kind. */
4518 :
4519 : static enum gomp_map_kind
4520 432 : omp_map_decayed_kind (enum gomp_map_kind mapper_kind,
4521 : enum gomp_map_kind invoked_as, bool exit_p)
4522 : {
4523 432 : if (invoked_as == GOMP_MAP_RELEASE || invoked_as == GOMP_MAP_DELETE)
4524 : return invoked_as;
4525 :
4526 416 : bool m_force_p, m_always_p, m_present_p;
4527 416 : bool force_p, always_p, present_p;
4528 :
4529 416 : mapper_kind = omp_split_map_kind (mapper_kind, &m_force_p, &m_always_p, &m_present_p);
4530 416 : invoked_as = omp_split_map_kind (invoked_as, &force_p, &always_p, &present_p);
4531 416 : gomp_map_kind decay_to;
4532 :
4533 416 : switch (mapper_kind)
4534 : {
4535 53 : case GOMP_MAP_ALLOC:
4536 53 : if (exit_p && invoked_as == GOMP_MAP_FROM)
4537 : decay_to = GOMP_MAP_RELEASE;
4538 : else
4539 77 : decay_to = GOMP_MAP_ALLOC;
4540 : break;
4541 :
4542 115 : case GOMP_MAP_TO:
4543 115 : if (invoked_as == GOMP_MAP_FROM)
4544 101 : decay_to = exit_p ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
4545 91 : else if (invoked_as == GOMP_MAP_ALLOC)
4546 : decay_to = GOMP_MAP_ALLOC;
4547 : else
4548 416 : decay_to = GOMP_MAP_TO;
4549 : break;
4550 :
4551 52 : case GOMP_MAP_FROM:
4552 52 : if (invoked_as == GOMP_MAP_ALLOC || invoked_as == GOMP_MAP_TO)
4553 : decay_to = GOMP_MAP_ALLOC;
4554 : else
4555 416 : decay_to = GOMP_MAP_FROM;
4556 : break;
4557 :
4558 : case GOMP_MAP_TOFROM:
4559 : case GOMP_MAP_UNSET:
4560 : decay_to = invoked_as;
4561 : break;
4562 :
4563 0 : default:
4564 0 : gcc_unreachable ();
4565 : }
4566 :
4567 416 : return omp_join_map_kind (decay_to, m_force_p | force_p,
4568 416 : m_always_p | always_p, m_present_p | present_p);
4569 : }
4570 :
4571 : /* Return a name to use for a "basic" map kind, e.g. as output from
4572 : omp_split_map_kind above. */
4573 :
4574 : static const char *
4575 16 : omp_basic_map_kind_name (enum gomp_map_kind kind)
4576 : {
4577 16 : switch (kind)
4578 : {
4579 : case GOMP_MAP_ALLOC:
4580 : return "alloc";
4581 4 : case GOMP_MAP_TO:
4582 4 : return "to";
4583 4 : case GOMP_MAP_FROM:
4584 4 : return "from";
4585 0 : case GOMP_MAP_TOFROM:
4586 0 : return "tofrom";
4587 0 : case GOMP_MAP_RELEASE:
4588 0 : return "release";
4589 0 : case GOMP_MAP_DELETE:
4590 0 : return "delete";
4591 0 : default:
4592 0 : gcc_unreachable ();
4593 : }
4594 : }
4595 :
4596 : /* Instantiate a mapper MAPPER for expression EXPR at location LOC,
4597 : adding new clauses to OUTLIST. OUTER_KIND is the mapping kind
4598 : to use if not already specified in the mapper declaration; ORT
4599 : denotes the directive that uses the mapper.
4600 : The resulting OUTLIST is also returned by the function. */
4601 :
4602 : static tree *
4603 142 : omp_instantiate_mapper (location_t loc, tree *outlist, tree mapper, tree expr,
4604 : enum gomp_map_kind outer_kind,
4605 : enum c_omp_region_type ort)
4606 : {
4607 142 : tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4608 142 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
4609 142 : tree mapper_name = NULL_TREE;
4610 :
4611 142 : remap_mapper_decl_info map_info;
4612 142 : map_info.dummy_var = dummy_var;
4613 142 : map_info.expr = expr;
4614 :
4615 574 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4616 : {
4617 432 : tree unshared = unshare_expr (c);
4618 432 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
4619 432 : tree t = OMP_CLAUSE_DECL (unshared);
4620 432 : tree type = NULL_TREE;
4621 432 : bool nonunit_array_with_mapper = false;
4622 :
4623 432 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4624 : {
4625 0 : mapper_name = t;
4626 2 : continue;
4627 : }
4628 432 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4629 : {
4630 0 : mapper_name = NULL_TREE;
4631 0 : continue;
4632 : }
4633 :
4634 432 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4635 : {
4636 43 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4637 :
4638 43 : if (t2 == t)
4639 : {
4640 42 : nonunit_array_with_mapper = true;
4641 : /* We'd want use the mapper for the element type if this worked:
4642 : look that one up. */
4643 42 : type = TREE_TYPE (TREE_TYPE (t));
4644 : }
4645 : else
4646 : {
4647 1 : t = t2;
4648 1 : type = TREE_TYPE (t);
4649 : }
4650 : }
4651 : else
4652 389 : type = TREE_TYPE (t);
4653 :
4654 432 : gcc_assert (type);
4655 :
4656 432 : if (type == error_mark_node)
4657 0 : continue;
4658 :
4659 432 : walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
4660 :
4661 432 : OMP_CLAUSE_LOCATION (unshared) = loc;
4662 :
4663 432 : enum gomp_map_kind decayed_kind
4664 548 : = omp_map_decayed_kind (clause_kind, outer_kind,
4665 : (ort & C_ORT_EXIT_DATA) != 0
4666 : || (outer_kind == GOMP_MAP_FROM
4667 32 : && (ort & C_ORT_UPDATE) != 0));
4668 432 : OMP_CLAUSE_SET_MAP_KIND (unshared, decayed_kind);
4669 :
4670 432 : type = TYPE_MAIN_VARIANT (type);
4671 :
4672 432 : tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4673 :
4674 432 : if (mapper_fn && nonunit_array_with_mapper)
4675 : {
4676 0 : sorry ("user-defined mapper with non-unit length array section");
4677 0 : continue;
4678 : }
4679 432 : else if (mapper_fn)
4680 : {
4681 27 : tree nested_mapper
4682 27 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4683 27 : if (nested_mapper != mapper)
4684 : {
4685 2 : outlist = omp_instantiate_mapper (loc, outlist, nested_mapper,
4686 : t, outer_kind, ort);
4687 2 : continue;
4688 : }
4689 : }
4690 405 : else if (mapper_name)
4691 : {
4692 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4693 0 : continue;
4694 : }
4695 :
4696 430 : if (ort & C_ORT_UPDATE)
4697 : {
4698 98 : bool force_p, always_p, present_p;
4699 98 : decayed_kind
4700 98 : = omp_split_map_kind (decayed_kind, &force_p, &always_p,
4701 : &present_p);
4702 : /* We don't expect to see these flags here. */
4703 98 : gcc_assert (!force_p && !always_p);
4704 : /* For a "target update" operation, we want to turn the map node
4705 : expanded from the mapper back into a OMP_CLAUSE_TO or
4706 : OMP_CLAUSE_FROM node. If we can do neither, emit a warning and
4707 : drop the clause. */
4708 98 : switch (decayed_kind)
4709 : {
4710 82 : case GOMP_MAP_TO:
4711 82 : case GOMP_MAP_FROM:
4712 82 : {
4713 82 : tree xfer
4714 122 : = build_omp_clause (loc, (decayed_kind == GOMP_MAP_TO
4715 : ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM));
4716 82 : OMP_CLAUSE_DECL (xfer) = OMP_CLAUSE_DECL (unshared);
4717 82 : OMP_CLAUSE_SIZE (xfer) = OMP_CLAUSE_SIZE (unshared);
4718 : /* For FROM/TO clauses, "present" is represented by a flag.
4719 : Set it for the expanded clause here. */
4720 82 : if (present_p)
4721 32 : OMP_CLAUSE_MOTION_PRESENT (xfer) = 1;
4722 82 : *outlist = xfer;
4723 82 : outlist = &OMP_CLAUSE_CHAIN (xfer);
4724 : }
4725 82 : break;
4726 16 : default:
4727 16 : clause_kind
4728 16 : = omp_split_map_kind (clause_kind, &force_p, &always_p,
4729 : &present_p);
4730 16 : warning_at (loc, OPT_Wopenmp,
4731 : "dropping %qs clause during mapper expansion "
4732 : "in %<#pragma omp target update%>",
4733 : omp_basic_map_kind_name (clause_kind));
4734 16 : inform (OMP_CLAUSE_LOCATION (c), "for map clause here");
4735 : }
4736 : }
4737 : else
4738 : {
4739 332 : *outlist = unshared;
4740 332 : outlist = &OMP_CLAUSE_CHAIN (unshared);
4741 : }
4742 : }
4743 :
4744 142 : return outlist;
4745 : }
4746 :
4747 : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
4748 : appropriate to the type of the data in that clause, if such a mapper is
4749 : visible in the current parsing context. */
4750 :
4751 : tree
4752 16773 : c_omp_instantiate_mappers (tree clauses, enum c_omp_region_type ort)
4753 : {
4754 16773 : tree c, *pc, mapper_name = NULL_TREE;
4755 :
4756 36673 : for (pc = &clauses, c = clauses; c; c = *pc)
4757 : {
4758 19900 : bool using_mapper = false;
4759 19900 : bool update_p = false, update_present_p = false;
4760 :
4761 19900 : switch (OMP_CLAUSE_CODE (c))
4762 : {
4763 6017 : case OMP_CLAUSE_TO:
4764 6017 : case OMP_CLAUSE_FROM:
4765 6017 : update_p = true;
4766 6017 : if (OMP_CLAUSE_MOTION_PRESENT (c))
4767 58 : update_present_p = true;
4768 : /* Fallthrough. */
4769 13343 : case OMP_CLAUSE_MAP:
4770 13343 : {
4771 13343 : tree t = OMP_CLAUSE_DECL (c);
4772 13343 : tree type = NULL_TREE;
4773 13343 : bool nonunit_array_with_mapper = false;
4774 :
4775 13417 : if (!update_p
4776 13343 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
4777 7289 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME))
4778 : {
4779 74 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
4780 37 : mapper_name = OMP_CLAUSE_DECL (c);
4781 : else
4782 : mapper_name = NULL_TREE;
4783 74 : pc = &OMP_CLAUSE_CHAIN (c);
4784 74 : continue;
4785 : }
4786 :
4787 13269 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4788 : {
4789 2451 : location_t loc = OMP_CLAUSE_LOCATION (c);
4790 2451 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4791 :
4792 2451 : if (t2 == t)
4793 : {
4794 : /* !!! Array sections of size >1 with mappers for elements
4795 : are hard to support. Do something here. */
4796 2037 : nonunit_array_with_mapper = true;
4797 2037 : type = TREE_TYPE (TREE_TYPE (t));
4798 : }
4799 : else
4800 : {
4801 414 : t = t2;
4802 414 : type = TREE_TYPE (t);
4803 : }
4804 : }
4805 : else
4806 10818 : type = TREE_TYPE (t);
4807 :
4808 13269 : if (type == NULL_TREE || type == error_mark_node)
4809 : {
4810 73 : pc = &OMP_CLAUSE_CHAIN (c);
4811 73 : continue;
4812 : }
4813 :
4814 13196 : enum gomp_map_kind kind;
4815 13196 : if (update_p)
4816 : {
4817 6017 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
4818 999 : kind = update_present_p ? GOMP_MAP_PRESENT_TO
4819 : : GOMP_MAP_TO;
4820 : else
4821 5018 : kind = update_present_p ? GOMP_MAP_PRESENT_FROM
4822 : : GOMP_MAP_FROM;
4823 : }
4824 : else
4825 : {
4826 7179 : kind = OMP_CLAUSE_MAP_KIND (c);
4827 7179 : if (kind == GOMP_MAP_UNSET)
4828 0 : kind = GOMP_MAP_TOFROM;
4829 : }
4830 :
4831 13196 : type = TYPE_MAIN_VARIANT (type);
4832 :
4833 13196 : tree mapper_fn
4834 13196 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4835 :
4836 13196 : if (mapper_fn && nonunit_array_with_mapper)
4837 : {
4838 0 : sorry ("user-defined mapper with non-unit length "
4839 : "array section");
4840 0 : using_mapper = true;
4841 : }
4842 13196 : else if (mapper_fn)
4843 : {
4844 140 : tree mapper
4845 140 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4846 140 : pc = omp_instantiate_mapper (OMP_CLAUSE_LOCATION (c),
4847 : pc, mapper, t, kind, ort);
4848 140 : using_mapper = true;
4849 : }
4850 13056 : else if (mapper_name)
4851 : {
4852 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4853 0 : using_mapper = true;
4854 : }
4855 : }
4856 : break;
4857 :
4858 140 : default:
4859 140 : ;
4860 : }
4861 :
4862 140 : if (using_mapper)
4863 140 : *pc = OMP_CLAUSE_CHAIN (c);
4864 : else
4865 19613 : pc = &OMP_CLAUSE_CHAIN (c);
4866 : }
4867 :
4868 16773 : return clauses;
4869 : }
4870 :
4871 : const struct c_omp_directive c_omp_directives[] = {
4872 : /* Keep this alphabetically sorted by the first word. Non-null second/third
4873 : if any should precede null ones. */
4874 : { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
4875 : C_OMP_DIR_DECLARATIVE, false },
4876 : { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
4877 : C_OMP_DIR_INFORMATIONAL, false },
4878 : { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
4879 : C_OMP_DIR_INFORMATIONAL, false },
4880 : { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
4881 : C_OMP_DIR_CONSTRUCT, false },
4882 : { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
4883 : C_OMP_DIR_STANDALONE, false },
4884 : { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
4885 : C_OMP_DIR_INFORMATIONAL, false },
4886 : { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
4887 : C_OMP_DIR_DECLARATIVE, false },
4888 : { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
4889 : C_OMP_DIR_DECLARATIVE, false },
4890 : /* 'begin metadirective' is not yet implemented; however,
4891 : it is only applicable if an end-directive exists, but
4892 : metadirectives are of limited use for declarative directives. */
4893 : /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
4894 : C_OMP_DIR_META, false }, */
4895 : { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
4896 : C_OMP_DIR_STANDALONE, false },
4897 : { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
4898 : C_OMP_DIR_STANDALONE, false },
4899 : { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
4900 : C_OMP_DIR_CONSTRUCT, false },
4901 : /* { "declare", "induction", nullptr, PRAGMA_OMP_DECLARE,
4902 : C_OMP_DIR_DECLARATIVE, true }, */
4903 : { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
4904 : C_OMP_DIR_DECLARATIVE, false },
4905 : { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
4906 : C_OMP_DIR_DECLARATIVE, true },
4907 : { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
4908 : C_OMP_DIR_DECLARATIVE, true },
4909 : { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
4910 : C_OMP_DIR_DECLARATIVE, false },
4911 : { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
4912 : C_OMP_DIR_DECLARATIVE, false },
4913 : { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
4914 : C_OMP_DIR_STANDALONE, false },
4915 : { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
4916 : C_OMP_DIR_DECLARATIVE, false },
4917 : { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
4918 : C_OMP_DIR_CONSTRUCT, true },
4919 : { "end", "assumes", nullptr, PRAGMA_OMP_END,
4920 : C_OMP_DIR_INFORMATIONAL, false },
4921 : { "end", "declare", "target", PRAGMA_OMP_END,
4922 : C_OMP_DIR_DECLARATIVE, false },
4923 : { "end", "declare", "variant", PRAGMA_OMP_END,
4924 : C_OMP_DIR_DECLARATIVE, false },
4925 : /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
4926 : C_OMP_DIR_META, false }, */
4927 : /* error with at(execution) is C_OMP_DIR_STANDALONE. */
4928 : { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
4929 : C_OMP_DIR_UTILITY, false },
4930 : /* { "flatten", nullptr, nullptr, PRAGMA_OMP_FLATTEN,
4931 : C_OMP_DIR_CONSTRUCT, true }, */
4932 : { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
4933 : C_OMP_DIR_STANDALONE, false },
4934 : { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
4935 : C_OMP_DIR_CONSTRUCT, true },
4936 : /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE,
4937 : C_OMP_DIR_CONSTRUCT, true }, */
4938 : { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
4939 : C_OMP_DIR_DECLARATIVE, false },
4940 : /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE,
4941 : C_OMP_DIR_CONSTRUCT, true }, */
4942 : { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
4943 : C_OMP_DIR_STANDALONE, false },
4944 : { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
4945 : C_OMP_DIR_CONSTRUCT, true },
4946 : { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
4947 : C_OMP_DIR_CONSTRUCT, true },
4948 : { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
4949 : C_OMP_DIR_CONSTRUCT, true },
4950 : { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
4951 : C_OMP_DIR_META, false },
4952 : { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
4953 : C_OMP_DIR_UTILITY, false },
4954 : /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
4955 : { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
4956 : C_OMP_DIR_CONSTRUCT, true },
4957 : { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
4958 : C_OMP_DIR_CONSTRUCT, true },
4959 : { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
4960 : C_OMP_DIR_INFORMATIONAL, false },
4961 : { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
4962 : C_OMP_DIR_CONSTRUCT, true },
4963 : { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
4964 : C_OMP_DIR_CONSTRUCT, false },
4965 : { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
4966 : C_OMP_DIR_CONSTRUCT, false },
4967 : { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
4968 : C_OMP_DIR_CONSTRUCT, false },
4969 : { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
4970 : C_OMP_DIR_CONSTRUCT, true },
4971 : { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
4972 : C_OMP_DIR_CONSTRUCT, false },
4973 : /* { "split", nullptr, nullptr, PRAGMA_OMP_SPLIT,
4974 : C_OMP_DIR_CONSTRUCT, true }, */
4975 : /* { "stripe", nullptr, nullptr, PRAGMA_OMP_STRIPE,
4976 : C_OMP_DIR_CONSTRUCT, true }, */
4977 : { "target", "data", nullptr, PRAGMA_OMP_TARGET,
4978 : C_OMP_DIR_CONSTRUCT, false },
4979 : { "target", "enter", "data", PRAGMA_OMP_TARGET,
4980 : C_OMP_DIR_STANDALONE, false },
4981 : { "target", "exit", "data", PRAGMA_OMP_TARGET,
4982 : C_OMP_DIR_STANDALONE, false },
4983 : { "target", "update", nullptr, PRAGMA_OMP_TARGET,
4984 : C_OMP_DIR_STANDALONE, false },
4985 : { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
4986 : C_OMP_DIR_CONSTRUCT, true },
4987 : { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
4988 : C_OMP_DIR_CONSTRUCT, false },
4989 : /* { "task", "iteration", nullptr, PRAGMA_OMP_TASK_ITERATION,
4990 : C_OMP_DIR_STANDALONE, false }, */
4991 : /* { "taskgraph", nullptr, nullptr, PRAGMA_OMP_TASKGRAPH,
4992 : C_OMP_DIR_CONSTRUCT, false }, */
4993 : { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
4994 : C_OMP_DIR_CONSTRUCT, false },
4995 : { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
4996 : C_OMP_DIR_CONSTRUCT, true },
4997 : { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
4998 : C_OMP_DIR_STANDALONE, false },
4999 : { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
5000 : C_OMP_DIR_STANDALONE, false },
5001 : { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
5002 : C_OMP_DIR_CONSTRUCT, false },
5003 : { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
5004 : C_OMP_DIR_CONSTRUCT, true },
5005 : { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
5006 : C_OMP_DIR_DECLARATIVE, false },
5007 : { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
5008 : C_OMP_DIR_CONSTRUCT, false },
5009 : };
5010 :
5011 : /* Find (non-combined/composite) OpenMP directive (if any) which starts
5012 : with FIRST keyword and for multi-word directives has SECOND and
5013 : THIRD keyword after it. */
5014 :
5015 : const struct c_omp_directive *
5016 6652 : c_omp_categorize_directive (const char *first, const char *second,
5017 : const char *third)
5018 : {
5019 6652 : const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
5020 211591 : for (size_t i = 0; i < n_omp_directives; i++)
5021 : {
5022 396186 : if ((unsigned char) c_omp_directives[i].first[0]
5023 211591 : < (unsigned char) first[0])
5024 184595 : continue;
5025 26996 : if ((unsigned char) c_omp_directives[i].first[0]
5026 : > (unsigned char) first[0])
5027 : break;
5028 26909 : if (strcmp (c_omp_directives[i].first, first))
5029 16103 : continue;
5030 10806 : if (!c_omp_directives[i].second)
5031 5138 : return &c_omp_directives[i];
5032 5668 : if (!second || strcmp (c_omp_directives[i].second, second))
5033 4205 : continue;
5034 1463 : if (!c_omp_directives[i].third)
5035 1127 : return &c_omp_directives[i];
5036 336 : if (!third || strcmp (c_omp_directives[i].third, third))
5037 36 : continue;
5038 300 : return &c_omp_directives[i];
5039 : }
5040 : return NULL;
5041 : }
5042 :
5043 : /* Auxiliary helper function for c_omp_expand_variant_construct. */
5044 :
5045 : static tree
5046 388 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
5047 : hash_map<tree, tree> &body_labels,
5048 : unsigned index)
5049 : {
5050 388 : struct omp_variant &candidate = candidates[index];
5051 388 : tree if_block = push_stmt_list ();
5052 388 : if (candidate.alternative != NULL_TREE)
5053 388 : add_stmt (candidate.alternative);
5054 388 : if (candidate.body != NULL_TREE)
5055 : {
5056 118 : tree *label = body_labels.get (candidate.body);
5057 118 : if (label != NULL)
5058 0 : add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
5059 : else
5060 : {
5061 118 : tree body_label = create_artificial_label (UNKNOWN_LOCATION);
5062 118 : add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
5063 118 : add_stmt (candidate.body);
5064 118 : body_labels.put (candidate.body, body_label);
5065 : }
5066 : }
5067 388 : if_block = pop_stmt_list (if_block);
5068 :
5069 776 : if (index == candidates.length () - 1)
5070 : return if_block;
5071 :
5072 154 : tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
5073 154 : gcc_assert (cond != NULL_TREE);
5074 :
5075 154 : tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
5076 : index + 1);
5077 154 : tree ret = push_stmt_list ();
5078 154 : tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
5079 154 : add_stmt (stmt);
5080 154 : ret = pop_stmt_list (ret);
5081 :
5082 154 : return ret;
5083 : }
5084 :
5085 : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
5086 : structure. */
5087 :
5088 : tree
5089 234 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
5090 : {
5091 234 : hash_map<tree, tree> body_labels;
5092 234 : return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
5093 234 : }
|