1 /* OpenMP directive translation -- generate GCC trees from gfc_code. 2 Copyright (C) 2005-2024 Free Software Foundation, Inc. 3 Contributed by Jakub Jelinek <jakub (at) redhat.com> 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 22 #include "config.h" 23 #include "system.h" 24 #include "coretypes.h" 25 #include "options.h" 26 #include "tree.h" 27 #include "gfortran.h" 28 #include "gimple-expr.h" 29 #include "trans.h" 30 #include "stringpool.h" 31 #include "fold-const.h" 32 #include "gimplify.h" /* For create_tmp_var_raw. */ 33 #include "trans-stmt.h" 34 #include "trans-types.h" 35 #include "trans-array.h" 36 #include "trans-const.h" 37 #include "arith.h" 38 #include "constructor.h" 39 #include "gomp-constants.h" 40 #include "omp-general.h" 41 #include "omp-low.h" 42 #include "memmodel.h" /* For MEMMODEL_ enums. */ 43 #include "dependency.h" 44 45 #undef GCC_DIAG_STYLE 46 #define GCC_DIAG_STYLE __gcc_tdiag__ 47 #include "diagnostic-core.h" 48 #undef GCC_DIAG_STYLE 49 #define GCC_DIAG_STYLE __gcc_gfc__ 50 #include "attribs.h" 51 #include "function.h" 52 53 int ompws_flags; 54 55 /* True if OpenMP should regard this DECL as being a scalar which has Fortran's 56 allocatable or pointer attribute. */ 57 58 bool 59 gfc_omp_is_allocatable_or_ptr (const_tree decl) 60 { 61 return (DECL_P (decl) 62 && (GFC_DECL_GET_SCALAR_POINTER (decl) 63 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))); 64 } 65 66 /* True if the argument is an optional argument; except that false is also 67 returned for arguments with the value attribute (nonpointers) and for 68 assumed-shape variables (decl is a local variable containing arg->data). 69 Note that for 'procedure(), optional' the value false is used as that's 70 always a pointer and no additional indirection is used. 71 Note that pvoid_type_node is for 'type(c_ptr), value' (and c_funloc). */ 72 73 static bool 74 gfc_omp_is_optional_argument (const_tree decl) 75 { 76 /* Note: VAR_DECL can occur with BIND(C) and array descriptors. */ 77 return ((TREE_CODE (decl) == PARM_DECL || VAR_P (decl)) 78 && DECL_LANG_SPECIFIC (decl) 79 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE 80 && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))) 81 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != FUNCTION_TYPE 82 && GFC_DECL_OPTIONAL_ARGUMENT (decl)); 83 } 84 85 /* Check whether this DECL belongs to a Fortran optional argument. 86 With 'for_present_check' set to false, decls which are optional parameters 87 themselves are returned as tree - or a NULL_TREE otherwise. Those decls are 88 always pointers. With 'for_present_check' set to true, the decl for checking 89 whether an argument is present is returned; for arguments with value 90 attribute this is the hidden argument and of BOOLEAN_TYPE. If the decl is 91 unrelated to optional arguments, NULL_TREE is returned. */ 92 93 tree 94 gfc_omp_check_optional_argument (tree decl, bool for_present_check) 95 { 96 if (!for_present_check) 97 return gfc_omp_is_optional_argument (decl) ? decl : NULL_TREE; 98 99 if (!DECL_LANG_SPECIFIC (decl)) 100 return NULL_TREE; 101 102 tree orig_decl = decl; 103 104 /* For assumed-shape arrays, a local decl with arg->data is used. */ 105 if (TREE_CODE (decl) != PARM_DECL 106 && (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)) 107 || GFC_ARRAY_TYPE_P (TREE_TYPE (decl)))) 108 decl = GFC_DECL_SAVED_DESCRIPTOR (decl); 109 110 /* Note: With BIND(C), array descriptors are converted to a VAR_DECL. */ 111 if (decl == NULL_TREE 112 || (TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != VAR_DECL) 113 || !DECL_LANG_SPECIFIC (decl) 114 || !GFC_DECL_OPTIONAL_ARGUMENT (decl)) 115 return NULL_TREE; 116 117 /* Scalars with VALUE attribute which are passed by value use a hidden 118 argument to denote the present status. They are passed as nonpointer type 119 with one exception: 'type(c_ptr), value' as 'void*'. */ 120 /* Cf. trans-expr.cc's gfc_conv_expr_present. */ 121 if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE 122 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) 123 { 124 char name[GFC_MAX_SYMBOL_LEN + 2]; 125 tree tree_name; 126 127 name[0] = '.'; 128 strcpy (&name[1], IDENTIFIER_POINTER (DECL_NAME (decl))); 129 tree_name = get_identifier (name); 130 131 /* Walk function argument list to find the hidden arg. */ 132 decl = DECL_ARGUMENTS (DECL_CONTEXT (decl)); 133 for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl)) 134 if (DECL_NAME (decl) == tree_name 135 && DECL_ARTIFICIAL (decl)) 136 break; 137 138 gcc_assert (decl); 139 return decl; 140 } 141 142 return fold_build2_loc (input_location, NE_EXPR, boolean_type_node, 143 orig_decl, null_pointer_node); 144 } 145 146 147 /* Returns tree with NULL if it is not an array descriptor and with the tree to 148 access the 'data' component otherwise. With type_only = true, it returns the 149 TREE_TYPE without creating a new tree. */ 150 151 tree 152 gfc_omp_array_data (tree decl, bool type_only) 153 { 154 tree type = TREE_TYPE (decl); 155 156 if (POINTER_TYPE_P (type)) 157 type = TREE_TYPE (type); 158 159 if (!GFC_DESCRIPTOR_TYPE_P (type)) 160 return NULL_TREE; 161 162 if (type_only) 163 return GFC_TYPE_ARRAY_DATAPTR_TYPE (type); 164 165 if (POINTER_TYPE_P (TREE_TYPE (decl))) 166 decl = build_fold_indirect_ref (decl); 167 168 decl = gfc_conv_descriptor_data_get (decl); 169 STRIP_NOPS (decl); 170 return decl; 171 } 172 173 /* Return the byte-size of the passed array descriptor. */ 174 175 tree 176 gfc_omp_array_size (tree decl, gimple_seq *pre_p) 177 { 178 stmtblock_t block; 179 if (POINTER_TYPE_P (TREE_TYPE (decl))) 180 decl = build_fold_indirect_ref (decl); 181 tree type = TREE_TYPE (decl); 182 gcc_assert (GFC_DESCRIPTOR_TYPE_P (type)); 183 bool allocatable = (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE 184 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER 185 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT); 186 gfc_init_block (&block); 187 tree size = gfc_full_array_size (&block, decl, 188 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl))); 189 size = fold_convert (size_type_node, size); 190 tree elemsz = gfc_get_element_type (TREE_TYPE (decl)); 191 if (TREE_CODE (elemsz) == ARRAY_TYPE && TYPE_STRING_FLAG (elemsz)) 192 elemsz = gfc_conv_descriptor_elem_len (decl); 193 else 194 elemsz = TYPE_SIZE_UNIT (elemsz); 195 size = fold_build2 (MULT_EXPR, size_type_node, size, elemsz); 196 if (!allocatable) 197 gimplify_and_add (gfc_finish_block (&block), pre_p); 198 else 199 { 200 tree var = create_tmp_var (size_type_node); 201 gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, sizetype, var, size)); 202 tree tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, 203 gfc_conv_descriptor_data_get (decl), 204 null_pointer_node); 205 tmp = build3_loc (input_location, COND_EXPR, void_type_node, tmp, 206 gfc_finish_block (&block), 207 build2 (MODIFY_EXPR, sizetype, var, size_zero_node)); 208 gimplify_and_add (tmp, pre_p); 209 size = var; 210 } 211 return size; 212 } 213 214 215 /* True if OpenMP should privatize what this DECL points to rather 216 than the DECL itself. */ 217 218 bool 219 gfc_omp_privatize_by_reference (const_tree decl) 220 { 221 tree type = TREE_TYPE (decl); 222 223 if (TREE_CODE (type) == REFERENCE_TYPE 224 && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL)) 225 return true; 226 227 if (TREE_CODE (type) == POINTER_TYPE 228 && gfc_omp_is_optional_argument (decl)) 229 return true; 230 231 if (TREE_CODE (type) == POINTER_TYPE) 232 { 233 while (TREE_CODE (decl) == COMPONENT_REF) 234 decl = TREE_OPERAND (decl, 1); 235 236 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables 237 that have POINTER_TYPE type and aren't scalar pointers, scalar 238 allocatables, Cray pointees or C pointers are supposed to be 239 privatized by reference. */ 240 if (GFC_DECL_GET_SCALAR_POINTER (decl) 241 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) 242 || GFC_DECL_CRAY_POINTEE (decl) 243 || GFC_DECL_ASSOCIATE_VAR_P (decl) 244 || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) 245 return false; 246 247 if (!DECL_ARTIFICIAL (decl) 248 && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) 249 return true; 250 251 /* Some arrays are expanded as DECL_ARTIFICIAL pointers 252 by the frontend. */ 253 if (DECL_LANG_SPECIFIC (decl) 254 && GFC_DECL_SAVED_DESCRIPTOR (decl)) 255 return true; 256 } 257 258 return false; 259 } 260 261 /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute 262 of DECL is predetermined. */ 263 264 enum omp_clause_default_kind 265 gfc_omp_predetermined_sharing (tree decl) 266 { 267 /* Associate names preserve the association established during ASSOCIATE. 268 As they are implemented either as pointers to the selector or array 269 descriptor and shouldn't really change in the ASSOCIATE region, 270 this decl can be either shared or firstprivate. If it is a pointer, 271 use firstprivate, as it is cheaper that way, otherwise make it shared. */ 272 if (GFC_DECL_ASSOCIATE_VAR_P (decl)) 273 { 274 if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE) 275 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; 276 else 277 return OMP_CLAUSE_DEFAULT_SHARED; 278 } 279 280 if (DECL_ARTIFICIAL (decl) 281 && ! GFC_DECL_RESULT (decl) 282 && ! (DECL_LANG_SPECIFIC (decl) 283 && GFC_DECL_SAVED_DESCRIPTOR (decl))) 284 return OMP_CLAUSE_DEFAULT_SHARED; 285 286 /* Cray pointees shouldn't be listed in any clauses and should be 287 gimplified to dereference of the corresponding Cray pointer. 288 Make them all private, so that they are emitted in the debug 289 information. */ 290 if (GFC_DECL_CRAY_POINTEE (decl)) 291 return OMP_CLAUSE_DEFAULT_PRIVATE; 292 293 /* Assumed-size arrays are predetermined shared. */ 294 if (TREE_CODE (decl) == PARM_DECL 295 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)) 296 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN 297 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl), 298 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1) 299 == NULL) 300 return OMP_CLAUSE_DEFAULT_SHARED; 301 302 /* Dummy procedures aren't considered variables by OpenMP, thus are 303 disallowed in OpenMP clauses. They are represented as PARM_DECLs 304 in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here 305 to avoid complaining about their uses with default(none). */ 306 if (TREE_CODE (decl) == PARM_DECL 307 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE 308 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE) 309 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; 310 311 /* COMMON and EQUIVALENCE decls are shared. They 312 are only referenced through DECL_VALUE_EXPR of the variables 313 contained in them. If those are privatized, they will not be 314 gimplified to the COMMON or EQUIVALENCE decls. */ 315 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl)) 316 return OMP_CLAUSE_DEFAULT_SHARED; 317 318 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl)) 319 return OMP_CLAUSE_DEFAULT_SHARED; 320 321 /* These are either array or derived parameters, or vtables. 322 In the former cases, the OpenMP standard doesn't consider them to be 323 variables at all (they can't be redefined), but they can nevertheless appear 324 in parallel/task regions and for default(none) purposes treat them as shared. 325 For vtables likely the same handling is desirable. */ 326 if (VAR_P (decl) && TREE_READONLY (decl) 327 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) 328 return OMP_CLAUSE_DEFAULT_SHARED; 329 330 return OMP_CLAUSE_DEFAULT_UNSPECIFIED; 331 } 332 333 334 /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute 335 of DECL is predetermined. */ 336 337 enum omp_clause_defaultmap_kind 338 gfc_omp_predetermined_mapping (tree decl) 339 { 340 if (DECL_ARTIFICIAL (decl) 341 && ! GFC_DECL_RESULT (decl) 342 && ! (DECL_LANG_SPECIFIC (decl) 343 && GFC_DECL_SAVED_DESCRIPTOR (decl))) 344 return OMP_CLAUSE_DEFAULTMAP_TO; 345 346 /* Dummy procedures aren't considered variables by OpenMP, thus are 347 disallowed in OpenMP clauses. They are represented as PARM_DECLs 348 in the middle-end, so return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE here 349 to avoid complaining about their uses with defaultmap(none). */ 350 if (TREE_CODE (decl) == PARM_DECL 351 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE 352 && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE) 353 return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE; 354 355 /* These are either array or derived parameters, or vtables. */ 356 if (VAR_P (decl) && TREE_READONLY (decl) 357 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) 358 return OMP_CLAUSE_DEFAULTMAP_TO; 359 360 return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED; 361 } 362 363 364 /* Return decl that should be used when reporting DEFAULT(NONE) 365 diagnostics. */ 366 367 tree 368 gfc_omp_report_decl (tree decl) 369 { 370 if (DECL_ARTIFICIAL (decl) 371 && DECL_LANG_SPECIFIC (decl) 372 && GFC_DECL_SAVED_DESCRIPTOR (decl)) 373 return GFC_DECL_SAVED_DESCRIPTOR (decl); 374 375 return decl; 376 } 377 378 /* Return true if TYPE has any allocatable components. */ 379 380 static bool 381 gfc_has_alloc_comps (tree type, tree decl) 382 { 383 tree field, ftype; 384 385 if (POINTER_TYPE_P (type)) 386 { 387 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)) 388 type = TREE_TYPE (type); 389 else if (GFC_DECL_GET_SCALAR_POINTER (decl)) 390 return false; 391 } 392 393 if (GFC_DESCRIPTOR_TYPE_P (type) 394 && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER 395 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)) 396 return false; 397 398 if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type)) 399 type = gfc_get_element_type (type); 400 401 if (TREE_CODE (type) != RECORD_TYPE) 402 return false; 403 404 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 405 { 406 ftype = TREE_TYPE (field); 407 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) 408 return true; 409 if (GFC_DESCRIPTOR_TYPE_P (ftype) 410 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) 411 return true; 412 if (gfc_has_alloc_comps (ftype, field)) 413 return true; 414 } 415 return false; 416 } 417 418 /* Return true if TYPE is a class container for a POINTER entity. */ 419 420 static bool 421 gfc_is_class_pointer_type (tree type) 422 { 423 tree name; 424 const char *s; 425 426 if (POINTER_TYPE_P (type)) 427 type = TREE_TYPE (type); 428 429 if (!GFC_CLASS_TYPE_P (type)) 430 return false; 431 432 name = TYPE_NAME (type); 433 if (name && TREE_CODE (name) == TYPE_DECL) 434 name = DECL_NAME (name); 435 if (!name) 436 return false; 437 438 s = IDENTIFIER_POINTER (name); 439 return startswith (s, "__class_") && s[strlen (s) - 1] == 'p'; 440 } 441 442 /* Return true if TYPE is polymorphic but not with pointer attribute. */ 443 444 static bool 445 gfc_is_polymorphic_nonptr (tree type) 446 { 447 if (POINTER_TYPE_P (type)) 448 type = TREE_TYPE (type); 449 return GFC_CLASS_TYPE_P (type); 450 } 451 452 /* Return true if TYPE is unlimited polymorphic but not with pointer attribute; 453 unlimited means also intrinsic types are handled and _len is used. */ 454 455 static bool 456 gfc_is_unlimited_polymorphic_nonptr (tree type) 457 { 458 if (POINTER_TYPE_P (type)) 459 type = TREE_TYPE (type); 460 if (!GFC_CLASS_TYPE_P (type)) 461 return false; 462 463 tree field = TYPE_FIELDS (type); /* _data */ 464 gcc_assert (field); 465 field = DECL_CHAIN (field); /* _vptr */ 466 gcc_assert (field); 467 field = DECL_CHAIN (field); 468 if (!field) 469 return false; 470 gcc_assert (strcmp ("_len", IDENTIFIER_POINTER (DECL_NAME (field))) == 0); 471 return true; 472 } 473 474 /* Return true if the DECL is for an allocatable array or scalar. */ 475 476 bool 477 gfc_omp_allocatable_p (tree decl) 478 { 479 if (!DECL_P (decl)) 480 return false; 481 482 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)) 483 return true; 484 485 tree type = TREE_TYPE (decl); 486 if (gfc_omp_privatize_by_reference (decl)) 487 type = TREE_TYPE (type); 488 489 if (GFC_DESCRIPTOR_TYPE_P (type) 490 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) 491 return true; 492 493 return false; 494 } 495 496 497 /* Return true if DECL in private clause needs 498 OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */ 499 bool 500 gfc_omp_private_outer_ref (tree decl) 501 { 502 tree type = TREE_TYPE (decl); 503 504 if (gfc_omp_privatize_by_reference (decl)) 505 type = TREE_TYPE (type); 506 507 if (GFC_DESCRIPTOR_TYPE_P (type) 508 && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) 509 return true; 510 511 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)) 512 return true; 513 514 if (gfc_has_alloc_comps (type, decl)) 515 return true; 516 517 return false; 518 } 519 520 /* Callback for gfc_omp_unshare_expr. */ 521 522 static tree 523 gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *) 524 { 525 tree t = *tp; 526 enum tree_code code = TREE_CODE (t); 527 528 /* Stop at types, decls, constants like copy_tree_r. */ 529 if (TREE_CODE_CLASS (code) == tcc_type 530 || TREE_CODE_CLASS (code) == tcc_declaration 531 || TREE_CODE_CLASS (code) == tcc_constant 532 || code == BLOCK) 533 *walk_subtrees = 0; 534 else if (handled_component_p (t) 535 || TREE_CODE (t) == MEM_REF) 536 { 537 *tp = unshare_expr (t); 538 *walk_subtrees = 0; 539 } 540 541 return NULL_TREE; 542 } 543 544 /* Unshare in expr anything that the FE which normally doesn't 545 care much about tree sharing (because during gimplification 546 everything is unshared) could cause problems with tree sharing 547 at omp-low.cc time. */ 548 549 static tree 550 gfc_omp_unshare_expr (tree expr) 551 { 552 walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL); 553 return expr; 554 } 555 556 enum walk_alloc_comps 557 { 558 WALK_ALLOC_COMPS_DTOR, 559 WALK_ALLOC_COMPS_DEFAULT_CTOR, 560 WALK_ALLOC_COMPS_COPY_CTOR 561 }; 562 563 /* Handle allocatable components in OpenMP clauses. */ 564 565 static tree 566 gfc_walk_alloc_comps (tree decl, tree dest, tree var, 567 enum walk_alloc_comps kind) 568 { 569 stmtblock_t block, tmpblock; 570 tree type = TREE_TYPE (decl), then_b, tem, field; 571 gfc_init_block (&block); 572 573 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type)) 574 { 575 if (GFC_DESCRIPTOR_TYPE_P (type)) 576 { 577 gfc_init_block (&tmpblock); 578 tem = gfc_full_array_size (&tmpblock, decl, 579 GFC_TYPE_ARRAY_RANK (type)); 580 then_b = gfc_finish_block (&tmpblock); 581 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b)); 582 tem = gfc_omp_unshare_expr (tem); 583 tem = fold_build2_loc (input_location, MINUS_EXPR, 584 gfc_array_index_type, tem, 585 gfc_index_one_node); 586 } 587 else 588 { 589 bool compute_nelts = false; 590 if (!TYPE_DOMAIN (type) 591 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE 592 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node 593 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node) 594 compute_nelts = true; 595 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) 596 { 597 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 598 if (lookup_attribute ("omp dummy var", a)) 599 compute_nelts = true; 600 } 601 if (compute_nelts) 602 { 603 tem = fold_build2 (EXACT_DIV_EXPR, sizetype, 604 TYPE_SIZE_UNIT (type), 605 TYPE_SIZE_UNIT (TREE_TYPE (type))); 606 tem = size_binop (MINUS_EXPR, tem, size_one_node); 607 } 608 else 609 tem = array_type_nelts (type); 610 tem = fold_convert (gfc_array_index_type, tem); 611 } 612 613 tree nelems = gfc_evaluate_now (tem, &block); 614 tree index = gfc_create_var (gfc_array_index_type, "S"); 615 616 gfc_init_block (&tmpblock); 617 tem = gfc_conv_array_data (decl); 618 tree declvar = build_fold_indirect_ref_loc (input_location, tem); 619 tree declvref = gfc_build_array_ref (declvar, index, NULL); 620 tree destvar, destvref = NULL_TREE; 621 if (dest) 622 { 623 tem = gfc_conv_array_data (dest); 624 destvar = build_fold_indirect_ref_loc (input_location, tem); 625 destvref = gfc_build_array_ref (destvar, index, NULL); 626 } 627 gfc_add_expr_to_block (&tmpblock, 628 gfc_walk_alloc_comps (declvref, destvref, 629 var, kind)); 630 631 gfc_loopinfo loop; 632 gfc_init_loopinfo (&loop); 633 loop.dimen = 1; 634 loop.from[0] = gfc_index_zero_node; 635 loop.loopvar[0] = index; 636 loop.to[0] = nelems; 637 gfc_trans_scalarizing_loops (&loop, &tmpblock); 638 gfc_add_block_to_block (&block, &loop.pre); 639 return gfc_finish_block (&block); 640 } 641 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var)) 642 { 643 decl = build_fold_indirect_ref_loc (input_location, decl); 644 if (dest) 645 dest = build_fold_indirect_ref_loc (input_location, dest); 646 type = TREE_TYPE (decl); 647 } 648 649 gcc_assert (TREE_CODE (type) == RECORD_TYPE); 650 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 651 { 652 tree ftype = TREE_TYPE (field); 653 tree declf, destf = NULL_TREE; 654 bool has_alloc_comps = gfc_has_alloc_comps (ftype, field); 655 if ((!GFC_DESCRIPTOR_TYPE_P (ftype) 656 || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE) 657 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field) 658 && !has_alloc_comps) 659 continue; 660 declf = fold_build3_loc (input_location, COMPONENT_REF, ftype, 661 decl, field, NULL_TREE); 662 if (dest) 663 destf = fold_build3_loc (input_location, COMPONENT_REF, ftype, 664 dest, field, NULL_TREE); 665 666 tem = NULL_TREE; 667 switch (kind) 668 { 669 case WALK_ALLOC_COMPS_DTOR: 670 break; 671 case WALK_ALLOC_COMPS_DEFAULT_CTOR: 672 if (GFC_DESCRIPTOR_TYPE_P (ftype) 673 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) 674 { 675 gfc_add_modify (&block, unshare_expr (destf), 676 unshare_expr (declf)); 677 tem = gfc_duplicate_allocatable_nocopy 678 (destf, declf, ftype, 679 GFC_TYPE_ARRAY_RANK (ftype)); 680 } 681 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) 682 tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0); 683 break; 684 case WALK_ALLOC_COMPS_COPY_CTOR: 685 if (GFC_DESCRIPTOR_TYPE_P (ftype) 686 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) 687 tem = gfc_duplicate_allocatable (destf, declf, ftype, 688 GFC_TYPE_ARRAY_RANK (ftype), 689 NULL_TREE); 690 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) 691 tem = gfc_duplicate_allocatable (destf, declf, ftype, 0, 692 NULL_TREE); 693 break; 694 } 695 if (tem) 696 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); 697 if (has_alloc_comps) 698 { 699 gfc_init_block (&tmpblock); 700 gfc_add_expr_to_block (&tmpblock, 701 gfc_walk_alloc_comps (declf, destf, 702 field, kind)); 703 then_b = gfc_finish_block (&tmpblock); 704 if (GFC_DESCRIPTOR_TYPE_P (ftype) 705 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) 706 tem = gfc_conv_descriptor_data_get (unshare_expr (declf)); 707 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) 708 tem = unshare_expr (declf); 709 else 710 tem = NULL_TREE; 711 if (tem) 712 { 713 tem = fold_convert (pvoid_type_node, tem); 714 tem = fold_build2_loc (input_location, NE_EXPR, 715 logical_type_node, tem, 716 null_pointer_node); 717 then_b = build3_loc (input_location, COND_EXPR, void_type_node, 718 tem, then_b, 719 build_empty_stmt (input_location)); 720 } 721 gfc_add_expr_to_block (&block, then_b); 722 } 723 if (kind == WALK_ALLOC_COMPS_DTOR) 724 { 725 if (GFC_DESCRIPTOR_TYPE_P (ftype) 726 && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE) 727 { 728 tem = gfc_conv_descriptor_data_get (unshare_expr (declf)); 729 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, 730 NULL_TREE, NULL_TREE, true, 731 NULL, 732 GFC_CAF_COARRAY_NOCOARRAY); 733 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); 734 } 735 else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field)) 736 { 737 tem = gfc_call_free (unshare_expr (declf)); 738 gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem)); 739 } 740 } 741 } 742 743 return gfc_finish_block (&block); 744 } 745 746 /* Return code to initialize DECL with its default constructor, or 747 NULL if there's nothing to do. */ 748 749 tree 750 gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer) 751 { 752 tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b; 753 stmtblock_t block, cond_block; 754 755 switch (OMP_CLAUSE_CODE (clause)) 756 { 757 case OMP_CLAUSE__LOOPTEMP_: 758 case OMP_CLAUSE__REDUCTEMP_: 759 case OMP_CLAUSE__CONDTEMP_: 760 case OMP_CLAUSE__SCANTEMP_: 761 return NULL; 762 case OMP_CLAUSE_PRIVATE: 763 case OMP_CLAUSE_LASTPRIVATE: 764 case OMP_CLAUSE_LINEAR: 765 case OMP_CLAUSE_REDUCTION: 766 case OMP_CLAUSE_IN_REDUCTION: 767 case OMP_CLAUSE_TASK_REDUCTION: 768 break; 769 default: 770 gcc_unreachable (); 771 } 772 773 if ((! GFC_DESCRIPTOR_TYPE_P (type) 774 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) 775 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) 776 || !POINTER_TYPE_P (type))) 777 { 778 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 779 { 780 gcc_assert (outer); 781 gfc_start_block (&block); 782 tree tem = gfc_walk_alloc_comps (outer, decl, 783 OMP_CLAUSE_DECL (clause), 784 WALK_ALLOC_COMPS_DEFAULT_CTOR); 785 gfc_add_expr_to_block (&block, tem); 786 return gfc_finish_block (&block); 787 } 788 return NULL_TREE; 789 } 790 791 gcc_assert (outer != NULL_TREE 792 || (!GFC_DESCRIPTOR_TYPE_P (type) 793 && !gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))); 794 795 /* Allocatable arrays and scalars in PRIVATE clauses need to be set to 796 "not currently allocated" allocation status if outer 797 array is "not currently allocated", otherwise should be allocated. */ 798 gfc_start_block (&block); 799 800 gfc_init_block (&cond_block); 801 802 if (GFC_DESCRIPTOR_TYPE_P (type)) 803 { 804 gfc_add_modify (&cond_block, decl, outer); 805 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; 806 size = gfc_conv_descriptor_ubound_get (decl, rank); 807 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 808 size, 809 gfc_conv_descriptor_lbound_get (decl, rank)); 810 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 811 size, gfc_index_one_node); 812 if (GFC_TYPE_ARRAY_RANK (type) > 1) 813 size = fold_build2_loc (input_location, MULT_EXPR, 814 gfc_array_index_type, size, 815 gfc_conv_descriptor_stride_get (decl, rank)); 816 tree esize = fold_convert (gfc_array_index_type, 817 TYPE_SIZE_UNIT (gfc_get_element_type (type))); 818 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, 819 size, esize); 820 size = unshare_expr (size); 821 size = gfc_evaluate_now (fold_convert (size_type_node, size), 822 &cond_block); 823 } 824 else 825 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); 826 ptr = gfc_create_var (pvoid_type_node, NULL); 827 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE); 828 if (GFC_DESCRIPTOR_TYPE_P (type)) 829 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr); 830 else 831 gfc_add_modify (&cond_block, unshare_expr (decl), 832 fold_convert (TREE_TYPE (decl), ptr)); 833 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 834 { 835 tree tem = gfc_walk_alloc_comps (outer, decl, 836 OMP_CLAUSE_DECL (clause), 837 WALK_ALLOC_COMPS_DEFAULT_CTOR); 838 gfc_add_expr_to_block (&cond_block, tem); 839 } 840 then_b = gfc_finish_block (&cond_block); 841 842 /* Reduction clause requires allocated ALLOCATABLE. */ 843 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION 844 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_IN_REDUCTION 845 && OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_TASK_REDUCTION) 846 { 847 gfc_init_block (&cond_block); 848 if (GFC_DESCRIPTOR_TYPE_P (type)) 849 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), 850 null_pointer_node); 851 else 852 gfc_add_modify (&cond_block, unshare_expr (decl), 853 build_zero_cst (TREE_TYPE (decl))); 854 else_b = gfc_finish_block (&cond_block); 855 856 tree tem = fold_convert (pvoid_type_node, 857 GFC_DESCRIPTOR_TYPE_P (type) 858 ? gfc_conv_descriptor_data_get (outer) : outer); 859 tem = unshare_expr (tem); 860 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 861 tem, null_pointer_node); 862 gfc_add_expr_to_block (&block, 863 build3_loc (input_location, COND_EXPR, 864 void_type_node, cond, then_b, 865 else_b)); 866 /* Avoid -W*uninitialized warnings. */ 867 if (DECL_P (decl)) 868 suppress_warning (decl, OPT_Wuninitialized); 869 } 870 else 871 gfc_add_expr_to_block (&block, then_b); 872 873 return gfc_finish_block (&block); 874 } 875 876 /* Build and return code for a copy constructor from SRC to DEST. */ 877 878 tree 879 gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) 880 { 881 tree type = TREE_TYPE (dest), ptr, size, call; 882 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause)); 883 tree orig_decl = OMP_CLAUSE_DECL (clause); 884 tree cond, then_b, else_b; 885 stmtblock_t block, cond_block; 886 887 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE 888 || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR); 889 890 if (DECL_ARTIFICIAL (orig_decl) 891 && DECL_LANG_SPECIFIC (orig_decl) 892 && GFC_DECL_SAVED_DESCRIPTOR (orig_decl)) 893 { 894 orig_decl = GFC_DECL_SAVED_DESCRIPTOR (orig_decl); 895 decl_type = TREE_TYPE (orig_decl); 896 } 897 898 /* Privatize pointer association only; cf. gfc_omp_predetermined_sharing. 899 This includes scalar class pointers, whose tree type is still the class 900 record even though the Fortran entity has POINTER semantics. */ 901 if (DECL_P (orig_decl) 902 && (GFC_DECL_ASSOCIATE_VAR_P (orig_decl) 903 || GFC_DECL_GET_SCALAR_POINTER (orig_decl) 904 || gfc_is_class_pointer_type (decl_type))) 905 return build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src); 906 907 if (gfc_is_polymorphic_nonptr (decl_type)) 908 { 909 if (POINTER_TYPE_P (decl_type)) 910 decl_type = TREE_TYPE (decl_type); 911 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type)); 912 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type)) 913 fatal_error (input_location, 914 "Sorry, polymorphic arrays not yet supported for " 915 "firstprivate"); 916 tree src_len; 917 tree nelems = build_int_cst (size_type_node, 1); /* Scalar. */ 918 tree src_data = gfc_class_data_get (unshare_expr (src)); 919 tree dest_data = gfc_class_data_get (unshare_expr (dest)); 920 bool unlimited = gfc_is_unlimited_polymorphic_nonptr (type); 921 922 gfc_start_block (&block); 923 gfc_add_modify (&block, gfc_class_vptr_get (dest), 924 gfc_class_vptr_get (src)); 925 gfc_init_block (&cond_block); 926 927 if (unlimited) 928 { 929 src_len = gfc_class_len_get (src); 930 gfc_add_modify (&cond_block, gfc_class_len_get (unshare_expr (dest)), src_len); 931 } 932 933 /* Use: size = class._vtab._size * (class._len > 0 ? class._len : 1). */ 934 size = fold_convert (size_type_node, gfc_class_vtab_size_get (src)); 935 if (unlimited) 936 { 937 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node, 938 unshare_expr (src_len), 939 build_zero_cst (TREE_TYPE (src_len))); 940 cond = build3_loc (input_location, COND_EXPR, size_type_node, cond, 941 fold_convert (size_type_node, 942 unshare_expr (src_len)), 943 build_int_cst (size_type_node, 1)); 944 size = fold_build2_loc (input_location, MULT_EXPR, size_type_node, 945 size, cond); 946 } 947 948 /* Malloc memory + call class->_vpt->_copy. */ 949 call = builtin_decl_explicit (BUILT_IN_MALLOC); 950 call = build_call_expr_loc (input_location, call, 1, size); 951 gfc_add_modify (&cond_block, dest_data, 952 fold_convert (TREE_TYPE (dest_data), call)); 953 gfc_add_expr_to_block (&cond_block, 954 gfc_copy_class_to_class (src, dest, nelems, 955 unlimited)); 956 957 gcc_assert (TREE_CODE (dest_data) == COMPONENT_REF); 958 if (!GFC_DECL_GET_SCALAR_ALLOCATABLE (TREE_OPERAND (dest_data, 1))) 959 { 960 gfc_add_block_to_block (&block, &cond_block); 961 } 962 else 963 { 964 /* Create: if (class._data != 0) <cond_block> else class._data = NULL; */ 965 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, 966 src_data, null_pointer_node); 967 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, 968 void_type_node, cond, 969 gfc_finish_block (&cond_block), 970 fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, 971 unshare_expr (dest_data), null_pointer_node))); 972 } 973 return gfc_finish_block (&block); 974 } 975 976 if ((! GFC_DESCRIPTOR_TYPE_P (type) 977 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) 978 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) 979 || !POINTER_TYPE_P (type))) 980 { 981 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 982 { 983 gfc_start_block (&block); 984 gfc_add_modify (&block, dest, src); 985 tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause), 986 WALK_ALLOC_COMPS_COPY_CTOR); 987 gfc_add_expr_to_block (&block, tem); 988 return gfc_finish_block (&block); 989 } 990 else 991 return build2_v (MODIFY_EXPR, dest, src); 992 } 993 994 /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated 995 and copied from SRC. */ 996 gfc_start_block (&block); 997 998 gfc_init_block (&cond_block); 999 1000 gfc_add_modify (&cond_block, dest, fold_convert (TREE_TYPE (dest), src)); 1001 if (GFC_DESCRIPTOR_TYPE_P (type)) 1002 { 1003 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; 1004 size = gfc_conv_descriptor_ubound_get (dest, rank); 1005 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 1006 size, 1007 gfc_conv_descriptor_lbound_get (dest, rank)); 1008 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 1009 size, gfc_index_one_node); 1010 if (GFC_TYPE_ARRAY_RANK (type) > 1) 1011 size = fold_build2_loc (input_location, MULT_EXPR, 1012 gfc_array_index_type, size, 1013 gfc_conv_descriptor_stride_get (dest, rank)); 1014 tree esize = fold_convert (gfc_array_index_type, 1015 TYPE_SIZE_UNIT (gfc_get_element_type (type))); 1016 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, 1017 size, esize); 1018 size = unshare_expr (size); 1019 size = gfc_evaluate_now (fold_convert (size_type_node, size), 1020 &cond_block); 1021 } 1022 else 1023 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); 1024 ptr = gfc_create_var (pvoid_type_node, NULL); 1025 gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE); 1026 if (GFC_DESCRIPTOR_TYPE_P (type)) 1027 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr); 1028 else 1029 gfc_add_modify (&cond_block, unshare_expr (dest), 1030 fold_convert (TREE_TYPE (dest), ptr)); 1031 1032 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type) 1033 ? gfc_conv_descriptor_data_get (src) : src; 1034 srcptr = unshare_expr (srcptr); 1035 srcptr = fold_convert (pvoid_type_node, srcptr); 1036 call = build_call_expr_loc (input_location, 1037 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr, 1038 srcptr, size); 1039 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); 1040 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1041 { 1042 tree tem = gfc_walk_alloc_comps (src, dest, 1043 OMP_CLAUSE_DECL (clause), 1044 WALK_ALLOC_COMPS_COPY_CTOR); 1045 gfc_add_expr_to_block (&cond_block, tem); 1046 } 1047 then_b = gfc_finish_block (&cond_block); 1048 1049 gfc_init_block (&cond_block); 1050 if (GFC_DESCRIPTOR_TYPE_P (type)) 1051 gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), 1052 null_pointer_node); 1053 else 1054 gfc_add_modify (&cond_block, unshare_expr (dest), 1055 build_zero_cst (TREE_TYPE (dest))); 1056 else_b = gfc_finish_block (&cond_block); 1057 1058 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1059 unshare_expr (srcptr), null_pointer_node); 1060 gfc_add_expr_to_block (&block, 1061 build3_loc (input_location, COND_EXPR, 1062 void_type_node, cond, then_b, else_b)); 1063 /* Avoid -W*uninitialized warnings. */ 1064 if (DECL_P (dest)) 1065 suppress_warning (dest, OPT_Wuninitialized); 1066 1067 return gfc_finish_block (&block); 1068 } 1069 1070 /* Similarly, except use an intrinsic or pointer assignment operator 1071 instead. */ 1072 1073 tree 1074 gfc_omp_clause_assign_op (tree clause, tree dest, tree src) 1075 { 1076 tree type = TREE_TYPE (dest), ptr, size, call, nonalloc; 1077 tree cond, then_b, else_b; 1078 stmtblock_t block, cond_block, cond_block2, inner_block; 1079 1080 if ((! GFC_DESCRIPTOR_TYPE_P (type) 1081 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) 1082 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) 1083 || !POINTER_TYPE_P (type))) 1084 { 1085 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1086 { 1087 gfc_start_block (&block); 1088 /* First dealloc any allocatable components in DEST. */ 1089 tree tem = gfc_walk_alloc_comps (dest, NULL_TREE, 1090 OMP_CLAUSE_DECL (clause), 1091 WALK_ALLOC_COMPS_DTOR); 1092 gfc_add_expr_to_block (&block, tem); 1093 /* Then copy over toplevel data. */ 1094 gfc_add_modify (&block, dest, src); 1095 /* Finally allocate any allocatable components and copy. */ 1096 tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause), 1097 WALK_ALLOC_COMPS_COPY_CTOR); 1098 gfc_add_expr_to_block (&block, tem); 1099 return gfc_finish_block (&block); 1100 } 1101 else 1102 return build2_v (MODIFY_EXPR, dest, src); 1103 } 1104 1105 gfc_start_block (&block); 1106 1107 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1108 { 1109 then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause), 1110 WALK_ALLOC_COMPS_DTOR); 1111 tree tem = fold_convert (pvoid_type_node, 1112 GFC_DESCRIPTOR_TYPE_P (type) 1113 ? gfc_conv_descriptor_data_get (dest) : dest); 1114 tem = unshare_expr (tem); 1115 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1116 tem, null_pointer_node); 1117 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond, 1118 then_b, build_empty_stmt (input_location)); 1119 gfc_add_expr_to_block (&block, tem); 1120 } 1121 1122 gfc_init_block (&cond_block); 1123 1124 if (GFC_DESCRIPTOR_TYPE_P (type)) 1125 { 1126 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; 1127 size = gfc_conv_descriptor_ubound_get (src, rank); 1128 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 1129 size, 1130 gfc_conv_descriptor_lbound_get (src, rank)); 1131 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 1132 size, gfc_index_one_node); 1133 if (GFC_TYPE_ARRAY_RANK (type) > 1) 1134 size = fold_build2_loc (input_location, MULT_EXPR, 1135 gfc_array_index_type, size, 1136 gfc_conv_descriptor_stride_get (src, rank)); 1137 tree esize = fold_convert (gfc_array_index_type, 1138 TYPE_SIZE_UNIT (gfc_get_element_type (type))); 1139 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, 1140 size, esize); 1141 size = unshare_expr (size); 1142 size = gfc_evaluate_now (fold_convert (size_type_node, size), 1143 &cond_block); 1144 } 1145 else 1146 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); 1147 ptr = gfc_create_var (pvoid_type_node, NULL); 1148 1149 tree destptr = GFC_DESCRIPTOR_TYPE_P (type) 1150 ? gfc_conv_descriptor_data_get (dest) : dest; 1151 destptr = unshare_expr (destptr); 1152 destptr = fold_convert (pvoid_type_node, destptr); 1153 gfc_add_modify (&cond_block, ptr, destptr); 1154 1155 nonalloc = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, 1156 destptr, null_pointer_node); 1157 cond = nonalloc; 1158 if (GFC_DESCRIPTOR_TYPE_P (type)) 1159 { 1160 int i; 1161 for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++) 1162 { 1163 tree rank = gfc_rank_cst[i]; 1164 tree tem = gfc_conv_descriptor_ubound_get (src, rank); 1165 tem = fold_build2_loc (input_location, MINUS_EXPR, 1166 gfc_array_index_type, tem, 1167 gfc_conv_descriptor_lbound_get (src, rank)); 1168 tem = fold_build2_loc (input_location, PLUS_EXPR, 1169 gfc_array_index_type, tem, 1170 gfc_conv_descriptor_lbound_get (dest, rank)); 1171 tem = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1172 tem, gfc_conv_descriptor_ubound_get (dest, 1173 rank)); 1174 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR, 1175 logical_type_node, cond, tem); 1176 } 1177 } 1178 1179 gfc_init_block (&cond_block2); 1180 1181 if (GFC_DESCRIPTOR_TYPE_P (type)) 1182 { 1183 gfc_init_block (&inner_block); 1184 gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE); 1185 then_b = gfc_finish_block (&inner_block); 1186 1187 gfc_init_block (&inner_block); 1188 gfc_add_modify (&inner_block, ptr, 1189 gfc_call_realloc (&inner_block, ptr, size)); 1190 else_b = gfc_finish_block (&inner_block); 1191 1192 gfc_add_expr_to_block (&cond_block2, 1193 build3_loc (input_location, COND_EXPR, 1194 void_type_node, 1195 unshare_expr (nonalloc), 1196 then_b, else_b)); 1197 gfc_add_modify (&cond_block2, dest, src); 1198 gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr); 1199 } 1200 else 1201 { 1202 gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE); 1203 gfc_add_modify (&cond_block2, unshare_expr (dest), 1204 fold_convert (type, ptr)); 1205 } 1206 then_b = gfc_finish_block (&cond_block2); 1207 else_b = build_empty_stmt (input_location); 1208 1209 gfc_add_expr_to_block (&cond_block, 1210 build3_loc (input_location, COND_EXPR, 1211 void_type_node, unshare_expr (cond), 1212 then_b, else_b)); 1213 1214 tree srcptr = GFC_DESCRIPTOR_TYPE_P (type) 1215 ? gfc_conv_descriptor_data_get (src) : src; 1216 srcptr = unshare_expr (srcptr); 1217 srcptr = fold_convert (pvoid_type_node, srcptr); 1218 call = build_call_expr_loc (input_location, 1219 builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr, 1220 srcptr, size); 1221 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); 1222 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1223 { 1224 tree tem = gfc_walk_alloc_comps (src, dest, 1225 OMP_CLAUSE_DECL (clause), 1226 WALK_ALLOC_COMPS_COPY_CTOR); 1227 gfc_add_expr_to_block (&cond_block, tem); 1228 } 1229 then_b = gfc_finish_block (&cond_block); 1230 1231 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN) 1232 { 1233 gfc_init_block (&cond_block); 1234 if (GFC_DESCRIPTOR_TYPE_P (type)) 1235 { 1236 tree tmp = gfc_conv_descriptor_data_get (unshare_expr (dest)); 1237 tmp = gfc_deallocate_with_status (tmp, NULL_TREE, NULL_TREE, 1238 NULL_TREE, NULL_TREE, true, NULL, 1239 GFC_CAF_COARRAY_NOCOARRAY); 1240 gfc_add_expr_to_block (&cond_block, tmp); 1241 } 1242 else 1243 { 1244 destptr = gfc_evaluate_now (destptr, &cond_block); 1245 gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr)); 1246 gfc_add_modify (&cond_block, unshare_expr (dest), 1247 build_zero_cst (TREE_TYPE (dest))); 1248 } 1249 else_b = gfc_finish_block (&cond_block); 1250 1251 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1252 unshare_expr (srcptr), null_pointer_node); 1253 gfc_add_expr_to_block (&block, 1254 build3_loc (input_location, COND_EXPR, 1255 void_type_node, cond, 1256 then_b, else_b)); 1257 } 1258 else 1259 gfc_add_expr_to_block (&block, then_b); 1260 1261 return gfc_finish_block (&block); 1262 } 1263 1264 static void 1265 gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src, 1266 tree add, tree nelems) 1267 { 1268 stmtblock_t tmpblock; 1269 tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S"); 1270 nelems = gfc_evaluate_now (nelems, block); 1271 1272 gfc_init_block (&tmpblock); 1273 if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE) 1274 { 1275 desta = gfc_build_array_ref (dest, index, NULL); 1276 srca = gfc_build_array_ref (src, index, NULL); 1277 } 1278 else 1279 { 1280 gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest))); 1281 tree idx = fold_build2 (MULT_EXPR, sizetype, 1282 fold_convert (sizetype, index), 1283 TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest)))); 1284 desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR, 1285 TREE_TYPE (dest), dest, 1286 idx)); 1287 srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR, 1288 TREE_TYPE (src), src, 1289 idx)); 1290 } 1291 gfc_add_modify (&tmpblock, desta, 1292 fold_build2 (PLUS_EXPR, TREE_TYPE (desta), 1293 srca, add)); 1294 1295 gfc_loopinfo loop; 1296 gfc_init_loopinfo (&loop); 1297 loop.dimen = 1; 1298 loop.from[0] = gfc_index_zero_node; 1299 loop.loopvar[0] = index; 1300 loop.to[0] = nelems; 1301 gfc_trans_scalarizing_loops (&loop, &tmpblock); 1302 gfc_add_block_to_block (block, &loop.pre); 1303 } 1304 1305 /* Build and return code for a constructor of DEST that initializes 1306 it to SRC plus ADD (ADD is scalar integer). */ 1307 1308 tree 1309 gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add) 1310 { 1311 tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE; 1312 stmtblock_t block; 1313 1314 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR); 1315 1316 gfc_start_block (&block); 1317 add = gfc_evaluate_now (add, &block); 1318 1319 if ((! GFC_DESCRIPTOR_TYPE_P (type) 1320 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) 1321 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) 1322 || !POINTER_TYPE_P (type))) 1323 { 1324 bool compute_nelts = false; 1325 gcc_assert (TREE_CODE (type) == ARRAY_TYPE); 1326 if (!TYPE_DOMAIN (type) 1327 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE 1328 || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node 1329 || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node) 1330 compute_nelts = true; 1331 else if (VAR_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) 1332 { 1333 tree a = DECL_ATTRIBUTES (TYPE_MAX_VALUE (TYPE_DOMAIN (type))); 1334 if (lookup_attribute ("omp dummy var", a)) 1335 compute_nelts = true; 1336 } 1337 if (compute_nelts) 1338 { 1339 nelems = fold_build2 (EXACT_DIV_EXPR, sizetype, 1340 TYPE_SIZE_UNIT (type), 1341 TYPE_SIZE_UNIT (TREE_TYPE (type))); 1342 nelems = size_binop (MINUS_EXPR, nelems, size_one_node); 1343 } 1344 else 1345 nelems = array_type_nelts (type); 1346 nelems = fold_convert (gfc_array_index_type, nelems); 1347 1348 gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems); 1349 return gfc_finish_block (&block); 1350 } 1351 1352 /* Allocatable arrays in LINEAR clauses need to be allocated 1353 and copied from SRC. */ 1354 gfc_add_modify (&block, dest, src); 1355 if (GFC_DESCRIPTOR_TYPE_P (type)) 1356 { 1357 tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1]; 1358 size = gfc_conv_descriptor_ubound_get (dest, rank); 1359 size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, 1360 size, 1361 gfc_conv_descriptor_lbound_get (dest, rank)); 1362 size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, 1363 size, gfc_index_one_node); 1364 if (GFC_TYPE_ARRAY_RANK (type) > 1) 1365 size = fold_build2_loc (input_location, MULT_EXPR, 1366 gfc_array_index_type, size, 1367 gfc_conv_descriptor_stride_get (dest, rank)); 1368 tree esize = fold_convert (gfc_array_index_type, 1369 TYPE_SIZE_UNIT (gfc_get_element_type (type))); 1370 nelems = gfc_evaluate_now (unshare_expr (size), &block); 1371 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, 1372 nelems, unshare_expr (esize)); 1373 size = gfc_evaluate_now (fold_convert (size_type_node, size), 1374 &block); 1375 nelems = fold_build2_loc (input_location, MINUS_EXPR, 1376 gfc_array_index_type, nelems, 1377 gfc_index_one_node); 1378 } 1379 else 1380 size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type))); 1381 ptr = gfc_create_var (pvoid_type_node, NULL); 1382 gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE); 1383 if (GFC_DESCRIPTOR_TYPE_P (type)) 1384 { 1385 gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr); 1386 tree etype = gfc_get_element_type (type); 1387 ptr = fold_convert (build_pointer_type (etype), ptr); 1388 tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src)); 1389 srcptr = fold_convert (build_pointer_type (etype), srcptr); 1390 gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems); 1391 } 1392 else 1393 { 1394 gfc_add_modify (&block, unshare_expr (dest), 1395 fold_convert (TREE_TYPE (dest), ptr)); 1396 ptr = fold_convert (TREE_TYPE (dest), ptr); 1397 tree dstm = build_fold_indirect_ref (ptr); 1398 tree srcm = build_fold_indirect_ref (unshare_expr (src)); 1399 gfc_add_modify (&block, dstm, 1400 fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add)); 1401 } 1402 return gfc_finish_block (&block); 1403 } 1404 1405 /* Build and return code destructing DECL. Return NULL if nothing 1406 to be done. */ 1407 1408 tree 1409 gfc_omp_clause_dtor (tree clause, tree decl) 1410 { 1411 tree type = TREE_TYPE (decl), tem; 1412 tree decl_type = TREE_TYPE (OMP_CLAUSE_DECL (clause)); 1413 tree orig_decl = OMP_CLAUSE_DECL (clause); 1414 1415 if (DECL_ARTIFICIAL (orig_decl) 1416 && DECL_LANG_SPECIFIC (orig_decl) 1417 && GFC_DECL_SAVED_DESCRIPTOR (orig_decl)) 1418 { 1419 orig_decl = GFC_DECL_SAVED_DESCRIPTOR (orig_decl); 1420 decl_type = TREE_TYPE (orig_decl); 1421 } 1422 1423 /* Only pointer association was privatized; cf. gfc_omp_clause_copy_ctr. 1424 Scalar class pointers must not finalize or free their targets here. */ 1425 if (DECL_P (orig_decl) 1426 && (GFC_DECL_ASSOCIATE_VAR_P (orig_decl) 1427 || GFC_DECL_GET_SCALAR_POINTER (orig_decl) 1428 || gfc_is_class_pointer_type (decl_type))) 1429 return NULL_TREE; 1430 1431 if (gfc_is_polymorphic_nonptr (decl_type)) 1432 { 1433 if (POINTER_TYPE_P (decl_type)) 1434 decl_type = TREE_TYPE (decl_type); 1435 decl_type = TREE_TYPE (TYPE_FIELDS (decl_type)); 1436 if (GFC_DESCRIPTOR_TYPE_P (decl_type) || GFC_ARRAY_TYPE_P (decl_type)) 1437 fatal_error (input_location, 1438 "Sorry, polymorphic arrays not yet supported for " 1439 "firstprivate"); 1440 stmtblock_t block, cond_block; 1441 gfc_start_block (&block); 1442 gfc_init_block (&cond_block); 1443 tree final = gfc_class_vtab_final_get (decl); 1444 tree size = fold_convert (size_type_node, gfc_class_vtab_size_get (decl)); 1445 gfc_se se; 1446 gfc_init_se (&se, NULL); 1447 symbol_attribute attr = {}; 1448 tree data = gfc_class_data_get (decl); 1449 tree desc = gfc_conv_scalar_to_descriptor (&se, data, attr); 1450 1451 /* Call class->_vpt->_finalize + free. */ 1452 tree call = build_fold_indirect_ref (final); 1453 call = build_call_expr_loc (input_location, call, 3, 1454 gfc_build_addr_expr (NULL, desc), 1455 size, boolean_false_node); 1456 gfc_add_block_to_block (&cond_block, &se.pre); 1457 gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call)); 1458 gfc_add_block_to_block (&cond_block, &se.post); 1459 /* Create: if (_vtab && _final) <cond_block> */ 1460 tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, 1461 gfc_class_vptr_get (decl), 1462 null_pointer_node); 1463 tree cond2 = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, 1464 final, null_pointer_node); 1465 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR, 1466 boolean_type_node, cond, cond2); 1467 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, 1468 void_type_node, cond, 1469 gfc_finish_block (&cond_block), NULL_TREE)); 1470 call = builtin_decl_explicit (BUILT_IN_FREE); 1471 call = build_call_expr_loc (input_location, call, 1, data); 1472 gfc_add_expr_to_block (&block, fold_convert (void_type_node, call)); 1473 return gfc_finish_block (&block); 1474 } 1475 1476 if ((! GFC_DESCRIPTOR_TYPE_P (type) 1477 || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE) 1478 && (!GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)) 1479 || !POINTER_TYPE_P (type))) 1480 { 1481 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1482 return gfc_walk_alloc_comps (decl, NULL_TREE, 1483 OMP_CLAUSE_DECL (clause), 1484 WALK_ALLOC_COMPS_DTOR); 1485 return NULL_TREE; 1486 } 1487 1488 if (GFC_DESCRIPTOR_TYPE_P (type)) 1489 { 1490 /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need 1491 to be deallocated if they were allocated. */ 1492 tem = gfc_conv_descriptor_data_get (decl); 1493 tem = gfc_deallocate_with_status (tem, NULL_TREE, NULL_TREE, NULL_TREE, 1494 NULL_TREE, true, NULL, 1495 GFC_CAF_COARRAY_NOCOARRAY); 1496 } 1497 else 1498 tem = gfc_call_free (decl); 1499 tem = gfc_omp_unshare_expr (tem); 1500 1501 if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause))) 1502 { 1503 stmtblock_t block; 1504 tree then_b; 1505 1506 gfc_init_block (&block); 1507 gfc_add_expr_to_block (&block, 1508 gfc_walk_alloc_comps (decl, NULL_TREE, 1509 OMP_CLAUSE_DECL (clause), 1510 WALK_ALLOC_COMPS_DTOR)); 1511 gfc_add_expr_to_block (&block, tem); 1512 then_b = gfc_finish_block (&block); 1513 1514 tem = fold_convert (pvoid_type_node, 1515 GFC_DESCRIPTOR_TYPE_P (type) 1516 ? gfc_conv_descriptor_data_get (decl) : decl); 1517 tem = unshare_expr (tem); 1518 tree cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, 1519 tem, null_pointer_node); 1520 tem = build3_loc (input_location, COND_EXPR, void_type_node, cond, 1521 then_b, build_empty_stmt (input_location)); 1522 } 1523 return tem; 1524 } 1525 1526 /* Build a conditional expression in BLOCK. If COND_VAL is not 1527 null, then the block THEN_B is executed, otherwise ELSE_VAL 1528 is assigned to VAL. */ 1529 1530 static void 1531 gfc_build_cond_assign (stmtblock_t *block, tree val, tree cond_val, 1532 tree then_b, tree else_val) 1533 { 1534 stmtblock_t cond_block; 1535 tree else_b = NULL_TREE; 1536 tree val_ty = TREE_TYPE (val); 1537 1538 if (else_val) 1539 { 1540 gfc_init_block (&cond_block); 1541 gfc_add_modify (&cond_block, val, fold_convert (val_ty, else_val)); 1542 else_b = gfc_finish_block (&cond_block); 1543 } 1544 gfc_add_expr_to_block (block, 1545 build3_loc (input_location, COND_EXPR, void_type_node, 1546 cond_val, then_b, else_b)); 1547 } 1548 1549 /* Build a conditional expression in BLOCK, returning a temporary 1550 variable containing the result. If COND_VAL is not null, then 1551 THEN_VAL will be assigned to the variable, otherwise ELSE_VAL 1552 is assigned. 1553 */ 1554 1555 static tree 1556 gfc_build_cond_assign_expr (stmtblock_t *block, tree cond_val, 1557 tree then_val, tree else_val) 1558 { 1559 tree val; 1560 tree val_ty = TREE_TYPE (then_val); 1561 stmtblock_t cond_block; 1562 1563 val = create_tmp_var (val_ty); 1564 1565 gfc_init_block (&cond_block); 1566 gfc_add_modify (&cond_block, val, then_val); 1567 tree then_b = gfc_finish_block (&cond_block); 1568 1569 gfc_build_cond_assign (block, val, cond_val, then_b, else_val); 1570 1571 return val; 1572 } 1573 1574 void 1575 gfc_omp_finish_clause (tree c, gimple_seq *pre_p, bool openacc) 1576 { 1577 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) 1578 return; 1579 1580 tree decl = OMP_CLAUSE_DECL (c); 1581 1582 /* Assumed-size arrays can't be mapped implicitly, they have to be 1583 mapped explicitly using array sections. */ 1584 if (TREE_CODE (decl) == PARM_DECL 1585 && GFC_ARRAY_TYPE_P (TREE_TYPE (decl)) 1586 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN 1587 && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl), 1588 GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1) 1589 == NULL) 1590 { 1591 error_at (OMP_CLAUSE_LOCATION (c), 1592 "implicit mapping of assumed size array %qD", decl); 1593 return; 1594 } 1595 1596 tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE; 1597 tree present = gfc_omp_check_optional_argument (decl, true); 1598 if (POINTER_TYPE_P (TREE_TYPE (decl))) 1599 { 1600 if (!gfc_omp_privatize_by_reference (decl) 1601 && !GFC_DECL_GET_SCALAR_POINTER (decl) 1602 && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) 1603 && !GFC_DECL_CRAY_POINTEE (decl) 1604 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))) 1605 return; 1606 tree orig_decl = decl; 1607 1608 c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); 1609 OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER); 1610 OMP_CLAUSE_DECL (c4) = decl; 1611 OMP_CLAUSE_SIZE (c4) = size_int (0); 1612 decl = build_fold_indirect_ref (decl); 1613 if (present 1614 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl) 1615 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl))) 1616 { 1617 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 1618 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER); 1619 OMP_CLAUSE_DECL (c2) = decl; 1620 OMP_CLAUSE_SIZE (c2) = size_int (0); 1621 1622 stmtblock_t block; 1623 gfc_start_block (&block); 1624 tree ptr = decl; 1625 ptr = gfc_build_cond_assign_expr (&block, present, decl, 1626 null_pointer_node); 1627 gimplify_and_add (gfc_finish_block (&block), pre_p); 1628 ptr = build_fold_indirect_ref (ptr); 1629 OMP_CLAUSE_DECL (c) = ptr; 1630 OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (ptr)); 1631 } 1632 else 1633 { 1634 OMP_CLAUSE_DECL (c) = decl; 1635 OMP_CLAUSE_SIZE (c) = NULL_TREE; 1636 } 1637 if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE 1638 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl) 1639 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl))) 1640 { 1641 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); 1642 OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER); 1643 OMP_CLAUSE_DECL (c3) = unshare_expr (decl); 1644 OMP_CLAUSE_SIZE (c3) = size_int (0); 1645 decl = build_fold_indirect_ref (decl); 1646 OMP_CLAUSE_DECL (c) = decl; 1647 } 1648 } 1649 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 1650 { 1651 stmtblock_t block; 1652 gfc_start_block (&block); 1653 tree type = TREE_TYPE (decl); 1654 tree ptr = gfc_conv_descriptor_data_get (decl); 1655 1656 /* OpenMP: automatically map pointer targets with the pointer; 1657 hence, always update the descriptor/pointer itself. 1658 NOTE: This also remaps the pointer for allocatable arrays with 1659 'target' attribute which also don't have the 'restrict' qualifier. */ 1660 bool always_modifier = false; 1661 1662 if (!openacc 1663 && !(TYPE_QUALS (TREE_TYPE (ptr)) & TYPE_QUAL_RESTRICT)) 1664 always_modifier = true; 1665 1666 if (present) 1667 ptr = gfc_build_cond_assign_expr (&block, present, ptr, 1668 null_pointer_node); 1669 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 1670 ptr = build_fold_indirect_ref (ptr); 1671 OMP_CLAUSE_DECL (c) = ptr; 1672 c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 1673 OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET); 1674 if (present) 1675 { 1676 ptr = create_tmp_var (TREE_TYPE (TREE_OPERAND (decl, 0))); 1677 gfc_add_modify (&block, ptr, TREE_OPERAND (decl, 0)); 1678 1679 OMP_CLAUSE_DECL (c2) = build_fold_indirect_ref (ptr); 1680 } 1681 else 1682 OMP_CLAUSE_DECL (c2) = decl; 1683 OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type); 1684 c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); 1685 OMP_CLAUSE_SET_MAP_KIND (c3, always_modifier ? GOMP_MAP_ALWAYS_POINTER 1686 : GOMP_MAP_POINTER); 1687 if (present) 1688 { 1689 ptr = gfc_conv_descriptor_data_get (decl); 1690 ptr = gfc_build_addr_expr (NULL, ptr); 1691 ptr = gfc_build_cond_assign_expr (&block, present, 1692 ptr, null_pointer_node); 1693 ptr = build_fold_indirect_ref (ptr); 1694 OMP_CLAUSE_DECL (c3) = ptr; 1695 } 1696 else 1697 OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl); 1698 OMP_CLAUSE_SIZE (c3) = size_int (0); 1699 tree size = create_tmp_var (gfc_array_index_type); 1700 tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 1701 elemsz = fold_convert (gfc_array_index_type, elemsz); 1702 if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE 1703 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER 1704 || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT) 1705 { 1706 stmtblock_t cond_block; 1707 tree tem, then_b, else_b, zero, cond; 1708 1709 gfc_init_block (&cond_block); 1710 tem = gfc_full_array_size (&cond_block, decl, 1711 GFC_TYPE_ARRAY_RANK (type)); 1712 gfc_add_modify (&cond_block, size, tem); 1713 gfc_add_modify (&cond_block, size, 1714 fold_build2 (MULT_EXPR, gfc_array_index_type, 1715 size, elemsz)); 1716 then_b = gfc_finish_block (&cond_block); 1717 gfc_init_block (&cond_block); 1718 zero = build_int_cst (gfc_array_index_type, 0); 1719 gfc_add_modify (&cond_block, size, zero); 1720 else_b = gfc_finish_block (&cond_block); 1721 tem = gfc_conv_descriptor_data_get (decl); 1722 tem = fold_convert (pvoid_type_node, tem); 1723 cond = fold_build2_loc (input_location, NE_EXPR, 1724 boolean_type_node, tem, null_pointer_node); 1725 if (present) 1726 { 1727 cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR, 1728 boolean_type_node, present, cond); 1729 } 1730 gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR, 1731 void_type_node, cond, 1732 then_b, else_b)); 1733 } 1734 else if (present) 1735 { 1736 stmtblock_t cond_block; 1737 tree then_b; 1738 1739 gfc_init_block (&cond_block); 1740 gfc_add_modify (&cond_block, size, 1741 gfc_full_array_size (&cond_block, decl, 1742 GFC_TYPE_ARRAY_RANK (type))); 1743 gfc_add_modify (&cond_block, size, 1744 fold_build2 (MULT_EXPR, gfc_array_index_type, 1745 size, elemsz)); 1746 then_b = gfc_finish_block (&cond_block); 1747 1748 gfc_build_cond_assign (&block, size, present, then_b, 1749 build_int_cst (gfc_array_index_type, 0)); 1750 } 1751 else 1752 { 1753 gfc_add_modify (&block, size, 1754 gfc_full_array_size (&block, decl, 1755 GFC_TYPE_ARRAY_RANK (type))); 1756 gfc_add_modify (&block, size, 1757 fold_build2 (MULT_EXPR, gfc_array_index_type, 1758 size, elemsz)); 1759 } 1760 OMP_CLAUSE_SIZE (c) = size; 1761 tree stmt = gfc_finish_block (&block); 1762 gimplify_and_add (stmt, pre_p); 1763 } 1764 tree last = c; 1765 if (OMP_CLAUSE_SIZE (c) == NULL_TREE) 1766 { 1767 if (DECL_P (decl)) 1768 OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl); 1769 else 1770 { 1771 tree type = TREE_TYPE (decl); 1772 tree size = TYPE_SIZE_UNIT (type); 1773 /* For variable-length character types, TYPE_SIZE_UNIT is a 1774 SAVE_EXPR. Gimplifying the SAVE_EXPR (here or elsewhere) 1775 resolves it in place, embedding a gimple temporary that 1776 later causes an ICE in remap_type during inlining because 1777 the temporary is not in scope (PR101760, PR102314). 1778 Compute the size from the array domain and element size 1779 to decouple completely from the type's SAVE_EXPRs. */ 1780 if (size 1781 && TREE_CODE (type) == ARRAY_TYPE 1782 && TYPE_DOMAIN (type) 1783 && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) 1784 && !TREE_CONSTANT (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))) 1785 { 1786 tree len = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); 1787 tree lb = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); 1788 tree eltsz = TYPE_SIZE_UNIT (TREE_TYPE (type)); 1789 len = fold_build2 (MINUS_EXPR, TREE_TYPE (len), len, lb); 1790 len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, 1791 build_one_cst (TREE_TYPE (len))); 1792 size = fold_build2 (MULT_EXPR, sizetype, 1793 fold_convert (sizetype, len), 1794 fold_convert (sizetype, eltsz)); 1795 } 1796 OMP_CLAUSE_SIZE (c) = size; 1797 } 1798 } 1799 if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, 1800 NULL, is_gimple_val, fb_rvalue) == GS_ERROR) 1801 OMP_CLAUSE_SIZE (c) = size_int (0); 1802 if (c2) 1803 { 1804 OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last); 1805 OMP_CLAUSE_CHAIN (last) = c2; 1806 last = c2; 1807 } 1808 if (c3) 1809 { 1810 OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last); 1811 OMP_CLAUSE_CHAIN (last) = c3; 1812 last = c3; 1813 } 1814 if (c4) 1815 { 1816 OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last); 1817 OMP_CLAUSE_CHAIN (last) = c4; 1818 } 1819 } 1820 1821 1822 /* Return true if DECL is a scalar variable (for the purpose of 1823 implicit firstprivatization/mapping). Only if 'ptr_alloc_ok.' 1824 is true, allocatables and pointers are permitted. */ 1825 1826 bool 1827 gfc_omp_scalar_p (tree decl, bool ptr_alloc_ok) 1828 { 1829 tree type = TREE_TYPE (decl); 1830 if (TREE_CODE (type) == REFERENCE_TYPE) 1831 type = TREE_TYPE (type); 1832 if (TREE_CODE (type) == POINTER_TYPE) 1833 { 1834 if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) 1835 || GFC_DECL_GET_SCALAR_POINTER (decl)) 1836 { 1837 if (!ptr_alloc_ok) 1838 return false; 1839 type = TREE_TYPE (type); 1840 } 1841 if (GFC_ARRAY_TYPE_P (type) 1842 || GFC_CLASS_TYPE_P (type)) 1843 return false; 1844 } 1845 if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE) 1846 && TYPE_STRING_FLAG (type)) 1847 return false; 1848 if (INTEGRAL_TYPE_P (type) 1849 || SCALAR_FLOAT_TYPE_P (type) 1850 || COMPLEX_FLOAT_TYPE_P (type)) 1851 return true; 1852 return false; 1853 } 1854 1855 1856 /* Return true if DECL is a scalar with target attribute but does not have the 1857 allocatable (or pointer) attribute (for the purpose of implicit mapping). */ 1858 1859 bool 1860 gfc_omp_scalar_target_p (tree decl) 1861 { 1862 return (DECL_P (decl) && GFC_DECL_GET_SCALAR_TARGET (decl) 1863 && gfc_omp_scalar_p (decl, false)); 1864 } 1865 1866 1867 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be 1868 disregarded in OpenMP construct, because it is going to be 1869 remapped during OpenMP lowering. SHARED is true if DECL 1870 is going to be shared, false if it is going to be privatized. */ 1871 1872 bool 1873 gfc_omp_disregard_value_expr (tree decl, bool shared) 1874 { 1875 if (GFC_DECL_COMMON_OR_EQUIV (decl) 1876 && DECL_HAS_VALUE_EXPR_P (decl)) 1877 { 1878 tree value = DECL_VALUE_EXPR (decl); 1879 1880 if (TREE_CODE (value) == COMPONENT_REF 1881 && VAR_P (TREE_OPERAND (value, 0)) 1882 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0))) 1883 { 1884 /* If variable in COMMON or EQUIVALENCE is privatized, return 1885 true, as just that variable is supposed to be privatized, 1886 not the whole COMMON or whole EQUIVALENCE. 1887 For shared variables in COMMON or EQUIVALENCE, let them be 1888 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars 1889 from the same COMMON or EQUIVALENCE just one sharing of the 1890 whole COMMON or EQUIVALENCE is enough. */ 1891 return ! shared; 1892 } 1893 } 1894 1895 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl)) 1896 return ! shared; 1897 1898 return false; 1899 } 1900 1901 /* Return true if DECL that is shared iff SHARED is true should 1902 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG 1903 flag set. */ 1904 1905 bool 1906 gfc_omp_private_debug_clause (tree decl, bool shared) 1907 { 1908 if (GFC_DECL_CRAY_POINTEE (decl)) 1909 return true; 1910 1911 if (GFC_DECL_COMMON_OR_EQUIV (decl) 1912 && DECL_HAS_VALUE_EXPR_P (decl)) 1913 { 1914 tree value = DECL_VALUE_EXPR (decl); 1915 1916 if (TREE_CODE (value) == COMPONENT_REF 1917 && VAR_P (TREE_OPERAND (value, 0)) 1918 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0))) 1919 return shared; 1920 } 1921 1922 return false; 1923 } 1924 1925 /* Register language specific type size variables as potentially OpenMP 1926 firstprivate variables. */ 1927 1928 void 1929 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type) 1930 { 1931 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type)) 1932 { 1933 int r; 1934 1935 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL); 1936 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++) 1937 { 1938 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r)); 1939 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r)); 1940 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r)); 1941 } 1942 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type)); 1943 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type)); 1944 } 1945 } 1946 1947 1948 static inline tree 1949 gfc_trans_add_clause (tree node, tree tail) 1950 { 1951 OMP_CLAUSE_CHAIN (node) = tail; 1952 return node; 1953 } 1954 1955 static tree 1956 gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd) 1957 { 1958 if (declare_simd) 1959 { 1960 int cnt = 0; 1961 gfc_symbol *proc_sym; 1962 gfc_formal_arglist *f; 1963 1964 gcc_assert (sym->attr.dummy); 1965 proc_sym = sym->ns->proc_name; 1966 if (proc_sym->attr.entry_master) 1967 ++cnt; 1968 if (gfc_return_by_reference (proc_sym)) 1969 { 1970 ++cnt; 1971 if (proc_sym->ts.type == BT_CHARACTER) 1972 ++cnt; 1973 } 1974 for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next) 1975 if (f->sym == sym) 1976 break; 1977 else if (f->sym) 1978 ++cnt; 1979 gcc_assert (f); 1980 return build_int_cst (integer_type_node, cnt); 1981 } 1982 1983 tree t = gfc_get_symbol_decl (sym); 1984 tree parent_decl; 1985 int parent_flag; 1986 bool return_value; 1987 bool alternate_entry; 1988 bool entry_master; 1989 1990 return_value = sym->attr.function && sym->result == sym; 1991 alternate_entry = sym->attr.function && sym->attr.entry 1992 && sym->result == sym; 1993 entry_master = sym->attr.result 1994 && sym->ns->proc_name->attr.entry_master 1995 && !gfc_return_by_reference (sym->ns->proc_name); 1996 parent_decl = current_function_decl 1997 ? DECL_CONTEXT (current_function_decl) : NULL_TREE; 1998 1999 if ((t == parent_decl && return_value) 2000 || (sym->ns && sym->ns->proc_name 2001 && sym->ns->proc_name->backend_decl == parent_decl 2002 && (alternate_entry || entry_master))) 2003 parent_flag = 1; 2004 else 2005 parent_flag = 0; 2006 2007 /* Special case for assigning the return value of a function. 2008 Self recursive functions must have an explicit return value. */ 2009 if (return_value && (t == current_function_decl || parent_flag)) 2010 t = gfc_get_fake_result_decl (sym, parent_flag); 2011 2012 /* Similarly for alternate entry points. */ 2013 else if (alternate_entry 2014 && (sym->ns->proc_name->backend_decl == current_function_decl 2015 || parent_flag)) 2016 { 2017 gfc_entry_list *el = NULL; 2018 2019 for (el = sym->ns->entries; el; el = el->next) 2020 if (sym == el->sym) 2021 { 2022 t = gfc_get_fake_result_decl (sym, parent_flag); 2023 break; 2024 } 2025 } 2026 2027 else if (entry_master 2028 && (sym->ns->proc_name->backend_decl == current_function_decl 2029 || parent_flag)) 2030 t = gfc_get_fake_result_decl (sym, parent_flag); 2031 2032 return t; 2033 } 2034 2035 static tree 2036 gfc_trans_omp_variable_list (enum omp_clause_code code, 2037 gfc_omp_namelist *namelist, tree list, 2038 bool declare_simd) 2039 { 2040 for (; namelist != NULL; namelist = namelist->next) 2041 if (namelist->sym->attr.referenced || declare_simd) 2042 { 2043 tree t = gfc_trans_omp_variable (namelist->sym, declare_simd); 2044 if (t != error_mark_node) 2045 { 2046 tree node; 2047 node = build_omp_clause (input_location, code); 2048 OMP_CLAUSE_DECL (node) = t; 2049 list = gfc_trans_add_clause (node, list); 2050 2051 if (code == OMP_CLAUSE_LASTPRIVATE 2052 && namelist->u.lastprivate_conditional) 2053 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (node) = 1; 2054 } 2055 } 2056 return list; 2057 } 2058 2059 struct omp_udr_find_orig_data 2060 { 2061 gfc_omp_udr *omp_udr; 2062 bool omp_orig_seen; 2063 }; 2064 2065 static int 2066 omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, 2067 void *data) 2068 { 2069 struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data; 2070 if ((*e)->expr_type == EXPR_VARIABLE 2071 && (*e)->symtree->n.sym == cd->omp_udr->omp_orig) 2072 cd->omp_orig_seen = true; 2073 2074 return 0; 2075 } 2076 2077 static void 2078 gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where) 2079 { 2080 gfc_symbol *sym = n->sym; 2081 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL; 2082 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL; 2083 gfc_symbol init_val_sym, outer_sym, intrinsic_sym; 2084 gfc_symbol omp_var_copy[4]; 2085 gfc_expr *e1, *e2, *e3, *e4; 2086 gfc_ref *ref; 2087 tree decl, backend_decl, stmt, type, outer_decl; 2088 locus old_loc = gfc_current_locus; 2089 const char *iname; 2090 bool t; 2091 gfc_omp_udr *udr = n->u2.udr ? n->u2.udr->udr : NULL; 2092 2093 decl = OMP_CLAUSE_DECL (c); 2094 gfc_current_locus = where; 2095 type = TREE_TYPE (decl); 2096 outer_decl = create_tmp_var_raw (type); 2097 if (TREE_CODE (decl) == PARM_DECL 2098 && TREE_CODE (type) == REFERENCE_TYPE 2099 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)) 2100 && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE) 2101 { 2102 decl = build_fold_indirect_ref (decl); 2103 type = TREE_TYPE (type); 2104 } 2105 2106 /* Create a fake symbol for init value. */ 2107 memset (&init_val_sym, 0, sizeof (init_val_sym)); 2108 init_val_sym.ns = sym->ns; 2109 init_val_sym.name = sym->name; 2110 init_val_sym.ts = sym->ts; 2111 init_val_sym.attr.referenced = 1; 2112 init_val_sym.declared_at = where; 2113 init_val_sym.attr.flavor = FL_VARIABLE; 2114 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK) 2115 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym)); 2116 else if (udr->initializer_ns) 2117 backend_decl = NULL; 2118 else 2119 switch (sym->ts.type) 2120 { 2121 case BT_LOGICAL: 2122 case BT_INTEGER: 2123 case BT_REAL: 2124 case BT_COMPLEX: 2125 backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym)); 2126 break; 2127 default: 2128 backend_decl = NULL_TREE; 2129 break; 2130 } 2131 init_val_sym.backend_decl = backend_decl; 2132 2133 /* Create a fake symbol for the outer array reference. */ 2134 outer_sym = *sym; 2135 if (sym->as) 2136 outer_sym.as = gfc_copy_array_spec (sym->as); 2137 outer_sym.attr.dummy = 0; 2138 outer_sym.attr.result = 0; 2139 outer_sym.attr.flavor = FL_VARIABLE; 2140 outer_sym.backend_decl = outer_decl; 2141 if (decl != OMP_CLAUSE_DECL (c)) 2142 outer_sym.backend_decl = build_fold_indirect_ref (outer_decl); 2143 2144 /* Create fake symtrees for it. */ 2145 symtree1 = gfc_new_symtree (&root1, sym->name); 2146 symtree1->n.sym = sym; 2147 gcc_assert (symtree1 == root1); 2148 2149 symtree2 = gfc_new_symtree (&root2, sym->name); 2150 symtree2->n.sym = &init_val_sym; 2151 gcc_assert (symtree2 == root2); 2152 2153 symtree3 = gfc_new_symtree (&root3, sym->name); 2154 symtree3->n.sym = &outer_sym; 2155 gcc_assert (symtree3 == root3); 2156 2157 memset (omp_var_copy, 0, sizeof omp_var_copy); 2158 if (udr) 2159 { 2160 omp_var_copy[0] = *udr->omp_out; 2161 omp_var_copy[1] = *udr->omp_in; 2162 *udr->omp_out = outer_sym; 2163 *udr->omp_in = *sym; 2164 if (udr->initializer_ns) 2165 { 2166 omp_var_copy[2] = *udr->omp_priv; 2167 omp_var_copy[3] = *udr->omp_orig; 2168 *udr->omp_priv = *sym; 2169 *udr->omp_orig = outer_sym; 2170 } 2171 } 2172 2173 /* Create expressions. */ 2174 e1 = gfc_get_expr (); 2175 e1->expr_type = EXPR_VARIABLE; 2176 e1->where = where; 2177 e1->symtree = symtree1; 2178 e1->ts = sym->ts; 2179 if (sym->attr.dimension) 2180 { 2181 e1->ref = ref = gfc_get_ref (); 2182 ref->type = REF_ARRAY; 2183 ref->u.ar.where = where; 2184 ref->u.ar.as = sym->as; 2185 ref->u.ar.type = AR_FULL; 2186 ref->u.ar.dimen = 0; 2187 } 2188 t = gfc_resolve_expr (e1); 2189 gcc_assert (t); 2190 2191 e2 = NULL; 2192 if (backend_decl != NULL_TREE) 2193 { 2194 e2 = gfc_get_expr (); 2195 e2->expr_type = EXPR_VARIABLE; 2196 e2->where = where; 2197 e2->symtree = symtree2; 2198 e2->ts = sym->ts; 2199 t = gfc_resolve_expr (e2); 2200 gcc_assert (t); 2201 } 2202 else if (udr->initializer_ns == NULL) 2203 { 2204 gcc_assert (sym->ts.type == BT_DERIVED); 2205 e2 = gfc_default_initializer (&sym->ts); 2206 gcc_assert (e2); 2207 t = gfc_resolve_expr (e2); 2208 gcc_assert (t); 2209 } 2210 else if (n->u2.udr->initializer->op == EXEC_ASSIGN) 2211 { 2212 e2 = gfc_copy_expr (n->u2.udr->initializer->expr2); 2213 t = gfc_resolve_expr (e2); 2214 gcc_assert (t); 2215 } 2216 if (udr && udr->initializer_ns) 2217 { 2218 struct omp_udr_find_orig_data cd; 2219 cd.omp_udr = udr; 2220 cd.omp_orig_seen = false; 2221 gfc_code_walker (&n->u2.udr->initializer, 2222 gfc_dummy_code_callback, omp_udr_find_orig, &cd); 2223 if (cd.omp_orig_seen) 2224 OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1; 2225 } 2226 2227 e3 = gfc_copy_expr (e1); 2228 e3->symtree = symtree3; 2229 t = gfc_resolve_expr (e3); 2230 gcc_assert (t); 2231 2232 iname = NULL; 2233 e4 = NULL; 2234 switch (OMP_CLAUSE_REDUCTION_CODE (c)) 2235 { 2236 case PLUS_EXPR: 2237 case MINUS_EXPR: 2238 e4 = gfc_add (e3, e1); 2239 break; 2240 case MULT_EXPR: 2241 e4 = gfc_multiply (e3, e1); 2242 break; 2243 case TRUTH_ANDIF_EXPR: 2244 e4 = gfc_and (e3, e1); 2245 break; 2246 case TRUTH_ORIF_EXPR: 2247 e4 = gfc_or (e3, e1); 2248 break; 2249 case EQ_EXPR: 2250 e4 = gfc_eqv (e3, e1); 2251 break; 2252 case NE_EXPR: 2253 e4 = gfc_neqv (e3, e1); 2254 break; 2255 case MIN_EXPR: 2256 iname = "min"; 2257 break; 2258 case MAX_EXPR: 2259 iname = "max"; 2260 break; 2261 case BIT_AND_EXPR: 2262 iname = "iand"; 2263 break; 2264 case BIT_IOR_EXPR: 2265 iname = "ior"; 2266 break; 2267 case BIT_XOR_EXPR: 2268 iname = "ieor"; 2269 break; 2270 case ERROR_MARK: 2271 if (n->u2.udr->combiner->op == EXEC_ASSIGN) 2272 { 2273 gfc_free_expr (e3); 2274 e3 = gfc_copy_expr (n->u2.udr->combiner->expr1); 2275 e4 = gfc_copy_expr (n->u2.udr->combiner->expr2); 2276 t = gfc_resolve_expr (e3); 2277 gcc_assert (t); 2278 t = gfc_resolve_expr (e4); 2279 gcc_assert (t); 2280 } 2281 break; 2282 default: 2283 gcc_unreachable (); 2284 } 2285 if (iname != NULL) 2286 { 2287 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym)); 2288 intrinsic_sym.ns = sym->ns; 2289 intrinsic_sym.name = iname; 2290 intrinsic_sym.ts = sym->ts; 2291 intrinsic_sym.attr.referenced = 1; 2292 intrinsic_sym.attr.intrinsic = 1; 2293 intrinsic_sym.attr.function = 1; 2294 intrinsic_sym.attr.implicit_type = 1; 2295 intrinsic_sym.result = &intrinsic_sym; 2296 intrinsic_sym.declared_at = where; 2297 2298 symtree4 = gfc_new_symtree (&root4, iname); 2299 symtree4->n.sym = &intrinsic_sym; 2300 gcc_assert (symtree4 == root4); 2301 2302 e4 = gfc_get_expr (); 2303 e4->expr_type = EXPR_FUNCTION; 2304 e4->where = where; 2305 e4->symtree = symtree4; 2306 e4->value.function.actual = gfc_get_actual_arglist (); 2307 e4->value.function.actual->expr = e3; 2308 e4->value.function.actual->next = gfc_get_actual_arglist (); 2309 e4->value.function.actual->next->expr = e1; 2310 } 2311 if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK) 2312 { 2313 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */ 2314 e1 = gfc_copy_expr (e1); 2315 e3 = gfc_copy_expr (e3); 2316 t = gfc_resolve_expr (e4); 2317 gcc_assert (t); 2318 } 2319 2320 /* Create the init statement list. */ 2321 pushlevel (); 2322 if (e2) 2323 stmt = gfc_trans_assignment (e1, e2, false, false); 2324 else 2325 stmt = gfc_trans_call (n->u2.udr->initializer, false, 2326 NULL_TREE, NULL_TREE, false); 2327 if (TREE_CODE (stmt) != BIND_EXPR) 2328 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 2329 else 2330 poplevel (0, 0); 2331 OMP_CLAUSE_REDUCTION_INIT (c) = stmt; 2332 2333 /* Create the merge statement list. */ 2334 pushlevel (); 2335 if (e4) 2336 stmt = gfc_trans_assignment (e3, e4, false, true); 2337 else 2338 stmt = gfc_trans_call (n->u2.udr->combiner, false, 2339 NULL_TREE, NULL_TREE, false); 2340 if (TREE_CODE (stmt) != BIND_EXPR) 2341 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 2342 else 2343 poplevel (0, 0); 2344 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt; 2345 2346 /* And stick the placeholder VAR_DECL into the clause as well. */ 2347 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl; 2348 2349 gfc_current_locus = old_loc; 2350 2351 gfc_free_expr (e1); 2352 if (e2) 2353 gfc_free_expr (e2); 2354 gfc_free_expr (e3); 2355 if (e4) 2356 gfc_free_expr (e4); 2357 free (symtree1); 2358 free (symtree2); 2359 free (symtree3); 2360 free (symtree4); 2361 if (outer_sym.as) 2362 gfc_free_array_spec (outer_sym.as); 2363 2364 if (udr) 2365 { 2366 *udr->omp_out = omp_var_copy[0]; 2367 *udr->omp_in = omp_var_copy[1]; 2368 if (udr->initializer_ns) 2369 { 2370 *udr->omp_priv = omp_var_copy[2]; 2371 *udr->omp_orig = omp_var_copy[3]; 2372 } 2373 } 2374 } 2375 2376 static tree 2377 gfc_trans_omp_reduction_list (int kind, gfc_omp_namelist *namelist, tree list, 2378 locus where, bool mark_addressable) 2379 { 2380 omp_clause_code clause = OMP_CLAUSE_REDUCTION; 2381 switch (kind) 2382 { 2383 case OMP_LIST_REDUCTION: 2384 case OMP_LIST_REDUCTION_INSCAN: 2385 case OMP_LIST_REDUCTION_TASK: 2386 break; 2387 case OMP_LIST_IN_REDUCTION: 2388 clause = OMP_CLAUSE_IN_REDUCTION; 2389 break; 2390 case OMP_LIST_TASK_REDUCTION: 2391 clause = OMP_CLAUSE_TASK_REDUCTION; 2392 break; 2393 default: 2394 gcc_unreachable (); 2395 } 2396 for (; namelist != NULL; namelist = namelist->next) 2397 if (namelist->sym->attr.referenced) 2398 { 2399 tree t = gfc_trans_omp_variable (namelist->sym, false); 2400 if (t != error_mark_node) 2401 { 2402 tree node = build_omp_clause (gfc_get_location (&namelist->where), 2403 clause); 2404 OMP_CLAUSE_DECL (node) = t; 2405 if (mark_addressable) 2406 TREE_ADDRESSABLE (t) = 1; 2407 if (kind == OMP_LIST_REDUCTION_INSCAN) 2408 OMP_CLAUSE_REDUCTION_INSCAN (node) = 1; 2409 if (kind == OMP_LIST_REDUCTION_TASK) 2410 OMP_CLAUSE_REDUCTION_TASK (node) = 1; 2411 switch (namelist->u.reduction_op) 2412 { 2413 case OMP_REDUCTION_PLUS: 2414 OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR; 2415 break; 2416 case OMP_REDUCTION_MINUS: 2417 OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR; 2418 break; 2419 case OMP_REDUCTION_TIMES: 2420 OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR; 2421 break; 2422 case OMP_REDUCTION_AND: 2423 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR; 2424 break; 2425 case OMP_REDUCTION_OR: 2426 OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR; 2427 break; 2428 case OMP_REDUCTION_EQV: 2429 OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR; 2430 break; 2431 case OMP_REDUCTION_NEQV: 2432 OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR; 2433 break; 2434 case OMP_REDUCTION_MAX: 2435 OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR; 2436 break; 2437 case OMP_REDUCTION_MIN: 2438 OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR; 2439 break; 2440 case OMP_REDUCTION_IAND: 2441 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR; 2442 break; 2443 case OMP_REDUCTION_IOR: 2444 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR; 2445 break; 2446 case OMP_REDUCTION_IEOR: 2447 OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR; 2448 break; 2449 case OMP_REDUCTION_USER: 2450 OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK; 2451 break; 2452 default: 2453 gcc_unreachable (); 2454 } 2455 if (namelist->sym->attr.dimension 2456 || namelist->u.reduction_op == OMP_REDUCTION_USER 2457 || namelist->sym->attr.allocatable) 2458 gfc_trans_omp_array_reduction_or_udr (node, namelist, where); 2459 list = gfc_trans_add_clause (node, list); 2460 } 2461 } 2462 return list; 2463 } 2464 2465 static inline tree 2466 gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr) 2467 { 2468 gfc_se se; 2469 tree result; 2470 2471 gfc_init_se (&se, NULL ); 2472 gfc_conv_expr (&se, expr); 2473 gfc_add_block_to_block (block, &se.pre); 2474 result = gfc_evaluate_now (se.expr, block); 2475 gfc_add_block_to_block (block, &se.post); 2476 2477 return result; 2478 } 2479 2480 static vec<tree, va_heap, vl_embed> *doacross_steps; 2481 2482 2483 /* Translate an array section or array element. */ 2484 2485 static void 2486 gfc_trans_omp_array_section (stmtblock_t *block, gfc_exec_op op, 2487 gfc_omp_namelist *n, tree decl, bool element, 2488 bool openmp, gomp_map_kind ptr_kind, tree &node, 2489 tree &node2, tree &node3, tree &node4) 2490 { 2491 gfc_se se; 2492 tree ptr, ptr2; 2493 tree elemsz = NULL_TREE; 2494 2495 gfc_init_se (&se, NULL); 2496 if (element) 2497 { 2498 gfc_conv_expr_reference (&se, n->expr); 2499 gfc_add_block_to_block (block, &se.pre); 2500 ptr = se.expr; 2501 } 2502 else 2503 { 2504 gfc_conv_expr_descriptor (&se, n->expr); 2505 ptr = gfc_conv_array_data (se.expr); 2506 } 2507 if (n->expr->ts.type == BT_CHARACTER && n->expr->ts.deferred) 2508 { 2509 gcc_assert (se.string_length); 2510 tree len = gfc_evaluate_now (se.string_length, block); 2511 elemsz = gfc_get_char_type (n->expr->ts.kind); 2512 elemsz = TYPE_SIZE_UNIT (elemsz); 2513 elemsz = fold_build2 (MULT_EXPR, size_type_node, 2514 fold_convert (size_type_node, len), elemsz); 2515 } 2516 if (element) 2517 { 2518 if (!elemsz) 2519 elemsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr))); 2520 OMP_CLAUSE_SIZE (node) = elemsz; 2521 } 2522 else 2523 { 2524 tree type = TREE_TYPE (se.expr); 2525 gfc_add_block_to_block (block, &se.pre); 2526 OMP_CLAUSE_SIZE (node) = gfc_full_array_size (block, se.expr, 2527 GFC_TYPE_ARRAY_RANK (type)); 2528 if (!elemsz) 2529 elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 2530 elemsz = fold_convert (gfc_array_index_type, elemsz); 2531 OMP_CLAUSE_SIZE (node) = fold_build2 (MULT_EXPR, gfc_array_index_type, 2532 OMP_CLAUSE_SIZE (node), elemsz); 2533 } 2534 gcc_assert (se.post.head == NULL_TREE); 2535 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 2536 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr); 2537 ptr = fold_convert (ptrdiff_type_node, ptr); 2538 2539 if (POINTER_TYPE_P (TREE_TYPE (decl)) 2540 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))) 2541 && ptr_kind == GOMP_MAP_POINTER 2542 && op != EXEC_OMP_TARGET_EXIT_DATA 2543 && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_RELEASE 2544 && OMP_CLAUSE_MAP_KIND (node) != GOMP_MAP_DELETE) 2545 2546 { 2547 node4 = build_omp_clause (input_location, 2548 OMP_CLAUSE_MAP); 2549 OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER); 2550 OMP_CLAUSE_DECL (node4) = decl; 2551 OMP_CLAUSE_SIZE (node4) = size_int (0); 2552 decl = build_fold_indirect_ref (decl); 2553 } 2554 else if (ptr_kind == GOMP_MAP_ALWAYS_POINTER 2555 && n->expr->ts.type == BT_CHARACTER 2556 && n->expr->ts.deferred) 2557 { 2558 gomp_map_kind map_kind; 2559 if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE) 2560 map_kind = OMP_CLAUSE_MAP_KIND (node); 2561 else if (op == EXEC_OMP_TARGET_EXIT_DATA 2562 || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE) 2563 map_kind = GOMP_MAP_RELEASE; 2564 else 2565 map_kind = GOMP_MAP_TO; 2566 gcc_assert (se.string_length); 2567 node4 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 2568 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind); 2569 OMP_CLAUSE_DECL (node4) = se.string_length; 2570 OMP_CLAUSE_SIZE (node4) = TYPE_SIZE_UNIT (gfc_charlen_type_node); 2571 } 2572 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 2573 { 2574 tree type = TREE_TYPE (decl); 2575 ptr2 = gfc_conv_descriptor_data_get (decl); 2576 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 2577 OMP_CLAUSE_DECL (node2) = decl; 2578 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type); 2579 if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE 2580 || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_RELEASE 2581 || op == EXEC_OMP_TARGET_EXIT_DATA 2582 || op == EXEC_OACC_EXIT_DATA) 2583 { 2584 gomp_map_kind map_kind 2585 = OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DELETE ? GOMP_MAP_DELETE 2586 : GOMP_MAP_RELEASE; 2587 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind); 2588 OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1; 2589 } 2590 else 2591 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET); 2592 node3 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 2593 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind); 2594 OMP_CLAUSE_DECL (node3) = gfc_conv_descriptor_data_get (decl); 2595 /* This purposely does not include GOMP_MAP_ALWAYS_POINTER. The extra 2596 cast prevents gimplify.cc from recognising it as being part of the 2597 struct - and adding an 'alloc: for the 'desc.data' pointer, which 2598 would break as the 'desc' (the descriptor) is also mapped 2599 (see node4 above). */ 2600 if (ptr_kind == GOMP_MAP_ATTACH_DETACH && !openmp) 2601 STRIP_NOPS (OMP_CLAUSE_DECL (node3)); 2602 } 2603 else 2604 { 2605 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) 2606 { 2607 tree offset; 2608 ptr2 = build_fold_addr_expr (decl); 2609 offset = fold_build2 (MINUS_EXPR, ptrdiff_type_node, ptr, 2610 fold_convert (ptrdiff_type_node, ptr2)); 2611 offset = build2 (TRUNC_DIV_EXPR, ptrdiff_type_node, 2612 offset, fold_convert (ptrdiff_type_node, elemsz)); 2613 offset = build4_loc (input_location, ARRAY_REF, 2614 TREE_TYPE (TREE_TYPE (decl)), 2615 decl, offset, NULL_TREE, NULL_TREE); 2616 OMP_CLAUSE_DECL (node) = offset; 2617 2618 if (ptr_kind == GOMP_MAP_ATTACH_DETACH && openmp) 2619 return; 2620 } 2621 else 2622 { 2623 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl))); 2624 ptr2 = decl; 2625 } 2626 node3 = build_omp_clause (input_location, 2627 OMP_CLAUSE_MAP); 2628 OMP_CLAUSE_SET_MAP_KIND (node3, ptr_kind); 2629 OMP_CLAUSE_DECL (node3) = decl; 2630 } 2631 ptr2 = fold_convert (ptrdiff_type_node, ptr2); 2632 OMP_CLAUSE_SIZE (node3) = fold_build2 (MINUS_EXPR, ptrdiff_type_node, 2633 ptr, ptr2); 2634 } 2635 2636 static tree 2637 handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block) 2638 { 2639 tree list = NULL_TREE; 2640 for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink) 2641 { 2642 gfc_constructor *c; 2643 gfc_se se; 2644 2645 tree last = make_tree_vec (6); 2646 tree iter_var = gfc_get_symbol_decl (sym); 2647 tree type = TREE_TYPE (iter_var); 2648 TREE_VEC_ELT (last, 0) = iter_var; 2649 DECL_CHAIN (iter_var) = BLOCK_VARS (block); 2650 BLOCK_VARS (block) = iter_var; 2651 2652 /* begin */ 2653 c = gfc_constructor_first (sym->value->value.constructor); 2654 gfc_init_se (&se, NULL); 2655 gfc_conv_expr (&se, c->expr); 2656 gfc_add_block_to_block (iter_block, &se.pre); 2657 gfc_add_block_to_block (iter_block, &se.post); 2658 TREE_VEC_ELT (last, 1) = fold_convert (type, 2659 gfc_evaluate_now (se.expr, 2660 iter_block)); 2661 /* end */ 2662 c = gfc_constructor_next (c); 2663 gfc_init_se (&se, NULL); 2664 gfc_conv_expr (&se, c->expr); 2665 gfc_add_block_to_block (iter_block, &se.pre); 2666 gfc_add_block_to_block (iter_block, &se.post); 2667 TREE_VEC_ELT (last, 2) = fold_convert (type, 2668 gfc_evaluate_now (se.expr, 2669 iter_block)); 2670 /* step */ 2671 c = gfc_constructor_next (c); 2672 tree step; 2673 if (c) 2674 { 2675 gfc_init_se (&se, NULL); 2676 gfc_conv_expr (&se, c->expr); 2677 gfc_add_block_to_block (iter_block, &se.pre); 2678 gfc_add_block_to_block (iter_block, &se.post); 2679 gfc_conv_expr (&se, c->expr); 2680 step = fold_convert (type, 2681 gfc_evaluate_now (se.expr, 2682 iter_block)); 2683 } 2684 else 2685 step = build_int_cst (type, 1); 2686 TREE_VEC_ELT (last, 3) = step; 2687 /* orig_step */ 2688 TREE_VEC_ELT (last, 4) = save_expr (step); 2689 TREE_CHAIN (last) = list; 2690 list = last; 2691 } 2692 return list; 2693 } 2694 2695 /* To alleviate quadratic behaviour in checking each entry of a 2696 gfc_omp_namelist against every other entry, we build a hashtable indexed by 2697 gfc_symbol pointer, which we can use in the usual case that a map 2698 expression has a symbol as its root term. Return a namelist based on the 2699 root symbol used by N, building a new table in SYM_ROOTED_NL using the 2700 gfc_omp_namelist N2 (all clauses) if we haven't done so already. */ 2701 2702 static gfc_omp_namelist * 2703 get_symbol_rooted_namelist (hash_map<gfc_symbol *, 2704 gfc_omp_namelist *> *&sym_rooted_nl, 2705 gfc_omp_namelist *n, 2706 gfc_omp_namelist *n2, bool *sym_based) 2707 { 2708 /* Early-out if we have a NULL clause list (e.g. for OpenACC). */ 2709 if (!n2) 2710 return NULL; 2711 2712 gfc_symbol *use_sym = NULL; 2713 2714 /* We're only interested in cases where we have an expression, e.g. a 2715 component access. */ 2716 if (n->expr && n->expr->expr_type == EXPR_VARIABLE && n->expr->symtree) 2717 use_sym = n->expr->symtree->n.sym; 2718 2719 *sym_based = false; 2720 2721 if (!use_sym) 2722 return n2; 2723 2724 if (!sym_rooted_nl) 2725 { 2726 sym_rooted_nl = new hash_map<gfc_symbol *, gfc_omp_namelist *> (); 2727 2728 for (; n2 != NULL; n2 = n2->next) 2729 { 2730 if (!n2->expr 2731 || n2->expr->expr_type != EXPR_VARIABLE 2732 || !n2->expr->symtree) 2733 continue; 2734 2735 gfc_omp_namelist *nl_copy = gfc_get_omp_namelist (); 2736 memcpy (nl_copy, n2, sizeof *nl_copy); 2737 nl_copy->u2.duplicate_of = n2; 2738 nl_copy->next = NULL; 2739 2740 gfc_symbol *idx_sym = n2->expr->symtree->n.sym; 2741 2742 bool existed; 2743 gfc_omp_namelist *&entry 2744 = sym_rooted_nl->get_or_insert (idx_sym, &existed); 2745 if (existed) 2746 nl_copy->next = entry; 2747 entry = nl_copy; 2748 } 2749 } 2750 2751 gfc_omp_namelist **n2_sym = sym_rooted_nl->get (use_sym); 2752 2753 if (n2_sym) 2754 { 2755 *sym_based = true; 2756 return *n2_sym; 2757 } 2758 2759 return NULL; 2760 } 2761 2762 static tree 2763 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, 2764 locus where, bool declare_simd = false, 2765 bool openacc = false, gfc_exec_op op = EXEC_NOP) 2766 { 2767 tree omp_clauses = NULL_TREE, prev_clauses, chunk_size, c; 2768 tree iterator = NULL_TREE; 2769 tree tree_block = NULL_TREE; 2770 stmtblock_t iter_block; 2771 int list, ifc; 2772 enum omp_clause_code clause_code; 2773 gfc_omp_namelist *prev = NULL; 2774 gfc_se se; 2775 2776 if (clauses == NULL) 2777 return NULL_TREE; 2778 2779 hash_map<gfc_symbol *, gfc_omp_namelist *> *sym_rooted_nl = NULL; 2780 2781 for (list = 0; list < OMP_LIST_NUM; list++) 2782 { 2783 gfc_omp_namelist *n = clauses->lists[list]; 2784 2785 if (n == NULL) 2786 continue; 2787 switch (list) 2788 { 2789 case OMP_LIST_REDUCTION: 2790 case OMP_LIST_REDUCTION_INSCAN: 2791 case OMP_LIST_REDUCTION_TASK: 2792 case OMP_LIST_IN_REDUCTION: 2793 case OMP_LIST_TASK_REDUCTION: 2794 /* An OpenACC async clause indicates the need to set reduction 2795 arguments addressable, to allow asynchronous copy-out. */ 2796 omp_clauses = gfc_trans_omp_reduction_list (list, n, omp_clauses, 2797 where, clauses->async); 2798 break; 2799 case OMP_LIST_PRIVATE: 2800 clause_code = OMP_CLAUSE_PRIVATE; 2801 goto add_clause; 2802 case OMP_LIST_SHARED: 2803 clause_code = OMP_CLAUSE_SHARED; 2804 goto add_clause; 2805 case OMP_LIST_FIRSTPRIVATE: 2806 clause_code = OMP_CLAUSE_FIRSTPRIVATE; 2807 goto add_clause; 2808 case OMP_LIST_LASTPRIVATE: 2809 clause_code = OMP_CLAUSE_LASTPRIVATE; 2810 goto add_clause; 2811 case OMP_LIST_COPYIN: 2812 clause_code = OMP_CLAUSE_COPYIN; 2813 goto add_clause; 2814 case OMP_LIST_COPYPRIVATE: 2815 clause_code = OMP_CLAUSE_COPYPRIVATE; 2816 goto add_clause; 2817 case OMP_LIST_UNIFORM: 2818 clause_code = OMP_CLAUSE_UNIFORM; 2819 goto add_clause; 2820 case OMP_LIST_USE_DEVICE: 2821 case OMP_LIST_USE_DEVICE_PTR: 2822 clause_code = OMP_CLAUSE_USE_DEVICE_PTR; 2823 goto add_clause; 2824 case OMP_LIST_USE_DEVICE_ADDR: 2825 clause_code = OMP_CLAUSE_USE_DEVICE_ADDR; 2826 goto add_clause; 2827 case OMP_LIST_IS_DEVICE_PTR: 2828 clause_code = OMP_CLAUSE_IS_DEVICE_PTR; 2829 goto add_clause; 2830 case OMP_LIST_HAS_DEVICE_ADDR: 2831 clause_code = OMP_CLAUSE_HAS_DEVICE_ADDR; 2832 goto add_clause; 2833 case OMP_LIST_NONTEMPORAL: 2834 clause_code = OMP_CLAUSE_NONTEMPORAL; 2835 goto add_clause; 2836 case OMP_LIST_SCAN_IN: 2837 clause_code = OMP_CLAUSE_INCLUSIVE; 2838 goto add_clause; 2839 case OMP_LIST_SCAN_EX: 2840 clause_code = OMP_CLAUSE_EXCLUSIVE; 2841 goto add_clause; 2842 2843 add_clause: 2844 omp_clauses 2845 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses, 2846 declare_simd); 2847 break; 2848 case OMP_LIST_ALIGNED: 2849 for (; n != NULL; n = n->next) 2850 if (n->sym->attr.referenced || declare_simd) 2851 { 2852 tree t = gfc_trans_omp_variable (n->sym, declare_simd); 2853 if (t != error_mark_node) 2854 { 2855 tree node = build_omp_clause (input_location, 2856 OMP_CLAUSE_ALIGNED); 2857 OMP_CLAUSE_DECL (node) = t; 2858 if (n->expr) 2859 { 2860 tree alignment_var; 2861 2862 if (declare_simd) 2863 alignment_var = gfc_conv_constant_to_tree (n->expr); 2864 else 2865 { 2866 gfc_init_se (&se, NULL); 2867 gfc_conv_expr (&se, n->expr); 2868 gfc_add_block_to_block (block, &se.pre); 2869 alignment_var = gfc_evaluate_now (se.expr, block); 2870 gfc_add_block_to_block (block, &se.post); 2871 } 2872 OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var; 2873 } 2874 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 2875 } 2876 } 2877 break; 2878 case OMP_LIST_ALLOCATE: 2879 { 2880 tree allocator_ = NULL_TREE; 2881 gfc_expr *alloc_expr = NULL; 2882 for (; n != NULL; n = n->next) 2883 if (n->sym->attr.referenced) 2884 { 2885 tree t = gfc_trans_omp_variable (n->sym, false); 2886 if (t != error_mark_node) 2887 { 2888 tree node = build_omp_clause (input_location, 2889 OMP_CLAUSE_ALLOCATE); 2890 OMP_CLAUSE_DECL (node) = t; 2891 if (n->u2.allocator) 2892 { 2893 if (alloc_expr != n->u2.allocator) 2894 { 2895 gfc_init_se (&se, NULL); 2896 gfc_conv_expr (&se, n->u2.allocator); 2897 gfc_add_block_to_block (block, &se.pre); 2898 allocator_ = gfc_evaluate_now (se.expr, block); 2899 gfc_add_block_to_block (block, &se.post); 2900 } 2901 OMP_CLAUSE_ALLOCATE_ALLOCATOR (node) = allocator_; 2902 } 2903 alloc_expr = n->u2.allocator; 2904 if (n->u.align) 2905 { 2906 tree align_; 2907 gfc_init_se (&se, NULL); 2908 gfc_conv_expr (&se, n->u.align); 2909 gcc_assert (CONSTANT_CLASS_P (se.expr) 2910 && se.pre.head == NULL 2911 && se.post.head == NULL); 2912 align_ = se.expr; 2913 OMP_CLAUSE_ALLOCATE_ALIGN (node) = align_; 2914 } 2915 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 2916 } 2917 } 2918 else 2919 alloc_expr = n->u2.allocator; 2920 } 2921 break; 2922 case OMP_LIST_LINEAR: 2923 { 2924 gfc_expr *last_step_expr = NULL; 2925 tree last_step = NULL_TREE; 2926 bool last_step_parm = false; 2927 2928 for (; n != NULL; n = n->next) 2929 { 2930 if (n->expr) 2931 { 2932 last_step_expr = n->expr; 2933 last_step = NULL_TREE; 2934 last_step_parm = false; 2935 } 2936 if (n->sym->attr.referenced || declare_simd) 2937 { 2938 tree t = gfc_trans_omp_variable (n->sym, declare_simd); 2939 if (t != error_mark_node) 2940 { 2941 tree node = build_omp_clause (input_location, 2942 OMP_CLAUSE_LINEAR); 2943 OMP_CLAUSE_DECL (node) = t; 2944 omp_clause_linear_kind kind; 2945 switch (n->u.linear.op) 2946 { 2947 case OMP_LINEAR_DEFAULT: 2948 kind = OMP_CLAUSE_LINEAR_DEFAULT; 2949 break; 2950 case OMP_LINEAR_REF: 2951 kind = OMP_CLAUSE_LINEAR_REF; 2952 break; 2953 case OMP_LINEAR_VAL: 2954 kind = OMP_CLAUSE_LINEAR_VAL; 2955 break; 2956 case OMP_LINEAR_UVAL: 2957 kind = OMP_CLAUSE_LINEAR_UVAL; 2958 break; 2959 default: 2960 gcc_unreachable (); 2961 } 2962 OMP_CLAUSE_LINEAR_KIND (node) = kind; 2963 OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (node) 2964 = n->u.linear.old_modifier; 2965 if (last_step_expr && last_step == NULL_TREE) 2966 { 2967 if (!declare_simd) 2968 { 2969 gfc_init_se (&se, NULL); 2970 gfc_conv_expr (&se, last_step_expr); 2971 gfc_add_block_to_block (block, &se.pre); 2972 last_step = gfc_evaluate_now (se.expr, block); 2973 gfc_add_block_to_block (block, &se.post); 2974 } 2975 else if (last_step_expr->expr_type == EXPR_VARIABLE) 2976 { 2977 gfc_symbol *s = last_step_expr->symtree->n.sym; 2978 last_step = gfc_trans_omp_variable (s, true); 2979 last_step_parm = true; 2980 } 2981 else 2982 last_step 2983 = gfc_conv_constant_to_tree (last_step_expr); 2984 } 2985 if (last_step_parm) 2986 { 2987 OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1; 2988 OMP_CLAUSE_LINEAR_STEP (node) = last_step; 2989 } 2990 else 2991 { 2992 if (kind == OMP_CLAUSE_LINEAR_REF) 2993 { 2994 tree type; 2995 if (n->sym->attr.flavor == FL_PROCEDURE) 2996 { 2997 type = gfc_get_function_type (n->sym); 2998 type = build_pointer_type (type); 2999 } 3000 else 3001 type = gfc_sym_type (n->sym); 3002 if (POINTER_TYPE_P (type)) 3003 type = TREE_TYPE (type); 3004 /* Otherwise to be determined what exactly 3005 should be done. */ 3006 tree t = fold_convert (sizetype, last_step); 3007 t = size_binop (MULT_EXPR, t, 3008 TYPE_SIZE_UNIT (type)); 3009 OMP_CLAUSE_LINEAR_STEP (node) = t; 3010 } 3011 else 3012 { 3013 tree type 3014 = gfc_typenode_for_spec (&n->sym->ts); 3015 OMP_CLAUSE_LINEAR_STEP (node) 3016 = fold_convert (type, last_step); 3017 } 3018 } 3019 if (n->sym->attr.dimension || n->sym->attr.allocatable) 3020 OMP_CLAUSE_LINEAR_ARRAY (node) = 1; 3021 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 3022 } 3023 } 3024 } 3025 } 3026 break; 3027 case OMP_LIST_AFFINITY: 3028 case OMP_LIST_DEPEND: 3029 iterator = NULL_TREE; 3030 prev = NULL; 3031 prev_clauses = omp_clauses; 3032 for (; n != NULL; n = n->next) 3033 { 3034 if (iterator && prev->u2.ns != n->u2.ns) 3035 { 3036 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block); 3037 TREE_VEC_ELT (iterator, 5) = tree_block; 3038 for (tree c = omp_clauses; c != prev_clauses; 3039 c = OMP_CLAUSE_CHAIN (c)) 3040 OMP_CLAUSE_DECL (c) = build_tree_list (iterator, 3041 OMP_CLAUSE_DECL (c)); 3042 prev_clauses = omp_clauses; 3043 iterator = NULL_TREE; 3044 } 3045 if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns)) 3046 { 3047 gfc_init_block (&iter_block); 3048 tree_block = make_node (BLOCK); 3049 TREE_USED (tree_block) = 1; 3050 BLOCK_VARS (tree_block) = NULL_TREE; 3051 iterator = handle_iterator (n->u2.ns, block, 3052 tree_block); 3053 } 3054 if (!iterator) 3055 gfc_init_block (&iter_block); 3056 prev = n; 3057 if (list == OMP_LIST_DEPEND 3058 && (n->u.depend_doacross_op == OMP_DOACROSS_SINK_FIRST 3059 || n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST)) 3060 { 3061 tree vec = NULL_TREE; 3062 unsigned int i; 3063 bool is_depend 3064 = n->u.depend_doacross_op == OMP_DEPEND_SINK_FIRST; 3065 for (i = 0; ; i++) 3066 { 3067 tree addend = integer_zero_node, t; 3068 bool neg = false; 3069 if (n->sym && n->expr) 3070 { 3071 addend = gfc_conv_constant_to_tree (n->expr); 3072 if (TREE_CODE (addend) == INTEGER_CST 3073 && tree_int_cst_sgn (addend) == -1) 3074 { 3075 neg = true; 3076 addend = const_unop (NEGATE_EXPR, 3077 TREE_TYPE (addend), addend); 3078 } 3079 } 3080 3081 if (n->sym == NULL) 3082 t = null_pointer_node; /* "omp_cur_iteration - 1". */ 3083 else 3084 t = gfc_trans_omp_variable (n->sym, false); 3085 if (t != error_mark_node) 3086 { 3087 if (i < vec_safe_length (doacross_steps) 3088 && !integer_zerop (addend) 3089 && (*doacross_steps)[i]) 3090 { 3091 tree step = (*doacross_steps)[i]; 3092 addend = fold_convert (TREE_TYPE (step), addend); 3093 addend = build2 (TRUNC_DIV_EXPR, 3094 TREE_TYPE (step), addend, step); 3095 } 3096 vec = tree_cons (addend, t, vec); 3097 if (neg) 3098 OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (vec) = 1; 3099 } 3100 if (n->next == NULL 3101 || n->next->u.depend_doacross_op != OMP_DOACROSS_SINK) 3102 break; 3103 n = n->next; 3104 } 3105 if (vec == NULL_TREE) 3106 continue; 3107 3108 tree node = build_omp_clause (input_location, 3109 OMP_CLAUSE_DOACROSS); 3110 OMP_CLAUSE_DOACROSS_KIND (node) = OMP_CLAUSE_DOACROSS_SINK; 3111 OMP_CLAUSE_DOACROSS_DEPEND (node) = is_depend; 3112 OMP_CLAUSE_DECL (node) = nreverse (vec); 3113 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 3114 continue; 3115 } 3116 3117 if (n->sym && !n->sym->attr.referenced) 3118 continue; 3119 3120 tree node = build_omp_clause (input_location, 3121 list == OMP_LIST_DEPEND 3122 ? OMP_CLAUSE_DEPEND 3123 : OMP_CLAUSE_AFFINITY); 3124 if (n->sym == NULL) /* omp_all_memory */ 3125 OMP_CLAUSE_DECL (node) = null_pointer_node; 3126 else if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL) 3127 { 3128 tree decl = gfc_trans_omp_variable (n->sym, false); 3129 if (gfc_omp_privatize_by_reference (decl)) 3130 decl = build_fold_indirect_ref (decl); 3131 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 3132 { 3133 decl = gfc_conv_descriptor_data_get (decl); 3134 gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl))); 3135 decl = build_fold_indirect_ref (decl); 3136 } 3137 else if (n->sym->attr.allocatable || n->sym->attr.pointer) 3138 decl = build_fold_indirect_ref (decl); 3139 else if (DECL_P (decl)) 3140 TREE_ADDRESSABLE (decl) = 1; 3141 OMP_CLAUSE_DECL (node) = decl; 3142 } 3143 else 3144 { 3145 tree ptr; 3146 gfc_init_se (&se, NULL); 3147 /* The first ref can be an element selection on the base 3148 object while the full expression still denotes an array, 3149 e.g. x(j)%a. Pick the lowering path from the overall 3150 expression rank, not from the first REF_ARRAY. */ 3151 if (n->expr->rank == 0) 3152 { 3153 gfc_conv_expr_reference (&se, n->expr); 3154 ptr = se.expr; 3155 } 3156 else 3157 { 3158 gfc_conv_expr_descriptor (&se, n->expr); 3159 ptr = gfc_conv_array_data (se.expr); 3160 } 3161 gfc_add_block_to_block (&iter_block, &se.pre); 3162 gfc_add_block_to_block (&iter_block, &se.post); 3163 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 3164 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr); 3165 } 3166 if (list == OMP_LIST_DEPEND) 3167 switch (n->u.depend_doacross_op) 3168 { 3169 case OMP_DEPEND_IN: 3170 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN; 3171 break; 3172 case OMP_DEPEND_OUT: 3173 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT; 3174 break; 3175 case OMP_DEPEND_INOUT: 3176 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT; 3177 break; 3178 case OMP_DEPEND_INOUTSET: 3179 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUTSET; 3180 break; 3181 case OMP_DEPEND_MUTEXINOUTSET: 3182 OMP_CLAUSE_DEPEND_KIND (node) 3183 = OMP_CLAUSE_DEPEND_MUTEXINOUTSET; 3184 break; 3185 case OMP_DEPEND_DEPOBJ: 3186 OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_DEPOBJ; 3187 break; 3188 default: 3189 gcc_unreachable (); 3190 } 3191 if (!iterator) 3192 gfc_add_block_to_block (block, &iter_block); 3193 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 3194 } 3195 if (iterator) 3196 { 3197 BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block); 3198 TREE_VEC_ELT (iterator, 5) = tree_block; 3199 for (tree c = omp_clauses; c != prev_clauses; 3200 c = OMP_CLAUSE_CHAIN (c)) 3201 OMP_CLAUSE_DECL (c) = build_tree_list (iterator, 3202 OMP_CLAUSE_DECL (c)); 3203 } 3204 break; 3205 case OMP_LIST_MAP: 3206 for (; n != NULL; n = n->next) 3207 { 3208 if (!n->sym->attr.referenced) 3209 continue; 3210 3211 bool always_modifier = false; 3212 tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP); 3213 tree node2 = NULL_TREE; 3214 tree node3 = NULL_TREE; 3215 tree node4 = NULL_TREE; 3216 tree node5 = NULL_TREE; 3217 3218 /* OpenMP: automatically map pointer targets with the pointer; 3219 hence, always update the descriptor/pointer itself. */ 3220 if (!openacc 3221 && ((n->expr == NULL && n->sym->attr.pointer) 3222 || (n->expr && gfc_expr_attr (n->expr).pointer))) 3223 always_modifier = true; 3224 3225 if (n->u.map.readonly) 3226 OMP_CLAUSE_MAP_READONLY (node) = 1; 3227 3228 switch (n->u.map.op) 3229 { 3230 case OMP_MAP_ALLOC: 3231 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC); 3232 break; 3233 case OMP_MAP_IF_PRESENT: 3234 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_IF_PRESENT); 3235 break; 3236 case OMP_MAP_ATTACH: 3237 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ATTACH); 3238 break; 3239 case OMP_MAP_TO: 3240 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO); 3241 break; 3242 case OMP_MAP_FROM: 3243 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM); 3244 break; 3245 case OMP_MAP_TOFROM: 3246 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM); 3247 break; 3248 case OMP_MAP_ALWAYS_TO: 3249 always_modifier = true; 3250 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO); 3251 break; 3252 case OMP_MAP_ALWAYS_FROM: 3253 always_modifier = true; 3254 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM); 3255 break; 3256 case OMP_MAP_ALWAYS_TOFROM: 3257 always_modifier = true; 3258 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM); 3259 break; 3260 case OMP_MAP_PRESENT_ALLOC: 3261 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_ALLOC); 3262 break; 3263 case OMP_MAP_PRESENT_TO: 3264 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TO); 3265 break; 3266 case OMP_MAP_PRESENT_FROM: 3267 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_FROM); 3268 break; 3269 case OMP_MAP_PRESENT_TOFROM: 3270 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_PRESENT_TOFROM); 3271 break; 3272 case OMP_MAP_ALWAYS_PRESENT_TO: 3273 always_modifier = true; 3274 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TO); 3275 break; 3276 case OMP_MAP_ALWAYS_PRESENT_FROM: 3277 always_modifier = true; 3278 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_FROM); 3279 break; 3280 case OMP_MAP_ALWAYS_PRESENT_TOFROM: 3281 always_modifier = true; 3282 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_PRESENT_TOFROM); 3283 break; 3284 case OMP_MAP_RELEASE: 3285 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE); 3286 break; 3287 case OMP_MAP_DELETE: 3288 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE); 3289 break; 3290 case OMP_MAP_DETACH: 3291 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DETACH); 3292 break; 3293 case OMP_MAP_FORCE_ALLOC: 3294 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC); 3295 break; 3296 case OMP_MAP_FORCE_TO: 3297 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO); 3298 break; 3299 case OMP_MAP_FORCE_FROM: 3300 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM); 3301 break; 3302 case OMP_MAP_FORCE_TOFROM: 3303 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM); 3304 break; 3305 case OMP_MAP_FORCE_PRESENT: 3306 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT); 3307 break; 3308 case OMP_MAP_FORCE_DEVICEPTR: 3309 OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR); 3310 break; 3311 default: 3312 gcc_unreachable (); 3313 } 3314 3315 tree decl = gfc_trans_omp_variable (n->sym, false); 3316 if (DECL_P (decl)) 3317 TREE_ADDRESSABLE (decl) = 1; 3318 3319 gfc_ref *lastref = NULL; 3320 3321 if (n->expr) 3322 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next) 3323 if (ref->type == REF_COMPONENT || ref->type == REF_ARRAY) 3324 lastref = ref; 3325 3326 bool allocatable = false, pointer = false; 3327 3328 if (lastref && lastref->type == REF_COMPONENT) 3329 { 3330 gfc_component *c = lastref->u.c.component; 3331 3332 if (c->ts.type == BT_CLASS) 3333 { 3334 pointer = CLASS_DATA (c)->attr.class_pointer; 3335 allocatable = CLASS_DATA (c)->attr.allocatable; 3336 } 3337 else 3338 { 3339 pointer = c->attr.pointer; 3340 allocatable = c->attr.allocatable; 3341 } 3342 } 3343 3344 if (n->expr == NULL 3345 || (n->expr->ref->type == REF_ARRAY 3346 && n->expr->ref->u.ar.type == AR_FULL)) 3347 { 3348 gomp_map_kind map_kind; 3349 tree type = TREE_TYPE (decl); 3350 if (n->sym->ts.type == BT_CHARACTER 3351 && n->sym->ts.deferred 3352 && n->sym->attr.omp_declare_target 3353 && (always_modifier || n->sym->attr.pointer) 3354 && op != EXEC_OMP_TARGET_EXIT_DATA 3355 && n->u.map.op != OMP_MAP_DELETE 3356 && n->u.map.op != OMP_MAP_RELEASE) 3357 { 3358 gcc_assert (n->sym->ts.u.cl->backend_decl); 3359 node5 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 3360 OMP_CLAUSE_SET_MAP_KIND (node5, GOMP_MAP_ALWAYS_TO); 3361 OMP_CLAUSE_DECL (node5) = n->sym->ts.u.cl->backend_decl; 3362 OMP_CLAUSE_SIZE (node5) 3363 = TYPE_SIZE_UNIT (gfc_charlen_type_node); 3364 } 3365 3366 tree present = gfc_omp_check_optional_argument (decl, true); 3367 if (openacc && n->sym->ts.type == BT_CLASS) 3368 { 3369 if (n->sym->attr.optional) 3370 sorry ("optional class parameter"); 3371 tree ptr = gfc_class_data_get (decl); 3372 ptr = build_fold_indirect_ref (ptr); 3373 OMP_CLAUSE_DECL (node) = ptr; 3374 OMP_CLAUSE_SIZE (node) = gfc_class_vtab_size_get (decl); 3375 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 3376 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH); 3377 OMP_CLAUSE_DECL (node2) = gfc_class_data_get (decl); 3378 OMP_CLAUSE_SIZE (node2) = size_int (0); 3379 goto finalize_map_clause; 3380 } 3381 else if (POINTER_TYPE_P (type) 3382 && (gfc_omp_privatize_by_reference (decl) 3383 || GFC_DECL_GET_SCALAR_POINTER (decl) 3384 || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl) 3385 || GFC_DECL_CRAY_POINTEE (decl) 3386 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)) 3387 || (n->sym->ts.type == BT_DERIVED 3388 && (n->sym->ts.u.derived->ts.f90_type 3389 != BT_VOID)))) 3390 { 3391 tree orig_decl = decl; 3392 bool bare_attach_detach 3393 = (openacc 3394 && (n->u.map.op == OMP_MAP_ATTACH 3395 || n->u.map.op == OMP_MAP_DETACH) 3396 && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)) 3397 && !(POINTER_TYPE_P (TREE_TYPE (decl)) 3398 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE 3399 (TREE_TYPE (decl))))); 3400 3401 /* For nonallocatable, nonpointer arrays, a temporary 3402 variable is generated, but this one is only defined if 3403 the variable is present; hence, we now set it to NULL 3404 to avoid accessing undefined variables. We cannot use 3405 a temporary variable here as otherwise the replacement 3406 of the variables in omp-low.cc will not work. */ 3407 if (present && GFC_ARRAY_TYPE_P (type)) 3408 { 3409 tree tmp = fold_build2_loc (input_location, 3410 MODIFY_EXPR, 3411 void_type_node, decl, 3412 null_pointer_node); 3413 tree cond = fold_build1_loc (input_location, 3414 TRUTH_NOT_EXPR, 3415 boolean_type_node, 3416 present); 3417 gfc_add_expr_to_block (block, 3418 build3_loc (input_location, 3419 COND_EXPR, 3420 void_type_node, 3421 cond, tmp, 3422 NULL_TREE)); 3423 } 3424 /* Bare OpenACC attach/detach on scalar pointer-like 3425 variables wants a single attach operation on the 3426 pointer itself, not a standalone pointer-mapping 3427 node. Component and descriptor cases have dedicated 3428 handling below; this covers the plain scalar path. */ 3429 if (bare_attach_detach) 3430 { 3431 decl = build_fold_indirect_ref (decl); 3432 OMP_CLAUSE_DECL (node) = build_fold_addr_expr (decl); 3433 OMP_CLAUSE_SIZE (node) = size_zero_node; 3434 goto finalize_map_clause; 3435 } 3436 /* For descriptor types, the unmapping happens below. */ 3437 if (op != EXEC_OMP_TARGET_EXIT_DATA 3438 || !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 3439 { 3440 enum gomp_map_kind gmk = GOMP_MAP_POINTER; 3441 if (op == EXEC_OMP_TARGET_EXIT_DATA 3442 && n->u.map.op == OMP_MAP_DELETE) 3443 gmk = GOMP_MAP_DELETE; 3444 else if (op == EXEC_OMP_TARGET_EXIT_DATA) 3445 gmk = GOMP_MAP_RELEASE; 3446 tree size; 3447 if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE) 3448 size = TYPE_SIZE_UNIT (TREE_TYPE (decl)); 3449 else 3450 size = size_int (0); 3451 node4 = build_omp_clause (input_location, 3452 OMP_CLAUSE_MAP); 3453 OMP_CLAUSE_SET_MAP_KIND (node4, gmk); 3454 OMP_CLAUSE_DECL (node4) = decl; 3455 OMP_CLAUSE_SIZE (node4) = size; 3456 } 3457 decl = build_fold_indirect_ref (decl); 3458 if ((TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE 3459 || gfc_omp_is_optional_argument (orig_decl)) 3460 && (GFC_DECL_GET_SCALAR_POINTER (orig_decl) 3461 || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl))) 3462 { 3463 enum gomp_map_kind gmk; 3464 if (op == EXEC_OMP_TARGET_EXIT_DATA 3465 && n->u.map.op == OMP_MAP_DELETE) 3466 gmk = GOMP_MAP_DELETE; 3467 else if (op == EXEC_OMP_TARGET_EXIT_DATA) 3468 gmk = GOMP_MAP_RELEASE; 3469 else 3470 gmk = GOMP_MAP_POINTER; 3471 tree size; 3472 if (gmk == GOMP_MAP_RELEASE || gmk == GOMP_MAP_DELETE) 3473 size = TYPE_SIZE_UNIT (TREE_TYPE (decl)); 3474 else 3475 size = size_int (0); 3476 node3 = build_omp_clause (input_location, 3477 OMP_CLAUSE_MAP); 3478 OMP_CLAUSE_SET_MAP_KIND (node3, gmk); 3479 OMP_CLAUSE_DECL (node3) = decl; 3480 OMP_CLAUSE_SIZE (node3) = size; 3481 decl = build_fold_indirect_ref (decl); 3482 } 3483 } 3484 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 3485 { 3486 tree type = TREE_TYPE (decl); 3487 tree ptr = gfc_conv_descriptor_data_get (decl); 3488 if (present) 3489 ptr = gfc_build_cond_assign_expr (block, present, ptr, 3490 null_pointer_node); 3491 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 3492 ptr = build_fold_indirect_ref (ptr); 3493 OMP_CLAUSE_DECL (node) = ptr; 3494 node2 = build_omp_clause (input_location, OMP_CLAUSE_MAP); 3495 OMP_CLAUSE_DECL (node2) = decl; 3496 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type); 3497 if (n->u.map.op == OMP_MAP_DELETE) 3498 map_kind = GOMP_MAP_DELETE; 3499 else if (op == EXEC_OMP_TARGET_EXIT_DATA 3500 || n->u.map.op == OMP_MAP_RELEASE) 3501 map_kind = GOMP_MAP_RELEASE; 3502 else 3503 map_kind = GOMP_MAP_TO_PSET; 3504 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind); 3505 3506 if (op != EXEC_OMP_TARGET_EXIT_DATA 3507 && n->u.map.op != OMP_MAP_DELETE 3508 && n->u.map.op != OMP_MAP_RELEASE) 3509 { 3510 node3 = build_omp_clause (input_location, 3511 OMP_CLAUSE_MAP); 3512 if (present) 3513 { 3514 ptr = gfc_conv_descriptor_data_get (decl); 3515 ptr = gfc_build_addr_expr (NULL, ptr); 3516 ptr = gfc_build_cond_assign_expr ( 3517 block, present, ptr, null_pointer_node); 3518 ptr = build_fold_indirect_ref (ptr); 3519 OMP_CLAUSE_DECL (node3) = ptr; 3520 } 3521 else 3522 OMP_CLAUSE_DECL (node3) 3523 = gfc_conv_descriptor_data_get (decl); 3524 OMP_CLAUSE_SIZE (node3) = size_int (0); 3525 3526 if (n->u.map.op == OMP_MAP_ATTACH) 3527 { 3528 /* Standalone attach clauses used with arrays with 3529 descriptors must copy the descriptor to the 3530 target, else they won't have anything to 3531 perform the attachment onto (see OpenACC 2.6, 3532 "2.6.3. Data Structures with Pointers"). */ 3533 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_ATTACH); 3534 /* We don't want to map PTR at all in this case, 3535 so delete its node and shuffle the others 3536 down. */ 3537 node = node2; 3538 node2 = node3; 3539 node3 = NULL; 3540 goto finalize_map_clause; 3541 } 3542 else if (n->u.map.op == OMP_MAP_DETACH) 3543 { 3544 OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_DETACH); 3545 /* Similarly to above, we don't want to unmap PTR 3546 here. */ 3547 node = node2; 3548 node2 = node3; 3549 node3 = NULL; 3550 goto finalize_map_clause; 3551 } 3552 else 3553 OMP_CLAUSE_SET_MAP_KIND (node3, 3554 always_modifier 3555 ? GOMP_MAP_ALWAYS_POINTER 3556 : GOMP_MAP_POINTER); 3557 } 3558 3559 /* We have to check for n->sym->attr.dimension because 3560 of scalar coarrays. */ 3561 if ((n->sym->attr.pointer || n->sym->attr.allocatable) 3562 && n->sym->attr.dimension) 3563 { 3564 stmtblock_t cond_block; 3565 tree size 3566 = gfc_create_var (gfc_array_index_type, NULL); 3567 tree tem, then_b, else_b, zero, cond; 3568 3569 gfc_init_block (&cond_block); 3570 tem 3571 = gfc_full_array_size (&cond_block, decl, 3572 GFC_TYPE_ARRAY_RANK (type)); 3573 tree elemsz; 3574 if (n->sym->ts.type == BT_CHARACTER 3575 && n->sym->ts.deferred) 3576 { 3577 tree len = n->sym->ts.u.cl->backend_decl; 3578 len = fold_convert (size_type_node, len); 3579 elemsz = gfc_get_char_type (n->sym->ts.kind); 3580 elemsz = TYPE_SIZE_UNIT (elemsz); 3581 elemsz = fold_build2 (MULT_EXPR, size_type_node, 3582 len, elemsz); 3583 } 3584 else 3585 elemsz 3586 = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 3587 elemsz = fold_convert (gfc_array_index_type, elemsz); 3588 tem = fold_build2 (MULT_EXPR, gfc_array_index_type, 3589 tem, elemsz); 3590 gfc_add_modify (&cond_block, size, tem); 3591 then_b = gfc_finish_block (&cond_block); 3592 gfc_init_block (&cond_block); 3593 zero = build_int_cst (gfc_array_index_type, 0); 3594 gfc_add_modify (&cond_block, size, zero); 3595 else_b = gfc_finish_block (&cond_block); 3596 tem = gfc_conv_descriptor_data_get (decl); 3597 tem = fold_convert (pvoid_type_node, tem); 3598 cond = fold_build2_loc (input_location, NE_EXPR, 3599 boolean_type_node, 3600 tem, null_pointer_node); 3601 if (present) 3602 cond = fold_build2_loc (input_location, 3603 TRUTH_ANDIF_EXPR, 3604 boolean_type_node, 3605 present, cond); 3606 gfc_add_expr_to_block (block, 3607 build3_loc (input_location, 3608 COND_EXPR, 3609 void_type_node, 3610 cond, then_b, 3611 else_b)); 3612 OMP_CLAUSE_SIZE (node) = size; 3613 } 3614 else if (n->sym->attr.dimension) 3615 { 3616 stmtblock_t cond_block; 3617 gfc_init_block (&cond_block); 3618 tree size = gfc_full_array_size (&cond_block, decl, 3619 GFC_TYPE_ARRAY_RANK (type)); 3620 tree elemsz 3621 = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 3622 elemsz = fold_convert (gfc_array_index_type, elemsz); 3623 size = fold_build2 (MULT_EXPR, gfc_array_index_type, 3624 size, elemsz); 3625 size = gfc_evaluate_now (size, &cond_block); 3626 if (present) 3627 { 3628 tree var = gfc_create_var (gfc_array_index_type, 3629 NULL); 3630 gfc_add_modify (&cond_block, var, size); 3631 tree cond_body = gfc_finish_block (&cond_block); 3632 tree cond = build3_loc (input_location, COND_EXPR, 3633 void_type_node, present, 3634 cond_body, NULL_TREE); 3635 gfc_add_expr_to_block (block, cond); 3636 OMP_CLAUSE_SIZE (node) = var; 3637 } 3638 else 3639 { 3640 gfc_add_block_to_block (block, &cond_block); 3641 OMP_CLAUSE_SIZE (node) = size; 3642 } 3643 } 3644 } 3645 else if (present 3646 && INDIRECT_REF_P (decl) 3647 && INDIRECT_REF_P (TREE_OPERAND (decl, 0))) 3648 { 3649 /* A single indirectref is handled by the middle end. */ 3650 gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl))); 3651 decl = TREE_OPERAND (decl, 0); 3652 decl = gfc_build_cond_assign_expr (block, present, decl, 3653 null_pointer_node); 3654 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (decl); 3655 } 3656 else 3657 OMP_CLAUSE_DECL (node) = decl; 3658 3659 if (!n->sym->attr.dimension 3660 && n->sym->ts.type == BT_CHARACTER 3661 && n->sym->ts.deferred) 3662 { 3663 if (!DECL_P (decl)) 3664 { 3665 gcc_assert (TREE_CODE (decl) == INDIRECT_REF); 3666 decl = TREE_OPERAND (decl, 0); 3667 } 3668 tree cond = fold_build2_loc (input_location, NE_EXPR, 3669 boolean_type_node, 3670 decl, null_pointer_node); 3671 if (present) 3672 cond = fold_build2_loc (input_location, 3673 TRUTH_ANDIF_EXPR, 3674 boolean_type_node, 3675 present, cond); 3676 tree len = n->sym->ts.u.cl->backend_decl; 3677 len = fold_convert (size_type_node, len); 3678 tree size = gfc_get_char_type (n->sym->ts.kind); 3679 size = TYPE_SIZE_UNIT (size); 3680 size = fold_build2 (MULT_EXPR, size_type_node, len, size); 3681 size = build3_loc (input_location, 3682 COND_EXPR, 3683 size_type_node, 3684 cond, size, 3685 size_zero_node); 3686 size = gfc_evaluate_now (size, block); 3687 OMP_CLAUSE_SIZE (node) = size; 3688 } 3689 } 3690 else if (n->expr 3691 && n->expr->expr_type == EXPR_VARIABLE 3692 && n->expr->ref->type == REF_ARRAY 3693 && !n->expr->ref->next) 3694 { 3695 /* An array element or array section which is not part of a 3696 derived type, etc. */ 3697 bool element = n->expr->ref->u.ar.type == AR_ELEMENT; 3698 tree type = TREE_TYPE (decl); 3699 gomp_map_kind k = GOMP_MAP_POINTER; 3700 if (!openacc 3701 && !GFC_DESCRIPTOR_TYPE_P (type) 3702 && !(POINTER_TYPE_P (type) 3703 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type)))) 3704 k = GOMP_MAP_FIRSTPRIVATE_POINTER; 3705 gfc_trans_omp_array_section (block, op, n, decl, element, 3706 !openacc, k, node, node2, 3707 node3, node4); 3708 } 3709 else if (n->expr 3710 && n->expr->expr_type == EXPR_VARIABLE 3711 && (n->expr->ref->type == REF_COMPONENT 3712 || n->expr->ref->type == REF_ARRAY) 3713 && lastref 3714 && lastref->type == REF_COMPONENT 3715 && lastref->u.c.component->ts.type != BT_CLASS 3716 && lastref->u.c.component->ts.type != BT_DERIVED 3717 && !lastref->u.c.component->attr.dimension) 3718 { 3719 /* Derived type access with last component being a scalar. */ 3720 gfc_init_se (&se, NULL); 3721 3722 gfc_conv_expr (&se, n->expr); 3723 gfc_add_block_to_block (block, &se.pre); 3724 /* For BT_CHARACTER a pointer is returned. */ 3725 OMP_CLAUSE_DECL (node) 3726 = POINTER_TYPE_P (TREE_TYPE (se.expr)) 3727 ? build_fold_indirect_ref (se.expr) : se.expr; 3728 gfc_add_block_to_block (block, &se.post); 3729 if (pointer || allocatable) 3730 { 3731 /* If it's a bare attach/detach clause, we just want 3732 to perform a single attach/detach operation, of the 3733 pointer itself, not of the pointed-to object. */ 3734 if (openacc 3735 && (n->u.map.op == OMP_MAP_ATTACH 3736 || n->u.map.op == OMP_MAP_DETACH)) 3737 { 3738 OMP_CLAUSE_DECL (node) 3739 = build_fold_addr_expr (OMP_CLAUSE_DECL (node)); 3740 OMP_CLAUSE_SIZE (node) = size_zero_node; 3741 goto finalize_map_clause; 3742 } 3743 3744 node2 = build_omp_clause (input_location, 3745 OMP_CLAUSE_MAP); 3746 OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_ATTACH_DETACH); 3747 OMP_CLAUSE_DECL (node2) 3748 = POINTER_TYPE_P (TREE_TYPE (se.expr)) 3749 ? se.expr 3750 : gfc_build_addr_expr (NULL, se.expr); 3751 OMP_CLAUSE_SIZE (node2) = size_int (0); 3752 if (!openacc 3753 && n->expr->ts.type == BT_CHARACTER 3754 && n->expr->ts.deferred) 3755 { 3756 gcc_assert (se.string_length); 3757 tree tmp 3758 = gfc_get_char_type (n->expr->ts.kind); 3759 OMP_CLAUSE_SIZE (node) 3760 = fold_build2 (MULT_EXPR, size_type_node, 3761 fold_convert (size_type_node, 3762 se.string_length), 3763 TYPE_SIZE_UNIT (tmp)); 3764 gomp_map_kind kind; 3765 if (n->u.map.op == OMP_MAP_DELETE) 3766 kind = GOMP_MAP_DELETE; 3767 else if (op == EXEC_OMP_TARGET_EXIT_DATA) 3768 kind = GOMP_MAP_RELEASE; 3769 else 3770 kind = GOMP_MAP_TO; 3771 node3 = build_omp_clause (input_location, 3772 OMP_CLAUSE_MAP); 3773 OMP_CLAUSE_SET_MAP_KIND (node3, kind); 3774 OMP_CLAUSE_DECL (node3) = se.string_length; 3775 OMP_CLAUSE_SIZE (node3) 3776 = TYPE_SIZE_UNIT (gfc_charlen_type_node); 3777 } 3778 } 3779 } 3780 else if (n->expr 3781 && n->expr->expr_type == EXPR_VARIABLE 3782 && (n->expr->ref->type == REF_COMPONENT 3783 || n->expr->ref->type == REF_ARRAY)) 3784 { 3785 gfc_init_se (&se, NULL); 3786 se.expr = gfc_maybe_dereference_var (n->sym, decl); 3787 3788 for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next) 3789 { 3790 if (ref->type == REF_COMPONENT) 3791 { 3792 if (ref->u.c.sym->attr.extension) 3793 conv_parent_component_references (&se, ref); 3794 3795 gfc_conv_component_ref (&se, ref); 3796 } 3797 else if (ref->type == REF_ARRAY) 3798 { 3799 if (ref->u.ar.type == AR_ELEMENT && ref->next) 3800 gfc_conv_array_ref (&se, &ref->u.ar, n->expr, 3801 &n->expr->where); 3802 else 3803 gcc_assert (!ref->next); 3804 } 3805 else 3806 sorry ("unhandled expression type"); 3807 } 3808 3809 tree inner = se.expr; 3810 3811 /* Last component is a derived type or class pointer. */ 3812 if (lastref->type == REF_COMPONENT 3813 && (lastref->u.c.component->ts.type == BT_DERIVED 3814 || lastref->u.c.component->ts.type == BT_CLASS)) 3815 { 3816 if (pointer || (openacc && allocatable)) 3817 { 3818 /* If it's a bare attach/detach clause, we just want 3819 to perform a single attach/detach operation, of the 3820 pointer itself, not of the pointed-to object. */ 3821 if (openacc 3822 && (n->u.map.op == OMP_MAP_ATTACH 3823 || n->u.map.op == OMP_MAP_DETACH)) 3824 { 3825 OMP_CLAUSE_DECL (node) 3826 = build_fold_addr_expr (inner); 3827 OMP_CLAUSE_SIZE (node) = size_zero_node; 3828 goto finalize_map_clause; 3829 } 3830 3831 gfc_omp_namelist *n2 3832 = openacc ? NULL : clauses->lists[OMP_LIST_MAP]; 3833 3834 bool sym_based; 3835 n2 = get_symbol_rooted_namelist (sym_rooted_nl, n, 3836 n2, &sym_based); 3837 3838 /* If the last reference is a pointer to a derived 3839 type ("foo%dt_ptr"), check if any subcomponents 3840 of the same derived type member are being mapped 3841 elsewhere in the clause list ("foo%dt_ptr%x", 3842 etc.). If we have such subcomponent mappings, 3843 we only create an ALLOC node for the pointer 3844 itself, and inhibit mapping the whole derived 3845 type. */ 3846 3847 for (; n2 != NULL; n2 = n2->next) 3848 { 3849 if ((!sym_based && n == n2) 3850 || (sym_based && n == n2->u2.duplicate_of) 3851 || !n2->expr) 3852 continue; 3853 3854 if (!gfc_omp_expr_prefix_same (n->expr, 3855 n2->expr)) 3856 continue; 3857 3858 gfc_ref *ref1 = n->expr->ref; 3859 gfc_ref *ref2 = n2->expr->ref; 3860 3861 while (ref1->next && ref2->next) 3862 { 3863 ref1 = ref1->next; 3864 ref2 = ref2->next; 3865 } 3866 3867 if (ref2->next) 3868 { 3869 inner = build_fold_addr_expr (inner); 3870 OMP_CLAUSE_SET_MAP_KIND (node, 3871 GOMP_MAP_ALLOC); 3872 OMP_CLAUSE_DECL (node) = inner; 3873 OMP_CLAUSE_SIZE (node) 3874 = TYPE_SIZE_UNIT (TREE_TYPE (inner)); 3875 goto finalize_map_clause; 3876 } 3877 } 3878 3879 tree data, size; 3880 3881 if (lastref->u.c.component->ts.type == BT_CLASS) 3882 { 3883 data = gfc_class_data_get (inner); 3884 gcc_assert (POINTER_TYPE_P (TREE_TYPE (data))); 3885 data = build_fold_indirect_ref (data); 3886 size = gfc_class_vtab_size_get (inner); 3887 } 3888 else /* BT_DERIVED. */ 3889 { 3890 data = inner; 3891 size = TYPE_SIZE_UNIT (TREE_TYPE (inner)); 3892 } 3893 3894 OMP_CLAUSE_DECL (node) = data; 3895 OMP_CLAUSE_SIZE (node) = size; 3896 node2 = build_omp_clause (input_location, 3897 OMP_CLAUSE_MAP); 3898 OMP_CLAUSE_SET_MAP_KIND (node2, 3899 GOMP_MAP_ATTACH_DETACH); 3900 OMP_CLAUSE_DECL (node2) = build_fold_addr_expr (data); 3901 OMP_CLAUSE_SIZE (node2) = size_int (0); 3902 } 3903 else 3904 { 3905 OMP_CLAUSE_DECL (node) = inner; 3906 OMP_CLAUSE_SIZE (node) 3907 = TYPE_SIZE_UNIT (TREE_TYPE (inner)); 3908 } 3909 } 3910 else if (lastref->type == REF_ARRAY 3911 && lastref->u.ar.type == AR_FULL) 3912 { 3913 /* Bare attach and detach clauses don't want any 3914 additional nodes. */ 3915 if ((n->u.map.op == OMP_MAP_ATTACH 3916 || n->u.map.op == OMP_MAP_DETACH) 3917 && (POINTER_TYPE_P (TREE_TYPE (inner)) 3918 || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner)))) 3919 { 3920 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner))) 3921 { 3922 tree ptr = gfc_conv_descriptor_data_get (inner); 3923 OMP_CLAUSE_DECL (node) = ptr; 3924 } 3925 else 3926 OMP_CLAUSE_DECL (node) = inner; 3927 OMP_CLAUSE_SIZE (node) = size_zero_node; 3928 goto finalize_map_clause; 3929 } 3930 3931 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (inner))) 3932 { 3933 gomp_map_kind map_kind; 3934 tree type = TREE_TYPE (inner); 3935 tree ptr = gfc_conv_descriptor_data_get (inner); 3936 ptr = build_fold_indirect_ref (ptr); 3937 OMP_CLAUSE_DECL (node) = ptr; 3938 int rank = GFC_TYPE_ARRAY_RANK (type); 3939 OMP_CLAUSE_SIZE (node) 3940 = gfc_full_array_size (block, inner, rank); 3941 tree elemsz 3942 = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 3943 map_kind = OMP_CLAUSE_MAP_KIND (node); 3944 if (GOMP_MAP_COPY_TO_P (map_kind) 3945 || map_kind == GOMP_MAP_ALLOC) 3946 map_kind = ((GOMP_MAP_ALWAYS_P (map_kind) 3947 || gfc_expr_attr (n->expr).pointer) 3948 ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO); 3949 else if (n->u.map.op == OMP_MAP_RELEASE 3950 || n->u.map.op == OMP_MAP_DELETE) 3951 ; 3952 else if (op == EXEC_OMP_TARGET_EXIT_DATA 3953 || op == EXEC_OACC_EXIT_DATA) 3954 map_kind = GOMP_MAP_RELEASE; 3955 else 3956 map_kind = GOMP_MAP_ALLOC; 3957 if (!openacc 3958 && n->expr->ts.type == BT_CHARACTER 3959 && n->expr->ts.deferred) 3960 { 3961 gcc_assert (se.string_length); 3962 tree len = fold_convert (size_type_node, 3963 se.string_length); 3964 elemsz = gfc_get_char_type (n->expr->ts.kind); 3965 elemsz = TYPE_SIZE_UNIT (elemsz); 3966 elemsz = fold_build2 (MULT_EXPR, size_type_node, 3967 len, elemsz); 3968 node4 = build_omp_clause (input_location, 3969 OMP_CLAUSE_MAP); 3970 OMP_CLAUSE_SET_MAP_KIND (node4, map_kind); 3971 OMP_CLAUSE_DECL (node4) = se.string_length; 3972 OMP_CLAUSE_SIZE (node4) 3973 = TYPE_SIZE_UNIT (gfc_charlen_type_node); 3974 } 3975 elemsz = fold_convert (gfc_array_index_type, elemsz); 3976 OMP_CLAUSE_SIZE (node) 3977 = fold_build2 (MULT_EXPR, gfc_array_index_type, 3978 OMP_CLAUSE_SIZE (node), elemsz); 3979 node2 = build_omp_clause (input_location, 3980 OMP_CLAUSE_MAP); 3981 if (map_kind == GOMP_MAP_RELEASE 3982 || map_kind == GOMP_MAP_DELETE) 3983 { 3984 OMP_CLAUSE_SET_MAP_KIND (node2, map_kind); 3985 OMP_CLAUSE_RELEASE_DESCRIPTOR (node2) = 1; 3986 } 3987 else 3988 OMP_CLAUSE_SET_MAP_KIND (node2, 3989 GOMP_MAP_TO_PSET); 3990 OMP_CLAUSE_DECL (node2) = inner; 3991 OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type); 3992 if (!openacc) 3993 { 3994 gfc_omp_namelist *n2 3995 = clauses->lists[OMP_LIST_MAP]; 3996 3997 /* If we don't have a mapping of a smaller part 3998 of the array -- or we can't prove that we do 3999 statically -- set this flag. If there is a 4000 mapping of a smaller part of the array after 4001 all, this will turn into a no-op at 4002 runtime. */ 4003 OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (node) = 1; 4004 4005 bool sym_based; 4006 n2 = get_symbol_rooted_namelist (sym_rooted_nl, 4007 n, n2, 4008 &sym_based); 4009 4010 bool drop_mapping = false; 4011 4012 for (; n2 != NULL; n2 = n2->next) 4013 { 4014 if ((!sym_based && n == n2) 4015 || (sym_based && n == n2->u2.duplicate_of) 4016 || !n2->expr) 4017 continue; 4018 4019 if (!gfc_omp_expr_prefix_same (n->expr, 4020 n2->expr)) 4021 continue; 4022 4023 gfc_ref *ref1 = n->expr->ref; 4024 gfc_ref *ref2 = n2->expr->ref; 4025 4026 /* We know ref1 and ref2 overlap. We're 4027 interested in whether ref2 describes a 4028 smaller part of the array than ref1, which 4029 we already know refers to the full 4030 array. */ 4031 4032 while (ref1->next && ref2->next) 4033 { 4034 ref1 = ref1->next; 4035 ref2 = ref2->next; 4036 } 4037 4038 if (ref2->next 4039 || (ref2->type == REF_ARRAY 4040 && (ref2->u.ar.type == AR_ELEMENT 4041 || (ref2->u.ar.type 4042 == AR_SECTION)))) 4043 { 4044 drop_mapping = true; 4045 break; 4046 } 4047 } 4048 if (drop_mapping) 4049 continue; 4050 } 4051 node3 = build_omp_clause (input_location, 4052 OMP_CLAUSE_MAP); 4053 OMP_CLAUSE_SET_MAP_KIND (node3, 4054 GOMP_MAP_ATTACH_DETACH); 4055 OMP_CLAUSE_DECL (node3) 4056 = gfc_conv_descriptor_data_get (inner); 4057 /* Similar to gfc_trans_omp_array_section (details 4058 there), we add/keep the cast for OpenMP to prevent 4059 that an 'alloc:' gets added for node3 ('desc.data') 4060 as that is part of the whole descriptor (node3). 4061 TODO: Remove once the ME handles this properly. */ 4062 if (!openacc) 4063 OMP_CLAUSE_DECL (node3) 4064 = fold_convert (TREE_TYPE (TREE_OPERAND(ptr, 0)), 4065 OMP_CLAUSE_DECL (node3)); 4066 else 4067 STRIP_NOPS (OMP_CLAUSE_DECL (node3)); 4068 OMP_CLAUSE_SIZE (node3) = size_int (0); 4069 } 4070 else 4071 OMP_CLAUSE_DECL (node) = inner; 4072 } 4073 else if (lastref->type == REF_ARRAY) 4074 { 4075 /* An array element or section. */ 4076 bool element = lastref->u.ar.type == AR_ELEMENT; 4077 gomp_map_kind kind = GOMP_MAP_ATTACH_DETACH; 4078 gfc_trans_omp_array_section (block, op, n, inner, element, 4079 !openacc, kind, node, node2, 4080 node3, node4); 4081 } 4082 else 4083 gcc_unreachable (); 4084 } 4085 else 4086 sorry ("unhandled expression"); 4087 4088 finalize_map_clause: 4089 4090 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 4091 if (node2) 4092 omp_clauses = gfc_trans_add_clause (node2, omp_clauses); 4093 if (node3) 4094 omp_clauses = gfc_trans_add_clause (node3, omp_clauses); 4095 if (node4) 4096 omp_clauses = gfc_trans_add_clause (node4, omp_clauses); 4097 if (node5) 4098 omp_clauses = gfc_trans_add_clause (node5, omp_clauses); 4099 } 4100 break; 4101 case OMP_LIST_TO: 4102 case OMP_LIST_FROM: 4103 case OMP_LIST_CACHE: 4104 for (; n != NULL; n = n->next) 4105 { 4106 if (!n->sym->attr.referenced) 4107 continue; 4108 4109 switch (list) 4110 { 4111 case OMP_LIST_TO: 4112 clause_code = OMP_CLAUSE_TO; 4113 break; 4114 case OMP_LIST_FROM: 4115 clause_code = OMP_CLAUSE_FROM; 4116 break; 4117 case OMP_LIST_CACHE: 4118 clause_code = OMP_CLAUSE__CACHE_; 4119 break; 4120 default: 4121 gcc_unreachable (); 4122 } 4123 tree node = build_omp_clause (input_location, clause_code); 4124 if (n->expr == NULL 4125 || (n->expr->ref->type == REF_ARRAY 4126 && n->expr->ref->u.ar.type == AR_FULL 4127 && n->expr->ref->next == NULL)) 4128 { 4129 tree decl = gfc_trans_omp_variable (n->sym, false); 4130 if (gfc_omp_privatize_by_reference (decl)) 4131 { 4132 if (gfc_omp_is_allocatable_or_ptr (decl)) 4133 decl = build_fold_indirect_ref (decl); 4134 decl = build_fold_indirect_ref (decl); 4135 } 4136 else if (DECL_P (decl)) 4137 TREE_ADDRESSABLE (decl) = 1; 4138 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl))) 4139 { 4140 tree type = TREE_TYPE (decl); 4141 tree ptr = gfc_conv_descriptor_data_get (decl); 4142 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 4143 ptr = build_fold_indirect_ref (ptr); 4144 OMP_CLAUSE_DECL (node) = ptr; 4145 OMP_CLAUSE_SIZE (node) 4146 = gfc_full_array_size (block, decl, 4147 GFC_TYPE_ARRAY_RANK (type)); 4148 tree elemsz 4149 = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 4150 elemsz = fold_convert (gfc_array_index_type, elemsz); 4151 OMP_CLAUSE_SIZE (node) 4152 = fold_build2 (MULT_EXPR, gfc_array_index_type, 4153 OMP_CLAUSE_SIZE (node), elemsz); 4154 } 4155 else 4156 { 4157 OMP_CLAUSE_DECL (node) = decl; 4158 if (gfc_omp_is_allocatable_or_ptr (decl)) 4159 OMP_CLAUSE_SIZE (node) 4160 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))); 4161 } 4162 } 4163 else 4164 { 4165 tree ptr; 4166 gfc_init_se (&se, NULL); 4167 if (n->expr->rank == 0) 4168 { 4169 gfc_conv_expr_reference (&se, n->expr); 4170 ptr = se.expr; 4171 gfc_add_block_to_block (block, &se.pre); 4172 OMP_CLAUSE_SIZE (node) 4173 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr))); 4174 } 4175 else 4176 { 4177 gfc_conv_expr_descriptor (&se, n->expr); 4178 ptr = gfc_conv_array_data (se.expr); 4179 tree type = TREE_TYPE (se.expr); 4180 gfc_add_block_to_block (block, &se.pre); 4181 OMP_CLAUSE_SIZE (node) 4182 = gfc_full_array_size (block, se.expr, 4183 GFC_TYPE_ARRAY_RANK (type)); 4184 tree elemsz 4185 = TYPE_SIZE_UNIT (gfc_get_element_type (type)); 4186 elemsz = fold_convert (gfc_array_index_type, elemsz); 4187 OMP_CLAUSE_SIZE (node) 4188 = fold_build2 (MULT_EXPR, gfc_array_index_type, 4189 OMP_CLAUSE_SIZE (node), elemsz); 4190 } 4191 gfc_add_block_to_block (block, &se.post); 4192 gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); 4193 OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr); 4194 } 4195 if (n->u.present_modifier) 4196 OMP_CLAUSE_MOTION_PRESENT (node) = 1; 4197 if (list == OMP_LIST_CACHE && n->u.map.readonly) 4198 OMP_CLAUSE__CACHE__READONLY (node) = 1; 4199 omp_clauses = gfc_trans_add_clause (node, omp_clauses); 4200 } 4201 break; 4202 case OMP_LIST_USES_ALLOCATORS: 4203 /* Ignore pre-defined allocators as no special treatment is needed. */ 4204 for (; n != NULL; n = n->next) 4205 if (n->sym->attr.flavor == FL_VARIABLE) 4206 break; 4207 if (n != NULL) 4208 sorry_at (input_location, "%<uses_allocators%> clause with traits " 4209 "and memory spaces"); 4210 break; 4211 default: 4212 break; 4213 } 4214 } 4215 4216 /* Free hashmap if we built it. */ 4217 if (sym_rooted_nl) 4218 { 4219 typedef hash_map<gfc_symbol *, gfc_omp_namelist *>::iterator hti; 4220 for (hti it = sym_rooted_nl->begin (); it != sym_rooted_nl->end (); ++it) 4221 { 4222 gfc_omp_namelist *&nl = (*it).second; 4223 while (nl) 4224 { 4225 gfc_omp_namelist *next = nl->next; 4226 free (nl); 4227 nl = next; 4228 } 4229 } 4230 delete sym_rooted_nl; 4231 } 4232 4233 if (clauses->if_expr) 4234 { 4235 tree if_var; 4236 4237 gfc_init_se (&se, NULL); 4238 gfc_conv_expr (&se, clauses->if_expr); 4239 gfc_add_block_to_block (block, &se.pre); 4240 if_var = gfc_evaluate_now (se.expr, block); 4241 gfc_add_block_to_block (block, &se.post); 4242 4243 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF); 4244 OMP_CLAUSE_IF_MODIFIER (c) = ERROR_MARK; 4245 OMP_CLAUSE_IF_EXPR (c) = if_var; 4246 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4247 } 4248 4249 for (ifc = 0; ifc < OMP_IF_LAST; ifc++) 4250 if (clauses->if_exprs[ifc]) 4251 { 4252 tree if_var; 4253 4254 gfc_init_se (&se, NULL); 4255 gfc_conv_expr (&se, clauses->if_exprs[ifc]); 4256 gfc_add_block_to_block (block, &se.pre); 4257 if_var = gfc_evaluate_now (se.expr, block); 4258 gfc_add_block_to_block (block, &se.post); 4259 4260 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF); 4261 switch (ifc) 4262 { 4263 case OMP_IF_CANCEL: 4264 OMP_CLAUSE_IF_MODIFIER (c) = VOID_CST; 4265 break; 4266 case OMP_IF_PARALLEL: 4267 OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL; 4268 break; 4269 case OMP_IF_SIMD: 4270 OMP_CLAUSE_IF_MODIFIER (c) = OMP_SIMD; 4271 break; 4272 case OMP_IF_TASK: 4273 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK; 4274 break; 4275 case OMP_IF_TASKLOOP: 4276 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP; 4277 break; 4278 case OMP_IF_TARGET: 4279 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET; 4280 break; 4281 case OMP_IF_TARGET_DATA: 4282 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA; 4283 break; 4284 case OMP_IF_TARGET_UPDATE: 4285 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE; 4286 break; 4287 case OMP_IF_TARGET_ENTER_DATA: 4288 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA; 4289 break; 4290 case OMP_IF_TARGET_EXIT_DATA: 4291 OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA; 4292 break; 4293 default: 4294 gcc_unreachable (); 4295 } 4296 OMP_CLAUSE_IF_EXPR (c) = if_var; 4297 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4298 } 4299 4300 if (clauses->self_expr) 4301 { 4302 tree self_var; 4303 4304 gfc_init_se (&se, NULL); 4305 gfc_conv_expr (&se, clauses->self_expr); 4306 gfc_add_block_to_block (block, &se.pre); 4307 self_var = gfc_evaluate_now (se.expr, block); 4308 gfc_add_block_to_block (block, &se.post); 4309 4310 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SELF); 4311 OMP_CLAUSE_SELF_EXPR (c) = self_var; 4312 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4313 } 4314 4315 if (clauses->final_expr) 4316 { 4317 tree final_var; 4318 4319 gfc_init_se (&se, NULL); 4320 gfc_conv_expr (&se, clauses->final_expr); 4321 gfc_add_block_to_block (block, &se.pre); 4322 final_var = gfc_evaluate_now (se.expr, block); 4323 gfc_add_block_to_block (block, &se.post); 4324 4325 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINAL); 4326 OMP_CLAUSE_FINAL_EXPR (c) = final_var; 4327 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4328 } 4329 4330 if (clauses->num_threads) 4331 { 4332 tree num_threads; 4333 4334 gfc_init_se (&se, NULL); 4335 gfc_conv_expr (&se, clauses->num_threads); 4336 gfc_add_block_to_block (block, &se.pre); 4337 num_threads = gfc_evaluate_now (se.expr, block); 4338 gfc_add_block_to_block (block, &se.post); 4339 4340 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_THREADS); 4341 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads; 4342 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4343 } 4344 4345 chunk_size = NULL_TREE; 4346 if (clauses->chunk_size) 4347 { 4348 gfc_init_se (&se, NULL); 4349 gfc_conv_expr (&se, clauses->chunk_size); 4350 gfc_add_block_to_block (block, &se.pre); 4351 chunk_size = gfc_evaluate_now (se.expr, block); 4352 gfc_add_block_to_block (block, &se.post); 4353 } 4354 4355 if (clauses->sched_kind != OMP_SCHED_NONE) 4356 { 4357 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SCHEDULE); 4358 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size; 4359 switch (clauses->sched_kind) 4360 { 4361 case OMP_SCHED_STATIC: 4362 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; 4363 break; 4364 case OMP_SCHED_DYNAMIC: 4365 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; 4366 break; 4367 case OMP_SCHED_GUIDED: 4368 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; 4369 break; 4370 case OMP_SCHED_RUNTIME: 4371 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; 4372 break; 4373 case OMP_SCHED_AUTO: 4374 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO; 4375 break; 4376 default: 4377 gcc_unreachable (); 4378 } 4379 if (clauses->sched_monotonic) 4380 OMP_CLAUSE_SCHEDULE_KIND (c) 4381 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c) 4382 | OMP_CLAUSE_SCHEDULE_MONOTONIC); 4383 else if (clauses->sched_nonmonotonic) 4384 OMP_CLAUSE_SCHEDULE_KIND (c) 4385 = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c) 4386 | OMP_CLAUSE_SCHEDULE_NONMONOTONIC); 4387 if (clauses->sched_simd) 4388 OMP_CLAUSE_SCHEDULE_SIMD (c) = 1; 4389 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4390 } 4391 4392 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN) 4393 { 4394 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULT); 4395 switch (clauses->default_sharing) 4396 { 4397 case OMP_DEFAULT_NONE: 4398 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE; 4399 break; 4400 case OMP_DEFAULT_SHARED: 4401 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED; 4402 break; 4403 case OMP_DEFAULT_PRIVATE: 4404 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE; 4405 break; 4406 case OMP_DEFAULT_FIRSTPRIVATE: 4407 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; 4408 break; 4409 case OMP_DEFAULT_PRESENT: 4410 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRESENT; 4411 break; 4412 default: 4413 gcc_unreachable (); 4414 } 4415 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4416 } 4417 4418 if (clauses->nowait) 4419 { 4420 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOWAIT); 4421 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4422 } 4423 4424 if (clauses->ordered) 4425 { 4426 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDERED); 4427 OMP_CLAUSE_ORDERED_EXPR (c) 4428 = clauses->orderedc ? build_int_cst (integer_type_node, 4429 clauses->orderedc) : NULL_TREE; 4430 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4431 } 4432 4433 if (clauses->order_concurrent) 4434 { 4435 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ORDER); 4436 OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = clauses->order_unconstrained; 4437 OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = clauses->order_reproducible; 4438 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4439 } 4440 4441 if (clauses->untied) 4442 { 4443 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_UNTIED); 4444 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4445 } 4446 4447 if (clauses->mergeable) 4448 { 4449 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_MERGEABLE); 4450 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4451 } 4452 4453 if (clauses->collapse) 4454 { 4455 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_COLLAPSE); 4456 OMP_CLAUSE_COLLAPSE_EXPR (c) 4457 = build_int_cst (integer_type_node, clauses->collapse); 4458 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4459 } 4460 4461 if (clauses->inbranch) 4462 { 4463 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INBRANCH); 4464 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4465 } 4466 4467 if (clauses->notinbranch) 4468 { 4469 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOTINBRANCH); 4470 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4471 } 4472 4473 switch (clauses->cancel) 4474 { 4475 case OMP_CANCEL_UNKNOWN: 4476 break; 4477 case OMP_CANCEL_PARALLEL: 4478 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PARALLEL); 4479 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4480 break; 4481 case OMP_CANCEL_SECTIONS: 4482 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SECTIONS); 4483 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4484 break; 4485 case OMP_CANCEL_DO: 4486 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FOR); 4487 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4488 break; 4489 case OMP_CANCEL_TASKGROUP: 4490 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TASKGROUP); 4491 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4492 break; 4493 } 4494 4495 if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN) 4496 { 4497 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PROC_BIND); 4498 switch (clauses->proc_bind) 4499 { 4500 case OMP_PROC_BIND_PRIMARY: 4501 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_PRIMARY; 4502 break; 4503 case OMP_PROC_BIND_MASTER: 4504 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER; 4505 break; 4506 case OMP_PROC_BIND_SPREAD: 4507 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD; 4508 break; 4509 case OMP_PROC_BIND_CLOSE: 4510 OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE; 4511 break; 4512 default: 4513 gcc_unreachable (); 4514 } 4515 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4516 } 4517 4518 if (clauses->safelen_expr) 4519 { 4520 tree safelen_var; 4521 4522 gfc_init_se (&se, NULL); 4523 gfc_conv_expr (&se, clauses->safelen_expr); 4524 gfc_add_block_to_block (block, &se.pre); 4525 safelen_var = gfc_evaluate_now (se.expr, block); 4526 gfc_add_block_to_block (block, &se.post); 4527 4528 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SAFELEN); 4529 OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var; 4530 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4531 } 4532 4533 if (clauses->simdlen_expr) 4534 { 4535 if (declare_simd) 4536 { 4537 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN); 4538 OMP_CLAUSE_SIMDLEN_EXPR (c) 4539 = gfc_conv_constant_to_tree (clauses->simdlen_expr); 4540 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4541 } 4542 else 4543 { 4544 tree simdlen_var; 4545 4546 gfc_init_se (&se, NULL); 4547 gfc_conv_expr (&se, clauses->simdlen_expr); 4548 gfc_add_block_to_block (block, &se.pre); 4549 simdlen_var = gfc_evaluate_now (se.expr, block); 4550 gfc_add_block_to_block (block, &se.post); 4551 4552 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMDLEN); 4553 OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var; 4554 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4555 } 4556 } 4557 4558 if (clauses->num_teams_upper) 4559 { 4560 tree num_teams_lower = NULL_TREE, num_teams_upper; 4561 4562 gfc_init_se (&se, NULL); 4563 gfc_conv_expr (&se, clauses->num_teams_upper); 4564 gfc_add_block_to_block (block, &se.pre); 4565 num_teams_upper = gfc_evaluate_now (se.expr, block); 4566 gfc_add_block_to_block (block, &se.post); 4567 4568 if (clauses->num_teams_lower) 4569 { 4570 gfc_init_se (&se, NULL); 4571 gfc_conv_expr (&se, clauses->num_teams_lower); 4572 gfc_add_block_to_block (block, &se.pre); 4573 num_teams_lower = gfc_evaluate_now (se.expr, block); 4574 gfc_add_block_to_block (block, &se.post); 4575 } 4576 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TEAMS); 4577 OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower; 4578 OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper; 4579 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4580 } 4581 4582 if (clauses->device) 4583 { 4584 tree device; 4585 4586 gfc_init_se (&se, NULL); 4587 gfc_conv_expr (&se, clauses->device); 4588 gfc_add_block_to_block (block, &se.pre); 4589 device = gfc_evaluate_now (se.expr, block); 4590 gfc_add_block_to_block (block, &se.post); 4591 4592 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEVICE); 4593 OMP_CLAUSE_DEVICE_ID (c) = device; 4594 4595 if (clauses->ancestor) 4596 OMP_CLAUSE_DEVICE_ANCESTOR (c) = 1; 4597 4598 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4599 } 4600 4601 if (clauses->thread_limit) 4602 { 4603 tree thread_limit; 4604 4605 gfc_init_se (&se, NULL); 4606 gfc_conv_expr (&se, clauses->thread_limit); 4607 gfc_add_block_to_block (block, &se.pre); 4608 thread_limit = gfc_evaluate_now (se.expr, block); 4609 gfc_add_block_to_block (block, &se.post); 4610 4611 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREAD_LIMIT); 4612 OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit; 4613 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4614 } 4615 4616 chunk_size = NULL_TREE; 4617 if (clauses->dist_chunk_size) 4618 { 4619 gfc_init_se (&se, NULL); 4620 gfc_conv_expr (&se, clauses->dist_chunk_size); 4621 gfc_add_block_to_block (block, &se.pre); 4622 chunk_size = gfc_evaluate_now (se.expr, block); 4623 gfc_add_block_to_block (block, &se.post); 4624 } 4625 4626 if (clauses->dist_sched_kind != OMP_SCHED_NONE) 4627 { 4628 c = build_omp_clause (gfc_get_location (&where), 4629 OMP_CLAUSE_DIST_SCHEDULE); 4630 OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size; 4631 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4632 } 4633 4634 if (clauses->grainsize) 4635 { 4636 tree grainsize; 4637 4638 gfc_init_se (&se, NULL); 4639 gfc_conv_expr (&se, clauses->grainsize); 4640 gfc_add_block_to_block (block, &se.pre); 4641 grainsize = gfc_evaluate_now (se.expr, block); 4642 gfc_add_block_to_block (block, &se.post); 4643 4644 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GRAINSIZE); 4645 OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize; 4646 if (clauses->grainsize_strict) 4647 OMP_CLAUSE_GRAINSIZE_STRICT (c) = 1; 4648 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4649 } 4650 4651 if (clauses->num_tasks) 4652 { 4653 tree num_tasks; 4654 4655 gfc_init_se (&se, NULL); 4656 gfc_conv_expr (&se, clauses->num_tasks); 4657 gfc_add_block_to_block (block, &se.pre); 4658 num_tasks = gfc_evaluate_now (se.expr, block); 4659 gfc_add_block_to_block (block, &se.post); 4660 4661 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_TASKS); 4662 OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks; 4663 if (clauses->num_tasks_strict) 4664 OMP_CLAUSE_NUM_TASKS_STRICT (c) = 1; 4665 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4666 } 4667 4668 if (clauses->priority) 4669 { 4670 tree priority; 4671 4672 gfc_init_se (&se, NULL); 4673 gfc_conv_expr (&se, clauses->priority); 4674 gfc_add_block_to_block (block, &se.pre); 4675 priority = gfc_evaluate_now (se.expr, block); 4676 gfc_add_block_to_block (block, &se.post); 4677 4678 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_PRIORITY); 4679 OMP_CLAUSE_PRIORITY_EXPR (c) = priority; 4680 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4681 } 4682 4683 if (clauses->detach) 4684 { 4685 tree detach; 4686 4687 gfc_init_se (&se, NULL); 4688 gfc_conv_expr (&se, clauses->detach); 4689 gfc_add_block_to_block (block, &se.pre); 4690 detach = se.expr; 4691 gfc_add_block_to_block (block, &se.post); 4692 4693 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DETACH); 4694 TREE_ADDRESSABLE (detach) = 1; 4695 OMP_CLAUSE_DECL (c) = detach; 4696 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4697 } 4698 4699 if (clauses->filter) 4700 { 4701 tree filter; 4702 4703 gfc_init_se (&se, NULL); 4704 gfc_conv_expr (&se, clauses->filter); 4705 gfc_add_block_to_block (block, &se.pre); 4706 filter = gfc_evaluate_now (se.expr, block); 4707 gfc_add_block_to_block (block, &se.post); 4708 4709 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FILTER); 4710 OMP_CLAUSE_FILTER_EXPR (c) = filter; 4711 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4712 } 4713 4714 if (clauses->hint) 4715 { 4716 tree hint; 4717 4718 gfc_init_se (&se, NULL); 4719 gfc_conv_expr (&se, clauses->hint); 4720 gfc_add_block_to_block (block, &se.pre); 4721 hint = gfc_evaluate_now (se.expr, block); 4722 gfc_add_block_to_block (block, &se.post); 4723 4724 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_HINT); 4725 OMP_CLAUSE_HINT_EXPR (c) = hint; 4726 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4727 } 4728 4729 if (clauses->simd) 4730 { 4731 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SIMD); 4732 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4733 } 4734 if (clauses->threads) 4735 { 4736 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_THREADS); 4737 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4738 } 4739 if (clauses->nogroup) 4740 { 4741 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NOGROUP); 4742 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4743 } 4744 4745 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++) 4746 { 4747 if (clauses->defaultmap[i] == OMP_DEFAULTMAP_UNSET) 4748 continue; 4749 enum omp_clause_defaultmap_kind behavior, category; 4750 switch ((gfc_omp_defaultmap_category) i) 4751 { 4752 case OMP_DEFAULTMAP_CAT_UNCATEGORIZED: 4753 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED; 4754 break; 4755 case OMP_DEFAULTMAP_CAT_ALL: 4756 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL; 4757 break; 4758 case OMP_DEFAULTMAP_CAT_SCALAR: 4759 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR; 4760 break; 4761 case OMP_DEFAULTMAP_CAT_AGGREGATE: 4762 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE; 4763 break; 4764 case OMP_DEFAULTMAP_CAT_ALLOCATABLE: 4765 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE; 4766 break; 4767 case OMP_DEFAULTMAP_CAT_POINTER: 4768 category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER; 4769 break; 4770 default: gcc_unreachable (); 4771 } 4772 switch (clauses->defaultmap[i]) 4773 { 4774 case OMP_DEFAULTMAP_ALLOC: 4775 behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC; 4776 break; 4777 case OMP_DEFAULTMAP_TO: behavior = OMP_CLAUSE_DEFAULTMAP_TO; break; 4778 case OMP_DEFAULTMAP_FROM: behavior = OMP_CLAUSE_DEFAULTMAP_FROM; break; 4779 case OMP_DEFAULTMAP_TOFROM: 4780 behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM; 4781 break; 4782 case OMP_DEFAULTMAP_FIRSTPRIVATE: 4783 behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE; 4784 break; 4785 case OMP_DEFAULTMAP_PRESENT: 4786 behavior = OMP_CLAUSE_DEFAULTMAP_PRESENT; 4787 break; 4788 case OMP_DEFAULTMAP_NONE: behavior = OMP_CLAUSE_DEFAULTMAP_NONE; break; 4789 case OMP_DEFAULTMAP_DEFAULT: 4790 behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT; 4791 break; 4792 default: gcc_unreachable (); 4793 } 4794 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DEFAULTMAP); 4795 OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category); 4796 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4797 } 4798 4799 if (clauses->doacross_source) 4800 { 4801 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_DOACROSS); 4802 OMP_CLAUSE_DOACROSS_KIND (c) = OMP_CLAUSE_DOACROSS_SOURCE; 4803 OMP_CLAUSE_DOACROSS_DEPEND (c) = clauses->depend_source; 4804 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4805 } 4806 4807 if (clauses->async) 4808 { 4809 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_ASYNC); 4810 if (clauses->async_expr) 4811 OMP_CLAUSE_ASYNC_EXPR (c) 4812 = gfc_convert_expr_to_tree (block, clauses->async_expr); 4813 else 4814 OMP_CLAUSE_ASYNC_EXPR (c) = NULL; 4815 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4816 } 4817 if (clauses->seq) 4818 { 4819 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_SEQ); 4820 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4821 } 4822 if (clauses->par_auto) 4823 { 4824 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_AUTO); 4825 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4826 } 4827 if (clauses->if_present) 4828 { 4829 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_IF_PRESENT); 4830 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4831 } 4832 if (clauses->finalize) 4833 { 4834 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_FINALIZE); 4835 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4836 } 4837 if (clauses->independent) 4838 { 4839 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_INDEPENDENT); 4840 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4841 } 4842 if (clauses->wait_list) 4843 { 4844 gfc_expr_list *el; 4845 4846 for (el = clauses->wait_list; el; el = el->next) 4847 { 4848 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WAIT); 4849 OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr); 4850 OMP_CLAUSE_CHAIN (c) = omp_clauses; 4851 omp_clauses = c; 4852 } 4853 } 4854 if (clauses->num_gangs_expr) 4855 { 4856 tree num_gangs_var 4857 = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr); 4858 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_GANGS); 4859 OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var; 4860 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4861 } 4862 if (clauses->num_workers_expr) 4863 { 4864 tree num_workers_var 4865 = gfc_convert_expr_to_tree (block, clauses->num_workers_expr); 4866 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_NUM_WORKERS); 4867 OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var; 4868 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4869 } 4870 if (clauses->vector_length_expr) 4871 { 4872 tree vector_length_var 4873 = gfc_convert_expr_to_tree (block, clauses->vector_length_expr); 4874 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR_LENGTH); 4875 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var; 4876 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4877 } 4878 if (clauses->tile_list) 4879 { 4880 vec<tree, va_gc> *tvec; 4881 gfc_expr_list *el; 4882 4883 vec_alloc (tvec, 4); 4884 4885 for (el = clauses->tile_list; el; el = el->next) 4886 vec_safe_push (tvec, gfc_convert_expr_to_tree (block, el->expr)); 4887 4888 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_TILE); 4889 OMP_CLAUSE_TILE_LIST (c) = build_tree_list_vec (tvec); 4890 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4891 tvec->truncate (0); 4892 } 4893 if (clauses->vector) 4894 { 4895 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_VECTOR); 4896 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4897 4898 if (clauses->vector_expr) 4899 { 4900 tree vector_var 4901 = gfc_convert_expr_to_tree (block, clauses->vector_expr); 4902 OMP_CLAUSE_VECTOR_EXPR (c) = vector_var; 4903 4904 /* TODO: We're not capturing location information for individual 4905 clauses. However, if we have an expression attached to the 4906 clause, that one provides better location information. */ 4907 OMP_CLAUSE_LOCATION (c) 4908 = gfc_get_location (&clauses->vector_expr->where); 4909 } 4910 } 4911 if (clauses->worker) 4912 { 4913 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_WORKER); 4914 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4915 4916 if (clauses->worker_expr) 4917 { 4918 tree worker_var 4919 = gfc_convert_expr_to_tree (block, clauses->worker_expr); 4920 OMP_CLAUSE_WORKER_EXPR (c) = worker_var; 4921 4922 /* TODO: We're not capturing location information for individual 4923 clauses. However, if we have an expression attached to the 4924 clause, that one provides better location information. */ 4925 OMP_CLAUSE_LOCATION (c) 4926 = gfc_get_location (&clauses->worker_expr->where); 4927 } 4928 } 4929 if (clauses->gang) 4930 { 4931 tree arg; 4932 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_GANG); 4933 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4934 4935 if (clauses->gang_num_expr) 4936 { 4937 arg = gfc_convert_expr_to_tree (block, clauses->gang_num_expr); 4938 OMP_CLAUSE_GANG_EXPR (c) = arg; 4939 4940 /* TODO: We're not capturing location information for individual 4941 clauses. However, if we have an expression attached to the 4942 clause, that one provides better location information. */ 4943 OMP_CLAUSE_LOCATION (c) 4944 = gfc_get_location (&clauses->gang_num_expr->where); 4945 } 4946 4947 if (clauses->gang_static) 4948 { 4949 arg = clauses->gang_static_expr 4950 ? gfc_convert_expr_to_tree (block, clauses->gang_static_expr) 4951 : integer_minus_one_node; 4952 OMP_CLAUSE_GANG_STATIC_EXPR (c) = arg; 4953 } 4954 } 4955 if (clauses->bind != OMP_BIND_UNSET) 4956 { 4957 c = build_omp_clause (gfc_get_location (&where), OMP_CLAUSE_BIND); 4958 omp_clauses = gfc_trans_add_clause (c, omp_clauses); 4959 switch (clauses->bind) 4960 { 4961 case OMP_BIND_TEAMS: 4962 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_TEAMS; 4963 break; 4964 case OMP_BIND_PARALLEL: 4965 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_PARALLEL; 4966 break; 4967 case OMP_BIND_THREAD: 4968 OMP_CLAUSE_BIND_KIND (c) = OMP_CLAUSE_BIND_THREAD; 4969 break; 4970 default: 4971 gcc_unreachable (); 4972 } 4973 } 4974 /* OpenACC 'nohost' clauses cannot appear here. */ 4975 gcc_checking_assert (!clauses->nohost); 4976 4977 return nreverse (omp_clauses); 4978 } 4979 4980 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */ 4981 4982 static tree 4983 gfc_trans_omp_code (gfc_code *code, bool force_empty) 4984 { 4985 tree stmt; 4986 4987 pushlevel (); 4988 stmt = gfc_trans_code (code); 4989 if (TREE_CODE (stmt) != BIND_EXPR) 4990 { 4991 if (!IS_EMPTY_STMT (stmt) || force_empty) 4992 { 4993 tree block = poplevel (1, 0); 4994 stmt = build3_v (BIND_EXPR, NULL, stmt, block); 4995 } 4996 else 4997 poplevel (0, 0); 4998 } 4999 else 5000 poplevel (0, 0); 5001 return stmt; 5002 } 5003 5004 /* Translate OpenACC 'parallel', 'kernels', 'serial', 'data', 'host_data' 5005 construct. */ 5006 5007 static tree 5008 gfc_trans_oacc_construct (gfc_code *code) 5009 { 5010 stmtblock_t block; 5011 tree stmt, oacc_clauses; 5012 enum tree_code construct_code; 5013 5014 switch (code->op) 5015 { 5016 case EXEC_OACC_PARALLEL: 5017 construct_code = OACC_PARALLEL; 5018 break; 5019 case EXEC_OACC_KERNELS: 5020 construct_code = OACC_KERNELS; 5021 break; 5022 case EXEC_OACC_SERIAL: 5023 construct_code = OACC_SERIAL; 5024 break; 5025 case EXEC_OACC_DATA: 5026 construct_code = OACC_DATA; 5027 break; 5028 case EXEC_OACC_HOST_DATA: 5029 construct_code = OACC_HOST_DATA; 5030 break; 5031 default: 5032 gcc_unreachable (); 5033 } 5034 5035 gfc_start_block (&block); 5036 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 5037 code->loc, false, true); 5038 pushlevel (); 5039 stmt = gfc_trans_omp_code (code->block->next, true); 5040 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 5041 stmt = build2_loc (gfc_get_location (&code->loc), construct_code, 5042 void_type_node, stmt, oacc_clauses); 5043 gfc_add_expr_to_block (&block, stmt); 5044 return gfc_finish_block (&block); 5045 } 5046 5047 /* update, enter_data, exit_data, cache. */ 5048 static tree 5049 gfc_trans_oacc_executable_directive (gfc_code *code) 5050 { 5051 stmtblock_t block; 5052 tree stmt, oacc_clauses; 5053 enum tree_code construct_code; 5054 5055 switch (code->op) 5056 { 5057 case EXEC_OACC_UPDATE: 5058 construct_code = OACC_UPDATE; 5059 break; 5060 case EXEC_OACC_ENTER_DATA: 5061 construct_code = OACC_ENTER_DATA; 5062 break; 5063 case EXEC_OACC_EXIT_DATA: 5064 construct_code = OACC_EXIT_DATA; 5065 break; 5066 case EXEC_OACC_CACHE: 5067 construct_code = OACC_CACHE; 5068 break; 5069 default: 5070 gcc_unreachable (); 5071 } 5072 5073 gfc_start_block (&block); 5074 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 5075 code->loc, false, true, code->op); 5076 stmt = build1_loc (input_location, construct_code, void_type_node, 5077 oacc_clauses); 5078 gfc_add_expr_to_block (&block, stmt); 5079 return gfc_finish_block (&block); 5080 } 5081 5082 static tree 5083 gfc_trans_oacc_wait_directive (gfc_code *code) 5084 { 5085 stmtblock_t block; 5086 tree stmt, t; 5087 vec<tree, va_gc> *args; 5088 int nparms = 0; 5089 gfc_expr_list *el; 5090 gfc_omp_clauses *clauses = code->ext.omp_clauses; 5091 location_t loc = input_location; 5092 5093 for (el = clauses->wait_list; el; el = el->next) 5094 nparms++; 5095 5096 vec_alloc (args, nparms + 2); 5097 stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT); 5098 5099 gfc_start_block (&block); 5100 5101 if (clauses->async_expr) 5102 t = gfc_convert_expr_to_tree (&block, clauses->async_expr); 5103 else 5104 t = build_int_cst (integer_type_node, -2); 5105 5106 args->quick_push (t); 5107 args->quick_push (build_int_cst (integer_type_node, nparms)); 5108 5109 for (el = clauses->wait_list; el; el = el->next) 5110 args->quick_push (gfc_convert_expr_to_tree (&block, el->expr)); 5111 5112 stmt = build_call_expr_loc_vec (loc, stmt, args); 5113 gfc_add_expr_to_block (&block, stmt); 5114 5115 vec_free (args); 5116 5117 return gfc_finish_block (&block); 5118 } 5119 5120 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *); 5121 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *); 5122 5123 static tree 5124 gfc_trans_omp_allocators (gfc_code *code) 5125 { 5126 static bool warned = false; 5127 gfc_omp_namelist *omp_allocate 5128 = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE]; 5129 if (!flag_openmp_allocators && !warned) 5130 { 5131 omp_allocate = NULL; 5132 gfc_error ("%<!$OMP %s%> at %L requires %<-fopenmp-allocators%>", 5133 code->op == EXEC_OMP_ALLOCATE ? "ALLOCATE" : "ALLOCATORS", 5134 &code->loc); 5135 warning (0, "All files that might deallocate such a variable must be " 5136 "compiled with %<-fopenmp-allocators%>"); 5137 inform (UNKNOWN_LOCATION, 5138 "This includes explicit DEALLOCATE, reallocation on intrinsic " 5139 "assignment, INTENT(OUT) for allocatable dummy arguments, and " 5140 "reallocation of allocatable components allocated with an " 5141 "OpenMP allocator"); 5142 warned = true; 5143 } 5144 return gfc_trans_allocate (code->block->next, omp_allocate); 5145 } 5146 5147 static tree 5148 gfc_trans_omp_assume (gfc_code *code) 5149 { 5150 stmtblock_t block; 5151 gfc_init_block (&block); 5152 gfc_omp_assumptions *assume = code->ext.omp_clauses->assume; 5153 if (assume) 5154 for (gfc_expr_list *el = assume->holds; el; el = el->next) 5155 { 5156 location_t loc = gfc_get_location (&el->expr->where); 5157 gfc_se se; 5158 gfc_init_se (&se, NULL); 5159 gfc_conv_expr (&se, el->expr); 5160 tree t; 5161 if (se.pre.head == NULL_TREE && se.post.head == NULL_TREE) 5162 t = se.expr; 5163 else 5164 { 5165 tree var = create_tmp_var_raw (boolean_type_node); 5166 DECL_CONTEXT (var) = current_function_decl; 5167 stmtblock_t block2; 5168 gfc_init_block (&block2); 5169 gfc_add_block_to_block (&block2, &se.pre); 5170 gfc_add_modify_loc (loc, &block2, var, 5171 fold_convert_loc (loc, boolean_type_node, 5172 se.expr)); 5173 gfc_add_block_to_block (&block2, &se.post); 5174 t = gfc_finish_block (&block2); 5175 t = build4 (TARGET_EXPR, boolean_type_node, var, t, NULL, NULL); 5176 } 5177 t = build_call_expr_internal_loc (loc, IFN_ASSUME, 5178 void_type_node, 1, t); 5179 gfc_add_expr_to_block (&block, t); 5180 } 5181 gfc_add_expr_to_block (&block, gfc_trans_omp_code (code->block->next, true)); 5182 return gfc_finish_block (&block); 5183 } 5184 5185 static tree 5186 gfc_trans_omp_atomic (gfc_code *code) 5187 { 5188 gfc_code *atomic_code = code->block; 5189 gfc_se lse; 5190 gfc_se rse; 5191 gfc_se vse; 5192 gfc_expr *expr1, *expr2, *e, *capture_expr1 = NULL, *capture_expr2 = NULL; 5193 gfc_symbol *var; 5194 stmtblock_t block; 5195 tree lhsaddr, type, rhs, x, compare = NULL_TREE, comp_tgt = NULL_TREE; 5196 enum tree_code op = ERROR_MARK; 5197 enum tree_code aop = OMP_ATOMIC; 5198 bool var_on_left = false, else_branch = false; 5199 enum omp_memory_order mo, fail_mo; 5200 switch (atomic_code->ext.omp_clauses->memorder) 5201 { 5202 case OMP_MEMORDER_UNSET: mo = OMP_MEMORY_ORDER_UNSPECIFIED; break; 5203 case OMP_MEMORDER_ACQ_REL: mo = OMP_MEMORY_ORDER_ACQ_REL; break; 5204 case OMP_MEMORDER_ACQUIRE: mo = OMP_MEMORY_ORDER_ACQUIRE; break; 5205 case OMP_MEMORDER_RELAXED: mo = OMP_MEMORY_ORDER_RELAXED; break; 5206 case OMP_MEMORDER_RELEASE: mo = OMP_MEMORY_ORDER_RELEASE; break; 5207 case OMP_MEMORDER_SEQ_CST: mo = OMP_MEMORY_ORDER_SEQ_CST; break; 5208 default: gcc_unreachable (); 5209 } 5210 switch (atomic_code->ext.omp_clauses->fail) 5211 { 5212 case OMP_MEMORDER_UNSET: fail_mo = OMP_FAIL_MEMORY_ORDER_UNSPECIFIED; break; 5213 case OMP_MEMORDER_ACQUIRE: fail_mo = OMP_FAIL_MEMORY_ORDER_ACQUIRE; break; 5214 case OMP_MEMORDER_RELAXED: fail_mo = OMP_FAIL_MEMORY_ORDER_RELAXED; break; 5215 case OMP_MEMORDER_SEQ_CST: fail_mo = OMP_FAIL_MEMORY_ORDER_SEQ_CST; break; 5216 default: gcc_unreachable (); 5217 } 5218 mo = (omp_memory_order) (mo | fail_mo); 5219 5220 code = code->block->next; 5221 if (atomic_code->ext.omp_clauses->compare) 5222 { 5223 gfc_expr *comp_expr; 5224 if (code->op == EXEC_IF) 5225 { 5226 comp_expr = code->block->expr1; 5227 gcc_assert (code->block->next->op == EXEC_ASSIGN); 5228 expr1 = code->block->next->expr1; 5229 expr2 = code->block->next->expr2; 5230 if (code->block->block) 5231 { 5232 gcc_assert (atomic_code->ext.omp_clauses->capture 5233 && code->block->block->next->op == EXEC_ASSIGN); 5234 else_branch = true; 5235 aop = OMP_ATOMIC_CAPTURE_OLD; 5236 capture_expr1 = code->block->block->next->expr1; 5237 capture_expr2 = code->block->block->next->expr2; 5238 } 5239 else if (atomic_code->ext.omp_clauses->capture) 5240 { 5241 gcc_assert (code->next->op == EXEC_ASSIGN); 5242 aop = OMP_ATOMIC_CAPTURE_NEW; 5243 capture_expr1 = code->next->expr1; 5244 capture_expr2 = code->next->expr2; 5245 } 5246 } 5247 else 5248 { 5249 gcc_assert (atomic_code->ext.omp_clauses->capture 5250 && code->op == EXEC_ASSIGN 5251 && code->next->op == EXEC_IF); 5252 aop = OMP_ATOMIC_CAPTURE_OLD; 5253 capture_expr1 = code->expr1; 5254 capture_expr2 = code->expr2; 5255 expr1 = code->next->block->next->expr1; 5256 expr2 = code->next->block->next->expr2; 5257 comp_expr = code->next->block->expr1; 5258 } 5259 gfc_init_se (&lse, NULL); 5260 gfc_conv_expr (&lse, comp_expr->value.op.op2); 5261 gfc_add_block_to_block (&block, &lse.pre); 5262 compare = lse.expr; 5263 var = expr1->symtree->n.sym; 5264 } 5265 else 5266 { 5267 gcc_assert (code->op == EXEC_ASSIGN); 5268 expr1 = code->expr1; 5269 expr2 = code->expr2; 5270 if (atomic_code->ext.omp_clauses->capture 5271 && (expr2->expr_type == EXPR_VARIABLE 5272 || (expr2->expr_type == EXPR_FUNCTION 5273 && expr2->value.function.isym 5274 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION 5275 && (expr2->value.function.actual->expr->expr_type 5276 == EXPR_VARIABLE)))) 5277 { 5278 capture_expr1 = expr1; 5279 capture_expr2 = expr2; 5280 expr1 = code->next->expr1; 5281 expr2 = code->next->expr2; 5282 aop = OMP_ATOMIC_CAPTURE_OLD; 5283 } 5284 else if (atomic_code->ext.omp_clauses->capture) 5285 { 5286 aop = OMP_ATOMIC_CAPTURE_NEW; 5287 capture_expr1 = code->next->expr1; 5288 capture_expr2 = code->next->expr2; 5289 } 5290 var = expr1->symtree->n.sym; 5291 } 5292 5293 gfc_init_se (&lse, NULL); 5294 gfc_init_se (&rse, NULL); 5295 gfc_init_se (&vse, NULL); 5296 gfc_start_block (&block); 5297 5298 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK) 5299 != GFC_OMP_ATOMIC_WRITE) 5300 && expr2->expr_type == EXPR_FUNCTION 5301 && expr2->value.function.isym 5302 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION) 5303 expr2 = expr2->value.function.actual->expr; 5304 5305 if ((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK) 5306 == GFC_OMP_ATOMIC_READ) 5307 { 5308 gfc_conv_expr (&vse, expr1); 5309 gfc_add_block_to_block (&block, &vse.pre); 5310 5311 gfc_conv_expr (&lse, expr2); 5312 gfc_add_block_to_block (&block, &lse.pre); 5313 type = TREE_TYPE (lse.expr); 5314 lhsaddr = gfc_build_addr_expr (NULL, lse.expr); 5315 5316 x = build1 (OMP_ATOMIC_READ, type, lhsaddr); 5317 OMP_ATOMIC_MEMORY_ORDER (x) = mo; 5318 x = convert (TREE_TYPE (vse.expr), x); 5319 gfc_add_modify (&block, vse.expr, x); 5320 5321 gfc_add_block_to_block (&block, &lse.pre); 5322 gfc_add_block_to_block (&block, &rse.pre); 5323 5324 return gfc_finish_block (&block); 5325 } 5326 5327 if (capture_expr2 5328 && capture_expr2->expr_type == EXPR_FUNCTION 5329 && capture_expr2->value.function.isym 5330 && capture_expr2->value.function.isym->id == GFC_ISYM_CONVERSION) 5331 capture_expr2 = capture_expr2->value.function.actual->expr; 5332 gcc_assert (!capture_expr2 || capture_expr2->expr_type == EXPR_VARIABLE); 5333 5334 if (aop == OMP_ATOMIC_CAPTURE_OLD) 5335 { 5336 gfc_conv_expr (&vse, capture_expr1); 5337 gfc_add_block_to_block (&block, &vse.pre); 5338 gfc_conv_expr (&lse, capture_expr2); 5339 gfc_add_block_to_block (&block, &lse.pre); 5340 gfc_init_se (&lse, NULL); 5341 } 5342 5343 gfc_conv_expr (&lse, expr1); 5344 gfc_add_block_to_block (&block, &lse.pre); 5345 type = TREE_TYPE (lse.expr); 5346 lhsaddr = gfc_build_addr_expr (NULL, lse.expr); 5347 5348 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK) 5349 == GFC_OMP_ATOMIC_WRITE) 5350 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP) 5351 || compare) 5352 { 5353 gfc_conv_expr (&rse, expr2); 5354 gfc_add_block_to_block (&block, &rse.pre); 5355 } 5356 else if (expr2->expr_type == EXPR_OP) 5357 { 5358 gfc_expr *e; 5359 switch (expr2->value.op.op) 5360 { 5361 case INTRINSIC_PLUS: 5362 op = PLUS_EXPR; 5363 break; 5364 case INTRINSIC_TIMES: 5365 op = MULT_EXPR; 5366 break; 5367 case INTRINSIC_MINUS: 5368 op = MINUS_EXPR; 5369 break; 5370 case INTRINSIC_DIVIDE: 5371 if (expr2->ts.type == BT_INTEGER) 5372 op = TRUNC_DIV_EXPR; 5373 else 5374 op = RDIV_EXPR; 5375 break; 5376 case INTRINSIC_AND: 5377 op = TRUTH_ANDIF_EXPR; 5378 break; 5379 case INTRINSIC_OR: 5380 op = TRUTH_ORIF_EXPR; 5381 break; 5382 case INTRINSIC_EQV: 5383 op = EQ_EXPR; 5384 break; 5385 case INTRINSIC_NEQV: 5386 op = NE_EXPR; 5387 break; 5388 default: 5389 gcc_unreachable (); 5390 } 5391 e = expr2->value.op.op1; 5392 if (e->expr_type == EXPR_FUNCTION 5393 && e->value.function.isym 5394 && e->value.function.isym->id == GFC_ISYM_CONVERSION) 5395 e = e->value.function.actual->expr; 5396 if (e->expr_type == EXPR_VARIABLE 5397 && e->symtree != NULL 5398 && e->symtree->n.sym == var) 5399 { 5400 expr2 = expr2->value.op.op2; 5401 var_on_left = true; 5402 } 5403 else 5404 { 5405 e = expr2->value.op.op2; 5406 if (e->expr_type == EXPR_FUNCTION 5407 && e->value.function.isym 5408 && e->value.function.isym->id == GFC_ISYM_CONVERSION) 5409 e = e->value.function.actual->expr; 5410 gcc_assert (e->expr_type == EXPR_VARIABLE 5411 && e->symtree != NULL 5412 && e->symtree->n.sym == var); 5413 expr2 = expr2->value.op.op1; 5414 var_on_left = false; 5415 } 5416 gfc_conv_expr (&rse, expr2); 5417 gfc_add_block_to_block (&block, &rse.pre); 5418 } 5419 else 5420 { 5421 gcc_assert (expr2->expr_type == EXPR_FUNCTION); 5422 switch (expr2->value.function.isym->id) 5423 { 5424 case GFC_ISYM_MIN: 5425 op = MIN_EXPR; 5426 break; 5427 case GFC_ISYM_MAX: 5428 op = MAX_EXPR; 5429 break; 5430 case GFC_ISYM_IAND: 5431 op = BIT_AND_EXPR; 5432 break; 5433 case GFC_ISYM_IOR: 5434 op = BIT_IOR_EXPR; 5435 break; 5436 case GFC_ISYM_IEOR: 5437 op = BIT_XOR_EXPR; 5438 break; 5439 default: 5440 gcc_unreachable (); 5441 } 5442 e = expr2->value.function.actual->expr; 5443 if (e->expr_type == EXPR_FUNCTION 5444 && e->value.function.isym 5445 && e->value.function.isym->id == GFC_ISYM_CONVERSION) 5446 e = e->value.function.actual->expr; 5447 gcc_assert (e->expr_type == EXPR_VARIABLE 5448 && e->symtree != NULL 5449 && e->symtree->n.sym == var); 5450 5451 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr); 5452 gfc_add_block_to_block (&block, &rse.pre); 5453 if (expr2->value.function.actual->next->next != NULL) 5454 { 5455 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL); 5456 gfc_actual_arglist *arg; 5457 5458 gfc_add_modify (&block, accum, rse.expr); 5459 for (arg = expr2->value.function.actual->next->next; arg; 5460 arg = arg->next) 5461 { 5462 gfc_init_block (&rse.pre); 5463 gfc_conv_expr (&rse, arg->expr); 5464 gfc_add_block_to_block (&block, &rse.pre); 5465 x = fold_build2_loc (input_location, op, TREE_TYPE (accum), 5466 accum, rse.expr); 5467 gfc_add_modify (&block, accum, x); 5468 } 5469 5470 rse.expr = accum; 5471 } 5472 5473 expr2 = expr2->value.function.actual->next->expr; 5474 } 5475 5476 lhsaddr = save_expr (lhsaddr); 5477 if (TREE_CODE (lhsaddr) != SAVE_EXPR 5478 && (TREE_CODE (lhsaddr) != ADDR_EXPR 5479 || !VAR_P (TREE_OPERAND (lhsaddr, 0)))) 5480 { 5481 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize 5482 it even after unsharing function body. */ 5483 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr)); 5484 DECL_CONTEXT (var) = current_function_decl; 5485 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, 5486 NULL_TREE, NULL_TREE); 5487 } 5488 5489 if (compare) 5490 { 5491 tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr)); 5492 DECL_CONTEXT (var) = current_function_decl; 5493 lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, NULL, 5494 NULL); 5495 lse.expr = build_fold_indirect_ref_loc (input_location, lhsaddr); 5496 compare = convert (TREE_TYPE (lse.expr), compare); 5497 compare = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, 5498 lse.expr, compare); 5499 } 5500 5501 if (expr2->expr_type == EXPR_VARIABLE || compare) 5502 rhs = rse.expr; 5503 else 5504 rhs = gfc_evaluate_now (rse.expr, &block); 5505 5506 if (((atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_MASK) 5507 == GFC_OMP_ATOMIC_WRITE) 5508 || (atomic_code->ext.omp_clauses->atomic_op & GFC_OMP_ATOMIC_SWAP) 5509 || compare) 5510 x = rhs; 5511 else 5512 { 5513 x = convert (TREE_TYPE (rhs), 5514 build_fold_indirect_ref_loc (input_location, lhsaddr)); 5515 if (var_on_left) 5516 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs); 5517 else 5518 x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x); 5519 } 5520 5521 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE 5522 && TREE_CODE (type) != COMPLEX_TYPE) 5523 x = fold_build1_loc (input_location, REALPART_EXPR, 5524 TREE_TYPE (TREE_TYPE (rhs)), x); 5525 5526 gfc_add_block_to_block (&block, &lse.pre); 5527 gfc_add_block_to_block (&block, &rse.pre); 5528 5529 if (aop == OMP_ATOMIC_CAPTURE_NEW) 5530 { 5531 gfc_conv_expr (&vse, capture_expr1); 5532 gfc_add_block_to_block (&block, &vse.pre); 5533 gfc_add_block_to_block (&block, &lse.pre); 5534 } 5535 5536 if (compare && else_branch) 5537 { 5538 tree var2 = create_tmp_var_raw (boolean_type_node); 5539 DECL_CONTEXT (var2) = current_function_decl; 5540 comp_tgt = build4 (TARGET_EXPR, boolean_type_node, var2, 5541 boolean_false_node, NULL, NULL); 5542 compare = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (var2), 5543 var2, compare); 5544 TREE_OPERAND (compare, 0) = comp_tgt; 5545 compare = omit_one_operand_loc (input_location, boolean_type_node, 5546 compare, comp_tgt); 5547 } 5548 5549 if (compare) 5550 x = build3_loc (input_location, COND_EXPR, type, compare, 5551 convert (type, x), lse.expr); 5552 5553 if (aop == OMP_ATOMIC) 5554 { 5555 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x)); 5556 OMP_ATOMIC_MEMORY_ORDER (x) = mo; 5557 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak; 5558 gfc_add_expr_to_block (&block, x); 5559 } 5560 else 5561 { 5562 x = build2 (aop, type, lhsaddr, convert (type, x)); 5563 OMP_ATOMIC_MEMORY_ORDER (x) = mo; 5564 OMP_ATOMIC_WEAK (x) = atomic_code->ext.omp_clauses->weak; 5565 if (compare && else_branch) 5566 { 5567 tree vtmp = create_tmp_var_raw (TREE_TYPE (x)); 5568 DECL_CONTEXT (vtmp) = current_function_decl; 5569 x = fold_build2_loc (input_location, MODIFY_EXPR, 5570 TREE_TYPE (vtmp), vtmp, x); 5571 vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp, 5572 build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL); 5573 TREE_OPERAND (x, 0) = vtmp; 5574 tree x2 = convert (TREE_TYPE (vse.expr), vtmp); 5575 x2 = fold_build2_loc (input_location, MODIFY_EXPR, 5576 TREE_TYPE (vse.expr), vse.expr, x2); 5577 x2 = build3_loc (input_location, COND_EXPR, void_type_node, comp_tgt, 5578 void_node, x2); 5579 x = omit_one_operand_loc (input_location, TREE_TYPE (x2), x2, x); 5580 gfc_add_expr_to_block (&block, x); 5581 } 5582 else 5583 { 5584 x = convert (TREE_TYPE (vse.expr), x); 5585 gfc_add_modify (&block, vse.expr, x); 5586 } 5587 } 5588 5589 return gfc_finish_block (&block); 5590 } 5591 5592 static tree 5593 gfc_trans_omp_barrier (void) 5594 { 5595 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER); 5596 return build_call_expr_loc (input_location, decl, 0); 5597 } 5598 5599 static tree 5600 gfc_trans_omp_cancel (gfc_code *code) 5601 { 5602 int mask = 0; 5603 tree ifc = boolean_true_node; 5604 stmtblock_t block; 5605 switch (code->ext.omp_clauses->cancel) 5606 { 5607 case OMP_CANCEL_PARALLEL: mask = 1; break; 5608 case OMP_CANCEL_DO: mask = 2; break; 5609 case OMP_CANCEL_SECTIONS: mask = 4; break; 5610 case OMP_CANCEL_TASKGROUP: mask = 8; break; 5611 default: gcc_unreachable (); 5612 } 5613 gfc_start_block (&block); 5614 if (code->ext.omp_clauses->if_expr 5615 || code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]) 5616 { 5617 gfc_se se; 5618 tree if_var; 5619 5620 gcc_assert ((code->ext.omp_clauses->if_expr == NULL) 5621 ^ (code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL] == NULL)); 5622 gfc_init_se (&se, NULL); 5623 gfc_conv_expr (&se, code->ext.omp_clauses->if_expr != NULL 5624 ? code->ext.omp_clauses->if_expr 5625 : code->ext.omp_clauses->if_exprs[OMP_IF_CANCEL]); 5626 gfc_add_block_to_block (&block, &se.pre); 5627 if_var = gfc_evaluate_now (se.expr, &block); 5628 gfc_add_block_to_block (&block, &se.post); 5629 tree type = TREE_TYPE (if_var); 5630 ifc = fold_build2_loc (input_location, NE_EXPR, 5631 boolean_type_node, if_var, 5632 build_zero_cst (type)); 5633 } 5634 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL); 5635 tree c_bool_type = TREE_TYPE (TREE_TYPE (decl)); 5636 ifc = fold_convert (c_bool_type, ifc); 5637 gfc_add_expr_to_block (&block, 5638 build_call_expr_loc (input_location, decl, 2, 5639 build_int_cst (integer_type_node, 5640 mask), ifc)); 5641 return gfc_finish_block (&block); 5642 } 5643 5644 static tree 5645 gfc_trans_omp_cancellation_point (gfc_code *code) 5646 { 5647 int mask = 0; 5648 switch (code->ext.omp_clauses->cancel) 5649 { 5650 case OMP_CANCEL_PARALLEL: mask = 1; break; 5651 case OMP_CANCEL_DO: mask = 2; break; 5652 case OMP_CANCEL_SECTIONS: mask = 4; break; 5653 case OMP_CANCEL_TASKGROUP: mask = 8; break; 5654 default: gcc_unreachable (); 5655 } 5656 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT); 5657 return build_call_expr_loc (input_location, decl, 1, 5658 build_int_cst (integer_type_node, mask)); 5659 } 5660 5661 static tree 5662 gfc_trans_omp_critical (gfc_code *code) 5663 { 5664 stmtblock_t block; 5665 tree stmt, name = NULL_TREE; 5666 if (code->ext.omp_clauses->critical_name != NULL) 5667 name = get_identifier (code->ext.omp_clauses->critical_name); 5668 gfc_start_block (&block); 5669 stmt = make_node (OMP_CRITICAL); 5670 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 5671 TREE_TYPE (stmt) = void_type_node; 5672 OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next); 5673 OMP_CRITICAL_NAME (stmt) = name; 5674 OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, 5675 code->ext.omp_clauses, 5676 code->loc); 5677 gfc_add_expr_to_block (&block, stmt); 5678 return gfc_finish_block (&block); 5679 } 5680 5681 typedef struct dovar_init_d { 5682 gfc_symbol *sym; 5683 tree var; 5684 tree init; 5685 bool non_unit_iter; 5686 } dovar_init; 5687 5688 static bool 5689 gfc_nonrect_loop_expr (stmtblock_t *pblock, gfc_se *sep, int loop_n, 5690 gfc_code *code, gfc_expr *expr, vec<dovar_init> *inits, 5691 int simple, gfc_expr *curr_loop_var) 5692 { 5693 int i; 5694 for (i = 0; i < loop_n; i++) 5695 { 5696 gcc_assert (code->ext.iterator->var->expr_type == EXPR_VARIABLE); 5697 if (gfc_find_sym_in_expr (code->ext.iterator->var->symtree->n.sym, expr)) 5698 break; 5699 code = code->block->next; 5700 } 5701 if (i >= loop_n) 5702 return false; 5703 5704 /* Canonical format: TREE_VEC with [var, multiplier, offset]. */ 5705 gfc_symbol *var = code->ext.iterator->var->symtree->n.sym; 5706 5707 tree tree_var = NULL_TREE; 5708 tree a1 = integer_one_node; 5709 tree a2 = integer_zero_node; 5710 5711 if (!simple) 5712 { 5713 /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */ 5714 sorry_at (gfc_get_location (&curr_loop_var->where), 5715 "non-rectangular loop nest with non-constant step for %qs", 5716 curr_loop_var->symtree->n.sym->name); 5717 return false; 5718 } 5719 5720 dovar_init *di; 5721 unsigned ix; 5722 FOR_EACH_VEC_ELT (*inits, ix, di) 5723 if (di->sym == var) 5724 { 5725 if (!di->non_unit_iter) 5726 { 5727 tree_var = di->init; 5728 gcc_assert (DECL_P (tree_var)); 5729 break; 5730 } 5731 else 5732 { 5733 /* FIXME: Handle non-const iter steps, cf. PR fortran/110735. */ 5734 sorry_at (gfc_get_location (&code->loc), 5735 "non-rectangular loop nest with non-constant step " 5736 "for %qs", var->name); 5737 inform (gfc_get_location (&expr->where), "Used here"); 5738 return false; 5739 } 5740 } 5741 if (tree_var == NULL_TREE) 5742 tree_var = var->backend_decl; 5743 5744 if (expr->expr_type == EXPR_VARIABLE) 5745 gcc_assert (expr->symtree->n.sym == var); 5746 else if (expr->expr_type != EXPR_OP 5747 || (expr->value.op.op != INTRINSIC_TIMES 5748 && expr->value.op.op != INTRINSIC_PLUS 5749 && expr->value.op.op != INTRINSIC_MINUS)) 5750 gcc_unreachable (); 5751 else 5752 { 5753 gfc_se se; 5754 gfc_expr *et = NULL, *eo = NULL, *e = expr; 5755 if (expr->value.op.op != INTRINSIC_TIMES) 5756 { 5757 if (gfc_find_sym_in_expr (var, expr->value.op.op1)) 5758 { 5759 e = expr->value.op.op1; 5760 eo = expr->value.op.op2; 5761 } 5762 else 5763 { 5764 eo = expr->value.op.op1; 5765 e = expr->value.op.op2; 5766 } 5767 } 5768 if (e->value.op.op == INTRINSIC_TIMES) 5769 { 5770 if (e->value.op.op1->expr_type == EXPR_VARIABLE 5771 && e->value.op.op1->symtree->n.sym == var) 5772 et = e->value.op.op2; 5773 else 5774 { 5775 et = e->value.op.op1; 5776 gcc_assert (e->value.op.op2->expr_type == EXPR_VARIABLE 5777 && e->value.op.op2->symtree->n.sym == var); 5778 } 5779 } 5780 else 5781 gcc_assert (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == var); 5782 if (et != NULL) 5783 { 5784 gfc_init_se (&se, NULL); 5785 gfc_conv_expr_val (&se, et); 5786 gfc_add_block_to_block (pblock, &se.pre); 5787 a1 = se.expr; 5788 } 5789 if (eo != NULL) 5790 { 5791 gfc_init_se (&se, NULL); 5792 gfc_conv_expr_val (&se, eo); 5793 gfc_add_block_to_block (pblock, &se.pre); 5794 a2 = se.expr; 5795 if (expr->value.op.op == INTRINSIC_MINUS && expr->value.op.op2 == eo) 5796 /* outer-var - a2. */ 5797 a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2); 5798 else if (expr->value.op.op == INTRINSIC_MINUS) 5799 /* a2 - outer-var. */ 5800 a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1); 5801 } 5802 a1 = DECL_P (a1) ? a1 : gfc_evaluate_now (a1, pblock); 5803 a2 = DECL_P (a2) ? a2 : gfc_evaluate_now (a2, pblock); 5804 } 5805 5806 gfc_init_se (sep, NULL); 5807 sep->expr = make_tree_vec (3); 5808 TREE_VEC_ELT (sep->expr, 0) = tree_var; 5809 TREE_VEC_ELT (sep->expr, 1) = fold_convert (TREE_TYPE (tree_var), a1); 5810 TREE_VEC_ELT (sep->expr, 2) = fold_convert (TREE_TYPE (tree_var), a2); 5811 5812 return true; 5813 } 5814 5815 static tree 5816 gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock, 5817 gfc_omp_clauses *do_clauses, tree par_clauses) 5818 { 5819 gfc_se se; 5820 tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls; 5821 tree local_dovar = NULL_TREE, cycle_label, tmp, omp_clauses; 5822 stmtblock_t block; 5823 stmtblock_t body; 5824 gfc_omp_clauses *clauses = code->ext.omp_clauses; 5825 int i, collapse = clauses->collapse; 5826 vec<dovar_init> inits = vNULL; 5827 dovar_init *di; 5828 unsigned ix; 5829 vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps; 5830 gfc_expr_list *tile = do_clauses ? do_clauses->tile_list : clauses->tile_list; 5831 gfc_code *orig_code = code; 5832 5833 /* Both collapsed and tiled loops are lowered the same way. In 5834 OpenACC, those clauses are not compatible, so prioritize the tile 5835 clause, if present. */ 5836 if (tile) 5837 { 5838 collapse = 0; 5839 for (gfc_expr_list *el = tile; el; el = el->next) 5840 collapse++; 5841 } 5842 5843 doacross_steps = NULL; 5844 if (clauses->orderedc) 5845 collapse = clauses->orderedc; 5846 if (collapse <= 0) 5847 collapse = 1; 5848 5849 code = code->block->next; 5850 gcc_assert (code->op == EXEC_DO); 5851 5852 init = make_tree_vec (collapse); 5853 cond = make_tree_vec (collapse); 5854 incr = make_tree_vec (collapse); 5855 orig_decls = clauses->ordered ? make_tree_vec (collapse) : NULL_TREE; 5856 5857 if (pblock == NULL) 5858 { 5859 gfc_start_block (&block); 5860 pblock = █ 5861 } 5862 5863 /* simd schedule modifier is only useful for composite do simd and other 5864 constructs including that, where gfc_trans_omp_do is only called 5865 on the simd construct and DO's clauses are translated elsewhere. */ 5866 do_clauses->sched_simd = false; 5867 5868 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc); 5869 5870 for (i = 0; i < collapse; i++) 5871 { 5872 int simple = 0; 5873 int dovar_found = 0; 5874 tree dovar_decl; 5875 5876 if (clauses) 5877 { 5878 gfc_omp_namelist *n = NULL; 5879 if (op == EXEC_OMP_SIMD && collapse == 1) 5880 for (n = clauses->lists[OMP_LIST_LINEAR]; 5881 n != NULL; n = n->next) 5882 if (code->ext.iterator->var->symtree->n.sym == n->sym) 5883 { 5884 dovar_found = 3; 5885 break; 5886 } 5887 if (n == NULL && op != EXEC_OMP_DISTRIBUTE) 5888 for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; 5889 n != NULL; n = n->next) 5890 if (code->ext.iterator->var->symtree->n.sym == n->sym) 5891 { 5892 dovar_found = 2; 5893 break; 5894 } 5895 if (n == NULL) 5896 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next) 5897 if (code->ext.iterator->var->symtree->n.sym == n->sym) 5898 { 5899 dovar_found = 1; 5900 break; 5901 } 5902 } 5903 5904 /* Evaluate all the expressions in the iterator. */ 5905 gfc_init_se (&se, NULL); 5906 gfc_conv_expr_lhs (&se, code->ext.iterator->var); 5907 gfc_add_block_to_block (pblock, &se.pre); 5908 local_dovar = dovar_decl = dovar = se.expr; 5909 type = TREE_TYPE (dovar); 5910 gcc_assert (TREE_CODE (type) == INTEGER_TYPE); 5911 5912 gfc_init_se (&se, NULL); 5913 gfc_conv_expr_val (&se, code->ext.iterator->step); 5914 gfc_add_block_to_block (pblock, &se.pre); 5915 step = gfc_evaluate_now (se.expr, pblock); 5916 5917 if (TREE_CODE (step) == INTEGER_CST) 5918 simple = tree_int_cst_sgn (step); 5919 5920 gfc_init_se (&se, NULL); 5921 if (!clauses->non_rectangular 5922 || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next, 5923 code->ext.iterator->start, &inits, simple, 5924 code->ext.iterator->var)) 5925 { 5926 gfc_conv_expr_val (&se, code->ext.iterator->start); 5927 gfc_add_block_to_block (pblock, &se.pre); 5928 if (!DECL_P (se.expr)) 5929 se.expr = gfc_evaluate_now (se.expr, pblock); 5930 } 5931 from = se.expr; 5932 5933 gfc_init_se (&se, NULL); 5934 if (!clauses->non_rectangular 5935 || !gfc_nonrect_loop_expr (pblock, &se, i, orig_code->block->next, 5936 code->ext.iterator->end, &inits, simple, 5937 code->ext.iterator->var)) 5938 { 5939 gfc_conv_expr_val (&se, code->ext.iterator->end); 5940 gfc_add_block_to_block (pblock, &se.pre); 5941 if (!DECL_P (se.expr)) 5942 se.expr = gfc_evaluate_now (se.expr, pblock); 5943 } 5944 to = se.expr; 5945 5946 if (!DECL_P (dovar)) 5947 dovar_decl 5948 = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym, 5949 false); 5950 if (simple && !DECL_P (dovar)) 5951 { 5952 const char *name = code->ext.iterator->var->symtree->n.sym->name; 5953 local_dovar = gfc_create_var (type, name); 5954 dovar_init e = {code->ext.iterator->var->symtree->n.sym, 5955 dovar, local_dovar, false}; 5956 inits.safe_push (e); 5957 } 5958 /* Loop body. */ 5959 if (simple) 5960 { 5961 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar, from); 5962 /* The condition should not be folded. */ 5963 TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0 5964 ? LE_EXPR : GE_EXPR, 5965 logical_type_node, local_dovar, 5966 to); 5967 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR, 5968 type, local_dovar, step); 5969 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, 5970 MODIFY_EXPR, 5971 type, local_dovar, 5972 TREE_VEC_ELT (incr, i)); 5973 if (orig_decls && !clauses->orderedc) 5974 orig_decls = NULL; 5975 else if (orig_decls) 5976 TREE_VEC_ELT (orig_decls, i) = dovar_decl; 5977 } 5978 else 5979 { 5980 /* STEP is not 1 or -1. Use: 5981 for (count = 0; count < (to + step - from) / step; count++) 5982 { 5983 dovar = from + count * step; 5984 body; 5985 cycle_label:; 5986 } */ 5987 tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from); 5988 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp); 5989 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp, 5990 step); 5991 tmp = gfc_evaluate_now (tmp, pblock); 5992 local_dovar = gfc_create_var (type, "count"); 5993 TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, local_dovar, 5994 build_int_cst (type, 0)); 5995 /* The condition should not be folded. */ 5996 TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR, 5997 logical_type_node, 5998 local_dovar, tmp); 5999 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR, 6000 type, local_dovar, 6001 build_int_cst (type, 1)); 6002 TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, 6003 MODIFY_EXPR, type, 6004 local_dovar, 6005 TREE_VEC_ELT (incr, i)); 6006 6007 /* Initialize DOVAR. */ 6008 tmp = fold_build2_loc (input_location, MULT_EXPR, type, local_dovar, 6009 step); 6010 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp); 6011 dovar_init e = {code->ext.iterator->var->symtree->n.sym, 6012 dovar, tmp, true}; 6013 inits.safe_push (e); 6014 if (clauses->orderedc) 6015 { 6016 if (doacross_steps == NULL) 6017 vec_safe_grow_cleared (doacross_steps, clauses->orderedc, true); 6018 (*doacross_steps)[i] = step; 6019 } 6020 if (orig_decls) 6021 TREE_VEC_ELT (orig_decls, i) = dovar_decl; 6022 } 6023 6024 if (dovar_found == 3 6025 && op == EXEC_OMP_SIMD 6026 && collapse == 1 6027 && local_dovar != dovar) 6028 { 6029 for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp)) 6030 if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR 6031 && OMP_CLAUSE_DECL (tmp) == dovar) 6032 { 6033 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1; 6034 break; 6035 } 6036 } 6037 if (!dovar_found && op == EXEC_OMP_SIMD) 6038 { 6039 if (collapse == 1) 6040 { 6041 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); 6042 OMP_CLAUSE_LINEAR_STEP (tmp) = step; 6043 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1; 6044 OMP_CLAUSE_DECL (tmp) = dovar_decl; 6045 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses); 6046 if (local_dovar != dovar) 6047 dovar_found = 3; 6048 } 6049 } 6050 else if (!dovar_found && local_dovar != dovar) 6051 { 6052 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); 6053 OMP_CLAUSE_DECL (tmp) = dovar_decl; 6054 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses); 6055 } 6056 if (dovar_found > 1) 6057 { 6058 tree c = NULL; 6059 6060 tmp = NULL; 6061 if (local_dovar != dovar) 6062 { 6063 /* If dovar is lastprivate, but different counter is used, 6064 dovar += step needs to be added to 6065 OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar 6066 will have the value on entry of the last loop, rather 6067 than value after iterator increment. */ 6068 if (clauses->orderedc) 6069 { 6070 if (clauses->collapse <= 1 || i >= clauses->collapse) 6071 tmp = local_dovar; 6072 else 6073 tmp = fold_build2_loc (input_location, PLUS_EXPR, 6074 type, local_dovar, 6075 build_one_cst (type)); 6076 tmp = fold_build2_loc (input_location, MULT_EXPR, type, 6077 tmp, step); 6078 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, 6079 from, tmp); 6080 } 6081 else 6082 tmp = fold_build2_loc (input_location, PLUS_EXPR, type, 6083 dovar, step); 6084 tmp = fold_build2_loc (input_location, MODIFY_EXPR, type, 6085 dovar, tmp); 6086 for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 6087 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE 6088 && OMP_CLAUSE_DECL (c) == dovar_decl) 6089 { 6090 OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp; 6091 break; 6092 } 6093 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR 6094 && OMP_CLAUSE_DECL (c) == dovar_decl) 6095 { 6096 OMP_CLAUSE_LINEAR_STMT (c) = tmp; 6097 break; 6098 } 6099 } 6100 if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL) 6101 { 6102 for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 6103 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE 6104 && OMP_CLAUSE_DECL (c) == dovar_decl) 6105 { 6106 tree l = build_omp_clause (input_location, 6107 OMP_CLAUSE_LASTPRIVATE); 6108 if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)) 6109 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (l) = 1; 6110 OMP_CLAUSE_DECL (l) = dovar_decl; 6111 OMP_CLAUSE_CHAIN (l) = omp_clauses; 6112 OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp; 6113 omp_clauses = l; 6114 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED); 6115 break; 6116 } 6117 } 6118 gcc_assert (local_dovar == dovar || c != NULL); 6119 } 6120 if (local_dovar != dovar) 6121 { 6122 if (op != EXEC_OMP_SIMD || dovar_found == 1) 6123 tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); 6124 else if (collapse == 1) 6125 { 6126 tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); 6127 OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1); 6128 OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1; 6129 OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1; 6130 } 6131 else 6132 tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE); 6133 OMP_CLAUSE_DECL (tmp) = local_dovar; 6134 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses); 6135 } 6136 6137 if (i + 1 < collapse) 6138 code = code->block->next; 6139 } 6140 6141 if (pblock != &block) 6142 { 6143 pushlevel (); 6144 gfc_start_block (&block); 6145 } 6146 6147 gfc_start_block (&body); 6148 6149 FOR_EACH_VEC_ELT (inits, ix, di) 6150 gfc_add_modify (&body, di->var, di->init); 6151 inits.release (); 6152 6153 /* Cycle statement is implemented with a goto. Exit statement must not be 6154 present for this loop. */ 6155 cycle_label = gfc_build_label_decl (NULL_TREE); 6156 6157 /* Put these labels where they can be found later. */ 6158 6159 code->cycle_label = cycle_label; 6160 code->exit_label = NULL_TREE; 6161 6162 /* Main loop body. */ 6163 if (clauses->lists[OMP_LIST_REDUCTION_INSCAN]) 6164 { 6165 gfc_code *code1, *scan, *code2, *tmpcode; 6166 code1 = tmpcode = code->block->next; 6167 if (tmpcode && tmpcode->op != EXEC_OMP_SCAN) 6168 while (tmpcode && tmpcode->next && tmpcode->next->op != EXEC_OMP_SCAN) 6169 tmpcode = tmpcode->next; 6170 scan = tmpcode->op == EXEC_OMP_SCAN ? tmpcode : tmpcode->next; 6171 if (code1 != scan) 6172 tmpcode->next = NULL; 6173 code2 = scan->next; 6174 gcc_assert (scan->op == EXEC_OMP_SCAN); 6175 location_t loc = gfc_get_location (&scan->loc); 6176 6177 tmp = code1 != scan ? gfc_trans_code (code1) : build_empty_stmt (loc); 6178 tmp = build2 (OMP_SCAN, void_type_node, tmp, NULL_TREE); 6179 SET_EXPR_LOCATION (tmp, loc); 6180 gfc_add_expr_to_block (&body, tmp); 6181 input_location = loc; 6182 tree c = gfc_trans_omp_clauses (&body, scan->ext.omp_clauses, scan->loc); 6183 tmp = code2 ? gfc_trans_code (code2) : build_empty_stmt (loc); 6184 tmp = build2 (OMP_SCAN, void_type_node, tmp, c); 6185 SET_EXPR_LOCATION (tmp, loc); 6186 if (code1 != scan) 6187 tmpcode->next = scan; 6188 } 6189 else 6190 tmp = gfc_trans_omp_code (code->block->next, true); 6191 gfc_add_expr_to_block (&body, tmp); 6192 6193 /* Label for cycle statements (if needed). */ 6194 if (TREE_USED (cycle_label)) 6195 { 6196 tmp = build1_v (LABEL_EXPR, cycle_label); 6197 gfc_add_expr_to_block (&body, tmp); 6198 } 6199 6200 /* End of loop body. */ 6201 switch (op) 6202 { 6203 case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break; 6204 case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break; 6205 case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break; 6206 case EXEC_OMP_LOOP: stmt = make_node (OMP_LOOP); break; 6207 case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break; 6208 case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break; 6209 default: gcc_unreachable (); 6210 } 6211 6212 SET_EXPR_LOCATION (stmt, gfc_get_location (&orig_code->loc)); 6213 TREE_TYPE (stmt) = void_type_node; 6214 OMP_FOR_BODY (stmt) = gfc_finish_block (&body); 6215 OMP_FOR_CLAUSES (stmt) = omp_clauses; 6216 OMP_FOR_INIT (stmt) = init; 6217 OMP_FOR_COND (stmt) = cond; 6218 OMP_FOR_INCR (stmt) = incr; 6219 if (orig_decls) 6220 OMP_FOR_ORIG_DECLS (stmt) = orig_decls; 6221 OMP_FOR_NON_RECTANGULAR (stmt) = clauses->non_rectangular; 6222 gfc_add_expr_to_block (&block, stmt); 6223 6224 vec_free (doacross_steps); 6225 doacross_steps = saved_doacross_steps; 6226 6227 return gfc_finish_block (&block); 6228 } 6229 6230 /* Translate combined OpenACC 'parallel loop', 'kernels loop', 'serial loop' 6231 construct. */ 6232 6233 static tree 6234 gfc_trans_oacc_combined_directive (gfc_code *code) 6235 { 6236 stmtblock_t block, *pblock = NULL; 6237 gfc_omp_clauses construct_clauses, loop_clauses; 6238 tree stmt, oacc_clauses = NULL_TREE; 6239 enum tree_code construct_code; 6240 location_t loc = input_location; 6241 6242 switch (code->op) 6243 { 6244 case EXEC_OACC_PARALLEL_LOOP: 6245 construct_code = OACC_PARALLEL; 6246 break; 6247 case EXEC_OACC_KERNELS_LOOP: 6248 construct_code = OACC_KERNELS; 6249 break; 6250 case EXEC_OACC_SERIAL_LOOP: 6251 construct_code = OACC_SERIAL; 6252 break; 6253 default: 6254 gcc_unreachable (); 6255 } 6256 6257 gfc_start_block (&block); 6258 6259 memset (&loop_clauses, 0, sizeof (loop_clauses)); 6260 if (code->ext.omp_clauses != NULL) 6261 { 6262 memcpy (&construct_clauses, code->ext.omp_clauses, 6263 sizeof (construct_clauses)); 6264 loop_clauses.collapse = construct_clauses.collapse; 6265 loop_clauses.gang = construct_clauses.gang; 6266 loop_clauses.gang_static = construct_clauses.gang_static; 6267 loop_clauses.gang_num_expr = construct_clauses.gang_num_expr; 6268 loop_clauses.gang_static_expr = construct_clauses.gang_static_expr; 6269 loop_clauses.vector = construct_clauses.vector; 6270 loop_clauses.vector_expr = construct_clauses.vector_expr; 6271 loop_clauses.worker = construct_clauses.worker; 6272 loop_clauses.worker_expr = construct_clauses.worker_expr; 6273 loop_clauses.seq = construct_clauses.seq; 6274 loop_clauses.par_auto = construct_clauses.par_auto; 6275 loop_clauses.independent = construct_clauses.independent; 6276 loop_clauses.tile_list = construct_clauses.tile_list; 6277 loop_clauses.lists[OMP_LIST_PRIVATE] 6278 = construct_clauses.lists[OMP_LIST_PRIVATE]; 6279 loop_clauses.lists[OMP_LIST_REDUCTION] 6280 = construct_clauses.lists[OMP_LIST_REDUCTION]; 6281 construct_clauses.gang = false; 6282 construct_clauses.gang_static = false; 6283 construct_clauses.gang_num_expr = NULL; 6284 construct_clauses.gang_static_expr = NULL; 6285 construct_clauses.vector = false; 6286 construct_clauses.vector_expr = NULL; 6287 construct_clauses.worker = false; 6288 construct_clauses.worker_expr = NULL; 6289 construct_clauses.seq = false; 6290 construct_clauses.par_auto = false; 6291 construct_clauses.independent = false; 6292 construct_clauses.independent = false; 6293 construct_clauses.tile_list = NULL; 6294 construct_clauses.lists[OMP_LIST_PRIVATE] = NULL; 6295 if (construct_code == OACC_KERNELS) 6296 construct_clauses.lists[OMP_LIST_REDUCTION] = NULL; 6297 oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses, 6298 code->loc, false, true); 6299 } 6300 if (!loop_clauses.seq) 6301 pblock = █ 6302 else 6303 pushlevel (); 6304 stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL); 6305 protected_set_expr_location (stmt, loc); 6306 if (TREE_CODE (stmt) != BIND_EXPR) 6307 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 6308 else 6309 poplevel (0, 0); 6310 stmt = build2_loc (loc, construct_code, void_type_node, stmt, oacc_clauses); 6311 gfc_add_expr_to_block (&block, stmt); 6312 return gfc_finish_block (&block); 6313 } 6314 6315 static tree 6316 gfc_trans_omp_depobj (gfc_code *code) 6317 { 6318 stmtblock_t block; 6319 gfc_se se; 6320 gfc_init_se (&se, NULL); 6321 gfc_init_block (&block); 6322 gfc_conv_expr (&se, code->ext.omp_clauses->depobj); 6323 gcc_assert (se.pre.head == NULL && se.post.head == NULL); 6324 tree depobj = se.expr; 6325 location_t loc = EXPR_LOCATION (depobj); 6326 if (!POINTER_TYPE_P (TREE_TYPE (depobj))) 6327 depobj = gfc_build_addr_expr (NULL, depobj); 6328 depobj = fold_convert (build_pointer_type_for_mode (ptr_type_node, 6329 TYPE_MODE (ptr_type_node), 6330 true), depobj); 6331 gfc_omp_namelist *n = code->ext.omp_clauses->lists[OMP_LIST_DEPEND]; 6332 if (n) 6333 { 6334 tree var; 6335 if (!n->sym) /* omp_all_memory. */ 6336 var = null_pointer_node; 6337 else if (n->expr && n->expr->ref->u.ar.type != AR_FULL) 6338 { 6339 gfc_init_se (&se, NULL); 6340 if (n->expr->rank == 0) 6341 { 6342 gfc_conv_expr_reference (&se, n->expr); 6343 var = se.expr; 6344 } 6345 else 6346 { 6347 gfc_conv_expr_descriptor (&se, n->expr); 6348 var = gfc_conv_array_data (se.expr); 6349 } 6350 gfc_add_block_to_block (&block, &se.pre); 6351 gfc_add_block_to_block (&block, &se.post); 6352 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var))); 6353 } 6354 else 6355 { 6356 var = gfc_get_symbol_decl (n->sym); 6357 if (POINTER_TYPE_P (TREE_TYPE (var)) 6358 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var)))) 6359 var = build_fold_indirect_ref (var); 6360 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var))) 6361 { 6362 var = gfc_conv_descriptor_data_get (var); 6363 gcc_assert (POINTER_TYPE_P (TREE_TYPE (var))); 6364 } 6365 else if ((n->sym->attr.allocatable || n->sym->attr.pointer) 6366 && n->sym->attr.dummy) 6367 var = build_fold_indirect_ref (var); 6368 else if (!POINTER_TYPE_P (TREE_TYPE (var)) 6369 || (n->sym->ts.f90_type == BT_VOID 6370 && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (var))) 6371 && !GFC_ARRAY_TYPE_P (TREE_TYPE (TREE_TYPE (var))))) 6372 { 6373 TREE_ADDRESSABLE (var) = 1; 6374 var = gfc_build_addr_expr (NULL, var); 6375 } 6376 } 6377 depobj = save_expr (depobj); 6378 tree r = build_fold_indirect_ref_loc (loc, depobj); 6379 gfc_add_expr_to_block (&block, 6380 build2 (MODIFY_EXPR, void_type_node, r, var)); 6381 } 6382 6383 /* Only one may be set. */ 6384 gcc_assert (((int)(n != NULL) + (int)(code->ext.omp_clauses->destroy) 6385 + (int)(code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET)) 6386 == 1); 6387 int k = -1; /* omp_clauses->destroy */ 6388 if (!code->ext.omp_clauses->destroy) 6389 switch (code->ext.omp_clauses->depobj_update != OMP_DEPEND_UNSET 6390 ? code->ext.omp_clauses->depobj_update : n->u.depend_doacross_op) 6391 { 6392 case OMP_DEPEND_IN: k = GOMP_DEPEND_IN; break; 6393 case OMP_DEPEND_OUT: k = GOMP_DEPEND_OUT; break; 6394 case OMP_DEPEND_INOUT: k = GOMP_DEPEND_INOUT; break; 6395 case OMP_DEPEND_INOUTSET: k = GOMP_DEPEND_INOUTSET; break; 6396 case OMP_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break; 6397 default: gcc_unreachable (); 6398 } 6399 tree t = build_int_cst (ptr_type_node, k); 6400 depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj, 6401 TYPE_SIZE_UNIT (ptr_type_node)); 6402 depobj = build_fold_indirect_ref_loc (loc, depobj); 6403 gfc_add_expr_to_block (&block, build2 (MODIFY_EXPR, void_type_node, depobj, t)); 6404 6405 return gfc_finish_block (&block); 6406 } 6407 6408 static tree 6409 gfc_trans_omp_error (gfc_code *code) 6410 { 6411 stmtblock_t block; 6412 gfc_se se; 6413 tree len, message; 6414 bool fatal = code->ext.omp_clauses->severity == OMP_SEVERITY_FATAL; 6415 tree fndecl = builtin_decl_explicit (fatal ? BUILT_IN_GOMP_ERROR 6416 : BUILT_IN_GOMP_WARNING); 6417 gfc_start_block (&block); 6418 gfc_init_se (&se, NULL ); 6419 if (!code->ext.omp_clauses->message) 6420 { 6421 message = null_pointer_node; 6422 len = build_int_cst (size_type_node, 0); 6423 } 6424 else 6425 { 6426 gfc_conv_expr (&se, code->ext.omp_clauses->message); 6427 message = se.expr; 6428 if (!POINTER_TYPE_P (TREE_TYPE (message))) 6429 /* To ensure an ARRAY_TYPE is not passed as such. */ 6430 message = gfc_build_addr_expr (NULL, message); 6431 len = se.string_length; 6432 } 6433 gfc_add_block_to_block (&block, &se.pre); 6434 gfc_add_expr_to_block (&block, build_call_expr_loc (input_location, fndecl, 6435 2, message, len)); 6436 gfc_add_block_to_block (&block, &se.post); 6437 return gfc_finish_block (&block); 6438 } 6439 6440 static tree 6441 gfc_trans_omp_flush (gfc_code *code) 6442 { 6443 tree call; 6444 if (!code->ext.omp_clauses 6445 || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET 6446 || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST) 6447 { 6448 call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); 6449 call = build_call_expr_loc (input_location, call, 0); 6450 } 6451 else 6452 { 6453 enum memmodel mo = MEMMODEL_LAST; 6454 switch (code->ext.omp_clauses->memorder) 6455 { 6456 case OMP_MEMORDER_ACQ_REL: mo = MEMMODEL_ACQ_REL; break; 6457 case OMP_MEMORDER_RELEASE: mo = MEMMODEL_RELEASE; break; 6458 case OMP_MEMORDER_ACQUIRE: mo = MEMMODEL_ACQUIRE; break; 6459 default: gcc_unreachable (); break; 6460 } 6461 call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); 6462 call = build_call_expr_loc (input_location, call, 1, 6463 build_int_cst (integer_type_node, mo)); 6464 } 6465 return call; 6466 } 6467 6468 static tree 6469 gfc_trans_omp_master (gfc_code *code) 6470 { 6471 tree stmt = gfc_trans_code (code->block->next); 6472 if (IS_EMPTY_STMT (stmt)) 6473 return stmt; 6474 return build1_v (OMP_MASTER, stmt); 6475 } 6476 6477 static tree 6478 gfc_trans_omp_masked (gfc_code *code, gfc_omp_clauses *clauses) 6479 { 6480 stmtblock_t block; 6481 tree body = gfc_trans_code (code->block->next); 6482 if (IS_EMPTY_STMT (body)) 6483 return body; 6484 if (!clauses) 6485 clauses = code->ext.omp_clauses; 6486 gfc_start_block (&block); 6487 tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); 6488 tree stmt = make_node (OMP_MASKED); 6489 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 6490 TREE_TYPE (stmt) = void_type_node; 6491 OMP_MASKED_BODY (stmt) = body; 6492 OMP_MASKED_CLAUSES (stmt) = omp_clauses; 6493 gfc_add_expr_to_block (&block, stmt); 6494 return gfc_finish_block (&block); 6495 } 6496 6497 6498 static tree 6499 gfc_trans_omp_ordered (gfc_code *code) 6500 { 6501 if (!flag_openmp) 6502 { 6503 if (!code->ext.omp_clauses->simd) 6504 return gfc_trans_code (code->block ? code->block->next : NULL); 6505 code->ext.omp_clauses->threads = 0; 6506 } 6507 tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses, 6508 code->loc); 6509 return build2_loc (input_location, OMP_ORDERED, void_type_node, 6510 code->block ? gfc_trans_code (code->block->next) 6511 : NULL_TREE, omp_clauses); 6512 } 6513 6514 static tree 6515 gfc_trans_omp_parallel (gfc_code *code) 6516 { 6517 stmtblock_t block; 6518 tree stmt, omp_clauses; 6519 6520 gfc_start_block (&block); 6521 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 6522 code->loc); 6523 pushlevel (); 6524 stmt = gfc_trans_omp_code (code->block->next, true); 6525 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 6526 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt, 6527 omp_clauses); 6528 gfc_add_expr_to_block (&block, stmt); 6529 return gfc_finish_block (&block); 6530 } 6531 6532 enum 6533 { 6534 GFC_OMP_SPLIT_SIMD, 6535 GFC_OMP_SPLIT_DO, 6536 GFC_OMP_SPLIT_PARALLEL, 6537 GFC_OMP_SPLIT_DISTRIBUTE, 6538 GFC_OMP_SPLIT_TEAMS, 6539 GFC_OMP_SPLIT_TARGET, 6540 GFC_OMP_SPLIT_TASKLOOP, 6541 GFC_OMP_SPLIT_MASKED, 6542 GFC_OMP_SPLIT_NUM 6543 }; 6544 6545 enum 6546 { 6547 GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD), 6548 GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO), 6549 GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL), 6550 GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE), 6551 GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS), 6552 GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET), 6553 GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP), 6554 GFC_OMP_MASK_MASKED = (1 << GFC_OMP_SPLIT_MASKED) 6555 }; 6556 6557 /* If a var is in lastprivate/firstprivate/reduction but not in a 6558 data mapping/sharing clause, add it to 'map(tofrom:' if is_target 6559 and to 'shared' otherwise. */ 6560 static void 6561 gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out, 6562 gfc_omp_clauses *clauses_in, 6563 bool is_target, bool is_parallel_do) 6564 { 6565 int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED; 6566 gfc_omp_namelist *tail = NULL; 6567 for (int i = 0; i < 5; ++i) 6568 { 6569 gfc_omp_namelist *n; 6570 switch (i) 6571 { 6572 case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break; 6573 case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break; 6574 case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break; 6575 case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break; 6576 case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break; 6577 default: gcc_unreachable (); 6578 } 6579 for (; n != NULL; n = n->next) 6580 { 6581 gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL; 6582 for (int j = 0; j < 6; ++j) 6583 { 6584 gfc_omp_namelist **n2ref = NULL, *prev2 = NULL; 6585 switch (j) 6586 { 6587 case 0: 6588 n2ref = &clauses_out->lists[clauselist_to_add]; 6589 break; 6590 case 1: 6591 n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE]; 6592 break; 6593 case 2: 6594 if (is_target) 6595 n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE]; 6596 else 6597 n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE]; 6598 break; 6599 case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break; 6600 case 4: 6601 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN]; 6602 break; 6603 case 5: 6604 n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK]; 6605 break; 6606 default: gcc_unreachable (); 6607 } 6608 for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next) 6609 if (n2->sym == n->sym) 6610 break; 6611 if (n2) 6612 { 6613 if (j == 0 /* clauselist_to_add */) 6614 break; /* Already present. */ 6615 if (j == 1 /* OMP_LIST_FIRSTPRIVATE */) 6616 { 6617 n_firstp = prev2 ? &prev2->next : n2ref; 6618 continue; 6619 } 6620 if (j == 2 /* OMP_LIST_LASTPRIVATE */) 6621 { 6622 n_lastp = prev2 ? &prev2->next : n2ref; 6623 continue; 6624 } 6625 break; 6626 } 6627 } 6628 if (n_firstp && n_lastp) 6629 { 6630 /* For parallel do, GCC puts firstprivate/lastprivate 6631 on the parallel. */ 6632 if (is_parallel_do) 6633 continue; 6634 *n_firstp = (*n_firstp)->next; 6635 if (!is_target) 6636 *n_lastp = (*n_lastp)->next; 6637 } 6638 else if (is_target && n_lastp) 6639 ; 6640 else if (n2 || n_firstp || n_lastp) 6641 continue; 6642 if (clauses_out->lists[clauselist_to_add] 6643 && (clauses_out->lists[clauselist_to_add] 6644 == clauses_in->lists[clauselist_to_add])) 6645 { 6646 gfc_omp_namelist *p = NULL; 6647 for (n2 = clauses_in->lists[clauselist_to_add]; n2; n2 = n2->next) 6648 { 6649 if (p) 6650 { 6651 p->next = gfc_get_omp_namelist (); 6652 p = p->next; 6653 } 6654 else 6655 { 6656 p = gfc_get_omp_namelist (); 6657 clauses_out->lists[clauselist_to_add] = p; 6658 } 6659 *p = *n2; 6660 } 6661 } 6662 if (!tail) 6663 { 6664 tail = clauses_out->lists[clauselist_to_add]; 6665 for (; tail && tail->next; tail = tail->next) 6666 ; 6667 } 6668 n2 = gfc_get_omp_namelist (); 6669 n2->where = n->where; 6670 n2->sym = n->sym; 6671 if (is_target) 6672 n2->u.map.op = OMP_MAP_TOFROM; 6673 if (tail) 6674 { 6675 tail->next = n2; 6676 tail = n2; 6677 } 6678 else 6679 clauses_out->lists[clauselist_to_add] = n2; 6680 } 6681 } 6682 } 6683 6684 /* Kind of opposite to above, add firstprivate to CLAUSES_OUT if it is mapped 6685 in CLAUSES_IN's FIRSTPRIVATE list but not its MAP list. */ 6686 6687 static void 6688 gfc_add_firstprivate_if_unmapped (gfc_omp_clauses *clauses_out, 6689 gfc_omp_clauses *clauses_in) 6690 { 6691 gfc_omp_namelist *n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; 6692 gfc_omp_namelist **tail = NULL; 6693 6694 for (; n != NULL; n = n->next) 6695 { 6696 gfc_omp_namelist *n2 = clauses_out->lists[OMP_LIST_MAP]; 6697 for (; n2 != NULL; n2 = n2->next) 6698 if (n->sym == n2->sym) 6699 break; 6700 if (n2 == NULL) 6701 { 6702 gfc_omp_namelist *dup = gfc_get_omp_namelist (); 6703 *dup = *n; 6704 dup->next = NULL; 6705 if (!tail) 6706 { 6707 tail = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE]; 6708 while (*tail && (*tail)->next) 6709 tail = &(*tail)->next; 6710 } 6711 *tail = dup; 6712 tail = &(*tail)->next; 6713 } 6714 } 6715 } 6716 6717 static void 6718 gfc_free_split_omp_clauses (gfc_code *code, gfc_omp_clauses *clausesa) 6719 { 6720 for (int i = 0; i < GFC_OMP_SPLIT_NUM; ++i) 6721 for (int j = 0; j < OMP_LIST_NUM; ++j) 6722 if (clausesa[i].lists[j] && clausesa[i].lists[j] != code->ext.omp_clauses->lists[j]) 6723 for (gfc_omp_namelist *n = clausesa[i].lists[j]; n;) 6724 { 6725 gfc_omp_namelist *p = n; 6726 n = n->next; 6727 free (p); 6728 } 6729 } 6730 6731 static void 6732 gfc_split_omp_clauses (gfc_code *code, 6733 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM]) 6734 { 6735 int mask = 0, innermost = 0; 6736 bool is_loop = false; 6737 memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses)); 6738 switch (code->op) 6739 { 6740 case EXEC_OMP_DISTRIBUTE: 6741 innermost = GFC_OMP_SPLIT_DISTRIBUTE; 6742 break; 6743 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: 6744 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO; 6745 innermost = GFC_OMP_SPLIT_DO; 6746 break; 6747 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: 6748 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL 6749 | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD; 6750 innermost = GFC_OMP_SPLIT_SIMD; 6751 break; 6752 case EXEC_OMP_DISTRIBUTE_SIMD: 6753 mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD; 6754 innermost = GFC_OMP_SPLIT_SIMD; 6755 break; 6756 case EXEC_OMP_DO: 6757 case EXEC_OMP_LOOP: 6758 innermost = GFC_OMP_SPLIT_DO; 6759 break; 6760 case EXEC_OMP_DO_SIMD: 6761 mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD; 6762 innermost = GFC_OMP_SPLIT_SIMD; 6763 break; 6764 case EXEC_OMP_PARALLEL: 6765 innermost = GFC_OMP_SPLIT_PARALLEL; 6766 break; 6767 case EXEC_OMP_PARALLEL_DO: 6768 case EXEC_OMP_PARALLEL_LOOP: 6769 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO; 6770 innermost = GFC_OMP_SPLIT_DO; 6771 break; 6772 case EXEC_OMP_PARALLEL_DO_SIMD: 6773 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD; 6774 innermost = GFC_OMP_SPLIT_SIMD; 6775 break; 6776 case EXEC_OMP_PARALLEL_MASKED: 6777 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED; 6778 innermost = GFC_OMP_SPLIT_MASKED; 6779 break; 6780 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: 6781 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED 6782 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD); 6783 innermost = GFC_OMP_SPLIT_TASKLOOP; 6784 break; 6785 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: 6786 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD; 6787 innermost = GFC_OMP_SPLIT_TASKLOOP; 6788 break; 6789 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: 6790 mask = (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_MASKED 6791 | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD); 6792 innermost = GFC_OMP_SPLIT_SIMD; 6793 break; 6794 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: 6795 mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD; 6796 innermost = GFC_OMP_SPLIT_SIMD; 6797 break; 6798 case EXEC_OMP_SIMD: 6799 innermost = GFC_OMP_SPLIT_SIMD; 6800 break; 6801 case EXEC_OMP_TARGET: 6802 innermost = GFC_OMP_SPLIT_TARGET; 6803 break; 6804 case EXEC_OMP_TARGET_PARALLEL: 6805 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL; 6806 innermost = GFC_OMP_SPLIT_PARALLEL; 6807 break; 6808 case EXEC_OMP_TARGET_PARALLEL_DO: 6809 case EXEC_OMP_TARGET_PARALLEL_LOOP: 6810 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO; 6811 innermost = GFC_OMP_SPLIT_DO; 6812 break; 6813 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: 6814 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO 6815 | GFC_OMP_MASK_SIMD; 6816 innermost = GFC_OMP_SPLIT_SIMD; 6817 break; 6818 case EXEC_OMP_TARGET_SIMD: 6819 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD; 6820 innermost = GFC_OMP_SPLIT_SIMD; 6821 break; 6822 case EXEC_OMP_TARGET_TEAMS: 6823 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS; 6824 innermost = GFC_OMP_SPLIT_TEAMS; 6825 break; 6826 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: 6827 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS 6828 | GFC_OMP_MASK_DISTRIBUTE; 6829 innermost = GFC_OMP_SPLIT_DISTRIBUTE; 6830 break; 6831 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: 6832 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE 6833 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO; 6834 innermost = GFC_OMP_SPLIT_DO; 6835 break; 6836 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 6837 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE 6838 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD; 6839 innermost = GFC_OMP_SPLIT_SIMD; 6840 break; 6841 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: 6842 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS 6843 | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD; 6844 innermost = GFC_OMP_SPLIT_SIMD; 6845 break; 6846 case EXEC_OMP_TARGET_TEAMS_LOOP: 6847 mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO; 6848 innermost = GFC_OMP_SPLIT_DO; 6849 break; 6850 case EXEC_OMP_MASKED_TASKLOOP: 6851 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP; 6852 innermost = GFC_OMP_SPLIT_TASKLOOP; 6853 break; 6854 case EXEC_OMP_MASTER_TASKLOOP: 6855 case EXEC_OMP_TASKLOOP: 6856 innermost = GFC_OMP_SPLIT_TASKLOOP; 6857 break; 6858 case EXEC_OMP_MASKED_TASKLOOP_SIMD: 6859 mask = GFC_OMP_MASK_MASKED | GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD; 6860 innermost = GFC_OMP_SPLIT_SIMD; 6861 break; 6862 case EXEC_OMP_MASTER_TASKLOOP_SIMD: 6863 case EXEC_OMP_TASKLOOP_SIMD: 6864 mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD; 6865 innermost = GFC_OMP_SPLIT_SIMD; 6866 break; 6867 case EXEC_OMP_TEAMS: 6868 innermost = GFC_OMP_SPLIT_TEAMS; 6869 break; 6870 case EXEC_OMP_TEAMS_DISTRIBUTE: 6871 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE; 6872 innermost = GFC_OMP_SPLIT_DISTRIBUTE; 6873 break; 6874 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: 6875 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE 6876 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO; 6877 innermost = GFC_OMP_SPLIT_DO; 6878 break; 6879 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 6880 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE 6881 | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD; 6882 innermost = GFC_OMP_SPLIT_SIMD; 6883 break; 6884 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: 6885 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD; 6886 innermost = GFC_OMP_SPLIT_SIMD; 6887 break; 6888 case EXEC_OMP_TEAMS_LOOP: 6889 mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DO; 6890 innermost = GFC_OMP_SPLIT_DO; 6891 break; 6892 default: 6893 gcc_unreachable (); 6894 } 6895 if (mask == 0) 6896 { 6897 clausesa[innermost] = *code->ext.omp_clauses; 6898 return; 6899 } 6900 /* Loops are similar to DO but still a bit different. */ 6901 switch (code->op) 6902 { 6903 case EXEC_OMP_LOOP: 6904 case EXEC_OMP_PARALLEL_LOOP: 6905 case EXEC_OMP_TEAMS_LOOP: 6906 case EXEC_OMP_TARGET_PARALLEL_LOOP: 6907 case EXEC_OMP_TARGET_TEAMS_LOOP: 6908 is_loop = true; 6909 default: 6910 break; 6911 } 6912 if (code->ext.omp_clauses != NULL) 6913 { 6914 if (mask & GFC_OMP_MASK_TARGET) 6915 { 6916 /* First the clauses that are unique to some constructs. */ 6917 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP] 6918 = code->ext.omp_clauses->lists[OMP_LIST_MAP]; 6919 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR] 6920 = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR]; 6921 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_HAS_DEVICE_ADDR] 6922 = code->ext.omp_clauses->lists[OMP_LIST_HAS_DEVICE_ADDR]; 6923 clausesa[GFC_OMP_SPLIT_TARGET].device 6924 = code->ext.omp_clauses->device; 6925 clausesa[GFC_OMP_SPLIT_TARGET].thread_limit 6926 = code->ext.omp_clauses->thread_limit; 6927 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_USES_ALLOCATORS] 6928 = code->ext.omp_clauses->lists[OMP_LIST_USES_ALLOCATORS]; 6929 for (int i = 0; i < OMP_DEFAULTMAP_CAT_NUM; i++) 6930 clausesa[GFC_OMP_SPLIT_TARGET].defaultmap[i] 6931 = code->ext.omp_clauses->defaultmap[i]; 6932 clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET] 6933 = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET]; 6934 /* And this is copied to all. */ 6935 clausesa[GFC_OMP_SPLIT_TARGET].if_expr 6936 = code->ext.omp_clauses->if_expr; 6937 clausesa[GFC_OMP_SPLIT_TARGET].nowait 6938 = code->ext.omp_clauses->nowait; 6939 } 6940 if (mask & GFC_OMP_MASK_TEAMS) 6941 { 6942 /* First the clauses that are unique to some constructs. */ 6943 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower 6944 = code->ext.omp_clauses->num_teams_lower; 6945 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper 6946 = code->ext.omp_clauses->num_teams_upper; 6947 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit 6948 = code->ext.omp_clauses->thread_limit; 6949 /* Shared and default clauses are allowed on parallel, teams 6950 and taskloop. */ 6951 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED] 6952 = code->ext.omp_clauses->lists[OMP_LIST_SHARED]; 6953 clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing 6954 = code->ext.omp_clauses->default_sharing; 6955 } 6956 if (mask & GFC_OMP_MASK_DISTRIBUTE) 6957 { 6958 /* First the clauses that are unique to some constructs. */ 6959 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind 6960 = code->ext.omp_clauses->dist_sched_kind; 6961 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size 6962 = code->ext.omp_clauses->dist_chunk_size; 6963 /* Duplicate collapse. */ 6964 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse 6965 = code->ext.omp_clauses->collapse; 6966 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_concurrent 6967 = code->ext.omp_clauses->order_concurrent; 6968 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_unconstrained 6969 = code->ext.omp_clauses->order_unconstrained; 6970 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].order_reproducible 6971 = code->ext.omp_clauses->order_reproducible; 6972 } 6973 if (mask & GFC_OMP_MASK_PARALLEL) 6974 { 6975 /* First the clauses that are unique to some constructs. */ 6976 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN] 6977 = code->ext.omp_clauses->lists[OMP_LIST_COPYIN]; 6978 clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads 6979 = code->ext.omp_clauses->num_threads; 6980 clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind 6981 = code->ext.omp_clauses->proc_bind; 6982 /* Shared and default clauses are allowed on parallel, teams 6983 and taskloop. */ 6984 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED] 6985 = code->ext.omp_clauses->lists[OMP_LIST_SHARED]; 6986 clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing 6987 = code->ext.omp_clauses->default_sharing; 6988 clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL] 6989 = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL]; 6990 /* And this is copied to all. */ 6991 clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr 6992 = code->ext.omp_clauses->if_expr; 6993 } 6994 if (mask & GFC_OMP_MASK_MASKED) 6995 clausesa[GFC_OMP_SPLIT_MASKED].filter = code->ext.omp_clauses->filter; 6996 if ((mask & GFC_OMP_MASK_DO) && !is_loop) 6997 { 6998 /* First the clauses that are unique to some constructs. */ 6999 clausesa[GFC_OMP_SPLIT_DO].ordered 7000 = code->ext.omp_clauses->ordered; 7001 clausesa[GFC_OMP_SPLIT_DO].orderedc 7002 = code->ext.omp_clauses->orderedc; 7003 clausesa[GFC_OMP_SPLIT_DO].sched_kind 7004 = code->ext.omp_clauses->sched_kind; 7005 if (innermost == GFC_OMP_SPLIT_SIMD) 7006 clausesa[GFC_OMP_SPLIT_DO].sched_simd 7007 = code->ext.omp_clauses->sched_simd; 7008 clausesa[GFC_OMP_SPLIT_DO].sched_monotonic 7009 = code->ext.omp_clauses->sched_monotonic; 7010 clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic 7011 = code->ext.omp_clauses->sched_nonmonotonic; 7012 clausesa[GFC_OMP_SPLIT_DO].chunk_size 7013 = code->ext.omp_clauses->chunk_size; 7014 clausesa[GFC_OMP_SPLIT_DO].nowait 7015 = code->ext.omp_clauses->nowait; 7016 } 7017 if (mask & GFC_OMP_MASK_DO) 7018 { 7019 clausesa[GFC_OMP_SPLIT_DO].bind 7020 = code->ext.omp_clauses->bind; 7021 /* Duplicate collapse. */ 7022 clausesa[GFC_OMP_SPLIT_DO].collapse 7023 = code->ext.omp_clauses->collapse; 7024 clausesa[GFC_OMP_SPLIT_DO].order_concurrent 7025 = code->ext.omp_clauses->order_concurrent; 7026 clausesa[GFC_OMP_SPLIT_DO].order_unconstrained 7027 = code->ext.omp_clauses->order_unconstrained; 7028 clausesa[GFC_OMP_SPLIT_DO].order_reproducible 7029 = code->ext.omp_clauses->order_reproducible; 7030 } 7031 if (mask & GFC_OMP_MASK_SIMD) 7032 { 7033 clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr 7034 = code->ext.omp_clauses->safelen_expr; 7035 clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr 7036 = code->ext.omp_clauses->simdlen_expr; 7037 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED] 7038 = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED]; 7039 /* Duplicate collapse. */ 7040 clausesa[GFC_OMP_SPLIT_SIMD].collapse 7041 = code->ext.omp_clauses->collapse; 7042 clausesa[GFC_OMP_SPLIT_SIMD].if_exprs[OMP_IF_SIMD] 7043 = code->ext.omp_clauses->if_exprs[OMP_IF_SIMD]; 7044 clausesa[GFC_OMP_SPLIT_SIMD].order_concurrent 7045 = code->ext.omp_clauses->order_concurrent; 7046 clausesa[GFC_OMP_SPLIT_SIMD].order_unconstrained 7047 = code->ext.omp_clauses->order_unconstrained; 7048 clausesa[GFC_OMP_SPLIT_SIMD].order_reproducible 7049 = code->ext.omp_clauses->order_reproducible; 7050 /* And this is copied to all. */ 7051 clausesa[GFC_OMP_SPLIT_SIMD].if_expr 7052 = code->ext.omp_clauses->if_expr; 7053 } 7054 if (mask & GFC_OMP_MASK_TASKLOOP) 7055 { 7056 /* First the clauses that are unique to some constructs. */ 7057 clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup 7058 = code->ext.omp_clauses->nogroup; 7059 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize 7060 = code->ext.omp_clauses->grainsize; 7061 clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize_strict 7062 = code->ext.omp_clauses->grainsize_strict; 7063 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks 7064 = code->ext.omp_clauses->num_tasks; 7065 clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks_strict 7066 = code->ext.omp_clauses->num_tasks_strict; 7067 clausesa[GFC_OMP_SPLIT_TASKLOOP].priority 7068 = code->ext.omp_clauses->priority; 7069 clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr 7070 = code->ext.omp_clauses->final_expr; 7071 clausesa[GFC_OMP_SPLIT_TASKLOOP].untied 7072 = code->ext.omp_clauses->untied; 7073 clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable 7074 = code->ext.omp_clauses->mergeable; 7075 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP] 7076 = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP]; 7077 /* And this is copied to all. */ 7078 clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr 7079 = code->ext.omp_clauses->if_expr; 7080 /* Shared and default clauses are allowed on parallel, teams 7081 and taskloop. */ 7082 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED] 7083 = code->ext.omp_clauses->lists[OMP_LIST_SHARED]; 7084 clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing 7085 = code->ext.omp_clauses->default_sharing; 7086 /* Duplicate collapse. */ 7087 clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse 7088 = code->ext.omp_clauses->collapse; 7089 } 7090 /* Private clause is supported on all constructs but master/masked, 7091 it is enough to put it on the innermost one except for master/masked. For 7092 !$ omp parallel do put it on parallel though, 7093 as that's what we did for OpenMP 3.1. */ 7094 clausesa[((innermost == GFC_OMP_SPLIT_DO && !is_loop) 7095 || code->op == EXEC_OMP_PARALLEL_MASTER 7096 || code->op == EXEC_OMP_PARALLEL_MASKED) 7097 ? (int) GFC_OMP_SPLIT_PARALLEL 7098 : innermost].lists[OMP_LIST_PRIVATE] 7099 = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE]; 7100 /* Firstprivate clause is supported on all constructs but 7101 simd and masked/master. Put it on the outermost of those and duplicate 7102 on parallel and teams. */ 7103 if (mask & GFC_OMP_MASK_TARGET) 7104 gfc_add_firstprivate_if_unmapped (&clausesa[GFC_OMP_SPLIT_TARGET], 7105 code->ext.omp_clauses); 7106 if (mask & GFC_OMP_MASK_TEAMS) 7107 clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE] 7108 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; 7109 else if (mask & GFC_OMP_MASK_DISTRIBUTE) 7110 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE] 7111 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; 7112 if (mask & GFC_OMP_MASK_TASKLOOP) 7113 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_FIRSTPRIVATE] 7114 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; 7115 if ((mask & GFC_OMP_MASK_PARALLEL) 7116 && !(mask & GFC_OMP_MASK_TASKLOOP)) 7117 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE] 7118 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; 7119 else if ((mask & GFC_OMP_MASK_DO) && !is_loop) 7120 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE] 7121 = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; 7122 /* Lastprivate is allowed on distribute, do, simd, taskloop and loop. 7123 In parallel do{, simd} we actually want to put it on 7124 parallel rather than do. */ 7125 if (mask & GFC_OMP_MASK_DISTRIBUTE) 7126 clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE] 7127 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE]; 7128 if (mask & GFC_OMP_MASK_TASKLOOP) 7129 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_LASTPRIVATE] 7130 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE]; 7131 if ((mask & GFC_OMP_MASK_PARALLEL) && !is_loop 7132 && !(mask & GFC_OMP_MASK_TASKLOOP)) 7133 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE] 7134 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE]; 7135 else if (mask & GFC_OMP_MASK_DO) 7136 clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE] 7137 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE]; 7138 if (mask & GFC_OMP_MASK_SIMD) 7139 clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE] 7140 = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE]; 7141 /* Reduction is allowed on simd, do, parallel, teams, taskloop, and loop. 7142 Duplicate it on all of them, but 7143 - omit on do if parallel is present; 7144 - omit on task and parallel if loop is present; 7145 additionally, inscan applies to do/simd only. */ 7146 for (int i = OMP_LIST_REDUCTION; i <= OMP_LIST_REDUCTION_TASK; i++) 7147 { 7148 if (mask & GFC_OMP_MASK_TASKLOOP 7149 && i != OMP_LIST_REDUCTION_INSCAN) 7150 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[i] 7151 = code->ext.omp_clauses->lists[i]; 7152 if (mask & GFC_OMP_MASK_TEAMS 7153 && i != OMP_LIST_REDUCTION_INSCAN 7154 && !is_loop) 7155 clausesa[GFC_OMP_SPLIT_TEAMS].lists[i] 7156 = code->ext.omp_clauses->lists[i]; 7157 if (mask & GFC_OMP_MASK_PARALLEL 7158 && i != OMP_LIST_REDUCTION_INSCAN 7159 && !(mask & GFC_OMP_MASK_TASKLOOP) 7160 && !is_loop) 7161 clausesa[GFC_OMP_SPLIT_PARALLEL].lists[i] 7162 = code->ext.omp_clauses->lists[i]; 7163 else if (mask & GFC_OMP_MASK_DO) 7164 clausesa[GFC_OMP_SPLIT_DO].lists[i] 7165 = code->ext.omp_clauses->lists[i]; 7166 if (mask & GFC_OMP_MASK_SIMD) 7167 clausesa[GFC_OMP_SPLIT_SIMD].lists[i] 7168 = code->ext.omp_clauses->lists[i]; 7169 } 7170 if (mask & GFC_OMP_MASK_TARGET) 7171 clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IN_REDUCTION] 7172 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION]; 7173 if (mask & GFC_OMP_MASK_TASKLOOP) 7174 clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_IN_REDUCTION] 7175 = code->ext.omp_clauses->lists[OMP_LIST_IN_REDUCTION]; 7176 /* Linear clause is supported on do and simd, 7177 put it on the innermost one. */ 7178 clausesa[innermost].lists[OMP_LIST_LINEAR] 7179 = code->ext.omp_clauses->lists[OMP_LIST_LINEAR]; 7180 } 7181 /* Propagate firstprivate/lastprivate/reduction vars to 7182 shared (parallel, teams) and map-tofrom (target). */ 7183 if (mask & GFC_OMP_MASK_TARGET) 7184 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TARGET], 7185 code->ext.omp_clauses, true, false); 7186 if ((mask & GFC_OMP_MASK_PARALLEL) && innermost != GFC_OMP_MASK_PARALLEL) 7187 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_PARALLEL], 7188 code->ext.omp_clauses, false, 7189 mask & GFC_OMP_MASK_DO); 7190 if (mask & GFC_OMP_MASK_TEAMS && innermost != GFC_OMP_MASK_TEAMS) 7191 gfc_add_clause_implicitly (&clausesa[GFC_OMP_SPLIT_TEAMS], 7192 code->ext.omp_clauses, false, false); 7193 if (((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO)) 7194 == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO)) 7195 && !is_loop) 7196 clausesa[GFC_OMP_SPLIT_DO].nowait = true; 7197 7198 /* Distribute allocate clause to do, parallel, distribute, teams, target 7199 and taskloop. The code below iterates over variables in the 7200 allocate list and checks if that available is also in any 7201 privatization clause on those construct. If yes, then we add it 7202 to the list of 'allocate'ed variables for that construct. If a 7203 variable is found in none of them then we issue an error. */ 7204 7205 if (code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE]) 7206 { 7207 gfc_omp_namelist *alloc_nl, *priv_nl; 7208 gfc_omp_namelist *tails[GFC_OMP_SPLIT_NUM]; 7209 for (alloc_nl = code->ext.omp_clauses->lists[OMP_LIST_ALLOCATE]; 7210 alloc_nl; alloc_nl = alloc_nl->next) 7211 { 7212 bool found = false; 7213 for (int i = GFC_OMP_SPLIT_DO; i <= GFC_OMP_SPLIT_TASKLOOP; i++) 7214 { 7215 gfc_omp_namelist *p; 7216 int list; 7217 for (list = 0; list < OMP_LIST_NUM; list++) 7218 { 7219 switch (list) 7220 { 7221 case OMP_LIST_PRIVATE: 7222 case OMP_LIST_FIRSTPRIVATE: 7223 case OMP_LIST_LASTPRIVATE: 7224 case OMP_LIST_REDUCTION: 7225 case OMP_LIST_REDUCTION_INSCAN: 7226 case OMP_LIST_REDUCTION_TASK: 7227 case OMP_LIST_IN_REDUCTION: 7228 case OMP_LIST_TASK_REDUCTION: 7229 case OMP_LIST_LINEAR: 7230 for (priv_nl = clausesa[i].lists[list]; priv_nl; 7231 priv_nl = priv_nl->next) 7232 if (alloc_nl->sym == priv_nl->sym) 7233 { 7234 found = true; 7235 p = gfc_get_omp_namelist (); 7236 p->sym = alloc_nl->sym; 7237 p->expr = alloc_nl->expr; 7238 p->u.align = alloc_nl->u.align; 7239 p->u2.allocator = alloc_nl->u2.allocator; 7240 p->where = alloc_nl->where; 7241 if (clausesa[i].lists[OMP_LIST_ALLOCATE] == NULL) 7242 { 7243 clausesa[i].lists[OMP_LIST_ALLOCATE] = p; 7244 tails[i] = p; 7245 } 7246 else 7247 { 7248 tails[i]->next = p; 7249 tails[i] = tails[i]->next; 7250 } 7251 } 7252 break; 7253 default: 7254 break; 7255 } 7256 } 7257 } 7258 if (!found) 7259 gfc_error ("%qs specified in 'allocate' clause at %L but not " 7260 "in an explicit privatization clause", 7261 alloc_nl->sym->name, &alloc_nl->where); 7262 } 7263 } 7264 } 7265 7266 static tree 7267 gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock, 7268 gfc_omp_clauses *clausesa, tree omp_clauses) 7269 { 7270 stmtblock_t block; 7271 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; 7272 tree stmt, body, omp_do_clauses = NULL_TREE; 7273 bool free_clausesa = false; 7274 7275 if (pblock == NULL) 7276 gfc_start_block (&block); 7277 else 7278 gfc_init_block (&block); 7279 7280 if (clausesa == NULL) 7281 { 7282 clausesa = clausesa_buf; 7283 gfc_split_omp_clauses (code, clausesa); 7284 free_clausesa = true; 7285 } 7286 if (flag_openmp) 7287 omp_do_clauses 7288 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc); 7289 body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block, 7290 &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses); 7291 if (pblock == NULL) 7292 { 7293 if (TREE_CODE (body) != BIND_EXPR) 7294 body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0)); 7295 else 7296 poplevel (0, 0); 7297 } 7298 else if (TREE_CODE (body) != BIND_EXPR) 7299 body = build3_v (BIND_EXPR, NULL, body, NULL_TREE); 7300 if (flag_openmp) 7301 { 7302 stmt = make_node (OMP_FOR); 7303 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 7304 TREE_TYPE (stmt) = void_type_node; 7305 OMP_FOR_BODY (stmt) = body; 7306 OMP_FOR_CLAUSES (stmt) = omp_do_clauses; 7307 } 7308 else 7309 stmt = body; 7310 gfc_add_expr_to_block (&block, stmt); 7311 if (free_clausesa) 7312 gfc_free_split_omp_clauses (code, clausesa); 7313 return gfc_finish_block (&block); 7314 } 7315 7316 static tree 7317 gfc_trans_omp_parallel_do (gfc_code *code, bool is_loop, stmtblock_t *pblock, 7318 gfc_omp_clauses *clausesa) 7319 { 7320 stmtblock_t block, *new_pblock = pblock; 7321 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; 7322 tree stmt, omp_clauses = NULL_TREE; 7323 bool free_clausesa = false; 7324 7325 if (pblock == NULL) 7326 gfc_start_block (&block); 7327 else 7328 gfc_init_block (&block); 7329 7330 if (clausesa == NULL) 7331 { 7332 clausesa = clausesa_buf; 7333 gfc_split_omp_clauses (code, clausesa); 7334 free_clausesa = true; 7335 } 7336 omp_clauses 7337 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL], 7338 code->loc); 7339 if (pblock == NULL) 7340 { 7341 if (!clausesa[GFC_OMP_SPLIT_DO].ordered 7342 && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC) 7343 new_pblock = █ 7344 else 7345 pushlevel (); 7346 } 7347 stmt = gfc_trans_omp_do (code, is_loop ? EXEC_OMP_LOOP : EXEC_OMP_DO, 7348 new_pblock, &clausesa[GFC_OMP_SPLIT_DO], 7349 omp_clauses); 7350 if (pblock == NULL) 7351 { 7352 if (TREE_CODE (stmt) != BIND_EXPR) 7353 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7354 else 7355 poplevel (0, 0); 7356 } 7357 else if (TREE_CODE (stmt) != BIND_EXPR) 7358 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE); 7359 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, 7360 void_type_node, stmt, omp_clauses); 7361 OMP_PARALLEL_COMBINED (stmt) = 1; 7362 gfc_add_expr_to_block (&block, stmt); 7363 if (free_clausesa) 7364 gfc_free_split_omp_clauses (code, clausesa); 7365 return gfc_finish_block (&block); 7366 } 7367 7368 static tree 7369 gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock, 7370 gfc_omp_clauses *clausesa) 7371 { 7372 stmtblock_t block; 7373 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; 7374 tree stmt, omp_clauses = NULL_TREE; 7375 bool free_clausesa = false; 7376 7377 if (pblock == NULL) 7378 gfc_start_block (&block); 7379 else 7380 gfc_init_block (&block); 7381 7382 if (clausesa == NULL) 7383 { 7384 clausesa = clausesa_buf; 7385 gfc_split_omp_clauses (code, clausesa); 7386 free_clausesa = true; 7387 } 7388 if (flag_openmp) 7389 omp_clauses 7390 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL], 7391 code->loc); 7392 if (pblock == NULL) 7393 pushlevel (); 7394 stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses); 7395 if (pblock == NULL) 7396 { 7397 if (TREE_CODE (stmt) != BIND_EXPR) 7398 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7399 else 7400 poplevel (0, 0); 7401 } 7402 else if (TREE_CODE (stmt) != BIND_EXPR) 7403 stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE); 7404 if (flag_openmp) 7405 { 7406 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, 7407 void_type_node, stmt, omp_clauses); 7408 OMP_PARALLEL_COMBINED (stmt) = 1; 7409 } 7410 gfc_add_expr_to_block (&block, stmt); 7411 if (free_clausesa) 7412 gfc_free_split_omp_clauses (code, clausesa); 7413 return gfc_finish_block (&block); 7414 } 7415 7416 static tree 7417 gfc_trans_omp_parallel_sections (gfc_code *code) 7418 { 7419 stmtblock_t block; 7420 gfc_omp_clauses section_clauses; 7421 tree stmt, omp_clauses; 7422 7423 memset (§ion_clauses, 0, sizeof (section_clauses)); 7424 section_clauses.nowait = true; 7425 7426 gfc_start_block (&block); 7427 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 7428 code->loc); 7429 pushlevel (); 7430 stmt = gfc_trans_omp_sections (code, §ion_clauses); 7431 if (TREE_CODE (stmt) != BIND_EXPR) 7432 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7433 else 7434 poplevel (0, 0); 7435 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, 7436 void_type_node, stmt, omp_clauses); 7437 OMP_PARALLEL_COMBINED (stmt) = 1; 7438 gfc_add_expr_to_block (&block, stmt); 7439 return gfc_finish_block (&block); 7440 } 7441 7442 static tree 7443 gfc_trans_omp_parallel_workshare (gfc_code *code) 7444 { 7445 stmtblock_t block; 7446 gfc_omp_clauses workshare_clauses; 7447 tree stmt, omp_clauses; 7448 7449 memset (&workshare_clauses, 0, sizeof (workshare_clauses)); 7450 workshare_clauses.nowait = true; 7451 7452 gfc_start_block (&block); 7453 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 7454 code->loc); 7455 pushlevel (); 7456 stmt = gfc_trans_omp_workshare (code, &workshare_clauses); 7457 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7458 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, 7459 void_type_node, stmt, omp_clauses); 7460 OMP_PARALLEL_COMBINED (stmt) = 1; 7461 gfc_add_expr_to_block (&block, stmt); 7462 return gfc_finish_block (&block); 7463 } 7464 7465 static tree 7466 gfc_trans_omp_scope (gfc_code *code) 7467 { 7468 stmtblock_t block; 7469 tree body = gfc_trans_code (code->block->next); 7470 if (IS_EMPTY_STMT (body)) 7471 return body; 7472 gfc_start_block (&block); 7473 tree omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 7474 code->loc); 7475 tree stmt = make_node (OMP_SCOPE); 7476 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 7477 TREE_TYPE (stmt) = void_type_node; 7478 OMP_SCOPE_BODY (stmt) = body; 7479 OMP_SCOPE_CLAUSES (stmt) = omp_clauses; 7480 gfc_add_expr_to_block (&block, stmt); 7481 return gfc_finish_block (&block); 7482 } 7483 7484 static tree 7485 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses) 7486 { 7487 stmtblock_t block, body; 7488 tree omp_clauses, stmt; 7489 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL; 7490 location_t loc = gfc_get_location (&code->loc); 7491 7492 gfc_start_block (&block); 7493 7494 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); 7495 7496 gfc_init_block (&body); 7497 for (code = code->block; code; code = code->block) 7498 { 7499 /* Last section is special because of lastprivate, so even if it 7500 is empty, chain it in. */ 7501 stmt = gfc_trans_omp_code (code->next, 7502 has_lastprivate && code->block == NULL); 7503 if (! IS_EMPTY_STMT (stmt)) 7504 { 7505 stmt = build1_v (OMP_SECTION, stmt); 7506 gfc_add_expr_to_block (&body, stmt); 7507 } 7508 } 7509 stmt = gfc_finish_block (&body); 7510 7511 stmt = build2_loc (loc, OMP_SECTIONS, void_type_node, stmt, omp_clauses); 7512 gfc_add_expr_to_block (&block, stmt); 7513 7514 return gfc_finish_block (&block); 7515 } 7516 7517 static tree 7518 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses) 7519 { 7520 stmtblock_t block; 7521 gfc_start_block (&block); 7522 tree omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc); 7523 tree stmt = gfc_trans_omp_code (code->block->next, true); 7524 stmt = build2_loc (gfc_get_location (&code->loc), OMP_SINGLE, void_type_node, 7525 stmt, omp_clauses); 7526 gfc_add_expr_to_block (&block, stmt); 7527 return gfc_finish_block (&block); 7528 } 7529 7530 static tree 7531 gfc_trans_omp_task (gfc_code *code) 7532 { 7533 stmtblock_t block; 7534 tree stmt, omp_clauses; 7535 7536 gfc_start_block (&block); 7537 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 7538 code->loc); 7539 pushlevel (); 7540 stmt = gfc_trans_omp_code (code->block->next, true); 7541 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7542 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TASK, void_type_node, 7543 stmt, omp_clauses); 7544 gfc_add_expr_to_block (&block, stmt); 7545 return gfc_finish_block (&block); 7546 } 7547 7548 static tree 7549 gfc_trans_omp_taskgroup (gfc_code *code) 7550 { 7551 stmtblock_t block; 7552 gfc_start_block (&block); 7553 tree body = gfc_trans_code (code->block->next); 7554 tree stmt = make_node (OMP_TASKGROUP); 7555 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 7556 TREE_TYPE (stmt) = void_type_node; 7557 OMP_TASKGROUP_BODY (stmt) = body; 7558 OMP_TASKGROUP_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, 7559 code->ext.omp_clauses, 7560 code->loc); 7561 gfc_add_expr_to_block (&block, stmt); 7562 return gfc_finish_block (&block); 7563 } 7564 7565 static tree 7566 gfc_trans_omp_taskwait (gfc_code *code) 7567 { 7568 if (!code->ext.omp_clauses) 7569 { 7570 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT); 7571 return build_call_expr_loc (input_location, decl, 0); 7572 } 7573 stmtblock_t block; 7574 gfc_start_block (&block); 7575 tree stmt = make_node (OMP_TASK); 7576 SET_EXPR_LOCATION (stmt, gfc_get_location (&code->loc)); 7577 TREE_TYPE (stmt) = void_type_node; 7578 OMP_TASK_BODY (stmt) = NULL_TREE; 7579 OMP_TASK_CLAUSES (stmt) = gfc_trans_omp_clauses (&block, 7580 code->ext.omp_clauses, 7581 code->loc); 7582 gfc_add_expr_to_block (&block, stmt); 7583 return gfc_finish_block (&block); 7584 } 7585 7586 static tree 7587 gfc_trans_omp_taskyield (void) 7588 { 7589 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD); 7590 return build_call_expr_loc (input_location, decl, 0); 7591 } 7592 7593 static tree 7594 gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa) 7595 { 7596 stmtblock_t block; 7597 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; 7598 tree stmt, omp_clauses = NULL_TREE; 7599 bool free_clausesa = false; 7600 7601 gfc_start_block (&block); 7602 if (clausesa == NULL) 7603 { 7604 clausesa = clausesa_buf; 7605 gfc_split_omp_clauses (code, clausesa); 7606 free_clausesa = true; 7607 } 7608 if (flag_openmp) 7609 omp_clauses 7610 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE], 7611 code->loc); 7612 switch (code->op) 7613 { 7614 case EXEC_OMP_DISTRIBUTE: 7615 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: 7616 case EXEC_OMP_TEAMS_DISTRIBUTE: 7617 /* This is handled in gfc_trans_omp_do. */ 7618 gcc_unreachable (); 7619 break; 7620 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: 7621 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: 7622 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: 7623 stmt = gfc_trans_omp_parallel_do (code, false, &block, clausesa); 7624 if (TREE_CODE (stmt) != BIND_EXPR) 7625 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7626 else 7627 poplevel (0, 0); 7628 break; 7629 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: 7630 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 7631 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 7632 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa); 7633 if (TREE_CODE (stmt) != BIND_EXPR) 7634 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7635 else 7636 poplevel (0, 0); 7637 break; 7638 case EXEC_OMP_DISTRIBUTE_SIMD: 7639 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: 7640 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: 7641 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block, 7642 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE); 7643 if (TREE_CODE (stmt) != BIND_EXPR) 7644 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7645 else 7646 poplevel (0, 0); 7647 break; 7648 default: 7649 gcc_unreachable (); 7650 } 7651 if (flag_openmp) 7652 { 7653 tree distribute = make_node (OMP_DISTRIBUTE); 7654 SET_EXPR_LOCATION (distribute, gfc_get_location (&code->loc)); 7655 TREE_TYPE (distribute) = void_type_node; 7656 OMP_FOR_BODY (distribute) = stmt; 7657 OMP_FOR_CLAUSES (distribute) = omp_clauses; 7658 stmt = distribute; 7659 } 7660 gfc_add_expr_to_block (&block, stmt); 7661 if (free_clausesa) 7662 gfc_free_split_omp_clauses (code, clausesa); 7663 return gfc_finish_block (&block); 7664 } 7665 7666 static tree 7667 gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa, 7668 tree omp_clauses) 7669 { 7670 stmtblock_t block; 7671 gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM]; 7672 tree stmt; 7673 bool combined = true, free_clausesa = false; 7674 7675 gfc_start_block (&block); 7676 if (clausesa == NULL) 7677 { 7678 clausesa = clausesa_buf; 7679 gfc_split_omp_clauses (code, clausesa); 7680 free_clausesa = true; 7681 } 7682 if (flag_openmp) 7683 { 7684 omp_clauses 7685 = chainon (omp_clauses, 7686 gfc_trans_omp_clauses (&block, 7687 &clausesa[GFC_OMP_SPLIT_TEAMS], 7688 code->loc)); 7689 pushlevel (); 7690 } 7691 switch (code->op) 7692 { 7693 case EXEC_OMP_TARGET_TEAMS: 7694 case EXEC_OMP_TEAMS: 7695 stmt = gfc_trans_omp_code (code->block->next, true); 7696 combined = false; 7697 break; 7698 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: 7699 case EXEC_OMP_TEAMS_DISTRIBUTE: 7700 stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL, 7701 &clausesa[GFC_OMP_SPLIT_DISTRIBUTE], 7702 NULL); 7703 break; 7704 case EXEC_OMP_TARGET_TEAMS_LOOP: 7705 case EXEC_OMP_TEAMS_LOOP: 7706 stmt = gfc_trans_omp_do (code, EXEC_OMP_LOOP, NULL, 7707 &clausesa[GFC_OMP_SPLIT_DO], 7708 NULL); 7709 break; 7710 default: 7711 stmt = gfc_trans_omp_distribute (code, clausesa); 7712 break; 7713 } 7714 if (flag_openmp) 7715 { 7716 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7717 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TEAMS, 7718 void_type_node, stmt, omp_clauses); 7719 if (combined) 7720 OMP_TEAMS_COMBINED (stmt) = 1; 7721 } 7722 gfc_add_expr_to_block (&block, stmt); 7723 if (free_clausesa) 7724 gfc_free_split_omp_clauses (code, clausesa); 7725 return gfc_finish_block (&block); 7726 } 7727 7728 static tree 7729 gfc_trans_omp_target (gfc_code *code) 7730 { 7731 stmtblock_t block; 7732 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM]; 7733 tree stmt, omp_clauses = NULL_TREE; 7734 7735 gfc_start_block (&block); 7736 gfc_split_omp_clauses (code, clausesa); 7737 if (flag_openmp) 7738 omp_clauses 7739 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET], 7740 code->loc); 7741 switch (code->op) 7742 { 7743 case EXEC_OMP_TARGET: 7744 pushlevel (); 7745 stmt = gfc_trans_omp_code (code->block->next, true); 7746 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7747 break; 7748 case EXEC_OMP_TARGET_PARALLEL: 7749 { 7750 stmtblock_t iblock; 7751 7752 pushlevel (); 7753 gfc_start_block (&iblock); 7754 tree inner_clauses 7755 = gfc_trans_omp_clauses (&iblock, &clausesa[GFC_OMP_SPLIT_PARALLEL], 7756 code->loc); 7757 stmt = gfc_trans_omp_code (code->block->next, true); 7758 stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt, 7759 inner_clauses); 7760 gfc_add_expr_to_block (&iblock, stmt); 7761 stmt = gfc_finish_block (&iblock); 7762 if (TREE_CODE (stmt) != BIND_EXPR) 7763 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7764 else 7765 poplevel (0, 0); 7766 } 7767 break; 7768 case EXEC_OMP_TARGET_PARALLEL_DO: 7769 case EXEC_OMP_TARGET_PARALLEL_LOOP: 7770 stmt = gfc_trans_omp_parallel_do (code, 7771 (code->op 7772 == EXEC_OMP_TARGET_PARALLEL_LOOP), 7773 &block, clausesa); 7774 if (TREE_CODE (stmt) != BIND_EXPR) 7775 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7776 else 7777 poplevel (0, 0); 7778 break; 7779 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: 7780 stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa); 7781 if (TREE_CODE (stmt) != BIND_EXPR) 7782 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7783 else 7784 poplevel (0, 0); 7785 break; 7786 case EXEC_OMP_TARGET_SIMD: 7787 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block, 7788 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE); 7789 if (TREE_CODE (stmt) != BIND_EXPR) 7790 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7791 else 7792 poplevel (0, 0); 7793 break; 7794 default: 7795 if (flag_openmp 7796 && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper 7797 || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit)) 7798 { 7799 gfc_omp_clauses clausesb; 7800 tree teams_clauses; 7801 /* For combined !$omp target teams, the num_teams and 7802 thread_limit clauses are evaluated before entering the 7803 target construct. */ 7804 memset (&clausesb, '\0', sizeof (clausesb)); 7805 clausesb.num_teams_lower 7806 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower; 7807 clausesb.num_teams_upper 7808 = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper; 7809 clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit; 7810 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_lower = NULL; 7811 clausesa[GFC_OMP_SPLIT_TEAMS].num_teams_upper = NULL; 7812 clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL; 7813 teams_clauses 7814 = gfc_trans_omp_clauses (&block, &clausesb, code->loc); 7815 pushlevel (); 7816 stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses); 7817 } 7818 else 7819 { 7820 pushlevel (); 7821 stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE); 7822 } 7823 if (TREE_CODE (stmt) != BIND_EXPR) 7824 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7825 else 7826 poplevel (0, 0); 7827 break; 7828 } 7829 if (flag_openmp) 7830 { 7831 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET, 7832 void_type_node, stmt, omp_clauses); 7833 if (code->op != EXEC_OMP_TARGET) 7834 OMP_TARGET_COMBINED (stmt) = 1; 7835 cfun->has_omp_target = true; 7836 } 7837 gfc_add_expr_to_block (&block, stmt); 7838 gfc_free_split_omp_clauses (code, clausesa); 7839 return gfc_finish_block (&block); 7840 } 7841 7842 static tree 7843 gfc_trans_omp_taskloop (gfc_code *code, gfc_exec_op op) 7844 { 7845 stmtblock_t block; 7846 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM]; 7847 tree stmt, omp_clauses = NULL_TREE; 7848 7849 gfc_start_block (&block); 7850 gfc_split_omp_clauses (code, clausesa); 7851 if (flag_openmp) 7852 omp_clauses 7853 = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP], 7854 code->loc); 7855 switch (op) 7856 { 7857 case EXEC_OMP_TASKLOOP: 7858 /* This is handled in gfc_trans_omp_do. */ 7859 gcc_unreachable (); 7860 break; 7861 case EXEC_OMP_TASKLOOP_SIMD: 7862 stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block, 7863 &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE); 7864 if (TREE_CODE (stmt) != BIND_EXPR) 7865 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7866 else 7867 poplevel (0, 0); 7868 break; 7869 default: 7870 gcc_unreachable (); 7871 } 7872 if (flag_openmp) 7873 { 7874 tree taskloop = make_node (OMP_TASKLOOP); 7875 SET_EXPR_LOCATION (taskloop, gfc_get_location (&code->loc)); 7876 TREE_TYPE (taskloop) = void_type_node; 7877 OMP_FOR_BODY (taskloop) = stmt; 7878 OMP_FOR_CLAUSES (taskloop) = omp_clauses; 7879 stmt = taskloop; 7880 } 7881 gfc_add_expr_to_block (&block, stmt); 7882 gfc_free_split_omp_clauses (code, clausesa); 7883 return gfc_finish_block (&block); 7884 } 7885 7886 static tree 7887 gfc_trans_omp_master_masked_taskloop (gfc_code *code, gfc_exec_op op) 7888 { 7889 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM]; 7890 stmtblock_t block; 7891 tree stmt; 7892 7893 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD 7894 && code->op != EXEC_OMP_MASTER_TASKLOOP) 7895 gfc_split_omp_clauses (code, clausesa); 7896 7897 pushlevel (); 7898 if (op == EXEC_OMP_MASKED_TASKLOOP_SIMD 7899 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD) 7900 stmt = gfc_trans_omp_taskloop (code, EXEC_OMP_TASKLOOP_SIMD); 7901 else 7902 { 7903 gcc_assert (op == EXEC_OMP_MASKED_TASKLOOP 7904 || op == EXEC_OMP_MASTER_TASKLOOP); 7905 stmt = gfc_trans_omp_do (code, EXEC_OMP_TASKLOOP, NULL, 7906 code->op != EXEC_OMP_MASTER_TASKLOOP 7907 ? &clausesa[GFC_OMP_SPLIT_TASKLOOP] 7908 : code->ext.omp_clauses, NULL); 7909 } 7910 if (TREE_CODE (stmt) != BIND_EXPR) 7911 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7912 else 7913 poplevel (0, 0); 7914 gfc_start_block (&block); 7915 if (op == EXEC_OMP_MASKED_TASKLOOP || op == EXEC_OMP_MASKED_TASKLOOP_SIMD) 7916 { 7917 tree clauses = gfc_trans_omp_clauses (&block, 7918 &clausesa[GFC_OMP_SPLIT_MASKED], 7919 code->loc); 7920 tree msk = make_node (OMP_MASKED); 7921 SET_EXPR_LOCATION (msk, gfc_get_location (&code->loc)); 7922 TREE_TYPE (msk) = void_type_node; 7923 OMP_MASKED_BODY (msk) = stmt; 7924 OMP_MASKED_CLAUSES (msk) = clauses; 7925 OMP_MASKED_COMBINED (msk) = 1; 7926 gfc_add_expr_to_block (&block, msk); 7927 } 7928 else 7929 { 7930 gcc_assert (op == EXEC_OMP_MASTER_TASKLOOP 7931 || op == EXEC_OMP_MASTER_TASKLOOP_SIMD); 7932 stmt = build1_v (OMP_MASTER, stmt); 7933 gfc_add_expr_to_block (&block, stmt); 7934 } 7935 if (op != EXEC_OMP_MASTER_TASKLOOP_SIMD 7936 && code->op != EXEC_OMP_MASTER_TASKLOOP) 7937 gfc_free_split_omp_clauses (code, clausesa); 7938 return gfc_finish_block (&block); 7939 } 7940 7941 static tree 7942 gfc_trans_omp_parallel_master_masked (gfc_code *code) 7943 { 7944 stmtblock_t block; 7945 tree stmt, omp_clauses; 7946 gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM]; 7947 bool parallel_combined = false; 7948 7949 if (code->op != EXEC_OMP_PARALLEL_MASTER) 7950 gfc_split_omp_clauses (code, clausesa); 7951 7952 gfc_start_block (&block); 7953 omp_clauses = gfc_trans_omp_clauses (&block, 7954 code->op == EXEC_OMP_PARALLEL_MASTER 7955 ? code->ext.omp_clauses 7956 : &clausesa[GFC_OMP_SPLIT_PARALLEL], 7957 code->loc); 7958 pushlevel (); 7959 if (code->op == EXEC_OMP_PARALLEL_MASTER) 7960 stmt = gfc_trans_omp_master (code); 7961 else if (code->op == EXEC_OMP_PARALLEL_MASKED) 7962 stmt = gfc_trans_omp_masked (code, &clausesa[GFC_OMP_SPLIT_MASKED]); 7963 else 7964 { 7965 gfc_exec_op op; 7966 switch (code->op) 7967 { 7968 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: 7969 op = EXEC_OMP_MASKED_TASKLOOP; 7970 break; 7971 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: 7972 op = EXEC_OMP_MASKED_TASKLOOP_SIMD; 7973 break; 7974 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: 7975 op = EXEC_OMP_MASTER_TASKLOOP; 7976 break; 7977 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: 7978 op = EXEC_OMP_MASTER_TASKLOOP_SIMD; 7979 break; 7980 default: 7981 gcc_unreachable (); 7982 } 7983 stmt = gfc_trans_omp_master_masked_taskloop (code, op); 7984 parallel_combined = true; 7985 } 7986 if (TREE_CODE (stmt) != BIND_EXPR) 7987 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0)); 7988 else 7989 poplevel (0, 0); 7990 stmt = build2_loc (gfc_get_location (&code->loc), OMP_PARALLEL, 7991 void_type_node, stmt, omp_clauses); 7992 /* masked does have just filter clause, but during gimplification 7993 isn't represented by a gimplification omp context, so for 7994 !$omp parallel masked don't set OMP_PARALLEL_COMBINED, 7995 so that 7996 !$omp parallel masked 7997 !$omp taskloop simd lastprivate (x) 7998 isn't confused with 7999 !$omp parallel masked taskloop simd lastprivate (x) */ 8000 if (parallel_combined) 8001 OMP_PARALLEL_COMBINED (stmt) = 1; 8002 gfc_add_expr_to_block (&block, stmt); 8003 if (code->op != EXEC_OMP_PARALLEL_MASTER) 8004 gfc_free_split_omp_clauses (code, clausesa); 8005 return gfc_finish_block (&block); 8006 } 8007 8008 static tree 8009 gfc_trans_omp_target_data (gfc_code *code) 8010 { 8011 stmtblock_t block; 8012 tree stmt, omp_clauses; 8013 8014 gfc_start_block (&block); 8015 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 8016 code->loc); 8017 stmt = gfc_trans_omp_code (code->block->next, true); 8018 stmt = build2_loc (gfc_get_location (&code->loc), OMP_TARGET_DATA, 8019 void_type_node, stmt, omp_clauses); 8020 gfc_add_expr_to_block (&block, stmt); 8021 return gfc_finish_block (&block); 8022 } 8023 8024 static tree 8025 gfc_trans_omp_target_enter_data (gfc_code *code) 8026 { 8027 stmtblock_t block; 8028 tree stmt, omp_clauses; 8029 8030 gfc_start_block (&block); 8031 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 8032 code->loc); 8033 stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node, 8034 omp_clauses); 8035 gfc_add_expr_to_block (&block, stmt); 8036 return gfc_finish_block (&block); 8037 } 8038 8039 static tree 8040 gfc_trans_omp_target_exit_data (gfc_code *code) 8041 { 8042 stmtblock_t block; 8043 tree stmt, omp_clauses; 8044 8045 gfc_start_block (&block); 8046 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 8047 code->loc, false, false, code->op); 8048 stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node, 8049 omp_clauses); 8050 gfc_add_expr_to_block (&block, stmt); 8051 return gfc_finish_block (&block); 8052 } 8053 8054 static tree 8055 gfc_trans_omp_target_update (gfc_code *code) 8056 { 8057 stmtblock_t block; 8058 tree stmt, omp_clauses; 8059 8060 gfc_start_block (&block); 8061 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses, 8062 code->loc); 8063 stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node, 8064 omp_clauses); 8065 gfc_add_expr_to_block (&block, stmt); 8066 return gfc_finish_block (&block); 8067 } 8068 8069 static tree 8070 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses) 8071 { 8072 tree res, tmp, stmt; 8073 stmtblock_t block, *pblock = NULL; 8074 stmtblock_t singleblock; 8075 int saved_ompws_flags; 8076 bool singleblock_in_progress = false; 8077 /* True if previous gfc_code in workshare construct is not workshared. */ 8078 bool prev_singleunit; 8079 location_t loc = gfc_get_location (&code->loc); 8080 8081 code = code->block->next; 8082 8083 pushlevel (); 8084 8085 gfc_start_block (&block); 8086 pblock = █ 8087 8088 ompws_flags = OMPWS_WORKSHARE_FLAG; 8089 prev_singleunit = false; 8090 8091 /* Translate statements one by one to trees until we reach 8092 the end of the workshare construct. Adjacent gfc_codes that 8093 are a single unit of work are clustered and encapsulated in a 8094 single OMP_SINGLE construct. */ 8095 for (; code; code = code->next) 8096 { 8097 if (code->here != 0) 8098 { 8099 res = gfc_trans_label_here (code); 8100 gfc_add_expr_to_block (pblock, res); 8101 } 8102 8103 /* No dependence analysis, use for clauses with wait. 8104 If this is the last gfc_code, use default omp_clauses. */ 8105 if (code->next == NULL && clauses->nowait) 8106 ompws_flags |= OMPWS_NOWAIT; 8107 8108 /* By default, every gfc_code is a single unit of work. */ 8109 ompws_flags |= OMPWS_CURR_SINGLEUNIT; 8110 ompws_flags &= ~(OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY); 8111 8112 switch (code->op) 8113 { 8114 case EXEC_NOP: 8115 res = NULL_TREE; 8116 break; 8117 8118 case EXEC_ASSIGN: 8119 res = gfc_trans_assign (code); 8120 break; 8121 8122 case EXEC_POINTER_ASSIGN: 8123 res = gfc_trans_pointer_assign (code); 8124 break; 8125 8126 case EXEC_INIT_ASSIGN: 8127 res = gfc_trans_init_assign (code); 8128 break; 8129 8130 case EXEC_FORALL: 8131 res = gfc_trans_forall (code); 8132 break; 8133 8134 case EXEC_WHERE: 8135 res = gfc_trans_where (code); 8136 break; 8137 8138 case EXEC_OMP_ATOMIC: 8139 res = gfc_trans_omp_directive (code); 8140 break; 8141 8142 case EXEC_OMP_PARALLEL: 8143 case EXEC_OMP_PARALLEL_DO: 8144 case EXEC_OMP_PARALLEL_MASTER: 8145 case EXEC_OMP_PARALLEL_SECTIONS: 8146 case EXEC_OMP_PARALLEL_WORKSHARE: 8147 case EXEC_OMP_CRITICAL: 8148 saved_ompws_flags = ompws_flags; 8149 ompws_flags = 0; 8150 res = gfc_trans_omp_directive (code); 8151 ompws_flags = saved_ompws_flags; 8152 break; 8153 8154 case EXEC_BLOCK: 8155 res = gfc_trans_block_construct (code); 8156 break; 8157 8158 default: 8159 gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code"); 8160 } 8161 8162 gfc_set_backend_locus (&code->loc); 8163 8164 if (res != NULL_TREE && ! IS_EMPTY_STMT (res)) 8165 { 8166 if (prev_singleunit) 8167 { 8168 if (ompws_flags & OMPWS_CURR_SINGLEUNIT) 8169 /* Add current gfc_code to single block. */ 8170 gfc_add_expr_to_block (&singleblock, res); 8171 else 8172 { 8173 /* Finish single block and add it to pblock. */ 8174 tmp = gfc_finish_block (&singleblock); 8175 tmp = build2_loc (loc, OMP_SINGLE, 8176 void_type_node, tmp, NULL_TREE); 8177 gfc_add_expr_to_block (pblock, tmp); 8178 /* Add current gfc_code to pblock. */ 8179 gfc_add_expr_to_block (pblock, res); 8180 singleblock_in_progress = false; 8181 } 8182 } 8183 else 8184 { 8185 if (ompws_flags & OMPWS_CURR_SINGLEUNIT) 8186 { 8187 /* Start single block. */ 8188 gfc_init_block (&singleblock); 8189 gfc_add_expr_to_block (&singleblock, res); 8190 singleblock_in_progress = true; 8191 loc = gfc_get_location (&code->loc); 8192 } 8193 else 8194 /* Add the new statement to the block. */ 8195 gfc_add_expr_to_block (pblock, res); 8196 } 8197 prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0; 8198 } 8199 } 8200 8201 /* Finish remaining SINGLE block, if we were in the middle of one. */ 8202 if (singleblock_in_progress) 8203 { 8204 /* Finish single block and add it to pblock. */ 8205 tmp = gfc_finish_block (&singleblock); 8206 tmp = build2_loc (loc, OMP_SINGLE, void_type_node, tmp, 8207 clauses->nowait 8208 ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT) 8209 : NULL_TREE); 8210 gfc_add_expr_to_block (pblock, tmp); 8211 } 8212 8213 stmt = gfc_finish_block (pblock); 8214 if (TREE_CODE (stmt) != BIND_EXPR) 8215 { 8216 if (!IS_EMPTY_STMT (stmt)) 8217 { 8218 tree bindblock = poplevel (1, 0); 8219 stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock); 8220 } 8221 else 8222 poplevel (0, 0); 8223 } 8224 else 8225 poplevel (0, 0); 8226 8227 if (IS_EMPTY_STMT (stmt) && !clauses->nowait) 8228 stmt = gfc_trans_omp_barrier (); 8229 8230 ompws_flags = 0; 8231 return stmt; 8232 } 8233 8234 tree 8235 gfc_trans_oacc_declare (gfc_code *code) 8236 { 8237 stmtblock_t block; 8238 tree stmt, oacc_clauses; 8239 enum tree_code construct_code; 8240 8241 construct_code = OACC_DATA; 8242 8243 gfc_start_block (&block); 8244 8245 oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.oacc_declare->clauses, 8246 code->loc, false, true); 8247 stmt = gfc_trans_omp_code (code->block->next, true); 8248 stmt = build2_loc (input_location, construct_code, void_type_node, stmt, 8249 oacc_clauses); 8250 gfc_add_expr_to_block (&block, stmt); 8251 8252 return gfc_finish_block (&block); 8253 } 8254 8255 tree 8256 gfc_trans_oacc_directive (gfc_code *code) 8257 { 8258 switch (code->op) 8259 { 8260 case EXEC_OACC_PARALLEL_LOOP: 8261 case EXEC_OACC_KERNELS_LOOP: 8262 case EXEC_OACC_SERIAL_LOOP: 8263 return gfc_trans_oacc_combined_directive (code); 8264 case EXEC_OACC_PARALLEL: 8265 case EXEC_OACC_KERNELS: 8266 case EXEC_OACC_SERIAL: 8267 case EXEC_OACC_DATA: 8268 case EXEC_OACC_HOST_DATA: 8269 return gfc_trans_oacc_construct (code); 8270 case EXEC_OACC_LOOP: 8271 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses, 8272 NULL); 8273 case EXEC_OACC_UPDATE: 8274 case EXEC_OACC_CACHE: 8275 case EXEC_OACC_ENTER_DATA: 8276 case EXEC_OACC_EXIT_DATA: 8277 return gfc_trans_oacc_executable_directive (code); 8278 case EXEC_OACC_WAIT: 8279 return gfc_trans_oacc_wait_directive (code); 8280 case EXEC_OACC_ATOMIC: 8281 return gfc_trans_omp_atomic (code); 8282 case EXEC_OACC_DECLARE: 8283 return gfc_trans_oacc_declare (code); 8284 default: 8285 gcc_unreachable (); 8286 } 8287 } 8288 8289 tree 8290 gfc_trans_omp_directive (gfc_code *code) 8291 { 8292 switch (code->op) 8293 { 8294 case EXEC_OMP_ALLOCATE: 8295 case EXEC_OMP_ALLOCATORS: 8296 return gfc_trans_omp_allocators (code); 8297 case EXEC_OMP_ASSUME: 8298 return gfc_trans_omp_assume (code); 8299 case EXEC_OMP_ATOMIC: 8300 return gfc_trans_omp_atomic (code); 8301 case EXEC_OMP_BARRIER: 8302 return gfc_trans_omp_barrier (); 8303 case EXEC_OMP_CANCEL: 8304 return gfc_trans_omp_cancel (code); 8305 case EXEC_OMP_CANCELLATION_POINT: 8306 return gfc_trans_omp_cancellation_point (code); 8307 case EXEC_OMP_CRITICAL: 8308 return gfc_trans_omp_critical (code); 8309 case EXEC_OMP_DEPOBJ: 8310 return gfc_trans_omp_depobj (code); 8311 case EXEC_OMP_DISTRIBUTE: 8312 case EXEC_OMP_DO: 8313 case EXEC_OMP_LOOP: 8314 case EXEC_OMP_SIMD: 8315 case EXEC_OMP_TASKLOOP: 8316 return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses, 8317 NULL); 8318 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: 8319 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: 8320 case EXEC_OMP_DISTRIBUTE_SIMD: 8321 return gfc_trans_omp_distribute (code, NULL); 8322 case EXEC_OMP_DO_SIMD: 8323 return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE); 8324 case EXEC_OMP_ERROR: 8325 return gfc_trans_omp_error (code); 8326 case EXEC_OMP_FLUSH: 8327 return gfc_trans_omp_flush (code); 8328 case EXEC_OMP_MASKED: 8329 return gfc_trans_omp_masked (code, NULL); 8330 case EXEC_OMP_MASTER: 8331 return gfc_trans_omp_master (code); 8332 case EXEC_OMP_MASKED_TASKLOOP: 8333 case EXEC_OMP_MASKED_TASKLOOP_SIMD: 8334 case EXEC_OMP_MASTER_TASKLOOP: 8335 case EXEC_OMP_MASTER_TASKLOOP_SIMD: 8336 return gfc_trans_omp_master_masked_taskloop (code, code->op); 8337 case EXEC_OMP_ORDERED: 8338 return gfc_trans_omp_ordered (code); 8339 case EXEC_OMP_PARALLEL: 8340 return gfc_trans_omp_parallel (code); 8341 case EXEC_OMP_PARALLEL_DO: 8342 return gfc_trans_omp_parallel_do (code, false, NULL, NULL); 8343 case EXEC_OMP_PARALLEL_LOOP: 8344 return gfc_trans_omp_parallel_do (code, true, NULL, NULL); 8345 case EXEC_OMP_PARALLEL_DO_SIMD: 8346 return gfc_trans_omp_parallel_do_simd (code, NULL, NULL); 8347 case EXEC_OMP_PARALLEL_MASKED: 8348 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: 8349 case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: 8350 case EXEC_OMP_PARALLEL_MASTER: 8351 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: 8352 case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: 8353 return gfc_trans_omp_parallel_master_masked (code); 8354 case EXEC_OMP_PARALLEL_SECTIONS: 8355 return gfc_trans_omp_parallel_sections (code); 8356 case EXEC_OMP_PARALLEL_WORKSHARE: 8357 return gfc_trans_omp_parallel_workshare (code); 8358 case EXEC_OMP_SCOPE: 8359 return gfc_trans_omp_scope (code); 8360 case EXEC_OMP_SECTIONS: 8361 return gfc_trans_omp_sections (code, code->ext.omp_clauses); 8362 case EXEC_OMP_SINGLE: 8363 return gfc_trans_omp_single (code, code->ext.omp_clauses); 8364 case EXEC_OMP_TARGET: 8365 case EXEC_OMP_TARGET_PARALLEL: 8366 case EXEC_OMP_TARGET_PARALLEL_DO: 8367 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: 8368 case EXEC_OMP_TARGET_PARALLEL_LOOP: 8369 case EXEC_OMP_TARGET_SIMD: 8370 case EXEC_OMP_TARGET_TEAMS: 8371 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: 8372 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: 8373 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 8374 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: 8375 case EXEC_OMP_TARGET_TEAMS_LOOP: 8376 return gfc_trans_omp_target (code); 8377 case EXEC_OMP_TARGET_DATA: 8378 return gfc_trans_omp_target_data (code); 8379 case EXEC_OMP_TARGET_ENTER_DATA: 8380 return gfc_trans_omp_target_enter_data (code); 8381 case EXEC_OMP_TARGET_EXIT_DATA: 8382 return gfc_trans_omp_target_exit_data (code); 8383 case EXEC_OMP_TARGET_UPDATE: 8384 return gfc_trans_omp_target_update (code); 8385 case EXEC_OMP_TASK: 8386 return gfc_trans_omp_task (code); 8387 case EXEC_OMP_TASKGROUP: 8388 return gfc_trans_omp_taskgroup (code); 8389 case EXEC_OMP_TASKLOOP_SIMD: 8390 return gfc_trans_omp_taskloop (code, code->op); 8391 case EXEC_OMP_TASKWAIT: 8392 return gfc_trans_omp_taskwait (code); 8393 case EXEC_OMP_TASKYIELD: 8394 return gfc_trans_omp_taskyield (); 8395 case EXEC_OMP_TEAMS: 8396 case EXEC_OMP_TEAMS_DISTRIBUTE: 8397 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: 8398 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: 8399 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: 8400 case EXEC_OMP_TEAMS_LOOP: 8401 return gfc_trans_omp_teams (code, NULL, NULL_TREE); 8402 case EXEC_OMP_WORKSHARE: 8403 return gfc_trans_omp_workshare (code, code->ext.omp_clauses); 8404 default: 8405 gcc_unreachable (); 8406 } 8407 } 8408 8409 void 8410 gfc_trans_omp_declare_simd (gfc_namespace *ns) 8411 { 8412 if (ns->entries) 8413 return; 8414 8415 gfc_omp_declare_simd *ods; 8416 for (ods = ns->omp_declare_simd; ods; ods = ods->next) 8417 { 8418 tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true); 8419 tree fndecl = ns->proc_name->backend_decl; 8420 if (c != NULL_TREE) 8421 c = tree_cons (NULL_TREE, c, NULL_TREE); 8422 c = build_tree_list (get_identifier ("omp declare simd"), c); 8423 TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); 8424 DECL_ATTRIBUTES (fndecl) = c; 8425 } 8426 } 8427 8428 void 8429 gfc_trans_omp_declare_variant (gfc_namespace *ns) 8430 { 8431 tree base_fn_decl = ns->proc_name->backend_decl; 8432 gfc_namespace *search_ns = ns; 8433 gfc_omp_declare_variant *next; 8434 8435 for (gfc_omp_declare_variant *odv = search_ns->omp_declare_variant; 8436 search_ns; odv = next) 8437 { 8438 /* Look in the parent namespace if there are no more directives in the 8439 current namespace. */ 8440 if (!odv) 8441 { 8442 search_ns = search_ns->parent; 8443 if (search_ns) 8444 next = search_ns->omp_declare_variant; 8445 continue; 8446 } 8447 8448 next = odv->next; 8449 8450 if (odv->error_p) 8451 continue; 8452 8453 /* Check directive the first time it is encountered. */ 8454 bool error_found = true; 8455 8456 if (odv->checked_p) 8457 error_found = false; 8458 if (odv->base_proc_symtree == NULL) 8459 { 8460 if (!search_ns->proc_name->attr.function 8461 && !search_ns->proc_name->attr.subroutine) 8462 gfc_error ("The base name for 'declare variant' must be " 8463 "specified at %L ", &odv->where); 8464 else 8465 error_found = false; 8466 } 8467 else 8468 { 8469 if (!search_ns->contained 8470 && strcmp (odv->base_proc_symtree->name, 8471 ns->proc_name->name)) 8472 gfc_error ("The base name at %L does not match the name of the " 8473 "current procedure", &odv->where); 8474 else if (odv->base_proc_symtree->n.sym->attr.entry) 8475 gfc_error ("The base name at %L must not be an entry name", 8476 &odv->where); 8477 else if (odv->base_proc_symtree->n.sym->attr.generic) 8478 gfc_error ("The base name at %L must not be a generic name", 8479 &odv->where); 8480 else if (odv->base_proc_symtree->n.sym->attr.proc_pointer) 8481 gfc_error ("The base name at %L must not be a procedure pointer", 8482 &odv->where); 8483 else if (odv->base_proc_symtree->n.sym->attr.implicit_type) 8484 gfc_error ("The base procedure at %L must have an explicit " 8485 "interface", &odv->where); 8486 else 8487 error_found = false; 8488 } 8489 8490 odv->checked_p = true; 8491 if (error_found) 8492 { 8493 odv->error_p = true; 8494 continue; 8495 } 8496 8497 /* Ignore directives that do not apply to the current procedure. */ 8498 if ((odv->base_proc_symtree == NULL && search_ns != ns) 8499 || (odv->base_proc_symtree != NULL 8500 && strcmp (odv->base_proc_symtree->name, ns->proc_name->name))) 8501 continue; 8502 8503 tree set_selectors = NULL_TREE; 8504 gfc_omp_set_selector *oss; 8505 8506 for (oss = odv->set_selectors; oss; oss = oss->next) 8507 { 8508 tree selectors = NULL_TREE; 8509 gfc_omp_selector *os; 8510 enum omp_tss_code set = oss->code; 8511 gcc_assert (set != OMP_TRAIT_SET_INVALID); 8512 8513 for (os = oss->trait_selectors; os; os = os->next) 8514 { 8515 tree scoreval = NULL_TREE; 8516 tree properties = NULL_TREE; 8517 gfc_omp_trait_property *otp; 8518 enum omp_ts_code sel = os->code; 8519 8520 /* Per the spec, "Implementations can ignore specified 8521 selectors that are not those described in this section"; 8522 however, we must record such selectors because they 8523 cause match failures. */ 8524 if (sel == OMP_TRAIT_INVALID) 8525 { 8526 selectors = make_trait_selector (sel, NULL_TREE, NULL_TREE, 8527 selectors); 8528 continue; 8529 } 8530 8531 for (otp = os->properties; otp; otp = otp->next) 8532 { 8533 switch (otp->property_kind) 8534 { 8535 case OMP_TRAIT_PROPERTY_DEV_NUM_EXPR: 8536 case OMP_TRAIT_PROPERTY_BOOL_EXPR: 8537 { 8538 gfc_se se; 8539 gfc_init_se (&se, NULL); 8540 gfc_conv_expr (&se, otp->expr); 8541 properties = make_trait_property (NULL_TREE, se.expr, 8542 properties); 8543 } 8544 break; 8545 case OMP_TRAIT_PROPERTY_ID: 8546 properties 8547 = make_trait_property (get_identifier (otp->name), 8548 NULL_TREE, properties); 8549 break; 8550 case OMP_TRAIT_PROPERTY_NAME_LIST: 8551 { 8552 tree prop = OMP_TP_NAMELIST_NODE; 8553 tree value = NULL_TREE; 8554 if (otp->is_name) 8555 value = get_identifier (otp->name); 8556 else 8557 value = gfc_conv_constant_to_tree (otp->expr); 8558 8559 properties = make_trait_property (prop, value, 8560 properties); 8561 } 8562 break; 8563 case OMP_TRAIT_PROPERTY_CLAUSE_LIST: 8564 properties = gfc_trans_omp_clauses (NULL, otp->clauses, 8565 odv->where, true); 8566 break; 8567 default: 8568 gcc_unreachable (); 8569 } 8570 } 8571 8572 if (os->score) 8573 { 8574 gfc_se se; 8575 gfc_init_se (&se, NULL); 8576 gfc_conv_expr (&se, os->score); 8577 scoreval = se.expr; 8578 } 8579 8580 selectors = make_trait_selector (sel, scoreval, 8581 properties, selectors); 8582 } 8583 set_selectors = make_trait_set_selector (set, selectors, 8584 set_selectors); 8585 } 8586 8587 const char *variant_proc_name = odv->variant_proc_symtree->name; 8588 gfc_symbol *variant_proc_sym = odv->variant_proc_symtree->n.sym; 8589 if (variant_proc_sym == NULL || variant_proc_sym->attr.implicit_type) 8590 { 8591 gfc_symtree *proc_st; 8592 gfc_find_sym_tree (variant_proc_name, gfc_current_ns, 1, &proc_st); 8593 variant_proc_sym = proc_st->n.sym; 8594 } 8595 if (variant_proc_sym == NULL) 8596 { 8597 gfc_error ("Cannot find symbol %qs", variant_proc_name); 8598 continue; 8599 } 8600 set_selectors = omp_check_context_selector 8601 (gfc_get_location (&odv->where), set_selectors); 8602 if (set_selectors != error_mark_node) 8603 { 8604 if (!variant_proc_sym->attr.implicit_type 8605 && !variant_proc_sym->attr.subroutine 8606 && !variant_proc_sym->attr.function) 8607 { 8608 gfc_error ("variant %qs at %L is not a function or subroutine", 8609 variant_proc_name, &odv->where); 8610 variant_proc_sym = NULL; 8611 } 8612 else if (omp_get_context_selector (set_selectors, 8613 OMP_TRAIT_SET_CONSTRUCT, 8614 OMP_TRAIT_CONSTRUCT_SIMD) 8615 == NULL_TREE) 8616 { 8617 char err[256]; 8618 if (!gfc_compare_interfaces (ns->proc_name, variant_proc_sym, 8619 variant_proc_sym->name, 0, 1, 8620 err, sizeof (err), NULL, NULL)) 8621 { 8622 gfc_error ("variant %qs and base %qs at %L have " 8623 "incompatible types: %s", 8624 variant_proc_name, ns->proc_name->name, 8625 &odv->where, err); 8626 variant_proc_sym = NULL; 8627 } 8628 } 8629 if (variant_proc_sym != NULL) 8630 { 8631 gfc_set_sym_referenced (variant_proc_sym); 8632 tree construct 8633 = omp_get_context_selector_list (set_selectors, 8634 OMP_TRAIT_SET_CONSTRUCT); 8635 omp_mark_declare_variant (gfc_get_location (&odv->where), 8636 gfc_get_symbol_decl (variant_proc_sym), 8637 construct); 8638 if (omp_context_selector_matches (set_selectors)) 8639 { 8640 tree id = get_identifier ("omp declare variant base"); 8641 tree variant = gfc_get_symbol_decl (variant_proc_sym); 8642 DECL_ATTRIBUTES (base_fn_decl) 8643 = tree_cons (id, build_tree_list (variant, set_selectors), 8644 DECL_ATTRIBUTES (base_fn_decl)); 8645 } 8646 } 8647 } 8648 } 8649 } 8650 8651 /* Add ptr for tracking as being allocated by GOMP_alloc. */ 8652 8653 tree 8654 gfc_omp_call_add_alloc (tree ptr) 8655 { 8656 static tree fn = NULL_TREE; 8657 if (fn == NULL_TREE) 8658 { 8659 fn = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); 8660 tree att = build_tree_list (NULL_TREE, build_string (4, ". R ")); 8661 att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn)); 8662 fn = build_type_attribute_variant (fn, att); 8663 fn = build_fn_decl ("GOMP_add_alloc", fn); 8664 } 8665 return build_call_expr_loc (input_location, fn, 1, ptr); 8666 } 8667 8668 /* Generated function returns true when it was tracked via GOMP_add_alloc and 8669 removes it from the tracking. As called just before GOMP_free or omp_realloc 8670 the pointer is or might become invalid, thus, it is always removed. */ 8671 8672 tree 8673 gfc_omp_call_is_alloc (tree ptr) 8674 { 8675 static tree fn = NULL_TREE; 8676 if (fn == NULL_TREE) 8677 { 8678 fn = build_function_type_list (boolean_type_node, ptr_type_node, 8679 NULL_TREE); 8680 tree att = build_tree_list (NULL_TREE, build_string (4, ". R ")); 8681 att = tree_cons (get_identifier ("fn spec"), att, TYPE_ATTRIBUTES (fn)); 8682 fn = build_type_attribute_variant (fn, att); 8683 fn = build_fn_decl ("GOMP_is_alloc", fn); 8684 } 8685 return build_call_expr_loc (input_location, fn, 1, ptr); 8686 } 8687