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