Branch data 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-2025 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 : 730 : c_finish_omp_master (location_t loc, tree stmt)
89 : : {
90 : 730 : tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
91 : 730 : SET_EXPR_LOCATION (t, loc);
92 : 730 : 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 : 377 : c_finish_omp_masked (location_t loc, tree body, tree clauses)
100 : : {
101 : 377 : tree stmt = make_node (OMP_MASKED);
102 : 377 : TREE_TYPE (stmt) = void_type_node;
103 : 377 : OMP_MASKED_BODY (stmt) = body;
104 : 377 : OMP_MASKED_CLAUSES (stmt) = clauses;
105 : 377 : SET_EXPR_LOCATION (stmt, loc);
106 : 377 : 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 : 1558 : c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
155 : : {
156 : 1558 : tree t = make_node (OMP_ORDERED);
157 : 1558 : TREE_TYPE (t) = void_type_node;
158 : 1558 : OMP_ORDERED_BODY (t) = stmt;
159 : 1558 : if (!flag_openmp /* flag_openmp_simd */
160 : 1598 : && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
161 : 40 : || OMP_CLAUSE_CHAIN (clauses)))
162 : 4 : clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
163 : 1558 : OMP_ORDERED_CLAUSES (t) = clauses;
164 : 1558 : SET_EXPR_LOCATION (t, loc);
165 : 1558 : 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 : 348 : c_finish_omp_barrier (location_t loc)
174 : : {
175 : 348 : tree x;
176 : :
177 : 348 : x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
178 : 348 : x = build_call_expr_loc (loc, x, 0);
179 : 348 : add_stmt (x);
180 : 348 : }
181 : :
182 : :
183 : : /* Complete a #pragma omp taskwait construct. LOC is the location of the
184 : : pragma. */
185 : :
186 : : void
187 : 72 : c_finish_omp_taskwait (location_t loc)
188 : : {
189 : 72 : tree x;
190 : :
191 : 72 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
192 : 72 : x = build_call_expr_loc (loc, x, 0);
193 : 72 : add_stmt (x);
194 : 72 : }
195 : :
196 : :
197 : : /* Complete a #pragma omp taskyield construct. LOC is the location of the
198 : : pragma. */
199 : :
200 : : void
201 : 6 : c_finish_omp_taskyield (location_t loc)
202 : : {
203 : 6 : tree x;
204 : :
205 : 6 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
206 : 6 : x = build_call_expr_loc (loc, x, 0);
207 : 6 : add_stmt (x);
208 : 6 : }
209 : :
210 : :
211 : : /* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC
212 : : the expression to be implemented atomically is LHS opcode= RHS.
213 : : For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
214 : : opcode= RHS with the new or old content of LHS returned.
215 : : LOC is the location of the atomic statement. The value returned
216 : : is either error_mark_node (if the construct was erroneous) or an
217 : : OMP_ATOMIC* node which should be added to the current statement
218 : : tree with add_stmt. If TEST is set, avoid calling save_expr
219 : : or create_tmp_var*. */
220 : :
221 : : tree
222 : 4592 : c_finish_omp_atomic (location_t loc, enum tree_code code,
223 : : enum tree_code opcode, tree lhs, tree rhs,
224 : : tree v, tree lhs1, tree rhs1, tree r, bool swapped,
225 : : enum omp_memory_order memory_order, bool weak,
226 : : bool test)
227 : : {
228 : 4592 : tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
229 : 4592 : HOST_WIDE_INT bitpos = 0, bitsize = 0;
230 : 4592 : enum tree_code orig_opcode = opcode;
231 : :
232 : 4592 : if (lhs == error_mark_node || rhs == error_mark_node
233 : 4592 : || v == error_mark_node || lhs1 == error_mark_node
234 : 4592 : || rhs1 == error_mark_node || r == error_mark_node)
235 : : return error_mark_node;
236 : :
237 : : /* ??? According to one reading of the OpenMP spec, complex type are
238 : : supported, but there are no atomic stores for any architecture.
239 : : But at least icc 9.0 doesn't support complex types here either.
240 : : And lets not even talk about vector types... */
241 : 4592 : type = TREE_TYPE (lhs);
242 : 4592 : if (!INTEGRAL_TYPE_P (type)
243 : 882 : && !POINTER_TYPE_P (type)
244 : 872 : && !SCALAR_FLOAT_TYPE_P (type))
245 : : {
246 : 7 : error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
247 : 7 : return error_mark_node;
248 : : }
249 : 4585 : if (TYPE_ATOMIC (type))
250 : : {
251 : 8 : error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
252 : 8 : return error_mark_node;
253 : : }
254 : 4577 : if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
255 : : {
256 : 4 : error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
257 : : "comparison result");
258 : 4 : return error_mark_node;
259 : : }
260 : :
261 : 4573 : if (opcode == RDIV_EXPR)
262 : 0 : opcode = TRUNC_DIV_EXPR;
263 : :
264 : : /* ??? Validate that rhs does not overlap lhs. */
265 : 4573 : tree blhs = NULL;
266 : 4573 : if (TREE_CODE (lhs) == COMPONENT_REF
267 : 69 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
268 : 69 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
269 : 4623 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
270 : : {
271 : 50 : tree field = TREE_OPERAND (lhs, 1);
272 : 50 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
273 : 50 : if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
274 : 100 : && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
275 : 50 : bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
276 : 50 : - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
277 : : else
278 : : bitpos = 0;
279 : 50 : bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
280 : 50 : - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
281 : 50 : gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
282 : 50 : bitsize = tree_to_shwi (DECL_SIZE (field));
283 : 50 : blhs = lhs;
284 : 50 : type = TREE_TYPE (repr);
285 : 50 : lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
286 : 50 : repr, TREE_OPERAND (lhs, 2));
287 : : }
288 : :
289 : : /* Take and save the address of the lhs. From then on we'll reference it
290 : : via indirection. */
291 : 4573 : addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
292 : 4573 : if (addr == error_mark_node)
293 : : return error_mark_node;
294 : 4564 : if (!test)
295 : 4351 : addr = save_expr (addr);
296 : 4351 : if (!test
297 : 4351 : && TREE_CODE (addr) != SAVE_EXPR
298 : 3756 : && (TREE_CODE (addr) != ADDR_EXPR
299 : 3577 : || !VAR_P (TREE_OPERAND (addr, 0))))
300 : : {
301 : : /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
302 : : it even after unsharing function body. */
303 : 364 : tree var = create_tmp_var_raw (TREE_TYPE (addr));
304 : 364 : DECL_CONTEXT (var) = current_function_decl;
305 : 364 : addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
306 : : }
307 : 4564 : tree orig_lhs = lhs;
308 : 4564 : lhs = build_indirect_ref (loc, addr, RO_NULL);
309 : 4564 : tree new_lhs = lhs;
310 : :
311 : 4564 : if (code == OMP_ATOMIC_READ)
312 : : {
313 : 750 : x = build1 (OMP_ATOMIC_READ, type, addr);
314 : 750 : SET_EXPR_LOCATION (x, loc);
315 : 750 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
316 : 750 : gcc_assert (!weak);
317 : 750 : if (blhs)
318 : 2 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
319 : 2 : bitsize_int (bitsize), bitsize_int (bitpos));
320 : 750 : return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
321 : 750 : loc, x, NULL_TREE);
322 : : }
323 : :
324 : : /* There are lots of warnings, errors, and conversions that need to happen
325 : : in the course of interpreting a statement. Use the normal mechanisms
326 : : to do this, and then take it apart again. */
327 : 3814 : if (blhs)
328 : : {
329 : 48 : lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
330 : 48 : bitsize_int (bitsize), bitsize_int (bitpos));
331 : 48 : if (opcode == COND_EXPR)
332 : : {
333 : 16 : bool save = in_late_binary_op;
334 : 16 : in_late_binary_op = true;
335 : 16 : std::swap (rhs, rhs1);
336 : 16 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
337 : 16 : in_late_binary_op = save;
338 : : }
339 : 32 : else if (swapped)
340 : 0 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
341 : 32 : else if (opcode != NOP_EXPR)
342 : 26 : rhs = build_binary_op (loc, opcode, lhs, rhs, true);
343 : : opcode = NOP_EXPR;
344 : : }
345 : 3766 : else if (opcode == COND_EXPR)
346 : : {
347 : 334 : bool save = in_late_binary_op;
348 : 334 : in_late_binary_op = true;
349 : 334 : std::swap (rhs, rhs1);
350 : 334 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
351 : 334 : in_late_binary_op = save;
352 : 334 : opcode = NOP_EXPR;
353 : : }
354 : 3432 : else if (swapped)
355 : : {
356 : 124 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
357 : 124 : opcode = NOP_EXPR;
358 : : }
359 : 3814 : bool save = in_late_binary_op;
360 : 3814 : in_late_binary_op = true;
361 : 3814 : if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
362 : 4102 : && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
363 : 288 : true) == error_mark_node)
364 : : x = error_mark_node;
365 : : else
366 : 7572 : x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
367 : : loc, rhs, NULL_TREE);
368 : 3814 : in_late_binary_op = save;
369 : 3814 : if (x == error_mark_node)
370 : : return error_mark_node;
371 : 3794 : if (TREE_CODE (x) == COMPOUND_EXPR)
372 : : {
373 : 14 : pre = TREE_OPERAND (x, 0);
374 : 14 : gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
375 : 14 : x = TREE_OPERAND (x, 1);
376 : : }
377 : 3794 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
378 : 3794 : rhs = TREE_OPERAND (x, 1);
379 : :
380 : 3794 : if (blhs)
381 : 48 : rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
382 : 48 : rhs, bitsize_int (bitpos));
383 : 3794 : if (orig_opcode == COND_EXPR)
384 : : {
385 : 350 : if (error_operand_p (rhs1))
386 : 0 : return error_mark_node;
387 : 350 : gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
388 : 350 : tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
389 : 350 : if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
390 : : {
391 : 114 : bool clear_padding = false;
392 : 114 : HOST_WIDE_INT non_padding_start = 0;
393 : 114 : HOST_WIDE_INT non_padding_end = 0;
394 : 114 : if (BITS_PER_UNIT == 8
395 : : && CHAR_BIT == 8
396 : 114 : && clear_padding_type_may_have_padding_p (cmptype))
397 : : {
398 : 30 : HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
399 : 30 : gcc_assert (sz > 0);
400 : 30 : unsigned char *buf = XALLOCAVEC (unsigned char, sz);
401 : 30 : memset (buf, ~0, sz);
402 : 30 : clear_type_padding_in_mask (cmptype, buf);
403 : 360 : for (i = 0; i < sz; i++)
404 : 330 : if (buf[i] != (unsigned char) ~0)
405 : : {
406 : : clear_padding = true;
407 : : break;
408 : : }
409 : 30 : if (clear_padding && buf[i] == 0)
410 : : {
411 : : /* Try to optimize. In the common case where
412 : : non-padding bits are all continuous and start
413 : : and end at a byte boundary, we can just adjust
414 : : the memcmp call arguments and don't need to
415 : : emit __builtin_clear_padding calls. */
416 : 30 : if (i == 0)
417 : : {
418 : 0 : for (i = 0; i < sz; i++)
419 : 0 : if (buf[i] != 0)
420 : : break;
421 : 0 : if (i < sz && buf[i] == (unsigned char) ~0)
422 : : {
423 : 0 : non_padding_start = i;
424 : 0 : for (; i < sz; i++)
425 : 0 : if (buf[i] != (unsigned char) ~0)
426 : : break;
427 : : }
428 : : else
429 : : i = 0;
430 : : }
431 : 30 : if (i != 0)
432 : : {
433 : 210 : non_padding_end = i;
434 : 210 : for (; i < sz; i++)
435 : 180 : if (buf[i] != 0)
436 : : {
437 : : non_padding_start = 0;
438 : : non_padding_end = 0;
439 : : break;
440 : : }
441 : : }
442 : : }
443 : : }
444 : 84 : tree inttype = NULL_TREE;
445 : 84 : if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
446 : : {
447 : 84 : HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
448 : 84 : inttype = c_common_type_for_size (prec, 1);
449 : 84 : if (inttype
450 : 168 : && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
451 : 84 : TYPE_SIZE (inttype))
452 : 84 : || TYPE_PRECISION (inttype) != prec))
453 : : inttype = NULL_TREE;
454 : : }
455 : 84 : if (inttype)
456 : : {
457 : 84 : TREE_OPERAND (rhs1, 0)
458 : 84 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
459 : 84 : TREE_OPERAND (rhs1, 0));
460 : 84 : TREE_OPERAND (rhs1, 1)
461 : 168 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
462 : 84 : TREE_OPERAND (rhs1, 1));
463 : : }
464 : : else
465 : : {
466 : 30 : tree pcmptype = build_pointer_type (cmptype);
467 : 30 : tree tmp1 = create_tmp_var_raw (cmptype);
468 : 30 : TREE_ADDRESSABLE (tmp1) = 1;
469 : 30 : DECL_CONTEXT (tmp1) = current_function_decl;
470 : 30 : tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
471 : 30 : TREE_OPERAND (rhs1, 0), NULL, NULL);
472 : 30 : tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
473 : 30 : tree tmp2 = create_tmp_var_raw (cmptype);
474 : 30 : TREE_ADDRESSABLE (tmp2) = 1;
475 : 30 : DECL_CONTEXT (tmp2) = current_function_decl;
476 : 30 : tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
477 : 30 : TREE_OPERAND (rhs1, 1), NULL, NULL);
478 : 30 : tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
479 : 30 : if (non_padding_start)
480 : : {
481 : 0 : tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
482 : 0 : size_int (non_padding_start));
483 : 0 : tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
484 : 0 : size_int (non_padding_start));
485 : : }
486 : 30 : tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
487 : 60 : rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
488 : : non_padding_end
489 : 30 : ? size_int (non_padding_end
490 : : - non_padding_start)
491 : 0 : : TYPE_SIZE_UNIT (cmptype));
492 : 30 : rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
493 : : integer_zero_node);
494 : 30 : if (clear_padding && non_padding_end == 0)
495 : : {
496 : 0 : fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
497 : 0 : tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
498 : 0 : tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
499 : 0 : rhs1 = omit_two_operands_loc (loc, boolean_type_node,
500 : : rhs1, cp2, cp1);
501 : : }
502 : : }
503 : : }
504 : 350 : if (r && test)
505 : : rtmp = rhs1;
506 : 325 : else if (r)
507 : : {
508 : 118 : tree var = create_tmp_var_raw (boolean_type_node);
509 : 118 : DECL_CONTEXT (var) = current_function_decl;
510 : 118 : rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
511 : : boolean_false_node, NULL, NULL);
512 : 118 : save = in_late_binary_op;
513 : 118 : in_late_binary_op = true;
514 : 118 : x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
515 : : loc, rhs1, NULL_TREE);
516 : 118 : in_late_binary_op = save;
517 : 118 : if (x == error_mark_node)
518 : : return error_mark_node;
519 : 118 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
520 : : && TREE_OPERAND (x, 0) == var);
521 : 118 : TREE_OPERAND (x, 0) = rtmp;
522 : 118 : rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
523 : : }
524 : 350 : rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs);
525 : 350 : rhs1 = NULL_TREE;
526 : : }
527 : :
528 : : /* Punt the actual generation of atomic operations to common code. */
529 : 3794 : if (code == OMP_ATOMIC)
530 : 2528 : type = void_type_node;
531 : 3794 : x = build2 (code, type, addr, rhs);
532 : 3794 : SET_EXPR_LOCATION (x, loc);
533 : 3794 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
534 : 3794 : OMP_ATOMIC_WEAK (x) = weak;
535 : :
536 : : /* Generally it is hard to prove lhs1 and lhs are the same memory
537 : : location, just diagnose different variables. */
538 : 3794 : if (rhs1
539 : 1031 : && VAR_P (rhs1)
540 : 439 : && VAR_P (orig_lhs)
541 : 439 : && rhs1 != orig_lhs
542 : 0 : && !test)
543 : : {
544 : 0 : if (code == OMP_ATOMIC)
545 : 0 : error_at (loc, "%<#pragma omp atomic update%> uses two different "
546 : : "variables for memory");
547 : : else
548 : 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two different "
549 : : "variables for memory");
550 : 0 : return error_mark_node;
551 : : }
552 : :
553 : 3794 : if (lhs1
554 : 3794 : && lhs1 != orig_lhs
555 : 325 : && TREE_CODE (lhs1) == COMPONENT_REF
556 : 12 : && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
557 : 12 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
558 : 3806 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
559 : : {
560 : 12 : tree field = TREE_OPERAND (lhs1, 1);
561 : 12 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
562 : 12 : lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
563 : 12 : repr, TREE_OPERAND (lhs1, 2));
564 : : }
565 : 3794 : if (rhs1
566 : 1031 : && rhs1 != orig_lhs
567 : 592 : && TREE_CODE (rhs1) == COMPONENT_REF
568 : 16 : && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
569 : 16 : && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
570 : 3810 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
571 : : {
572 : 16 : tree field = TREE_OPERAND (rhs1, 1);
573 : 16 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
574 : 16 : rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
575 : 16 : repr, TREE_OPERAND (rhs1, 2));
576 : : }
577 : :
578 : 3794 : if (code != OMP_ATOMIC)
579 : : {
580 : : /* Generally it is hard to prove lhs1 and lhs are the same memory
581 : : location, just diagnose different variables. */
582 : 1266 : if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
583 : : {
584 : 434 : if (lhs1 != orig_lhs && !test)
585 : : {
586 : 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two "
587 : : "different variables for memory");
588 : 0 : return error_mark_node;
589 : : }
590 : : }
591 : 1266 : if (blhs)
592 : 28 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
593 : 28 : bitsize_int (bitsize), bitsize_int (bitpos));
594 : 1266 : if (r && !test)
595 : : {
596 : 80 : vtmp = create_tmp_var_raw (TREE_TYPE (x));
597 : 80 : DECL_CONTEXT (vtmp) = current_function_decl;
598 : : }
599 : : else
600 : : vtmp = v;
601 : 1266 : x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
602 : : loc, x, NULL_TREE);
603 : 1266 : if (x == error_mark_node)
604 : : return error_mark_node;
605 : 1262 : type = TREE_TYPE (x);
606 : 1262 : if (r && !test)
607 : : {
608 : 80 : vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
609 : 80 : build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
610 : 80 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
611 : : && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
612 : 80 : TREE_OPERAND (x, 0) = vtmp;
613 : : }
614 : 1262 : if (rhs1 && rhs1 != orig_lhs)
615 : : {
616 : 238 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
617 : 238 : if (rhs1addr == error_mark_node)
618 : : return error_mark_node;
619 : 238 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
620 : : }
621 : 1262 : if (lhs1 && lhs1 != orig_lhs)
622 : : {
623 : 325 : tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
624 : 325 : if (lhs1addr == error_mark_node)
625 : : return error_mark_node;
626 : 324 : if (code == OMP_ATOMIC_CAPTURE_OLD)
627 : 205 : x = omit_one_operand_loc (loc, type, x, lhs1addr);
628 : : else
629 : : {
630 : 119 : if (!test)
631 : 103 : x = save_expr (x);
632 : 119 : x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
633 : : }
634 : : }
635 : : }
636 : 2528 : else if (rhs1 && rhs1 != orig_lhs)
637 : : {
638 : 354 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
639 : 354 : if (rhs1addr == error_mark_node)
640 : : return error_mark_node;
641 : 354 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
642 : : }
643 : :
644 : 3789 : if (pre)
645 : 14 : x = omit_one_operand_loc (loc, type, x, pre);
646 : 3789 : if (r && r != void_list_node)
647 : : {
648 : 88 : in_late_binary_op = true;
649 : 88 : tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
650 : : loc, rtmp, NULL_TREE);
651 : 88 : in_late_binary_op = save;
652 : 88 : if (x2 == error_mark_node)
653 : : return error_mark_node;
654 : 88 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
655 : : }
656 : 3789 : if (v && vtmp != v)
657 : : {
658 : 80 : in_late_binary_op = true;
659 : 80 : tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
660 : : loc, vtmp, NULL_TREE);
661 : 80 : in_late_binary_op = save;
662 : 80 : if (x2 == error_mark_node)
663 : : return error_mark_node;
664 : 80 : x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp,
665 : : void_node, x2);
666 : 80 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
667 : : }
668 : : return x;
669 : : }
670 : :
671 : :
672 : : /* Return true if TYPE is the implementation's omp_interop_t. */
673 : :
674 : : bool
675 : 1841 : c_omp_interop_t_p (tree type)
676 : : {
677 : 1841 : if (type == error_mark_node)
678 : : return false;
679 : 1817 : type = TYPE_MAIN_VARIANT (type);
680 : 1817 : return (TREE_CODE (type) == ENUMERAL_TYPE
681 : 1724 : && TYPE_NAME (type)
682 : 3448 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
683 : 1724 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
684 : 1724 : == get_identifier ("omp_interop_t"))
685 : 1724 : && TYPE_FILE_SCOPE_P (type)
686 : 1724 : && COMPLETE_TYPE_P (type)
687 : 1724 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
688 : 3541 : && !compare_tree_int (TYPE_SIZE (type),
689 : 1724 : tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
690 : : }
691 : :
692 : : /* Return true if TYPE is the implementation's omp_depend_t. */
693 : :
694 : : bool
695 : 1212 : c_omp_depend_t_p (tree type)
696 : : {
697 : 1212 : type = TYPE_MAIN_VARIANT (type);
698 : 1212 : return (TREE_CODE (type) == RECORD_TYPE
699 : 429 : && TYPE_NAME (type)
700 : 858 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
701 : 429 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
702 : 429 : == get_identifier ("omp_depend_t"))
703 : 411 : && TYPE_FILE_SCOPE_P (type)
704 : 411 : && COMPLETE_TYPE_P (type)
705 : 411 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
706 : 1623 : && !compare_tree_int (TYPE_SIZE (type),
707 : 411 : 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
708 : : }
709 : :
710 : :
711 : : /* Complete a #pragma omp depobj construct. LOC is the location of the
712 : : #pragma. */
713 : :
714 : : void
715 : 355 : c_finish_omp_depobj (location_t loc, tree depobj,
716 : : enum omp_clause_depend_kind kind, tree clause)
717 : : {
718 : 355 : tree t = NULL_TREE;
719 : 355 : if (!error_operand_p (depobj))
720 : : {
721 : 344 : if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
722 : : {
723 : 42 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
724 : : "type of %<depobj%> expression is not %<omp_depend_t%>");
725 : 21 : depobj = error_mark_node;
726 : : }
727 : 323 : else if (TYPE_READONLY (TREE_TYPE (depobj)))
728 : : {
729 : 14 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
730 : : "%<const%> qualified %<depobj%> expression");
731 : 7 : depobj = error_mark_node;
732 : : }
733 : : }
734 : : else
735 : 11 : depobj = error_mark_node;
736 : :
737 : 355 : if (clause == error_mark_node)
738 : 355 : return;
739 : :
740 : 317 : if (clause)
741 : : {
742 : 169 : gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
743 : 169 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
744 : : {
745 : 42 : error_at (OMP_CLAUSE_LOCATION (clause),
746 : : "%<depend(%s)%> is only allowed in %<omp ordered%>",
747 : 14 : OMP_CLAUSE_DOACROSS_KIND (clause)
748 : : == OMP_CLAUSE_DOACROSS_SOURCE
749 : : ? "source" : "sink");
750 : 14 : return;
751 : : }
752 : 155 : gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
753 : 155 : if (OMP_CLAUSE_CHAIN (clause))
754 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
755 : : "more than one locator in %<depend%> clause on %<depobj%> "
756 : : "construct");
757 : 155 : switch (OMP_CLAUSE_DEPEND_KIND (clause))
758 : : {
759 : 7 : case OMP_CLAUSE_DEPEND_DEPOBJ:
760 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
761 : : "%<depobj%> dependence type specified in %<depend%> "
762 : : "clause on %<depobj%> construct");
763 : 7 : return;
764 : 148 : case OMP_CLAUSE_DEPEND_IN:
765 : 148 : case OMP_CLAUSE_DEPEND_OUT:
766 : 148 : case OMP_CLAUSE_DEPEND_INOUT:
767 : 148 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
768 : 148 : case OMP_CLAUSE_DEPEND_INOUTSET:
769 : 148 : kind = OMP_CLAUSE_DEPEND_KIND (clause);
770 : 148 : t = OMP_CLAUSE_DECL (clause);
771 : 148 : gcc_assert (t);
772 : 148 : if (TREE_CODE (t) == TREE_LIST
773 : 7 : && TREE_PURPOSE (t)
774 : 155 : && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
775 : : {
776 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
777 : : "%<iterator%> modifier may not be specified on "
778 : : "%<depobj%> construct");
779 : 7 : return;
780 : : }
781 : 141 : if (TREE_CODE (t) == COMPOUND_EXPR)
782 : : {
783 : 0 : tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
784 : 0 : t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
785 : : t1);
786 : : }
787 : 141 : else if (t != null_pointer_node)
788 : 133 : t = build_fold_addr_expr (t);
789 : : break;
790 : 0 : default:
791 : 0 : gcc_unreachable ();
792 : : }
793 : : }
794 : : else
795 : 148 : gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
796 : :
797 : 289 : if (depobj == error_mark_node)
798 : : return;
799 : :
800 : 483 : depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
801 : 250 : tree dtype
802 : 250 : = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
803 : : true);
804 : 250 : depobj = fold_convert (dtype, depobj);
805 : 250 : tree r;
806 : 250 : if (clause)
807 : : {
808 : 127 : depobj = save_expr (depobj);
809 : 127 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
810 : 127 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
811 : : }
812 : 250 : int k;
813 : 250 : switch (kind)
814 : : {
815 : : case OMP_CLAUSE_DEPEND_IN:
816 : : k = GOMP_DEPEND_IN;
817 : : break;
818 : 11 : case OMP_CLAUSE_DEPEND_OUT:
819 : 11 : k = GOMP_DEPEND_OUT;
820 : 11 : break;
821 : 45 : case OMP_CLAUSE_DEPEND_INOUT:
822 : 45 : k = GOMP_DEPEND_INOUT;
823 : 45 : break;
824 : 14 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
825 : 14 : k = GOMP_DEPEND_MUTEXINOUTSET;
826 : 14 : break;
827 : 12 : case OMP_CLAUSE_DEPEND_INOUTSET:
828 : 12 : k = GOMP_DEPEND_INOUTSET;
829 : 12 : break;
830 : 87 : case OMP_CLAUSE_DEPEND_LAST:
831 : 87 : k = -1;
832 : 87 : break;
833 : 0 : default:
834 : 0 : gcc_unreachable ();
835 : : }
836 : 250 : t = build_int_cst (ptr_type_node, k);
837 : 250 : depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
838 : 250 : TYPE_SIZE_UNIT (ptr_type_node));
839 : 250 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
840 : 250 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
841 : : }
842 : :
843 : :
844 : : /* Complete a #pragma omp flush construct. We don't do anything with
845 : : the variable list that the syntax allows. LOC is the location of
846 : : the #pragma. */
847 : :
848 : : void
849 : 61 : c_finish_omp_flush (location_t loc, int mo)
850 : : {
851 : 61 : tree x;
852 : :
853 : 61 : if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
854 : : {
855 : 43 : x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
856 : 43 : 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 : 61 : add_stmt (x);
865 : 61 : }
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 : 31934 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
940 : : {
941 : 61861 : if (POINTER_TYPE_P (TREE_TYPE (decl))
942 : 31934 : && 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 : 31934 : 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 : 31899 : 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 : 31899 : location_t elocus;
973 : 31899 : bool fail = false;
974 : 31899 : int i;
975 : :
976 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
977 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
978 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
979 : 73780 : for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
980 : : {
981 : 43259 : tree decl = TREE_VEC_ELT (declv, i);
982 : 43259 : tree init = TREE_VEC_ELT (initv, i);
983 : 43259 : tree cond = TREE_VEC_ELT (condv, i);
984 : 43259 : tree incr = TREE_VEC_ELT (incrv, i);
985 : :
986 : 43259 : 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 : 41881 : elocus = locus;
1000 : 41881 : if (EXPR_HAS_LOCATION (init))
1001 : 37205 : elocus = EXPR_LOCATION (init);
1002 : :
1003 : : /* Validate the iteration variable. */
1004 : 83762 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
1005 : 44751 : && 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 : 41880 : 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 : 41865 : if (init == decl)
1022 : : {
1023 : 4660 : elocus = DECL_SOURCE_LOCATION (decl);
1024 : :
1025 : 4660 : init = DECL_INITIAL (decl);
1026 : 4660 : 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 : 4660 : DECL_INITIAL (decl) = NULL_TREE;
1033 : :
1034 : 4660 : 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 : 41865 : if (init != error_mark_node)
1042 : : {
1043 : 41865 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1044 : 41865 : gcc_assert (TREE_OPERAND (init, 0) == decl);
1045 : : }
1046 : :
1047 : 41865 : if (cond == NULL_TREE)
1048 : : {
1049 : 2 : error_at (elocus, "missing controlling predicate");
1050 : 2 : fail = true;
1051 : : }
1052 : : else
1053 : : {
1054 : 41863 : 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 : 41863 : while (TREE_CODE (cond) == COMPOUND_EXPR)
1060 : 0 : cond = TREE_OPERAND (cond, 1);
1061 : :
1062 : 41863 : if (EXPR_HAS_LOCATION (cond))
1063 : 41735 : elocus = EXPR_LOCATION (cond);
1064 : :
1065 : 41863 : if (TREE_CODE (cond) == LT_EXPR
1066 : : || TREE_CODE (cond) == LE_EXPR
1067 : : || TREE_CODE (cond) == GT_EXPR
1068 : 41863 : || TREE_CODE (cond) == GE_EXPR
1069 : 5587 : || TREE_CODE (cond) == NE_EXPR
1070 : 31 : || TREE_CODE (cond) == EQ_EXPR)
1071 : : {
1072 : 41832 : tree op0 = TREE_OPERAND (cond, 0);
1073 : 41832 : 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 : 41832 : if (TREE_CODE (op0) == NOP_EXPR
1088 : 41832 : && 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 : 41774 : else if (TREE_CODE (op1) == NOP_EXPR
1096 : 41774 : && 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 : 41832 : 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 : 41832 : if (TREE_CODE (cond) == NE_EXPR
1116 : 41832 : || 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 : 41832 : 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 : 41832 : if (!cond_ok)
1154 : : {
1155 : 32 : error_at (elocus, "invalid controlling predicate");
1156 : 32 : fail = true;
1157 : : }
1158 : : }
1159 : :
1160 : 41865 : if (incr == NULL_TREE)
1161 : : {
1162 : 0 : error_at (elocus, "missing increment expression");
1163 : 0 : fail = true;
1164 : : }
1165 : : else
1166 : : {
1167 : 41865 : bool incr_ok = false;
1168 : :
1169 : 41865 : if (EXPR_HAS_LOCATION (incr))
1170 : 40972 : 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 : 41865 : switch (TREE_CODE (incr))
1175 : : {
1176 : 31940 : case POSTINCREMENT_EXPR:
1177 : 31940 : case PREINCREMENT_EXPR:
1178 : 31940 : case POSTDECREMENT_EXPR:
1179 : 31940 : case PREDECREMENT_EXPR:
1180 : 31940 : if (TREE_OPERAND (incr, 0) != decl)
1181 : : break;
1182 : :
1183 : 31934 : incr_ok = true;
1184 : 31934 : if (!fail
1185 : 31909 : && 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 : 32753 : && (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 : 31934 : incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
1200 : 31934 : 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 : 9909 : case MODIFY_EXPR:
1210 : 9909 : if (TREE_OPERAND (incr, 0) != decl)
1211 : : break;
1212 : 9909 : if (TREE_OPERAND (incr, 1) == decl)
1213 : : break;
1214 : 9909 : if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
1215 : 9909 : && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
1216 : 286 : || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
1217 : : incr_ok = true;
1218 : 2065 : else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
1219 : 1041 : || (TREE_CODE (TREE_OPERAND (incr, 1))
1220 : : == POINTER_PLUS_EXPR))
1221 : 2926 : && 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 : 9909 : if (!fail
1236 : 9909 : && incr_ok
1237 : 9891 : && 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 : 41843 : if (!incr_ok)
1293 : : {
1294 : 34 : error_at (elocus, "invalid increment expression");
1295 : 34 : fail = true;
1296 : : }
1297 : : }
1298 : :
1299 : 41865 : TREE_VEC_ELT (initv, i) = init;
1300 : 41865 : TREE_VEC_ELT (incrv, i) = incr;
1301 : : }
1302 : :
1303 : 31899 : if (fail)
1304 : : return NULL;
1305 : : else
1306 : : {
1307 : 31614 : tree t = make_node (code);
1308 : :
1309 : 31614 : TREE_TYPE (t) = void_type_node;
1310 : 31614 : OMP_FOR_INIT (t) = initv;
1311 : 31614 : OMP_FOR_COND (t) = condv;
1312 : 31614 : OMP_FOR_INCR (t) = incrv;
1313 : 31614 : OMP_FOR_BODY (t) = body;
1314 : 31614 : OMP_FOR_PRE_BODY (t) = pre_body;
1315 : 31614 : OMP_FOR_ORIG_DECLS (t) = orig_declv;
1316 : :
1317 : 31614 : SET_EXPR_LOCATION (t, locus);
1318 : 31614 : 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 : 41980 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1344 : : {
1345 : 133052 : for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1346 : 105567 : if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
1347 : 253 : continue;
1348 : 105314 : else if (decl == TREE_VEC_ELT (d->declv, i)
1349 : 105314 : || (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 : 90900 : else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1353 : 2223 : && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1354 : 91939 : && (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 : 169776 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1369 : : {
1370 : 169776 : struct c_omp_check_loop_iv_data *d
1371 : : = (struct c_omp_check_loop_iv_data *) data;
1372 : 169776 : if (DECL_P (*tp))
1373 : : {
1374 : 28522 : int idx = c_omp_is_loop_iterator (*tp, d);
1375 : 28522 : 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 : 175 : 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 : 141254 : 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 : 17112 : *walk_subtrees = 0;
1417 : 17112 : d->kind &= 3;
1418 : 17112 : walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
1419 : 17112 : d->kind |= 4;
1420 : 17112 : return NULL_TREE;
1421 : : }
1422 : 124142 : else if (d->ppset->add (*tp))
1423 : 17846 : *walk_subtrees = 0;
1424 : : /* Don't walk dtors added by C++ wrap_cleanups_r. */
1425 : 106296 : else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1426 : 106296 : && 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 : 10060 : c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *)
1632 : : {
1633 : 10060 : *walk_subtrees = 0;
1634 : 10060 : switch (TREE_CODE (*tp))
1635 : : {
1636 : : case OMP_TILE:
1637 : : case OMP_UNROLL:
1638 : : return *tp;
1639 : 2817 : case BIND_EXPR:
1640 : 2817 : *walk_subtrees = 1;
1641 : 2817 : break;
1642 : 41 : case STATEMENT_LIST:
1643 : 41 : *walk_subtrees = 1;
1644 : 41 : break;
1645 : 46 : case TRY_FINALLY_EXPR:
1646 : 46 : case CLEANUP_POINT_EXPR:
1647 : 46 : *walk_subtrees = 1;
1648 : 46 : break;
1649 : : default:
1650 : : break;
1651 : : }
1652 : : return NULL;
1653 : : }
1654 : :
1655 : : /* Find Jth loop among generated loops of STMT. */
1656 : :
1657 : : int
1658 : 1659 : c_omp_find_generated_loop (tree &stmt, int j, walk_tree_lh lh)
1659 : : {
1660 : 2498 : stmt = walk_tree_1 (&stmt, c_find_nested_loop_xform_r,
1661 : : NULL, NULL, lh);
1662 : 2498 : gcc_assert (stmt);
1663 : 2498 : switch (TREE_CODE (stmt))
1664 : : {
1665 : 726 : case OMP_UNROLL:
1666 : 726 : gcc_assert (omp_find_clause (OMP_FOR_CLAUSES (stmt),
1667 : : OMP_CLAUSE_PARTIAL));
1668 : : /* FALLTHRU */
1669 : : case OMP_TILE:
1670 : : int k;
1671 : : k = 0;
1672 : 2859 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); ++i)
1673 : 2859 : if (i == j)
1674 : : {
1675 : 2498 : if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1676 : : {
1677 : 839 : stmt = OMP_FOR_BODY (stmt);
1678 : 839 : return c_omp_find_generated_loop (stmt, k, lh);
1679 : : }
1680 : : else
1681 : 1659 : return i;
1682 : : }
1683 : 361 : else if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1684 : 56 : ++k;
1685 : 0 : gcc_unreachable ();
1686 : 0 : default:
1687 : 0 : gcc_unreachable ();
1688 : : }
1689 : : }
1690 : :
1691 : : /* Diagnose invalid references to loop iterators in lb, b and incr
1692 : : expressions. */
1693 : :
1694 : : bool
1695 : 31614 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1696 : : {
1697 : 31614 : hash_set<tree> pset;
1698 : 31614 : struct c_omp_check_loop_iv_data data;
1699 : 31614 : int i, k = 0;
1700 : :
1701 : 31614 : data.declv = declv;
1702 : 31614 : data.fail = false;
1703 : 31614 : data.maybe_nonrect = false;
1704 : 31614 : data.stmt_loc = EXPR_LOCATION (stmt);
1705 : 31614 : data.lh = lh;
1706 : 31614 : data.ppset = &pset;
1707 : 74855 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1708 : : {
1709 : 43241 : tree this_stmt = stmt;
1710 : 43241 : int j = i;
1711 : 43241 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1712 : 43241 : 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 : 43241 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1722 : 43241 : tree decl = TREE_OPERAND (init, 0);
1723 : 43241 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
1724 : 43241 : gcc_assert (COMPARISON_CLASS_P (cond));
1725 : 43241 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
1726 : 43241 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
1727 : 43241 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1728 : 43241 : tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1729 : 43241 : int kind = 0;
1730 : 43241 : if (i > 0
1731 : 43241 : && (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 : 43241 : if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1742 : 43241 : kind = 4;
1743 : 43241 : data.kind = kind;
1744 : 43241 : data.idx = i;
1745 : 43241 : walk_tree_1 (&TREE_OPERAND (init, 1),
1746 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1747 : 43241 : 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 : 43241 : if (decl == TREE_VEC_ELT (data.declv, i)
1755 : 43241 : || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
1756 : 933 : && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
1757 : : {
1758 : 42308 : data.expr_loc = EXPR_LOCATION (cond);
1759 : 42308 : data.kind = kind | 1;
1760 : 42308 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1761 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1762 : 42308 : if (data.maybe_nonrect)
1763 : 387 : vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
1764 : : &data, lh);
1765 : : }
1766 : 43241 : 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 : 43233 : 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 : 43241 : if (vec_outer1 || vec_outer2)
1785 : 474 : OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1786 : 43241 : if (TREE_CODE (incr) == MODIFY_EXPR)
1787 : : {
1788 : 11740 : gcc_assert (TREE_OPERAND (incr, 0) == decl);
1789 : 11740 : incr = TREE_OPERAND (incr, 1);
1790 : 11740 : data.kind = 2;
1791 : 11740 : if (TREE_CODE (incr) == PLUS_EXPR
1792 : 11740 : && 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 : 11441 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
1801 : 11441 : walk_tree_1 (&TREE_OPERAND (incr, 1),
1802 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1803 : : }
1804 : : }
1805 : : }
1806 : 31614 : return !data.fail;
1807 : 31614 : }
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 : 3909 : find_binding_in_body (tree decl, tree body)
1864 : : {
1865 : 5367 : if (!body)
1866 : : return NULL_TREE;
1867 : :
1868 : 5367 : switch (TREE_CODE (body))
1869 : : {
1870 : 365 : case BIND_EXPR:
1871 : 502 : for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
1872 : 165 : if (b == decl)
1873 : : return body;
1874 : 337 : return find_binding_in_body (decl, BIND_EXPR_BODY (body));
1875 : :
1876 : 257 : case DECL_EXPR:
1877 : 257 : if (DECL_EXPR_DECL (body) == decl)
1878 : : return body;
1879 : : return NULL_TREE;
1880 : :
1881 : 1016 : case STATEMENT_LIST:
1882 : 4509 : for (tree_stmt_iterator si = tsi_start (body); !tsi_end_p (si);
1883 : 3493 : tsi_next (&si))
1884 : : {
1885 : 3521 : tree b = find_binding_in_body (decl, tsi_stmt (si));
1886 : 3521 : if (b)
1887 : 28 : return b;
1888 : : }
1889 : 988 : return NULL_TREE;
1890 : :
1891 : 1121 : case OMP_STRUCTURED_BLOCK:
1892 : 1121 : 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 : 808 : check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1906 : : void *data)
1907 : : {
1908 : 808 : tree body = *(tree *)data;
1909 : :
1910 : 808 : 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 : 622 : check_loop_binding_expr (tree expr, tree body, location_t loc,
1933 : : check_loop_binding_expr_ctx ctx)
1934 : : {
1935 : 622 : tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
1936 : :
1937 : 622 : if (bad)
1938 : : {
1939 : 49 : location_t eloc = EXPR_LOCATION (expr);
1940 : 49 : eloc = LOCATION_OR (eloc, loc);
1941 : 49 : switch (ctx)
1942 : : {
1943 : 14 : case CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR:
1944 : 14 : error_at (eloc, "variable %qD used as loop variable is bound "
1945 : : "in intervening code", bad);
1946 : 14 : break;
1947 : 21 : case CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT:
1948 : 21 : error_at (eloc, "variable %qD used in initializer is bound "
1949 : : "in intervening code", bad);
1950 : 21 : break;
1951 : 7 : case CHECK_LOOP_BINDING_EXPR_CTX_END_TEST:
1952 : 7 : error_at (eloc, "variable %qD used in end test is bound "
1953 : : "in intervening code", bad);
1954 : 7 : break;
1955 : 7 : case CHECK_LOOP_BINDING_EXPR_CTX_INCR:
1956 : 7 : error_at (eloc, "variable %qD used in increment expression is bound "
1957 : : "in intervening code", bad);
1958 : 7 : break;
1959 : : }
1960 : 49 : return false;
1961 : : }
1962 : : return true;
1963 : : }
1964 : :
1965 : : /* STMT is an OMP_FOR construct. Check all of the iteration variable,
1966 : : initializer, end condition, and increment for bindings inside the
1967 : : loop body. If ORIG_INITS is provided, check those elements too.
1968 : : Return true if OK, false otherwise. */
1969 : : bool
1970 : 173 : c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
1971 : : {
1972 : 173 : bool ok = true;
1973 : 173 : location_t loc = EXPR_LOCATION (stmt);
1974 : 173 : tree body = OMP_FOR_BODY (stmt);
1975 : 308 : int orig_init_length = orig_inits ? orig_inits->length () : 0;
1976 : :
1977 : 376 : for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1978 : : {
1979 : 203 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1980 : 203 : 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 : 187 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1987 : 187 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1988 : 187 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1989 : 187 : tree decl = TREE_OPERAND (init, 0);
1990 : 187 : tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
1991 : 187 : tree e;
1992 : 187 : location_t eloc;
1993 : :
1994 : 187 : e = TREE_OPERAND (init, 1);
1995 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
1996 : 187 : if (!check_loop_binding_expr (decl, body, eloc,
1997 : : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR))
1998 : 14 : ok = false;
1999 : 187 : if (!check_loop_binding_expr (e, body, eloc,
2000 : : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
2001 : 15 : ok = false;
2002 : 187 : if (orig_init
2003 : 187 : && !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 : 187 : if (cond)
2010 : : {
2011 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
2012 : 187 : if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
2013 : 185 : 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 : 187 : if (!check_loop_binding_expr (e, body, eloc,
2019 : : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST))
2020 : 187 : ok = false;
2021 : : }
2022 : :
2023 : 187 : if (incr)
2024 : : {
2025 : 185 : 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 : 185 : if (TREE_CODE (incr) == MODIFY_EXPR
2030 : 185 : && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body, eloc,
2031 : : CHECK_LOOP_BINDING_EXPR_CTX_INCR))
2032 : : ok = false;
2033 : : }
2034 : : }
2035 : :
2036 : 173 : 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 : 1832 : c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
2046 : : bool is_parallel)
2047 : : {
2048 : 1832 : tree next, loop_clauses, nc;
2049 : :
2050 : 1832 : loop_clauses = *not_loop_clauses = NULL_TREE;
2051 : 3616 : for (; clauses ; clauses = next)
2052 : : {
2053 : 1784 : next = OMP_CLAUSE_CHAIN (clauses);
2054 : :
2055 : 1784 : 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 : 496 : default:
2090 : 496 : OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
2091 : 496 : *not_loop_clauses = clauses;
2092 : 496 : break;
2093 : : }
2094 : : }
2095 : :
2096 : 1832 : 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 : 15815 : c_omp_split_clauses (location_t loc, enum tree_code code,
2145 : : omp_clause_mask mask, tree clauses, tree *cclauses)
2146 : : {
2147 : 15815 : tree next, c;
2148 : 15815 : enum c_omp_clause_split s;
2149 : 15815 : int i;
2150 : 15815 : bool has_dup_allocate = false;
2151 : :
2152 : 110705 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2153 : 94890 : cclauses[i] = NULL;
2154 : : /* Add implicit nowait clause on
2155 : : #pragma omp parallel {for,for simd,sections}. */
2156 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2157 : 10942 : switch (code)
2158 : : {
2159 : 10284 : case OMP_FOR:
2160 : 10284 : case OMP_SIMD:
2161 : 25917 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2162 : 10102 : cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2163 : 10102 : = 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 : 55626 : for (; clauses ; clauses = next)
2174 : : {
2175 : 39811 : next = OMP_CLAUSE_CHAIN (clauses);
2176 : :
2177 : 39811 : 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_MAP:
2182 : : case OMP_CLAUSE_IS_DEVICE_PTR:
2183 : : case OMP_CLAUSE_HAS_DEVICE_ADDR:
2184 : : case OMP_CLAUSE_DEFAULTMAP:
2185 : : case OMP_CLAUSE_DEPEND:
2186 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2187 : : break;
2188 : 4 : case OMP_CLAUSE_DOACROSS:
2189 : : /* This can happen with invalid depend(source) or
2190 : : depend(sink:vec) on target combined with other constructs. */
2191 : 4 : gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
2192 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2193 : : break;
2194 : : case OMP_CLAUSE_NUM_TEAMS:
2195 : 2454 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2196 : : break;
2197 : : case OMP_CLAUSE_DIST_SCHEDULE:
2198 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2199 : : break;
2200 : : case OMP_CLAUSE_COPYIN:
2201 : : case OMP_CLAUSE_NUM_THREADS:
2202 : : case OMP_CLAUSE_PROC_BIND:
2203 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2204 : : break;
2205 : : case OMP_CLAUSE_ORDERED:
2206 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2207 : : break;
2208 : 6075 : case OMP_CLAUSE_SCHEDULE:
2209 : 6075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2210 : 6075 : if (code != OMP_SIMD)
2211 : 3076 : OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
2212 : : break;
2213 : : case OMP_CLAUSE_SAFELEN:
2214 : : case OMP_CLAUSE_SIMDLEN:
2215 : : case OMP_CLAUSE_ALIGNED:
2216 : : case OMP_CLAUSE_NONTEMPORAL:
2217 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2218 : : break;
2219 : : case OMP_CLAUSE_GRAINSIZE:
2220 : : case OMP_CLAUSE_NUM_TASKS:
2221 : : case OMP_CLAUSE_FINAL:
2222 : : case OMP_CLAUSE_UNTIED:
2223 : : case OMP_CLAUSE_MERGEABLE:
2224 : : case OMP_CLAUSE_NOGROUP:
2225 : : case OMP_CLAUSE_PRIORITY:
2226 : 13074 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2227 : : break;
2228 : : case OMP_CLAUSE_BIND:
2229 : 13074 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2230 : : break;
2231 : : case OMP_CLAUSE_FILTER:
2232 : 6925 : s = C_OMP_CLAUSE_SPLIT_MASKED;
2233 : : break;
2234 : : /* Duplicate this to all of taskloop, distribute, for, simd and
2235 : : loop. */
2236 : 5055 : case OMP_CLAUSE_COLLAPSE:
2237 : 5055 : if (code == OMP_SIMD)
2238 : : {
2239 : 2574 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2240 : 2574 : | (OMP_CLAUSE_MASK_1
2241 : 2574 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2242 : 2574 : | (OMP_CLAUSE_MASK_1
2243 : 2574 : << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
2244 : : {
2245 : 2526 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2246 : : OMP_CLAUSE_COLLAPSE);
2247 : 2526 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2248 : 2526 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2249 : 2526 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2250 : 2526 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2251 : : }
2252 : : else
2253 : : {
2254 : : /* This must be #pragma omp target simd */
2255 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2256 : : break;
2257 : : }
2258 : : }
2259 : 5007 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2260 : : {
2261 : 3907 : if ((mask & (OMP_CLAUSE_MASK_1
2262 : 3907 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2263 : : {
2264 : 2621 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2265 : : OMP_CLAUSE_COLLAPSE);
2266 : 2621 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2267 : 2621 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2268 : 2621 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2269 : 2621 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2270 : 2621 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2271 : : }
2272 : : else
2273 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2274 : : }
2275 : 1100 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2276 : 13760 : != 0)
2277 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2278 : 686 : else if (code == OMP_LOOP)
2279 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2280 : : else
2281 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2282 : : break;
2283 : : /* Private clause is supported on all constructs but master/masked,
2284 : : it is enough to put it on the innermost one other than
2285 : : master/masked. For #pragma omp {for,sections} put it on parallel
2286 : : though, as that's what we did for OpenMP 3.1. */
2287 : 1293 : case OMP_CLAUSE_PRIVATE:
2288 : 1293 : switch (code)
2289 : : {
2290 : : case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2291 : : case OMP_FOR: case OMP_SECTIONS:
2292 : 7732 : case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2293 : 6925 : case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2294 : 2454 : case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2295 : 7732 : case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2296 : 7732 : case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2297 : 13074 : case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2298 : 13074 : case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
2299 : 0 : default: gcc_unreachable ();
2300 : : }
2301 : : break;
2302 : : /* Firstprivate clause is supported on all constructs but
2303 : : simd, master, masked and loop. Put it on the outermost of those
2304 : : and duplicate on teams and parallel. */
2305 : 1741 : case OMP_CLAUSE_FIRSTPRIVATE:
2306 : 1741 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2307 : 2101 : != 0)
2308 : : {
2309 : 388 : if (code == OMP_SIMD
2310 : 388 : && (mask & ((OMP_CLAUSE_MASK_1
2311 : 134 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2312 : 134 : | (OMP_CLAUSE_MASK_1
2313 : 134 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
2314 : : {
2315 : : /* This must be #pragma omp target simd. */
2316 : 28 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2317 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
2318 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
2319 : 28 : break;
2320 : : }
2321 : 360 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2322 : : OMP_CLAUSE_FIRSTPRIVATE);
2323 : : /* firstprivate should not be applied to target if it is
2324 : : also lastprivate or on the combined/composite construct,
2325 : : or if it is mentioned in map clause. OMP_CLAUSE_DECLs
2326 : : may need to go through FE handling though (instantiation,
2327 : : C++ non-static data members, array section lowering), so
2328 : : add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
2329 : : let *finish_omp_clauses and the gimplifier handle it
2330 : : right. */
2331 : 360 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
2332 : 360 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2333 : 360 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2334 : 360 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2335 : : }
2336 : 1713 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2337 : 1713 : != 0)
2338 : : {
2339 : 1105 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2340 : 1105 : | (OMP_CLAUSE_MASK_1
2341 : 1105 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2342 : : {
2343 : 465 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2344 : : OMP_CLAUSE_FIRSTPRIVATE);
2345 : 465 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2346 : 465 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2347 : 465 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2348 : 465 : if ((mask & (OMP_CLAUSE_MASK_1
2349 : 465 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2350 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2351 : : else
2352 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2353 : : }
2354 : 640 : else if ((mask & (OMP_CLAUSE_MASK_1
2355 : 640 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2356 : : /* This must be
2357 : : #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
2358 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2359 : : else
2360 : : /* This must be
2361 : : #pragma omp parallel{, for{, simd}, sections,loop}
2362 : : or
2363 : : #pragma omp target parallel. */
2364 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2365 : : }
2366 : 608 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2367 : 608 : != 0)
2368 : : {
2369 : : /* This must be one of
2370 : : #pragma omp {,target }teams {distribute,loop}
2371 : : #pragma omp target teams
2372 : : #pragma omp {,target }teams distribute simd. */
2373 : 276 : gcc_assert (code == OMP_DISTRIBUTE
2374 : : || code == OMP_LOOP
2375 : : || code == OMP_TEAMS
2376 : : || code == OMP_SIMD);
2377 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2378 : : }
2379 : 332 : else if ((mask & (OMP_CLAUSE_MASK_1
2380 : 332 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2381 : : {
2382 : : /* This must be #pragma omp distribute simd. */
2383 : 76 : gcc_assert (code == OMP_SIMD);
2384 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2385 : : }
2386 : 256 : else if ((mask & (OMP_CLAUSE_MASK_1
2387 : 256 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2388 : : {
2389 : : /* This must be
2390 : : #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
2391 : : or
2392 : : #pragma omp {,parallel }mas{ked,ter} taskloop. */
2393 : 228 : gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
2394 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2395 : : }
2396 : : else
2397 : : {
2398 : : /* This must be #pragma omp for simd. */
2399 : 28 : gcc_assert (code == OMP_SIMD);
2400 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2401 : : }
2402 : : break;
2403 : : /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
2404 : : and simd. In parallel {for{, simd},sections} we actually want to
2405 : : put it on parallel rather than for or sections. */
2406 : 1955 : case OMP_CLAUSE_LASTPRIVATE:
2407 : 1955 : if (code == OMP_DISTRIBUTE)
2408 : : {
2409 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2410 : : break;
2411 : : }
2412 : 1947 : if ((mask & (OMP_CLAUSE_MASK_1
2413 : 1947 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2414 : : {
2415 : 548 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2416 : : OMP_CLAUSE_LASTPRIVATE);
2417 : 548 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2418 : 548 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2419 : 1096 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2420 : 548 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2421 : 548 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2422 : : }
2423 : 1947 : if (code == OMP_FOR || code == OMP_SECTIONS)
2424 : : {
2425 : 823 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2426 : 20806 : != 0)
2427 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2428 : : else
2429 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2430 : : break;
2431 : : }
2432 : : if (code == OMP_TASKLOOP)
2433 : : {
2434 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2435 : : break;
2436 : : }
2437 : : if (code == OMP_LOOP)
2438 : : {
2439 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2440 : : break;
2441 : : }
2442 : 0 : gcc_assert (code == OMP_SIMD);
2443 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2444 : : {
2445 : 423 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2446 : : OMP_CLAUSE_LASTPRIVATE);
2447 : 423 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2448 : 846 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2449 : 423 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2450 : 423 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2451 : 498 : != 0)
2452 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2453 : : else
2454 : 75 : s = C_OMP_CLAUSE_SPLIT_FOR;
2455 : 423 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2456 : 423 : cclauses[s] = c;
2457 : : }
2458 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2459 : : {
2460 : 253 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2461 : : OMP_CLAUSE_LASTPRIVATE);
2462 : 253 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2463 : 506 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2464 : 253 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2465 : 253 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2466 : 253 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2467 : : }
2468 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2469 : : break;
2470 : : /* Shared and default clauses are allowed on parallel, teams and
2471 : : taskloop. */
2472 : 3559 : case OMP_CLAUSE_SHARED:
2473 : 3559 : case OMP_CLAUSE_DEFAULT:
2474 : 3559 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2475 : 3559 : != 0)
2476 : : {
2477 : 890 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2478 : 13430 : != 0)
2479 : : {
2480 : 712 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2481 : 356 : OMP_CLAUSE_CODE (clauses));
2482 : 356 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2483 : 128 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2484 : : else
2485 : 456 : OMP_CLAUSE_DEFAULT_KIND (c)
2486 : 228 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2487 : 356 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2488 : 356 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2489 : : }
2490 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2491 : : break;
2492 : : }
2493 : 2669 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2494 : 9027 : != 0)
2495 : : {
2496 : 1295 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2497 : 3062 : == 0)
2498 : : {
2499 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2500 : : break;
2501 : : }
2502 : 1216 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2503 : 608 : OMP_CLAUSE_CODE (clauses));
2504 : 608 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2505 : 284 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2506 : : else
2507 : 648 : OMP_CLAUSE_DEFAULT_KIND (c)
2508 : 324 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2509 : 608 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2510 : 608 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2511 : : }
2512 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2513 : : break;
2514 : : /* order clauses are allowed on distribute, for, simd and loop. */
2515 : 880 : case OMP_CLAUSE_ORDER:
2516 : 880 : if ((mask & (OMP_CLAUSE_MASK_1
2517 : 880 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2518 : : {
2519 : 332 : if (code == OMP_DISTRIBUTE)
2520 : : {
2521 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2522 : : break;
2523 : : }
2524 : 288 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2525 : : OMP_CLAUSE_ORDER);
2526 : 576 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2527 : 288 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2528 : 576 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2529 : 288 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2530 : 288 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2531 : 288 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2532 : : }
2533 : 836 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2534 : : {
2535 : 465 : if (code == OMP_SIMD)
2536 : : {
2537 : 317 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2538 : : OMP_CLAUSE_ORDER);
2539 : 634 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2540 : 317 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2541 : 634 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2542 : 317 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2543 : 317 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2544 : 317 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2545 : 317 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2546 : : }
2547 : : else
2548 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2549 : : }
2550 : 371 : else if (code == OMP_LOOP)
2551 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2552 : : else
2553 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2554 : : break;
2555 : : /* Reduction is allowed on simd, for, parallel, sections, taskloop,
2556 : : teams and loop. Duplicate it on all of them, but omit on for or
2557 : : sections if parallel is present (unless inscan, in that case
2558 : : omit on parallel). If taskloop or loop is combined with
2559 : : parallel, omit it on parallel. */
2560 : 2905 : case OMP_CLAUSE_REDUCTION:
2561 : 2905 : if (OMP_CLAUSE_REDUCTION_TASK (clauses))
2562 : : {
2563 : 56 : if (code == OMP_SIMD || code == OMP_LOOP)
2564 : : {
2565 : 16 : error_at (OMP_CLAUSE_LOCATION (clauses),
2566 : : "invalid %<task%> reduction modifier on construct "
2567 : : "combined with %<simd%> or %<loop%>");
2568 : 16 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2569 : : }
2570 : 40 : else if (code != OMP_SECTIONS
2571 : 34 : && (mask & (OMP_CLAUSE_MASK_1
2572 : 34 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
2573 : 40 : && (mask & (OMP_CLAUSE_MASK_1
2574 : 4 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
2575 : : {
2576 : 4 : error_at (OMP_CLAUSE_LOCATION (clauses),
2577 : : "invalid %<task%> reduction modifier on construct "
2578 : : "not combined with %<parallel%>, %<for%> or "
2579 : : "%<sections%>");
2580 : 4 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2581 : : }
2582 : : }
2583 : 2905 : if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2584 : 2905 : && ((mask & ((OMP_CLAUSE_MASK_1
2585 : 196 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2586 : 196 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2587 : 2917 : != 0))
2588 : : {
2589 : 12 : error_at (OMP_CLAUSE_LOCATION (clauses),
2590 : : "%<inscan%> %<reduction%> clause on construct other "
2591 : : "than %<for%>, %<simd%>, %<for simd%>, "
2592 : : "%<parallel for%>, %<parallel for simd%>");
2593 : 12 : OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
2594 : : }
2595 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2596 : : {
2597 : 572 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2598 : : OMP_CLAUSE_MAP);
2599 : 572 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2600 : 572 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
2601 : 572 : OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
2602 : 572 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2603 : 572 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2604 : : }
2605 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2606 : : {
2607 : 1748 : if (code == OMP_SIMD)
2608 : : {
2609 : 561 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2610 : : OMP_CLAUSE_REDUCTION);
2611 : 561 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2612 : 1122 : OMP_CLAUSE_REDUCTION_CODE (c)
2613 : 561 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2614 : 561 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2615 : 561 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2616 : 561 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2617 : 561 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2618 : 1122 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2619 : 561 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2620 : 561 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2621 : 561 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2622 : : }
2623 : 1748 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2624 : 1748 : != 0)
2625 : : {
2626 : 464 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2627 : : OMP_CLAUSE_REDUCTION);
2628 : 464 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2629 : 928 : OMP_CLAUSE_REDUCTION_CODE (c)
2630 : 464 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2631 : 464 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2632 : 464 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2633 : 464 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2634 : 464 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2635 : 928 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2636 : 464 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2637 : 464 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2638 : 464 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2639 : 464 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2640 : : }
2641 : 1284 : else if ((mask & (OMP_CLAUSE_MASK_1
2642 : 1284 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2643 : 1195 : && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2644 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2645 : : else
2646 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2647 : : }
2648 : 1157 : else if (code == OMP_SECTIONS
2649 : 1157 : || code == OMP_PARALLEL
2650 : : || code == OMP_MASTER
2651 : : || code == OMP_MASKED)
2652 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2653 : : else if (code == OMP_TASKLOOP)
2654 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2655 : : else if (code == OMP_LOOP)
2656 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2657 : : else if (code == OMP_SIMD)
2658 : : {
2659 : 437 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2660 : 437 : != 0)
2661 : : {
2662 : 247 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2663 : : OMP_CLAUSE_REDUCTION);
2664 : 247 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2665 : 494 : OMP_CLAUSE_REDUCTION_CODE (c)
2666 : 247 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2667 : 247 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2668 : 247 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2669 : 247 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2670 : 247 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2671 : 494 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2672 : 247 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2673 : 247 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2674 : 247 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2675 : : }
2676 : 190 : else if ((mask & (OMP_CLAUSE_MASK_1
2677 : 190 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2678 : : {
2679 : 90 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2680 : : OMP_CLAUSE_REDUCTION);
2681 : 90 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2682 : 180 : OMP_CLAUSE_REDUCTION_CODE (c)
2683 : 90 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2684 : 90 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2685 : 90 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2686 : 90 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2687 : 90 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2688 : 180 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2689 : 90 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2690 : 90 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2691 : 90 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2692 : : }
2693 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2694 : : }
2695 : : else
2696 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2697 : : break;
2698 : 396 : case OMP_CLAUSE_IN_REDUCTION:
2699 : 396 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2700 : : {
2701 : : /* When on target, map(always, tofrom: item) is added as
2702 : : well. For non-combined target it is added in the FEs. */
2703 : 228 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2704 : : OMP_CLAUSE_MAP);
2705 : 228 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2706 : 228 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
2707 : 228 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2708 : 228 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2709 : 228 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2710 : 228 : break;
2711 : : }
2712 : : /* in_reduction on taskloop simd becomes reduction on the simd
2713 : : and keeps being in_reduction on taskloop. */
2714 : 168 : if (code == OMP_SIMD)
2715 : : {
2716 : 108 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2717 : : OMP_CLAUSE_REDUCTION);
2718 : 108 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2719 : 216 : OMP_CLAUSE_REDUCTION_CODE (c)
2720 : 108 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2721 : 108 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2722 : 108 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2723 : 108 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2724 : 108 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2725 : 108 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2726 : 108 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2727 : : }
2728 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2729 : : break;
2730 : 1613 : case OMP_CLAUSE_IF:
2731 : 1613 : if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
2732 : : {
2733 : 1188 : s = C_OMP_CLAUSE_SPLIT_COUNT;
2734 : 1188 : switch (OMP_CLAUSE_IF_MODIFIER (clauses))
2735 : : {
2736 : 510 : case OMP_PARALLEL:
2737 : 510 : if ((mask & (OMP_CLAUSE_MASK_1
2738 : 510 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2739 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2740 : : break;
2741 : 280 : case OMP_SIMD:
2742 : 280 : if (code == OMP_SIMD)
2743 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2744 : : break;
2745 : 168 : case OMP_TASKLOOP:
2746 : 168 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2747 : 13082 : != 0)
2748 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2749 : : break;
2750 : 222 : case OMP_TARGET:
2751 : 222 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2752 : 3144 : != 0)
2753 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2754 : : break;
2755 : : default:
2756 : : break;
2757 : : }
2758 : : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2759 : : break;
2760 : : /* Error-recovery here, invalid if-modifier specified, add the
2761 : : clause to just one construct. */
2762 : 8 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2763 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2764 : 4 : else if ((mask & (OMP_CLAUSE_MASK_1
2765 : 4 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2766 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2767 : 0 : else if ((mask & (OMP_CLAUSE_MASK_1
2768 : 0 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2769 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2770 : 0 : else if (code == OMP_SIMD)
2771 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2772 : : else
2773 : 0 : gcc_unreachable ();
2774 : : break;
2775 : : }
2776 : : /* Otherwise, duplicate if clause to all constructs. */
2777 : 425 : if (code == OMP_SIMD)
2778 : : {
2779 : 266 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
2780 : 266 : | (OMP_CLAUSE_MASK_1
2781 : 266 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2782 : 266 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
2783 : 5337 : != 0)
2784 : : {
2785 : 176 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2786 : : OMP_CLAUSE_IF);
2787 : 352 : OMP_CLAUSE_IF_MODIFIER (c)
2788 : 176 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2789 : 176 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2790 : 176 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2791 : 176 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2792 : : }
2793 : : else
2794 : : {
2795 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2796 : : break;
2797 : : }
2798 : : }
2799 : 335 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2800 : 335 : != 0)
2801 : : {
2802 : 144 : if ((mask & (OMP_CLAUSE_MASK_1
2803 : 144 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2804 : : {
2805 : 64 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2806 : : OMP_CLAUSE_IF);
2807 : 128 : OMP_CLAUSE_IF_MODIFIER (c)
2808 : 64 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2809 : 64 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2810 : 64 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2811 : 64 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2812 : 64 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2813 : : }
2814 : : else
2815 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2816 : : }
2817 : 191 : else if ((mask & (OMP_CLAUSE_MASK_1
2818 : 191 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2819 : : {
2820 : 119 : if ((mask & (OMP_CLAUSE_MASK_1
2821 : 7752 : << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2822 : : {
2823 : 20 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2824 : : OMP_CLAUSE_IF);
2825 : 40 : OMP_CLAUSE_IF_MODIFIER (c)
2826 : 20 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2827 : 20 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2828 : 20 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2829 : 20 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2830 : 20 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2831 : : }
2832 : : else
2833 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2834 : : }
2835 : : else
2836 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2837 : : break;
2838 : 800 : case OMP_CLAUSE_LINEAR:
2839 : : /* Linear clause is allowed on simd and for. Put it on the
2840 : : innermost construct. */
2841 : 800 : if (code == OMP_SIMD)
2842 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2843 : : else
2844 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2845 : : break;
2846 : 247 : case OMP_CLAUSE_NOWAIT:
2847 : : /* Nowait clause is allowed on target, for and sections, but
2848 : : is not allowed on parallel for or parallel sections. Therefore,
2849 : : put it on target construct if present, because that can only
2850 : : be combined with parallel for{, simd} and not with for{, simd},
2851 : : otherwise to the worksharing construct. */
2852 : 247 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2853 : 16210 : != 0)
2854 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2855 : : else
2856 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2857 : : break;
2858 : : /* thread_limit is allowed on target and teams. Distribute it
2859 : : to all. */
2860 : 443 : case OMP_CLAUSE_THREAD_LIMIT:
2861 : 443 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2862 : 2454 : != 0)
2863 : : {
2864 : 231 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2865 : 3136 : != 0)
2866 : : {
2867 : 229 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2868 : : OMP_CLAUSE_THREAD_LIMIT);
2869 : 229 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
2870 : 229 : = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
2871 : 229 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2872 : 229 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2873 : : }
2874 : : else
2875 : : {
2876 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2877 : : break;
2878 : : }
2879 : : }
2880 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2881 : : break;
2882 : : /* Allocate clause is allowed on target, teams, distribute, parallel,
2883 : : for, sections and taskloop. Distribute it to all. */
2884 : : case OMP_CLAUSE_ALLOCATE:
2885 : : s = C_OMP_CLAUSE_SPLIT_COUNT;
2886 : 8071 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2887 : : {
2888 : 6918 : switch (i)
2889 : : {
2890 : 1153 : case C_OMP_CLAUSE_SPLIT_TARGET:
2891 : 2046 : if ((mask & (OMP_CLAUSE_MASK_1
2892 : 1153 : << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2893 : 893 : continue;
2894 : : break;
2895 : 1153 : case C_OMP_CLAUSE_SPLIT_TEAMS:
2896 : 1872 : if ((mask & (OMP_CLAUSE_MASK_1
2897 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2898 : 719 : continue;
2899 : : break;
2900 : 1153 : case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2901 : 1824 : if ((mask & (OMP_CLAUSE_MASK_1
2902 : 1153 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2903 : 671 : continue;
2904 : : break;
2905 : 1153 : case C_OMP_CLAUSE_SPLIT_PARALLEL:
2906 : 1525 : if ((mask & (OMP_CLAUSE_MASK_1
2907 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2908 : 372 : continue;
2909 : : break;
2910 : 1153 : case C_OMP_CLAUSE_SPLIT_FOR:
2911 : 1153 : STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
2912 : : == C_OMP_CLAUSE_SPLIT_FOR
2913 : : && (C_OMP_CLAUSE_SPLIT_TASKLOOP
2914 : : == C_OMP_CLAUSE_SPLIT_FOR)
2915 : : && (C_OMP_CLAUSE_SPLIT_LOOP
2916 : : == C_OMP_CLAUSE_SPLIT_FOR));
2917 : 1153 : if (code == OMP_SECTIONS)
2918 : : break;
2919 : 1137 : if ((mask & (OMP_CLAUSE_MASK_1
2920 : 1137 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2921 : : break;
2922 : 602 : if ((mask & (OMP_CLAUSE_MASK_1
2923 : 602 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2924 : : break;
2925 : 322 : continue;
2926 : 1153 : case C_OMP_CLAUSE_SPLIT_SIMD:
2927 : 1153 : continue;
2928 : : default:
2929 : : gcc_unreachable ();
2930 : : }
2931 : 2788 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2932 : : {
2933 : 1635 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2934 : : OMP_CLAUSE_ALLOCATE);
2935 : 3270 : OMP_CLAUSE_DECL (c)
2936 : 1635 : = OMP_CLAUSE_DECL (clauses);
2937 : 1635 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2938 : 1635 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2939 : 1635 : OMP_CLAUSE_ALLOCATE_ALIGN (c)
2940 : 1635 : = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2941 : 1635 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2942 : 1635 : cclauses[s] = c;
2943 : 1635 : has_dup_allocate = true;
2944 : : }
2945 : 2788 : s = (enum c_omp_clause_split) i;
2946 : : }
2947 : 1153 : gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2948 : : break;
2949 : 0 : default:
2950 : 0 : gcc_unreachable ();
2951 : : }
2952 : 39811 : OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2953 : 39811 : cclauses[s] = clauses;
2954 : : }
2955 : :
2956 : 15815 : if (has_dup_allocate)
2957 : : {
2958 : 783 : bool need_prune = false;
2959 : 783 : bitmap_obstack_initialize (NULL);
2960 : 8948 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2961 : 3851 : if (cclauses[i])
2962 : : {
2963 : 2350 : bitmap_head allocate_head;
2964 : 2350 : bitmap_initialize (&allocate_head, &bitmap_default_obstack);
2965 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2966 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2967 : 15396 : && DECL_P (OMP_CLAUSE_DECL (c)))
2968 : 4956 : bitmap_set_bit (&allocate_head,
2969 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c)));
2970 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2971 : 15396 : switch (OMP_CLAUSE_CODE (c))
2972 : : {
2973 : 1159 : case OMP_CLAUSE_REDUCTION:
2974 : 1159 : case OMP_CLAUSE_IN_REDUCTION:
2975 : 1159 : case OMP_CLAUSE_TASK_REDUCTION:
2976 : 1159 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
2977 : : {
2978 : 0 : tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
2979 : 0 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
2980 : 0 : t = TREE_OPERAND (t, 0);
2981 : 0 : if (TREE_CODE (t) == ADDR_EXPR
2982 : 0 : || INDIRECT_REF_P (t))
2983 : 0 : t = TREE_OPERAND (t, 0);
2984 : 0 : if (DECL_P (t))
2985 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2986 : : break;
2987 : : }
2988 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
2989 : : {
2990 : : /* TODO: This can go away once we transition all uses of
2991 : : TREE_LIST for representing OMP array sections to
2992 : : OMP_ARRAY_SECTION. */
2993 : 0 : tree t;
2994 : 0 : for (t = OMP_CLAUSE_DECL (c);
2995 : 0 : TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
2996 : : ;
2997 : 0 : if (DECL_P (t))
2998 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2999 : : break;
3000 : : }
3001 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
3002 : : {
3003 : 152 : tree t;
3004 : 152 : for (t = OMP_CLAUSE_DECL (c);
3005 : 304 : TREE_CODE (t) == OMP_ARRAY_SECTION;
3006 : 152 : t = TREE_OPERAND (t, 0))
3007 : : ;
3008 : 152 : if (DECL_P (t))
3009 : 152 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3010 : : break;
3011 : : }
3012 : : /* FALLTHRU */
3013 : 3261 : case OMP_CLAUSE_PRIVATE:
3014 : 3261 : case OMP_CLAUSE_FIRSTPRIVATE:
3015 : 3261 : case OMP_CLAUSE_LASTPRIVATE:
3016 : 3261 : case OMP_CLAUSE_LINEAR:
3017 : 3261 : if (DECL_P (OMP_CLAUSE_DECL (c)))
3018 : 6522 : bitmap_clear_bit (&allocate_head,
3019 : 3261 : DECL_UID (OMP_CLAUSE_DECL (c)));
3020 : : break;
3021 : : default:
3022 : : break;
3023 : : }
3024 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
3025 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
3026 : 2478 : && DECL_P (OMP_CLAUSE_DECL (c))
3027 : 17874 : && bitmap_bit_p (&allocate_head,
3028 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c))))
3029 : : {
3030 : : /* Mark allocate clauses which don't have corresponding
3031 : : explicit data sharing clause. */
3032 : 1089 : OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
3033 : 1089 : need_prune = true;
3034 : : }
3035 : : }
3036 : 783 : bitmap_obstack_release (NULL);
3037 : 783 : if (need_prune)
3038 : : {
3039 : : /* At least one allocate clause has been marked. Walk all the
3040 : : duplicated allocate clauses in sync. If it is marked in all
3041 : : constituent constructs, diagnose it as invalid and remove
3042 : : them. Otherwise, remove all marked inner clauses inside
3043 : : a construct that doesn't have them marked. Keep the outer
3044 : : marked ones, because some clause duplication is done only
3045 : : during gimplification. */
3046 : : tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
3047 : 4809 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3048 : 4122 : if (cclauses[i] == NULL_TREE
3049 : 2418 : || i == C_OMP_CLAUSE_SPLIT_SIMD
3050 : 2158 : || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
3051 : 1964 : p[i] = NULL;
3052 : : else
3053 : 2158 : p[i] = &cclauses[i];
3054 : 1370 : do
3055 : : {
3056 : 1370 : int j = -1;
3057 : 1370 : tree seen = NULL_TREE;
3058 : 6443 : for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
3059 : 5760 : if (p[i])
3060 : : {
3061 : 13697 : while (*p[i]
3062 : 13697 : && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
3063 : 10724 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3064 : 2973 : if (*p[i] == NULL_TREE)
3065 : : {
3066 : : i = C_OMP_CLAUSE_SPLIT_COUNT;
3067 : : break;
3068 : : }
3069 : 2286 : if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
3070 : 5073 : j = i;
3071 : : seen = *p[i];
3072 : : }
3073 : 1370 : if (i == C_OMP_CLAUSE_SPLIT_COUNT)
3074 : : break;
3075 : 683 : if (j == -1)
3076 : 8 : error_at (OMP_CLAUSE_LOCATION (seen),
3077 : : "%qD specified in %<allocate%> clause but not in "
3078 : : "an explicit privatization clause",
3079 : 4 : OMP_CLAUSE_DECL (seen));
3080 : 4781 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3081 : 4098 : if (p[i])
3082 : : {
3083 : 2158 : if (i > j)
3084 : : /* Remove. */
3085 : 610 : *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
3086 : : else
3087 : : /* Keep. */
3088 : 1548 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3089 : : }
3090 : : }
3091 : : while (1);
3092 : : }
3093 : : }
3094 : :
3095 : 15815 : if (!flag_checking)
3096 : : return;
3097 : :
3098 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
3099 : 10651 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
3100 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
3101 : 8962 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
3102 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
3103 : 8513 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
3104 : 8267 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
3105 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
3106 : 4873 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
3107 : 15815 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
3108 : 15815 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
3109 : 4092 : && code != OMP_SECTIONS
3110 : 4092 : && code != OMP_LOOP)
3111 : 3632 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
3112 : 15815 : if (code != OMP_SIMD)
3113 : 9310 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
3114 : : }
3115 : :
3116 : :
3117 : : /* qsort callback to compare #pragma omp declare simd clauses. */
3118 : :
3119 : : static int
3120 : 12176 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
3121 : : {
3122 : 12176 : tree a = *(const tree *) p;
3123 : 12176 : tree b = *(const tree *) q;
3124 : 12176 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
3125 : : {
3126 : 10701 : if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
3127 : : return -1;
3128 : 4474 : return 1;
3129 : : }
3130 : 1475 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
3131 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
3132 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
3133 : : {
3134 : 1451 : int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
3135 : 1451 : int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
3136 : 1451 : if (c < d)
3137 : : return 1;
3138 : 670 : if (c > d)
3139 : 670 : return -1;
3140 : : }
3141 : : return 0;
3142 : : }
3143 : :
3144 : : /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
3145 : : CLAUSES on FNDECL into argument indexes and sort them. */
3146 : :
3147 : : tree
3148 : 1396 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
3149 : : {
3150 : 1396 : tree c;
3151 : 1396 : vec<tree> clvec = vNULL;
3152 : :
3153 : 4443 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3154 : : {
3155 : 3047 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3156 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3157 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3158 : : {
3159 : 1692 : tree decl = OMP_CLAUSE_DECL (c);
3160 : 1692 : tree arg;
3161 : 1692 : int idx;
3162 : 3785 : for (arg = parms, idx = 0; arg;
3163 : 2093 : arg = TREE_CHAIN (arg), idx++)
3164 : 3785 : if (arg == decl)
3165 : : break;
3166 : 1692 : if (arg == NULL_TREE)
3167 : : {
3168 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3169 : : "%qD is not a function argument", decl);
3170 : 3047 : continue;
3171 : : }
3172 : 1692 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3173 : 1692 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3174 : 1692 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3175 : : {
3176 : 43 : decl = OMP_CLAUSE_LINEAR_STEP (c);
3177 : 121 : for (arg = parms, idx = 0; arg;
3178 : 78 : arg = TREE_CHAIN (arg), idx++)
3179 : 121 : if (arg == decl)
3180 : : break;
3181 : 43 : if (arg == NULL_TREE)
3182 : : {
3183 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3184 : : "%qD is not a function argument", decl);
3185 : 0 : continue;
3186 : : }
3187 : 43 : OMP_CLAUSE_LINEAR_STEP (c)
3188 : 86 : = build_int_cst (integer_type_node, idx);
3189 : : }
3190 : : }
3191 : 3047 : clvec.safe_push (c);
3192 : : }
3193 : 1396 : if (!clvec.is_empty ())
3194 : : {
3195 : 1287 : unsigned int len = clvec.length (), i;
3196 : 1287 : clvec.qsort (c_omp_declare_simd_clause_cmp);
3197 : 1287 : clauses = clvec[0];
3198 : 4334 : for (i = 0; i < len; i++)
3199 : 3047 : OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3200 : : }
3201 : : else
3202 : : clauses = NULL_TREE;
3203 : 1396 : clvec.release ();
3204 : 1396 : return clauses;
3205 : : }
3206 : :
3207 : : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3208 : :
3209 : : void
3210 : 105 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3211 : : {
3212 : 105 : tree c;
3213 : :
3214 : 393 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3215 : 288 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3216 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3217 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3218 : : {
3219 : 189 : int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3220 : 189 : tree arg;
3221 : 369 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3222 : 180 : arg = TREE_CHAIN (arg), i++)
3223 : 369 : if (i == idx)
3224 : : break;
3225 : 0 : gcc_assert (arg);
3226 : 189 : OMP_CLAUSE_DECL (c) = arg;
3227 : 189 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3228 : 189 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3229 : : {
3230 : 0 : idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3231 : 0 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3232 : 0 : arg = TREE_CHAIN (arg), i++)
3233 : 0 : if (i == idx)
3234 : : break;
3235 : 0 : gcc_assert (arg);
3236 : 0 : OMP_CLAUSE_LINEAR_STEP (c) = arg;
3237 : : }
3238 : : }
3239 : 105 : }
3240 : :
3241 : : /* Return true for __func__ and similar function-local predefined
3242 : : variables (which are in OpenMP predetermined shared, allowed in
3243 : : shared/firstprivate clauses). */
3244 : :
3245 : : bool
3246 : 65435 : c_omp_predefined_variable (tree decl)
3247 : : {
3248 : 65435 : if (VAR_P (decl)
3249 : 34202 : && DECL_ARTIFICIAL (decl)
3250 : 306 : && TREE_STATIC (decl)
3251 : 65726 : && DECL_NAME (decl))
3252 : : {
3253 : 291 : if (TREE_READONLY (decl)
3254 : 291 : && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3255 : 223 : || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3256 : 179 : || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3257 : : return true;
3258 : : /* For UBSan handle the same also ubsan_create_data created
3259 : : variables. There is no magic flag for those, but user variables
3260 : : shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3261 : : such names. */
3262 : 139 : if ((flag_sanitize & (SANITIZE_UNDEFINED
3263 : : | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3264 : 36 : && DECL_IGNORED_P (decl)
3265 : 36 : && !TREE_READONLY (decl)
3266 : 30 : && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3267 : 30 : && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3268 : 30 : && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3269 : 30 : && TYPE_NAME (TREE_TYPE (decl))
3270 : 30 : && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3271 : 30 : && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3272 : 169 : && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3273 : : == IDENTIFIER_NODE))
3274 : : {
3275 : 30 : tree id1 = DECL_NAME (decl);
3276 : 30 : tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3277 : 30 : if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3278 : 30 : && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3279 : 30 : && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
3280 : : sizeof ("__ubsan_") - 1)
3281 : 30 : && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3282 : 30 : - sizeof ("_data") + 1, "_data",
3283 : : sizeof ("_data") - 1)
3284 : 60 : && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
3285 : 30 : return true;
3286 : : }
3287 : : }
3288 : : return false;
3289 : : }
3290 : :
3291 : : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3292 : : is predetermined. */
3293 : :
3294 : : enum omp_clause_default_kind
3295 : 27939 : c_omp_predetermined_sharing (tree decl)
3296 : : {
3297 : : /* Predetermine artificial variables holding integral values, those
3298 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3299 : : gimplification. */
3300 : 27939 : if (VAR_P (decl)
3301 : 17173 : && DECL_ARTIFICIAL (decl)
3302 : 28578 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3303 : : return OMP_CLAUSE_DEFAULT_SHARED;
3304 : :
3305 : 27391 : if (c_omp_predefined_variable (decl))
3306 : : return OMP_CLAUSE_DEFAULT_SHARED;
3307 : :
3308 : : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3309 : : }
3310 : :
3311 : : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3312 : : of DECL is predetermined. */
3313 : :
3314 : : enum omp_clause_defaultmap_kind
3315 : 5137 : c_omp_predetermined_mapping (tree decl)
3316 : : {
3317 : : /* Predetermine artificial variables holding integral values, those
3318 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3319 : : gimplification. */
3320 : 5137 : if (VAR_P (decl)
3321 : 947 : && DECL_ARTIFICIAL (decl)
3322 : 5169 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3323 : : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3324 : :
3325 : 5109 : if (c_omp_predefined_variable (decl))
3326 : 2 : return OMP_CLAUSE_DEFAULTMAP_TO;
3327 : :
3328 : : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3329 : : }
3330 : :
3331 : :
3332 : : /* Used to merge map clause information in c_omp_adjust_map_clauses. */
3333 : : struct map_clause
3334 : : {
3335 : : tree clause;
3336 : : bool firstprivate_ptr_p;
3337 : : bool decl_mapped;
3338 : : bool omp_declare_target;
3339 : 3256 : map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3340 : 3256 : decl_mapped (false), omp_declare_target (false) { }
3341 : : };
3342 : :
3343 : : /* Adjust map clauses after normal clause parsing, mainly to mark specific
3344 : : base-pointer map cases addressable that may be turned into attach/detach
3345 : : operations during gimplification. */
3346 : : void
3347 : 12073 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
3348 : : {
3349 : 12073 : if (!is_target)
3350 : : {
3351 : : /* If this is not a target construct, just turn firstprivate pointers
3352 : : into attach/detach, the runtime will check and do the rest. */
3353 : :
3354 : 4100 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3355 : 2768 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3356 : 2307 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3357 : 0 : && DECL_P (OMP_CLAUSE_DECL (c))
3358 : 2768 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3359 : : {
3360 : 0 : tree ptr = OMP_CLAUSE_DECL (c);
3361 : 0 : c_common_mark_addressable_vec (ptr);
3362 : : }
3363 : 1332 : return;
3364 : : }
3365 : :
3366 : 10741 : hash_map<tree, map_clause> maps;
3367 : :
3368 : 23241 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3369 : 12500 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3370 : 12500 : && DECL_P (OMP_CLAUSE_DECL (c)))
3371 : : {
3372 : : /* If this is for a target construct, the firstprivate pointer
3373 : : is marked addressable if either is true:
3374 : : (1) the base-pointer is mapped in this same construct, or
3375 : : (2) the base-pointer is a variable place on the device by
3376 : : "declare target" directives.
3377 : :
3378 : : Here we iterate through all map clauses collecting these cases,
3379 : : and merge them with a hash_map to process below. */
3380 : :
3381 : 3812 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3382 : 3812 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3383 : : {
3384 : 300 : tree ptr = OMP_CLAUSE_DECL (c);
3385 : 300 : map_clause &mc = maps.get_or_insert (ptr);
3386 : 300 : if (mc.clause == NULL_TREE)
3387 : 300 : mc.clause = c;
3388 : 300 : mc.firstprivate_ptr_p = true;
3389 : :
3390 : 300 : if (is_global_var (ptr)
3391 : 348 : && lookup_attribute ("omp declare target",
3392 : 48 : DECL_ATTRIBUTES (ptr)))
3393 : 0 : mc.omp_declare_target = true;
3394 : : }
3395 : 3512 : else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3396 : 3433 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3397 : 2999 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3398 : 2129 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3399 : 957 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3400 : 895 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3401 : 4406 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3402 : : {
3403 : 2979 : map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3404 : 2979 : mc.decl_mapped = true;
3405 : : }
3406 : : }
3407 : :
3408 : 13997 : for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3409 : 27994 : i != maps.end (); ++i)
3410 : : {
3411 : 3256 : map_clause &mc = (*i).second;
3412 : :
3413 : 3256 : if (mc.firstprivate_ptr_p
3414 : 300 : && (mc.decl_mapped || mc.omp_declare_target))
3415 : 23 : c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3416 : : }
3417 : 10741 : }
3418 : :
3419 : : /* Maybe strip off an indirection from a "converted" reference, then find the
3420 : : origin of a pointer (i.e. without any offset). */
3421 : :
3422 : : tree
3423 : 69848 : c_omp_address_inspector::unconverted_ref_origin ()
3424 : : {
3425 : 69848 : tree t = orig;
3426 : :
3427 : : /* We may have a reference-typed component access at the outermost level
3428 : : that has had convert_from_reference called on it. Get the un-dereferenced
3429 : : reference itself. */
3430 : 69848 : t = maybe_unconvert_ref (t);
3431 : :
3432 : : /* Find base pointer for POINTER_PLUS_EXPR, etc. */
3433 : 69848 : t = get_origin (t);
3434 : :
3435 : 69848 : return t;
3436 : : }
3437 : :
3438 : : /* Return TRUE if the address is a component access. */
3439 : :
3440 : : bool
3441 : 12422 : c_omp_address_inspector::component_access_p ()
3442 : : {
3443 : 12422 : tree t = maybe_unconvert_ref (orig);
3444 : :
3445 : 12422 : t = get_origin (t);
3446 : :
3447 : 12422 : return TREE_CODE (t) == COMPONENT_REF;
3448 : : }
3449 : :
3450 : : /* Perform various checks on the address, as described by clause CLAUSE (we
3451 : : only use its code and location here). */
3452 : :
3453 : : bool
3454 : 32653 : c_omp_address_inspector::check_clause (tree clause)
3455 : : {
3456 : 32653 : tree t = unconverted_ref_origin ();
3457 : :
3458 : 32653 : if (TREE_CODE (t) != COMPONENT_REF)
3459 : : return true;
3460 : :
3461 : 4541 : if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
3462 : 4541 : && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
3463 : : {
3464 : 24 : error_at (OMP_CLAUSE_LOCATION (clause),
3465 : : "bit-field %qE in %qs clause",
3466 : 24 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3467 : 24 : return false;
3468 : : }
3469 : 4517 : else if (!processing_template_decl_p ()
3470 : 4517 : && !omp_mappable_type (TREE_TYPE (t)))
3471 : : {
3472 : 0 : error_at (OMP_CLAUSE_LOCATION (clause),
3473 : : "%qE does not have a mappable type in %qs clause",
3474 : 0 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3475 : 0 : emit_unmappable_type_notes (TREE_TYPE (t));
3476 : 0 : return false;
3477 : : }
3478 : 4517 : else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
3479 : : {
3480 : 2 : error_at (OMP_CLAUSE_LOCATION (clause),
3481 : : "%<_Atomic%> %qE in %qs clause", t,
3482 : 2 : omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3483 : 2 : return false;
3484 : : }
3485 : :
3486 : : return true;
3487 : : }
3488 : :
3489 : : /* Find the "root term" for the address. This is the innermost decl, etc.
3490 : : of the access. */
3491 : :
3492 : : tree
3493 : 1690 : c_omp_address_inspector::get_root_term (bool checking)
3494 : : {
3495 : 1690 : if (root_term && !checking)
3496 : : return root_term;
3497 : :
3498 : 1690 : tree t = unconverted_ref_origin ();
3499 : :
3500 : 5734 : while (TREE_CODE (t) == COMPONENT_REF)
3501 : : {
3502 : 2354 : if (checking
3503 : 2354 : && TREE_TYPE (TREE_OPERAND (t, 0))
3504 : 4520 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
3505 : : {
3506 : 0 : error_at (loc, "%qE is a member of a union", t);
3507 : 0 : return error_mark_node;
3508 : : }
3509 : 2354 : t = TREE_OPERAND (t, 0);
3510 : 2354 : while (TREE_CODE (t) == MEM_REF
3511 : 3773 : || TREE_CODE (t) == INDIRECT_REF
3512 : 3773 : || TREE_CODE (t) == ARRAY_REF)
3513 : : {
3514 : 1419 : if (TREE_CODE (t) == MEM_REF
3515 : : || TREE_CODE (t) == INDIRECT_REF)
3516 : 1275 : indirections = true;
3517 : 1419 : t = TREE_OPERAND (t, 0);
3518 : 1419 : STRIP_NOPS (t);
3519 : 1419 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
3520 : 102 : t = TREE_OPERAND (t, 0);
3521 : : }
3522 : : }
3523 : :
3524 : 1690 : root_term = t;
3525 : :
3526 : 1690 : return t;
3527 : : }
3528 : :
3529 : : /* Return TRUE if the address is supported in mapping clauses. At present,
3530 : : this means that the innermost expression is a DECL_P, but could be extended
3531 : : to other types of expression in the future. */
3532 : :
3533 : : bool
3534 : 24773 : c_omp_address_inspector::map_supported_p ()
3535 : : {
3536 : : /* If we've already decided if the mapped address is supported, return
3537 : : that. */
3538 : 24773 : if (map_supported != -1)
3539 : 0 : return map_supported;
3540 : :
3541 : 24773 : tree t = unconverted_ref_origin ();
3542 : :
3543 : 24773 : STRIP_NOPS (t);
3544 : :
3545 : 24773 : while (TREE_CODE (t) == INDIRECT_REF
3546 : 40341 : || TREE_CODE (t) == MEM_REF
3547 : : || TREE_CODE (t) == ARRAY_REF
3548 : : || TREE_CODE (t) == COMPONENT_REF
3549 : : || TREE_CODE (t) == COMPOUND_EXPR
3550 : : || TREE_CODE (t) == SAVE_EXPR
3551 : : || TREE_CODE (t) == POINTER_PLUS_EXPR
3552 : : || TREE_CODE (t) == NON_LVALUE_EXPR
3553 : : || TREE_CODE (t) == OMP_ARRAY_SECTION
3554 : 40341 : || TREE_CODE (t) == NOP_EXPR)
3555 : 15568 : if (TREE_CODE (t) == COMPOUND_EXPR)
3556 : 27 : t = TREE_OPERAND (t, 1);
3557 : : else
3558 : 15541 : t = TREE_OPERAND (t, 0);
3559 : :
3560 : 24773 : STRIP_NOPS (t);
3561 : :
3562 : 24773 : map_supported = DECL_P (t);
3563 : :
3564 : 24773 : return map_supported;
3565 : : }
3566 : :
3567 : : /* Get the origin of an address T, stripping off offsets and some other
3568 : : bits. */
3569 : :
3570 : : tree
3571 : 82270 : c_omp_address_inspector::get_origin (tree t)
3572 : : {
3573 : 82538 : while (1)
3574 : : {
3575 : 82538 : if (TREE_CODE (t) == COMPOUND_EXPR)
3576 : : {
3577 : 10 : t = TREE_OPERAND (t, 1);
3578 : 10 : STRIP_NOPS (t);
3579 : : }
3580 : 82528 : else if (TREE_CODE (t) == POINTER_PLUS_EXPR
3581 : 82528 : || TREE_CODE (t) == SAVE_EXPR)
3582 : 231 : t = TREE_OPERAND (t, 0);
3583 : 82297 : else if (!processing_template_decl_p ()
3584 : 75348 : && TREE_CODE (t) == INDIRECT_REF
3585 : 84781 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3586 : 27 : t = TREE_OPERAND (t, 0);
3587 : : else
3588 : : break;
3589 : : }
3590 : 82270 : STRIP_NOPS (t);
3591 : 82270 : return t;
3592 : : }
3593 : :
3594 : : /* For an address T that might be a reference that has had
3595 : : "convert_from_reference" called on it, return the actual reference without
3596 : : any indirection. */
3597 : :
3598 : : tree
3599 : 91758 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
3600 : : {
3601 : : /* Be careful not to dereference the type if we're processing a
3602 : : template decl, else it might be NULL. */
3603 : 91758 : if (!processing_template_decl_p ()
3604 : 82747 : && TREE_CODE (t) == INDIRECT_REF
3605 : 94805 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3606 : 587 : return TREE_OPERAND (t, 0);
3607 : :
3608 : : return t;
3609 : : }
3610 : :
3611 : : /* Return TRUE if CLAUSE might describe a zero-length array section. */
3612 : :
3613 : : bool
3614 : 5369 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
3615 : : {
3616 : 5369 : switch (OMP_CLAUSE_MAP_KIND (clause))
3617 : : {
3618 : : case GOMP_MAP_ALLOC:
3619 : : case GOMP_MAP_IF_PRESENT:
3620 : : case GOMP_MAP_TO:
3621 : : case GOMP_MAP_FROM:
3622 : : case GOMP_MAP_TOFROM:
3623 : : case GOMP_MAP_ALWAYS_TO:
3624 : : case GOMP_MAP_ALWAYS_FROM:
3625 : : case GOMP_MAP_ALWAYS_TOFROM:
3626 : : case GOMP_MAP_PRESENT_ALLOC:
3627 : : case GOMP_MAP_PRESENT_TO:
3628 : : case GOMP_MAP_PRESENT_FROM:
3629 : : case GOMP_MAP_PRESENT_TOFROM:
3630 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
3631 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
3632 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
3633 : : case GOMP_MAP_RELEASE:
3634 : : case GOMP_MAP_DELETE:
3635 : : case GOMP_MAP_FORCE_TO:
3636 : : case GOMP_MAP_FORCE_FROM:
3637 : : case GOMP_MAP_FORCE_TOFROM:
3638 : : case GOMP_MAP_FORCE_PRESENT:
3639 : : return true;
3640 : 28 : default:
3641 : 28 : return false;
3642 : : }
3643 : : }
3644 : :
3645 : : /* Expand a chained access. We only expect to see a quite limited range of
3646 : : expression types here, because e.g. you can't have an array of
3647 : : references. */
3648 : :
3649 : : static tree
3650 : 49 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
3651 : : unsigned *idx, c_omp_region_type ort)
3652 : : {
3653 : 49 : using namespace omp_addr_tokenizer;
3654 : 49 : location_t loc = OMP_CLAUSE_LOCATION (c);
3655 : 49 : unsigned i = *idx;
3656 : 49 : tree c2 = NULL_TREE;
3657 : 49 : gomp_map_kind kind;
3658 : :
3659 : 49 : if ((ort & C_ORT_EXIT_DATA) != 0
3660 : 37 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
3661 : 86 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3662 : 37 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3663 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
3664 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
3665 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3666 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
3667 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
3668 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
3669 : : kind = GOMP_MAP_DETACH;
3670 : : else
3671 : : kind = GOMP_MAP_ATTACH;
3672 : :
3673 : 49 : switch (addr_tokens[i]->u.access_kind)
3674 : : {
3675 : 49 : case ACCESS_POINTER:
3676 : 49 : case ACCESS_POINTER_OFFSET:
3677 : 49 : {
3678 : 49 : tree virtual_origin
3679 : 49 : = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
3680 : 49 : tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
3681 : 49 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3682 : 49 : OMP_CLAUSE_SET_MAP_KIND (c2, kind);
3683 : 49 : OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
3684 : 49 : OMP_CLAUSE_SIZE (c2)
3685 : 49 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3686 : : fold_convert_loc (loc, ptrdiff_type_node,
3687 : : data_addr),
3688 : : virtual_origin);
3689 : : }
3690 : 49 : break;
3691 : :
3692 : : case ACCESS_INDEXED_ARRAY:
3693 : : break;
3694 : :
3695 : 0 : default:
3696 : 0 : return error_mark_node;
3697 : : }
3698 : :
3699 : 49 : if (c2)
3700 : : {
3701 : 49 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
3702 : 49 : OMP_CLAUSE_CHAIN (c) = c2;
3703 : 49 : c = c2;
3704 : : }
3705 : :
3706 : 49 : *idx = ++i;
3707 : :
3708 : 49 : if (i < addr_tokens.length ()
3709 : 49 : && addr_tokens[i]->type == ACCESS_METHOD)
3710 : : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
3711 : :
3712 : : return c;
3713 : : }
3714 : :
3715 : : /* Translate "array_base_decl access_method" to OMP mapping clauses. */
3716 : :
3717 : : tree
3718 : 17798 : c_omp_address_inspector::expand_array_base (tree c,
3719 : : vec<omp_addr_token *> &addr_tokens,
3720 : : tree expr, unsigned *idx,
3721 : : c_omp_region_type ort)
3722 : : {
3723 : 17798 : using namespace omp_addr_tokenizer;
3724 : 17798 : location_t loc = OMP_CLAUSE_LOCATION (c);
3725 : 17798 : int i = *idx;
3726 : 17798 : tree decl = addr_tokens[i + 1]->expr;
3727 : 17798 : bool decl_p = DECL_P (decl);
3728 : 17798 : bool declare_target_p = (decl_p
3729 : 17789 : && is_global_var (decl)
3730 : 25273 : && lookup_attribute ("omp declare target",
3731 : 7475 : DECL_ATTRIBUTES (decl)));
3732 : 17798 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
3733 : 17798 : bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
3734 : 17798 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
3735 : 17798 : tree c2 = NULL_TREE, c3 = NULL_TREE;
3736 : 17798 : unsigned consume_tokens = 2;
3737 : 17798 : bool target_p = (ort & C_ORT_TARGET) != 0;
3738 : 17798 : bool openmp_p = (ort & C_ORT_OMP) != 0;
3739 : :
3740 : 17798 : gcc_assert (i == 0);
3741 : :
3742 : 17798 : if (!openmp_p
3743 : 17798 : && map_p
3744 : 17798 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
3745 : 6753 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
3746 : : {
3747 : 28 : i += 2;
3748 : 28 : *idx = i;
3749 : 28 : return c;
3750 : : }
3751 : :
3752 : 17770 : switch (addr_tokens[i + 1]->u.access_kind)
3753 : : {
3754 : 13586 : case ACCESS_DIRECT:
3755 : 13586 : if (decl_p && !target_p)
3756 : 8559 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3757 : : break;
3758 : :
3759 : 150 : case ACCESS_REF:
3760 : 150 : {
3761 : : /* Copy the referenced object. Note that we do this even for !MAP_P
3762 : : clauses. */
3763 : 150 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
3764 : 150 : if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
3765 : : /* We have a ref to array: add a [0] element as the ME expects. */
3766 : 43 : OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
3767 : : else
3768 : 107 : OMP_CLAUSE_DECL (c) = obj;
3769 : 150 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
3770 : :
3771 : 150 : if (!map_p)
3772 : : {
3773 : 6 : if (decl_p)
3774 : 6 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3775 : : break;
3776 : : }
3777 : :
3778 : 144 : if (!target_p)
3779 : : break;
3780 : :
3781 : : /* If we have a reference to a pointer, avoid using
3782 : : FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
3783 : : offload region (we can only do that if the pointer does not point
3784 : : to a mapped block). We could avoid doing this if we don't have a
3785 : : FROM mapping... */
3786 : 84 : bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
3787 : :
3788 : 84 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3789 : 84 : if (!ref_to_ptr
3790 : 84 : && !declare_target_p
3791 : 50 : && decl_p)
3792 : 50 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3793 : : else
3794 : : {
3795 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3796 : 34 : if (decl_p)
3797 : 34 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3798 : : }
3799 : 84 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3800 : 84 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
3801 : :
3802 : 84 : if (ref_to_ptr)
3803 : : {
3804 : 34 : c3 = c2;
3805 : 34 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3806 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
3807 : 34 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3808 : 68 : OMP_CLAUSE_SIZE (c2)
3809 : 34 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
3810 : : }
3811 : : }
3812 : : break;
3813 : :
3814 : 83 : case ACCESS_INDEXED_REF_TO_ARRAY:
3815 : 83 : {
3816 : 83 : if (!map_p)
3817 : : {
3818 : 0 : if (decl_p)
3819 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3820 : : break;
3821 : : }
3822 : :
3823 : 83 : if (!target_p)
3824 : : break;
3825 : :
3826 : 64 : tree virtual_origin
3827 : 64 : = convert_from_reference (addr_tokens[i + 1]->expr);
3828 : 64 : virtual_origin = build_fold_addr_expr (virtual_origin);
3829 : 64 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3830 : : virtual_origin);
3831 : 64 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3832 : 64 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3833 : 64 : if (decl_p && target_p && !declare_target_p)
3834 : : {
3835 : : /* It appears that omp-low.cc mishandles cases where we have a
3836 : : [reference to an] array of pointers such as:
3837 : :
3838 : : int *arr[N]; (or "int *(&arr)[N] = ...")
3839 : : #pragma omp target map(arr[a][b:c])
3840 : : { ... }
3841 : :
3842 : : in such cases chain_p will be true. For now, fall back to
3843 : : GOMP_MAP_POINTER. */
3844 : 61 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3845 : : : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
3846 : 61 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3847 : 61 : }
3848 : : else
3849 : : {
3850 : 3 : if (decl_p)
3851 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3852 : 3 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3853 : : }
3854 : 64 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3855 : 64 : OMP_CLAUSE_SIZE (c2)
3856 : 64 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3857 : : fold_convert_loc (loc, ptrdiff_type_node,
3858 : : data_addr),
3859 : : virtual_origin);
3860 : : }
3861 : 64 : break;
3862 : :
3863 : 1306 : case ACCESS_INDEXED_ARRAY:
3864 : 1306 : {
3865 : 1306 : if (!map_p)
3866 : : {
3867 : 0 : if (decl_p)
3868 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3869 : : break;
3870 : : }
3871 : :
3872 : : /* The code handling "firstprivatize_array_bases" in gimplify.cc is
3873 : : relevant here. What do we need to create for arrays at this
3874 : : stage? (This condition doesn't feel quite right. FIXME?) */
3875 : 1306 : if (!target_p
3876 : 1306 : && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
3877 : : == ARRAY_TYPE))
3878 : : break;
3879 : :
3880 : 653 : tree virtual_origin
3881 : 653 : = build_fold_addr_expr (addr_tokens[i + 1]->expr);
3882 : 653 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3883 : : virtual_origin);
3884 : 653 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3885 : 653 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3886 : 653 : if (decl_p && target_p)
3887 : : {
3888 : : /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above. */
3889 : 653 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3890 : : : GOMP_MAP_FIRSTPRIVATE_POINTER;
3891 : 653 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3892 : : }
3893 : : else
3894 : : {
3895 : 0 : if (decl_p)
3896 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3897 : 0 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3898 : : }
3899 : 653 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3900 : 653 : OMP_CLAUSE_SIZE (c2)
3901 : 653 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3902 : : fold_convert_loc (loc, ptrdiff_type_node,
3903 : : data_addr),
3904 : : virtual_origin);
3905 : : }
3906 : 653 : break;
3907 : :
3908 : 2571 : case ACCESS_POINTER:
3909 : 2571 : case ACCESS_POINTER_OFFSET:
3910 : 2571 : {
3911 : 2571 : if (!map_p)
3912 : : {
3913 : 0 : if (decl_p)
3914 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3915 : : break;
3916 : : }
3917 : :
3918 : 2571 : unsigned last_access = i + 1;
3919 : 2571 : tree virtual_origin;
3920 : :
3921 : 2571 : if (chain_p
3922 : 127 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3923 : 2698 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3924 : : {
3925 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3926 : 117 : consume_tokens = 3;
3927 : 117 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3928 : 117 : last_access = i + 2;
3929 : 117 : virtual_origin
3930 : 117 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3931 : : integer_zero_node);
3932 : 117 : virtual_origin = build_fold_addr_expr (virtual_origin);
3933 : 117 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3934 : : virtual_origin);
3935 : : }
3936 : : else
3937 : 2454 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3938 : 2454 : addr_tokens[last_access]->expr);
3939 : 2571 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3940 : 2571 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3941 : : /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
3942 : : regions (e.g. "acc data" constructs). It'll be removed anyway in
3943 : : gimplify.cc, but doing it this way maintains diagnostic
3944 : : behaviour. */
3945 : 2571 : if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
3946 : 2406 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
3947 : : else
3948 : : {
3949 : 162 : if (decl_p)
3950 : 162 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3951 : 165 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3952 : : }
3953 : 2571 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3954 : 2571 : OMP_CLAUSE_SIZE (c2)
3955 : 2571 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3956 : : fold_convert_loc (loc, ptrdiff_type_node,
3957 : : data_addr),
3958 : : virtual_origin);
3959 : : }
3960 : 2571 : break;
3961 : :
3962 : 74 : case ACCESS_REF_TO_POINTER:
3963 : 74 : case ACCESS_REF_TO_POINTER_OFFSET:
3964 : 74 : {
3965 : 74 : if (!map_p)
3966 : : {
3967 : 0 : if (decl_p)
3968 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3969 : : break;
3970 : : }
3971 : :
3972 : 74 : unsigned last_access = i + 1;
3973 : 74 : tree virtual_origin;
3974 : :
3975 : 74 : if (chain_p
3976 : 6 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3977 : 80 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3978 : : {
3979 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3980 : 2 : consume_tokens = 3;
3981 : 2 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3982 : 2 : last_access = i + 2;
3983 : 2 : virtual_origin
3984 : 2 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3985 : : integer_zero_node);
3986 : 2 : virtual_origin = build_fold_addr_expr (virtual_origin);
3987 : 2 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3988 : : virtual_origin);
3989 : : }
3990 : : else
3991 : : {
3992 : 72 : virtual_origin
3993 : 72 : = convert_from_reference (addr_tokens[last_access]->expr);
3994 : 72 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3995 : : virtual_origin);
3996 : : }
3997 : :
3998 : 74 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3999 : 74 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4000 : 74 : if (decl_p && target_p && !chain_p && !declare_target_p)
4001 : : {
4002 : 58 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
4003 : 58 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4004 : : }
4005 : : else
4006 : : {
4007 : 16 : if (decl_p)
4008 : 16 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4009 : 16 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4010 : 16 : OMP_CLAUSE_DECL (c2)
4011 : 32 : = convert_from_reference (addr_tokens[i + 1]->expr);
4012 : : }
4013 : 74 : OMP_CLAUSE_SIZE (c2)
4014 : 74 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4015 : : fold_convert_loc (loc, ptrdiff_type_node,
4016 : : data_addr),
4017 : : virtual_origin);
4018 : : }
4019 : 74 : break;
4020 : :
4021 : 0 : default:
4022 : 0 : *idx = i + consume_tokens;
4023 : 0 : return error_mark_node;
4024 : : }
4025 : :
4026 : 11927 : if (c3)
4027 : : {
4028 : 34 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4029 : 34 : OMP_CLAUSE_CHAIN (c2) = c3;
4030 : 34 : OMP_CLAUSE_CHAIN (c) = c2;
4031 : 34 : if (implicit_p)
4032 : : {
4033 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4034 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
4035 : : }
4036 : : c = c3;
4037 : : }
4038 : 17736 : else if (c2)
4039 : : {
4040 : 3412 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4041 : 3412 : OMP_CLAUSE_CHAIN (c) = c2;
4042 : 3412 : if (implicit_p)
4043 : 116 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4044 : : c = c2;
4045 : : }
4046 : :
4047 : 17770 : i += consume_tokens;
4048 : 17770 : *idx = i;
4049 : :
4050 : 17770 : if (chain_p && map_p)
4051 : 27 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4052 : :
4053 : : return c;
4054 : : }
4055 : :
4056 : : /* Translate "component_selector access_method" to OMP mapping clauses. */
4057 : :
4058 : : tree
4059 : 2894 : c_omp_address_inspector::expand_component_selector (tree c,
4060 : : vec<omp_addr_token *>
4061 : : &addr_tokens,
4062 : : tree expr, unsigned *idx,
4063 : : c_omp_region_type ort)
4064 : : {
4065 : 2894 : using namespace omp_addr_tokenizer;
4066 : 2894 : location_t loc = OMP_CLAUSE_LOCATION (c);
4067 : 2894 : unsigned i = *idx;
4068 : 2894 : tree c2 = NULL_TREE, c3 = NULL_TREE;
4069 : 2894 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
4070 : 2894 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
4071 : :
4072 : 2894 : switch (addr_tokens[i + 1]->u.access_kind)
4073 : : {
4074 : : case ACCESS_DIRECT:
4075 : : case ACCESS_INDEXED_ARRAY:
4076 : : break;
4077 : :
4078 : 479 : case ACCESS_REF:
4079 : 479 : {
4080 : : /* Copy the referenced object. Note that we also do this for !MAP_P
4081 : : clauses. */
4082 : 479 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
4083 : 479 : OMP_CLAUSE_DECL (c) = obj;
4084 : 479 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
4085 : :
4086 : 479 : if (!map_p)
4087 : : break;
4088 : :
4089 : 461 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4090 : 461 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4091 : 461 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4092 : 461 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
4093 : : }
4094 : 461 : break;
4095 : :
4096 : 92 : case ACCESS_INDEXED_REF_TO_ARRAY:
4097 : 92 : {
4098 : 92 : if (!map_p)
4099 : : break;
4100 : :
4101 : 92 : tree virtual_origin
4102 : 92 : = convert_from_reference (addr_tokens[i + 1]->expr);
4103 : 92 : virtual_origin = build_fold_addr_expr (virtual_origin);
4104 : 92 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4105 : : virtual_origin);
4106 : 92 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4107 : :
4108 : 92 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4109 : 92 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4110 : 92 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4111 : 92 : OMP_CLAUSE_SIZE (c2)
4112 : 92 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4113 : : fold_convert_loc (loc, ptrdiff_type_node,
4114 : : data_addr),
4115 : : virtual_origin);
4116 : : }
4117 : 92 : break;
4118 : :
4119 : 778 : case ACCESS_POINTER:
4120 : 778 : case ACCESS_POINTER_OFFSET:
4121 : 778 : {
4122 : 778 : if (!map_p)
4123 : : break;
4124 : :
4125 : 778 : tree virtual_origin
4126 : 1556 : = fold_convert_loc (loc, ptrdiff_type_node,
4127 : 778 : addr_tokens[i + 1]->expr);
4128 : 778 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4129 : :
4130 : 778 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4131 : 778 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4132 : 778 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4133 : 778 : OMP_CLAUSE_SIZE (c2)
4134 : 778 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4135 : : fold_convert_loc (loc, ptrdiff_type_node,
4136 : : data_addr),
4137 : : virtual_origin);
4138 : : }
4139 : 778 : break;
4140 : :
4141 : 185 : case ACCESS_REF_TO_POINTER:
4142 : 185 : case ACCESS_REF_TO_POINTER_OFFSET:
4143 : 185 : {
4144 : 185 : if (!map_p)
4145 : : break;
4146 : :
4147 : 185 : tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
4148 : 185 : tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4149 : : ptr);
4150 : 185 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4151 : :
4152 : : /* Attach the pointer... */
4153 : 185 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4154 : 185 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4155 : 185 : OMP_CLAUSE_DECL (c2) = ptr;
4156 : 185 : OMP_CLAUSE_SIZE (c2)
4157 : 185 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4158 : : fold_convert_loc (loc, ptrdiff_type_node,
4159 : : data_addr),
4160 : : virtual_origin);
4161 : :
4162 : : /* ...and also the reference. */
4163 : 185 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4164 : 185 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
4165 : 185 : OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
4166 : 185 : OMP_CLAUSE_SIZE (c3) = size_zero_node;
4167 : : }
4168 : 185 : break;
4169 : :
4170 : 0 : default:
4171 : 0 : *idx = i + 2;
4172 : 0 : return error_mark_node;
4173 : : }
4174 : :
4175 : 1331 : if (c3)
4176 : : {
4177 : 185 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4178 : 185 : OMP_CLAUSE_CHAIN (c2) = c3;
4179 : 185 : OMP_CLAUSE_CHAIN (c) = c2;
4180 : 185 : c = c3;
4181 : : }
4182 : 2709 : else if (c2)
4183 : : {
4184 : 1331 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4185 : 1331 : OMP_CLAUSE_CHAIN (c) = c2;
4186 : 1331 : c = c2;
4187 : : }
4188 : :
4189 : 2894 : i += 2;
4190 : 2894 : *idx = i;
4191 : :
4192 : 2894 : if (chain_p && map_p)
4193 : 22 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4194 : :
4195 : : return c;
4196 : : }
4197 : :
4198 : : /* Expand a map clause into a group of mapping clauses, creating nodes to
4199 : : attach/detach pointers and so forth as necessary. */
4200 : :
4201 : : tree
4202 : 20692 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
4203 : : vec<omp_addr_token *> &addr_tokens,
4204 : : c_omp_region_type ort)
4205 : : {
4206 : 20692 : using namespace omp_addr_tokenizer;
4207 : 20692 : unsigned i, length = addr_tokens.length ();
4208 : :
4209 : 44973 : for (i = 0; i < length;)
4210 : : {
4211 : 24281 : int remaining = length - i;
4212 : :
4213 : 24281 : if (remaining >= 2
4214 : 24281 : && addr_tokens[i]->type == ARRAY_BASE
4215 : 17798 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4216 : 42070 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4217 : : {
4218 : 17789 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4219 : 17789 : if (c == error_mark_node)
4220 : : return error_mark_node;
4221 : : }
4222 : 6492 : else if (remaining >= 2
4223 : 6492 : && addr_tokens[i]->type == ARRAY_BASE
4224 : 9 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4225 : 6501 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4226 : : {
4227 : 9 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4228 : 9 : if (c == error_mark_node)
4229 : : return error_mark_node;
4230 : : }
4231 : 6483 : else if (remaining >= 2
4232 : 6483 : && addr_tokens[i]->type == STRUCTURE_BASE
4233 : 2894 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4234 : 9374 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4235 : : {
4236 : 2891 : if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
4237 : 1422 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4238 : 2891 : i += 2;
4239 : 3051 : while (addr_tokens[i]->type == ACCESS_METHOD)
4240 : 160 : i++;
4241 : : }
4242 : 3592 : else if (remaining >= 2
4243 : 3592 : && addr_tokens[i]->type == STRUCTURE_BASE
4244 : 3 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4245 : 3595 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4246 : : {
4247 : 3 : switch (addr_tokens[i + 1]->u.access_kind)
4248 : : {
4249 : 3 : case ACCESS_DIRECT:
4250 : 3 : case ACCESS_POINTER:
4251 : 3 : i += 2;
4252 : 3 : while (addr_tokens[i]->type == ACCESS_METHOD)
4253 : 0 : i++;
4254 : : break;
4255 : 0 : default:
4256 : 0 : return error_mark_node;
4257 : : }
4258 : : }
4259 : 3589 : else if (remaining >= 2
4260 : 3589 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4261 : 7178 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4262 : : {
4263 : 2894 : c = expand_component_selector (c, addr_tokens, expr, &i, ort);
4264 : : /* We used 'expr', so these must have been the last tokens. */
4265 : 2894 : gcc_assert (i == length);
4266 : 2894 : if (c == error_mark_node)
4267 : : return error_mark_node;
4268 : : }
4269 : 695 : else if (remaining >= 3
4270 : 695 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4271 : 695 : && addr_tokens[i + 1]->type == STRUCTURE_BASE
4272 : 695 : && (addr_tokens[i + 1]->u.structure_base_kind
4273 : : == BASE_COMPONENT_EXPR)
4274 : 1390 : && addr_tokens[i + 2]->type == ACCESS_METHOD)
4275 : : {
4276 : 695 : i += 3;
4277 : 719 : while (addr_tokens[i]->type == ACCESS_METHOD)
4278 : 24 : i++;
4279 : : }
4280 : : else
4281 : : break;
4282 : : }
4283 : :
4284 : 20692 : if (i == length)
4285 : : return c;
4286 : :
4287 : 0 : return error_mark_node;
4288 : : }
4289 : :
4290 : : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
4291 : : for that mapper, and if any of those should use a (named or unnamed) mapper
4292 : : themselves, add it to MLIST. */
4293 : :
4294 : : void
4295 : 130 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
4296 : : {
4297 : 130 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4298 : 130 : tree mapper_name = NULL_TREE;
4299 : :
4300 : 130 : if (mapper == error_mark_node)
4301 : : return;
4302 : :
4303 : 130 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
4304 : :
4305 : 410 : for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4306 : 410 : clause;
4307 : 280 : clause = OMP_CLAUSE_CHAIN (clause))
4308 : : {
4309 : 280 : tree expr = OMP_CLAUSE_DECL (clause);
4310 : 280 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
4311 : 280 : tree elem_type;
4312 : :
4313 : 280 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4314 : : {
4315 : 0 : mapper_name = expr;
4316 : 0 : continue;
4317 : : }
4318 : 280 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4319 : : {
4320 : 0 : mapper_name = NULL_TREE;
4321 : 0 : continue;
4322 : : }
4323 : :
4324 : 280 : gcc_assert (TREE_CODE (expr) != TREE_LIST);
4325 : 280 : if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4326 : : {
4327 : 220 : while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4328 : 110 : expr = TREE_OPERAND (expr, 0);
4329 : :
4330 : 110 : elem_type = TREE_TYPE (expr);
4331 : : }
4332 : : else
4333 : 170 : elem_type = TREE_TYPE (expr);
4334 : :
4335 : : /* This might be too much... or not enough? */
4336 : 478 : while (TREE_CODE (elem_type) == ARRAY_TYPE
4337 : 472 : || TREE_CODE (elem_type) == POINTER_TYPE
4338 : 758 : || TREE_CODE (elem_type) == REFERENCE_TYPE)
4339 : 198 : elem_type = TREE_TYPE (elem_type);
4340 : :
4341 : 280 : elem_type = TYPE_MAIN_VARIANT (elem_type);
4342 : :
4343 : 280 : if (RECORD_OR_UNION_TYPE_P (elem_type)
4344 : 280 : && !mlist->contains (mapper_name, elem_type))
4345 : : {
4346 : 5 : tree nested_mapper_fn
4347 : 5 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
4348 : :
4349 : 5 : if (nested_mapper_fn)
4350 : : {
4351 : 5 : mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
4352 : 5 : c_omp_find_nested_mappers (mlist, nested_mapper_fn);
4353 : : }
4354 : 0 : else if (mapper_name)
4355 : : {
4356 : 0 : error ("mapper %qE not found for type %qT", mapper_name,
4357 : : elem_type);
4358 : 0 : continue;
4359 : : }
4360 : : }
4361 : : }
4362 : : }
4363 : :
4364 : : struct remap_mapper_decl_info
4365 : : {
4366 : : tree dummy_var;
4367 : : tree expr;
4368 : : };
4369 : :
4370 : : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
4371 : :
4372 : : static tree
4373 : 1072 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
4374 : : {
4375 : 1072 : remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
4376 : :
4377 : 1072 : if (operand_equal_p (*tp, map_info->dummy_var))
4378 : : {
4379 : 251 : *tp = map_info->expr;
4380 : 251 : *walk_subtrees = 0;
4381 : : }
4382 : :
4383 : 1072 : return NULL_TREE;
4384 : : }
4385 : :
4386 : : /* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to
4387 : : OUTLIST. OUTER_KIND is the mapping kind to use if not already specified in
4388 : : the mapper declaration. */
4389 : :
4390 : : static tree *
4391 : 49 : omp_instantiate_mapper (tree *outlist, tree mapper, tree expr,
4392 : : enum gomp_map_kind outer_kind)
4393 : : {
4394 : 49 : tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4395 : 49 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
4396 : 49 : tree mapper_name = NULL_TREE;
4397 : :
4398 : 49 : remap_mapper_decl_info map_info;
4399 : 49 : map_info.dummy_var = dummy_var;
4400 : 49 : map_info.expr = expr;
4401 : :
4402 : 163 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4403 : : {
4404 : 114 : tree unshared = unshare_expr (c);
4405 : 114 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
4406 : 114 : tree t = OMP_CLAUSE_DECL (unshared);
4407 : 114 : tree type = NULL_TREE;
4408 : 114 : bool nonunit_array_with_mapper = false;
4409 : :
4410 : 114 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4411 : : {
4412 : 0 : mapper_name = t;
4413 : 2 : continue;
4414 : : }
4415 : 114 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4416 : : {
4417 : 0 : mapper_name = NULL_TREE;
4418 : 0 : continue;
4419 : : }
4420 : :
4421 : 114 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4422 : : {
4423 : 41 : location_t loc = OMP_CLAUSE_LOCATION (c);
4424 : 41 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4425 : :
4426 : 41 : if (t2 == t)
4427 : : {
4428 : 40 : nonunit_array_with_mapper = true;
4429 : : /* We'd want use the mapper for the element type if this worked:
4430 : : look that one up. */
4431 : 40 : type = TREE_TYPE (TREE_TYPE (t));
4432 : : }
4433 : : else
4434 : : {
4435 : 1 : t = t2;
4436 : 1 : type = TREE_TYPE (t);
4437 : : }
4438 : : }
4439 : : else
4440 : 73 : type = TREE_TYPE (t);
4441 : :
4442 : 114 : gcc_assert (type);
4443 : :
4444 : 114 : if (type == error_mark_node)
4445 : 0 : continue;
4446 : :
4447 : 114 : walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
4448 : :
4449 : 114 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
4450 : 56 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
4451 : :
4452 : 114 : type = TYPE_MAIN_VARIANT (type);
4453 : :
4454 : 114 : tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4455 : :
4456 : 114 : if (mapper_fn && nonunit_array_with_mapper)
4457 : : {
4458 : 0 : sorry ("user-defined mapper with non-unit length array section");
4459 : 0 : continue;
4460 : : }
4461 : 114 : else if (mapper_fn)
4462 : : {
4463 : 12 : tree nested_mapper
4464 : 12 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4465 : 12 : if (nested_mapper != mapper)
4466 : : {
4467 : 2 : if (clause_kind == GOMP_MAP_UNSET)
4468 : 0 : clause_kind = outer_kind;
4469 : :
4470 : 2 : outlist = omp_instantiate_mapper (outlist, nested_mapper,
4471 : : t, clause_kind);
4472 : 2 : continue;
4473 : : }
4474 : : }
4475 : 102 : else if (mapper_name)
4476 : : {
4477 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4478 : 0 : continue;
4479 : : }
4480 : :
4481 : 112 : *outlist = unshared;
4482 : 112 : outlist = &OMP_CLAUSE_CHAIN (unshared);
4483 : : }
4484 : :
4485 : 49 : return outlist;
4486 : : }
4487 : :
4488 : : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
4489 : : appropriate to the type of the data in that clause, if such a mapper is
4490 : : visible in the current parsing context. */
4491 : :
4492 : : tree
4493 : 5734 : c_omp_instantiate_mappers (tree clauses)
4494 : : {
4495 : 5734 : tree c, *pc, mapper_name = NULL_TREE;
4496 : :
4497 : 12054 : for (pc = &clauses, c = clauses; c; c = *pc)
4498 : : {
4499 : 6320 : bool using_mapper = false;
4500 : :
4501 : 6320 : switch (OMP_CLAUSE_CODE (c))
4502 : : {
4503 : 4577 : case OMP_CLAUSE_MAP:
4504 : 4577 : {
4505 : 4577 : tree t = OMP_CLAUSE_DECL (c);
4506 : 4577 : tree type = NULL_TREE;
4507 : 4577 : bool nonunit_array_with_mapper = false;
4508 : :
4509 : 4577 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
4510 : 4577 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
4511 : : {
4512 : 38 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
4513 : 19 : mapper_name = OMP_CLAUSE_DECL (c);
4514 : : else
4515 : : mapper_name = NULL_TREE;
4516 : 38 : pc = &OMP_CLAUSE_CHAIN (c);
4517 : 38 : continue;
4518 : : }
4519 : :
4520 : 4539 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4521 : : {
4522 : 1717 : location_t loc = OMP_CLAUSE_LOCATION (c);
4523 : 1717 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4524 : :
4525 : 1717 : if (t2 == t)
4526 : : {
4527 : : /* !!! Array sections of size >1 with mappers for elements
4528 : : are hard to support. Do something here. */
4529 : 1462 : nonunit_array_with_mapper = true;
4530 : 1462 : type = TREE_TYPE (TREE_TYPE (t));
4531 : : }
4532 : : else
4533 : : {
4534 : 255 : t = t2;
4535 : 255 : type = TREE_TYPE (t);
4536 : : }
4537 : : }
4538 : : else
4539 : 2822 : type = TREE_TYPE (t);
4540 : :
4541 : 4539 : if (type == NULL_TREE || type == error_mark_node)
4542 : : {
4543 : 56 : pc = &OMP_CLAUSE_CHAIN (c);
4544 : 56 : continue;
4545 : : }
4546 : :
4547 : 4483 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
4548 : 4483 : if (kind == GOMP_MAP_UNSET)
4549 : 0 : kind = GOMP_MAP_TOFROM;
4550 : :
4551 : 4483 : type = TYPE_MAIN_VARIANT (type);
4552 : :
4553 : 4483 : tree mapper_fn
4554 : 4483 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4555 : :
4556 : 4483 : if (mapper_fn && nonunit_array_with_mapper)
4557 : : {
4558 : 0 : sorry ("user-defined mapper with non-unit length "
4559 : : "array section");
4560 : 0 : using_mapper = true;
4561 : : }
4562 : 4483 : else if (mapper_fn)
4563 : : {
4564 : 47 : tree mapper
4565 : 47 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4566 : 47 : pc = omp_instantiate_mapper (pc, mapper, t, kind);
4567 : 47 : using_mapper = true;
4568 : : }
4569 : 4436 : else if (mapper_name)
4570 : : {
4571 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4572 : 0 : using_mapper = true;
4573 : : }
4574 : : }
4575 : : break;
4576 : :
4577 : 47 : default:
4578 : 47 : ;
4579 : : }
4580 : :
4581 : 47 : if (using_mapper)
4582 : 47 : *pc = OMP_CLAUSE_CHAIN (c);
4583 : : else
4584 : 6179 : pc = &OMP_CLAUSE_CHAIN (c);
4585 : : }
4586 : :
4587 : 5734 : return clauses;
4588 : : }
4589 : :
4590 : : const struct c_omp_directive c_omp_directives[] = {
4591 : : /* Keep this alphabetically sorted by the first word. Non-null second/third
4592 : : if any should precede null ones. */
4593 : : { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
4594 : : C_OMP_DIR_DECLARATIVE, false },
4595 : : { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
4596 : : C_OMP_DIR_INFORMATIONAL, false },
4597 : : { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
4598 : : C_OMP_DIR_INFORMATIONAL, false },
4599 : : { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
4600 : : C_OMP_DIR_CONSTRUCT, false },
4601 : : { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
4602 : : C_OMP_DIR_STANDALONE, false },
4603 : : { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
4604 : : C_OMP_DIR_INFORMATIONAL, false },
4605 : : { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
4606 : : C_OMP_DIR_DECLARATIVE, false },
4607 : : /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
4608 : : C_OMP_DIR_DECLARATIVE, false }, */
4609 : : /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
4610 : : C_OMP_DIR_META, false }, */
4611 : : { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
4612 : : C_OMP_DIR_STANDALONE, false },
4613 : : { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
4614 : : C_OMP_DIR_STANDALONE, false },
4615 : : { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
4616 : : C_OMP_DIR_CONSTRUCT, false },
4617 : : /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
4618 : : C_OMP_DIR_DECLARATIVE, false }, */
4619 : : { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
4620 : : C_OMP_DIR_DECLARATIVE, true },
4621 : : { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
4622 : : C_OMP_DIR_DECLARATIVE, true },
4623 : : { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
4624 : : C_OMP_DIR_DECLARATIVE, false },
4625 : : { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
4626 : : C_OMP_DIR_DECLARATIVE, false },
4627 : : { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
4628 : : C_OMP_DIR_STANDALONE, false },
4629 : : { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
4630 : : C_OMP_DIR_DECLARATIVE, false },
4631 : : { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
4632 : : C_OMP_DIR_CONSTRUCT, true },
4633 : : { "end", "assumes", nullptr, PRAGMA_OMP_END,
4634 : : C_OMP_DIR_INFORMATIONAL, false },
4635 : : { "end", "declare", "target", PRAGMA_OMP_END,
4636 : : C_OMP_DIR_DECLARATIVE, false },
4637 : : /* { "end", "declare", "variant", PRAGMA_OMP_END,
4638 : : C_OMP_DIR_DECLARATIVE, false }, */
4639 : : /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
4640 : : C_OMP_DIR_META, false }, */
4641 : : /* error with at(execution) is C_OMP_DIR_STANDALONE. */
4642 : : { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
4643 : : C_OMP_DIR_UTILITY, false },
4644 : : { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
4645 : : C_OMP_DIR_STANDALONE, false },
4646 : : { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
4647 : : C_OMP_DIR_CONSTRUCT, true },
4648 : : /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
4649 : : C_OMP_DIR_DECLARATIVE, false }, */
4650 : : { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
4651 : : C_OMP_DIR_STANDALONE, false },
4652 : : { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
4653 : : C_OMP_DIR_CONSTRUCT, true },
4654 : : { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
4655 : : C_OMP_DIR_CONSTRUCT, true },
4656 : : { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
4657 : : C_OMP_DIR_CONSTRUCT, true },
4658 : : { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
4659 : : C_OMP_DIR_META, false },
4660 : : { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
4661 : : C_OMP_DIR_UTILITY, false },
4662 : : /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
4663 : : { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
4664 : : C_OMP_DIR_CONSTRUCT, true },
4665 : : { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
4666 : : C_OMP_DIR_CONSTRUCT, true },
4667 : : { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
4668 : : C_OMP_DIR_INFORMATIONAL, false },
4669 : : { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
4670 : : C_OMP_DIR_CONSTRUCT, true },
4671 : : { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
4672 : : C_OMP_DIR_CONSTRUCT, false },
4673 : : { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
4674 : : C_OMP_DIR_CONSTRUCT, false },
4675 : : { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
4676 : : C_OMP_DIR_CONSTRUCT, false },
4677 : : { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
4678 : : C_OMP_DIR_CONSTRUCT, true },
4679 : : { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
4680 : : C_OMP_DIR_CONSTRUCT, false },
4681 : : { "target", "data", nullptr, PRAGMA_OMP_TARGET,
4682 : : C_OMP_DIR_CONSTRUCT, false },
4683 : : { "target", "enter", "data", PRAGMA_OMP_TARGET,
4684 : : C_OMP_DIR_STANDALONE, false },
4685 : : { "target", "exit", "data", PRAGMA_OMP_TARGET,
4686 : : C_OMP_DIR_STANDALONE, false },
4687 : : { "target", "update", nullptr, PRAGMA_OMP_TARGET,
4688 : : C_OMP_DIR_STANDALONE, false },
4689 : : { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
4690 : : C_OMP_DIR_CONSTRUCT, true },
4691 : : { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
4692 : : C_OMP_DIR_CONSTRUCT, false },
4693 : : { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
4694 : : C_OMP_DIR_CONSTRUCT, false },
4695 : : { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
4696 : : C_OMP_DIR_CONSTRUCT, true },
4697 : : { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
4698 : : C_OMP_DIR_STANDALONE, false },
4699 : : { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
4700 : : C_OMP_DIR_STANDALONE, false },
4701 : : { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
4702 : : C_OMP_DIR_CONSTRUCT, false },
4703 : : { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
4704 : : C_OMP_DIR_CONSTRUCT, true },
4705 : : { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
4706 : : C_OMP_DIR_DECLARATIVE, false },
4707 : : { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
4708 : : C_OMP_DIR_CONSTRUCT, false },
4709 : : };
4710 : :
4711 : : /* Find (non-combined/composite) OpenMP directive (if any) which starts
4712 : : with FIRST keyword and for multi-word directives has SECOND and
4713 : : THIRD keyword after it. */
4714 : :
4715 : : const struct c_omp_directive *
4716 : 6534 : c_omp_categorize_directive (const char *first, const char *second,
4717 : : const char *third)
4718 : : {
4719 : 6534 : const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
4720 : 187941 : for (size_t i = 0; i < n_omp_directives; i++)
4721 : : {
4722 : 350536 : if ((unsigned char) c_omp_directives[i].first[0]
4723 : 187941 : < (unsigned char) first[0])
4724 : 162595 : continue;
4725 : 25346 : if ((unsigned char) c_omp_directives[i].first[0]
4726 : : > (unsigned char) first[0])
4727 : : break;
4728 : 25259 : if (strcmp (c_omp_directives[i].first, first))
4729 : 15566 : continue;
4730 : 9693 : if (!c_omp_directives[i].second)
4731 : 5072 : return &c_omp_directives[i];
4732 : 4621 : if (!second || strcmp (c_omp_directives[i].second, second))
4733 : 3234 : continue;
4734 : 1387 : if (!c_omp_directives[i].third)
4735 : 1099 : return &c_omp_directives[i];
4736 : 288 : if (!third || strcmp (c_omp_directives[i].third, third))
4737 : 12 : continue;
4738 : 276 : return &c_omp_directives[i];
4739 : : }
4740 : : return NULL;
4741 : : }
4742 : :
4743 : : /* Auxilliary helper function for c_omp_expand_variant_construct. */
4744 : :
4745 : : static tree
4746 : 462 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
4747 : : hash_map<tree, tree> &body_labels,
4748 : : unsigned index)
4749 : : {
4750 : 462 : struct omp_variant &candidate = candidates[index];
4751 : 462 : tree if_block = push_stmt_list ();
4752 : 462 : if (candidate.alternative != NULL_TREE)
4753 : 462 : add_stmt (candidate.alternative);
4754 : 462 : if (candidate.body != NULL_TREE)
4755 : : {
4756 : 138 : tree *label = body_labels.get (candidate.body);
4757 : 138 : if (label != NULL)
4758 : 0 : add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
4759 : : else
4760 : : {
4761 : 138 : tree body_label = create_artificial_label (UNKNOWN_LOCATION);
4762 : 138 : add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
4763 : 138 : add_stmt (candidate.body);
4764 : 138 : body_labels.put (candidate.body, body_label);
4765 : : }
4766 : : }
4767 : 462 : if_block = pop_stmt_list (if_block);
4768 : :
4769 : 924 : if (index == candidates.length () - 1)
4770 : : return if_block;
4771 : :
4772 : 154 : tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
4773 : 154 : gcc_assert (cond != NULL_TREE);
4774 : :
4775 : 154 : tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
4776 : : index + 1);
4777 : 154 : tree ret = push_stmt_list ();
4778 : 154 : tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
4779 : 154 : add_stmt (stmt);
4780 : 154 : ret = pop_stmt_list (ret);
4781 : :
4782 : 154 : return ret;
4783 : : }
4784 : :
4785 : : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
4786 : : structure. */
4787 : :
4788 : : tree
4789 : 308 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
4790 : : {
4791 : 308 : hash_map<tree, tree> body_labels;
4792 : 308 : return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
4793 : 308 : }
|