omp-low.c revision 169689
1/* Lowering pass for OpenMP directives. Converts OpenMP directives 2 into explicit calls to the runtime library (libgomp) and data 3 marshalling to implement data sharing and copying clauses. 4 Contributed by Diego Novillo <dnovillo@redhat.com> 5 6 Copyright (C) 2005, 2006 Free Software Foundation, Inc. 7 8This file is part of GCC. 9 10GCC is free software; you can redistribute it and/or modify it under 11the terms of the GNU General Public License as published by the Free 12Software Foundation; either version 2, or (at your option) any later 13version. 14 15GCC is distributed in the hope that it will be useful, but WITHOUT ANY 16WARRANTY; without even the implied warranty of MERCHANTABILITY or 17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18for more details. 19 20You should have received a copy of the GNU General Public License 21along with GCC; see the file COPYING. If not, write to the Free 22Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2302110-1301, USA. */ 24 25#include "config.h" 26#include "system.h" 27#include "coretypes.h" 28#include "tm.h" 29#include "tree.h" 30#include "rtl.h" 31#include "tree-gimple.h" 32#include "tree-inline.h" 33#include "langhooks.h" 34#include "diagnostic.h" 35#include "tree-flow.h" 36#include "timevar.h" 37#include "flags.h" 38#include "function.h" 39#include "expr.h" 40#include "toplev.h" 41#include "tree-pass.h" 42#include "ggc.h" 43#include "except.h" 44 45 46/* Lowering of OpenMP parallel and workshare constructs proceeds in two 47 phases. The first phase scans the function looking for OMP statements 48 and then for variables that must be replaced to satisfy data sharing 49 clauses. The second phase expands code for the constructs, as well as 50 re-gimplifying things when variables have been replaced with complex 51 expressions. 52 53 Final code generation is done by pass_expand_omp. The flowgraph is 54 scanned for parallel regions which are then moved to a new 55 function, to be invoked by the thread library. */ 56 57/* Context structure. Used to store information about each parallel 58 directive in the code. */ 59 60typedef struct omp_context 61{ 62 /* This field must be at the beginning, as we do "inheritance": Some 63 callback functions for tree-inline.c (e.g., omp_copy_decl) 64 receive a copy_body_data pointer that is up-casted to an 65 omp_context pointer. */ 66 copy_body_data cb; 67 68 /* The tree of contexts corresponding to the encountered constructs. */ 69 struct omp_context *outer; 70 tree stmt; 71 72 /* Map variables to fields in a structure that allows communication 73 between sending and receiving threads. */ 74 splay_tree field_map; 75 tree record_type; 76 tree sender_decl; 77 tree receiver_decl; 78 79 /* A chain of variables to add to the top-level block surrounding the 80 construct. In the case of a parallel, this is in the child function. */ 81 tree block_vars; 82 83 /* What to do with variables with implicitly determined sharing 84 attributes. */ 85 enum omp_clause_default_kind default_kind; 86 87 /* Nesting depth of this context. Used to beautify error messages re 88 invalid gotos. The outermost ctx is depth 1, with depth 0 being 89 reserved for the main body of the function. */ 90 int depth; 91 92 /* True if this parallel directive is nested within another. */ 93 bool is_nested; 94} omp_context; 95 96 97/* A structure describing the main elements of a parallel loop. */ 98 99struct omp_for_data 100{ 101 tree v, n1, n2, step, chunk_size, for_stmt; 102 enum tree_code cond_code; 103 tree pre; 104 bool have_nowait, have_ordered; 105 enum omp_clause_schedule_kind sched_kind; 106}; 107 108 109static splay_tree all_contexts; 110static int parallel_nesting_level; 111struct omp_region *root_omp_region; 112 113static void scan_omp (tree *, omp_context *); 114static void lower_omp (tree *, omp_context *); 115static tree lookup_decl_in_outer_ctx (tree, omp_context *); 116static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *); 117 118/* Find an OpenMP clause of type KIND within CLAUSES. */ 119 120static tree 121find_omp_clause (tree clauses, enum tree_code kind) 122{ 123 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses)) 124 if (OMP_CLAUSE_CODE (clauses) == kind) 125 return clauses; 126 127 return NULL_TREE; 128} 129 130/* Return true if CTX is for an omp parallel. */ 131 132static inline bool 133is_parallel_ctx (omp_context *ctx) 134{ 135 return TREE_CODE (ctx->stmt) == OMP_PARALLEL; 136} 137 138 139/* Return true if REGION is a combined parallel+workshare region. */ 140 141static inline bool 142is_combined_parallel (struct omp_region *region) 143{ 144 return region->is_combined_parallel; 145} 146 147 148/* Extract the header elements of parallel loop FOR_STMT and store 149 them into *FD. */ 150 151static void 152extract_omp_for_data (tree for_stmt, struct omp_for_data *fd) 153{ 154 tree t; 155 156 fd->for_stmt = for_stmt; 157 fd->pre = NULL; 158 159 t = OMP_FOR_INIT (for_stmt); 160 gcc_assert (TREE_CODE (t) == MODIFY_EXPR); 161 fd->v = TREE_OPERAND (t, 0); 162 gcc_assert (DECL_P (fd->v)); 163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE); 164 fd->n1 = TREE_OPERAND (t, 1); 165 166 t = OMP_FOR_COND (for_stmt); 167 fd->cond_code = TREE_CODE (t); 168 gcc_assert (TREE_OPERAND (t, 0) == fd->v); 169 fd->n2 = TREE_OPERAND (t, 1); 170 switch (fd->cond_code) 171 { 172 case LT_EXPR: 173 case GT_EXPR: 174 break; 175 case LE_EXPR: 176 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2, 177 build_int_cst (TREE_TYPE (fd->n2), 1)); 178 fd->cond_code = LT_EXPR; 179 break; 180 case GE_EXPR: 181 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2, 182 build_int_cst (TREE_TYPE (fd->n2), 1)); 183 fd->cond_code = GT_EXPR; 184 break; 185 default: 186 gcc_unreachable (); 187 } 188 189 t = OMP_FOR_INCR (fd->for_stmt); 190 gcc_assert (TREE_CODE (t) == MODIFY_EXPR); 191 gcc_assert (TREE_OPERAND (t, 0) == fd->v); 192 t = TREE_OPERAND (t, 1); 193 gcc_assert (TREE_OPERAND (t, 0) == fd->v); 194 switch (TREE_CODE (t)) 195 { 196 case PLUS_EXPR: 197 fd->step = TREE_OPERAND (t, 1); 198 break; 199 case MINUS_EXPR: 200 fd->step = TREE_OPERAND (t, 1); 201 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step); 202 break; 203 default: 204 gcc_unreachable (); 205 } 206 207 fd->have_nowait = fd->have_ordered = false; 208 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC; 209 fd->chunk_size = NULL_TREE; 210 211 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t)) 212 switch (OMP_CLAUSE_CODE (t)) 213 { 214 case OMP_CLAUSE_NOWAIT: 215 fd->have_nowait = true; 216 break; 217 case OMP_CLAUSE_ORDERED: 218 fd->have_ordered = true; 219 break; 220 case OMP_CLAUSE_SCHEDULE: 221 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t); 222 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t); 223 break; 224 default: 225 break; 226 } 227 228 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME) 229 gcc_assert (fd->chunk_size == NULL); 230 else if (fd->chunk_size == NULL) 231 { 232 /* We only need to compute a default chunk size for ordered 233 static loops and dynamic loops. */ 234 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered) 235 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC) 236 ? integer_zero_node : integer_one_node; 237 } 238} 239 240 241/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB 242 is the immediate dominator of PAR_ENTRY_BB, return true if there 243 are no data dependencies that would prevent expanding the parallel 244 directive at PAR_ENTRY_BB as a combined parallel+workshare region. 245 246 When expanding a combined parallel+workshare region, the call to 247 the child function may need additional arguments in the case of 248 OMP_FOR regions. In some cases, these arguments are computed out 249 of variables passed in from the parent to the child via 'struct 250 .omp_data_s'. For instance: 251 252 #pragma omp parallel for schedule (guided, i * 4) 253 for (j ...) 254 255 Is lowered into: 256 257 # BLOCK 2 (PAR_ENTRY_BB) 258 .omp_data_o.i = i; 259 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598) 260 261 # BLOCK 3 (WS_ENTRY_BB) 262 .omp_data_i = &.omp_data_o; 263 D.1667 = .omp_data_i->i; 264 D.1598 = D.1667 * 4; 265 #pragma omp for schedule (guided, D.1598) 266 267 When we outline the parallel region, the call to the child function 268 'bar.omp_fn.0' will need the value D.1598 in its argument list, but 269 that value is computed *after* the call site. So, in principle we 270 cannot do the transformation. 271 272 To see whether the code in WS_ENTRY_BB blocks the combined 273 parallel+workshare call, we collect all the variables used in the 274 OMP_FOR header check whether they appear on the LHS of any 275 statement in WS_ENTRY_BB. If so, then we cannot emit the combined 276 call. 277 278 FIXME. If we had the SSA form built at this point, we could merely 279 hoist the code in block 3 into block 2 and be done with it. But at 280 this point we don't have dataflow information and though we could 281 hack something up here, it is really not worth the aggravation. */ 282 283static bool 284workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb) 285{ 286 struct omp_for_data fd; 287 tree par_stmt, ws_stmt; 288 289 par_stmt = last_stmt (par_entry_bb); 290 ws_stmt = last_stmt (ws_entry_bb); 291 292 if (TREE_CODE (ws_stmt) == OMP_SECTIONS) 293 return true; 294 295 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR); 296 297 extract_omp_for_data (ws_stmt, &fd); 298 299 /* FIXME. We give up too easily here. If any of these arguments 300 are not constants, they will likely involve variables that have 301 been mapped into fields of .omp_data_s for sharing with the child 302 function. With appropriate data flow, it would be possible to 303 see through this. */ 304 if (!is_gimple_min_invariant (fd.n1) 305 || !is_gimple_min_invariant (fd.n2) 306 || !is_gimple_min_invariant (fd.step) 307 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size))) 308 return false; 309 310 return true; 311} 312 313 314/* Collect additional arguments needed to emit a combined 315 parallel+workshare call. WS_STMT is the workshare directive being 316 expanded. */ 317 318static tree 319get_ws_args_for (tree ws_stmt) 320{ 321 tree t; 322 323 if (TREE_CODE (ws_stmt) == OMP_FOR) 324 { 325 struct omp_for_data fd; 326 tree ws_args; 327 328 extract_omp_for_data (ws_stmt, &fd); 329 330 ws_args = NULL_TREE; 331 if (fd.chunk_size) 332 { 333 t = fold_convert (long_integer_type_node, fd.chunk_size); 334 ws_args = tree_cons (NULL, t, ws_args); 335 } 336 337 t = fold_convert (long_integer_type_node, fd.step); 338 ws_args = tree_cons (NULL, t, ws_args); 339 340 t = fold_convert (long_integer_type_node, fd.n2); 341 ws_args = tree_cons (NULL, t, ws_args); 342 343 t = fold_convert (long_integer_type_node, fd.n1); 344 ws_args = tree_cons (NULL, t, ws_args); 345 346 return ws_args; 347 } 348 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS) 349 { 350 basic_block bb = bb_for_stmt (ws_stmt); 351 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs)); 352 t = tree_cons (NULL, t, NULL); 353 return t; 354 } 355 356 gcc_unreachable (); 357} 358 359 360/* Discover whether REGION is a combined parallel+workshare region. */ 361 362static void 363determine_parallel_type (struct omp_region *region) 364{ 365 basic_block par_entry_bb, par_exit_bb; 366 basic_block ws_entry_bb, ws_exit_bb; 367 368 if (region == NULL || region->inner == NULL 369 || region->exit == NULL || region->inner->exit == NULL) 370 return; 371 372 /* We only support parallel+for and parallel+sections. */ 373 if (region->type != OMP_PARALLEL 374 || (region->inner->type != OMP_FOR 375 && region->inner->type != OMP_SECTIONS)) 376 return; 377 378 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and 379 WS_EXIT_BB -> PAR_EXIT_BB. */ 380 par_entry_bb = region->entry; 381 par_exit_bb = region->exit; 382 ws_entry_bb = region->inner->entry; 383 ws_exit_bb = region->inner->exit; 384 385 if (single_succ (par_entry_bb) == ws_entry_bb 386 && single_succ (ws_exit_bb) == par_exit_bb 387 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb)) 388 { 389 tree ws_stmt = last_stmt (region->inner->entry); 390 391 if (region->inner->type == OMP_FOR) 392 { 393 /* If this is a combined parallel loop, we need to determine 394 whether or not to use the combined library calls. There 395 are two cases where we do not apply the transformation: 396 static loops and any kind of ordered loop. In the first 397 case, we already open code the loop so there is no need 398 to do anything else. In the latter case, the combined 399 parallel loop call would still need extra synchronization 400 to implement ordered semantics, so there would not be any 401 gain in using the combined call. */ 402 tree clauses = OMP_FOR_CLAUSES (ws_stmt); 403 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE); 404 if (c == NULL 405 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC 406 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED)) 407 { 408 region->is_combined_parallel = false; 409 region->inner->is_combined_parallel = false; 410 return; 411 } 412 } 413 414 region->is_combined_parallel = true; 415 region->inner->is_combined_parallel = true; 416 region->ws_args = get_ws_args_for (ws_stmt); 417 } 418} 419 420 421/* Return true if EXPR is variable sized. */ 422 423static inline bool 424is_variable_sized (tree expr) 425{ 426 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr))); 427} 428 429/* Return true if DECL is a reference type. */ 430 431static inline bool 432is_reference (tree decl) 433{ 434 return lang_hooks.decls.omp_privatize_by_reference (decl); 435} 436 437/* Lookup variables in the decl or field splay trees. The "maybe" form 438 allows for the variable form to not have been entered, otherwise we 439 assert that the variable must have been entered. */ 440 441static inline tree 442lookup_decl (tree var, omp_context *ctx) 443{ 444 splay_tree_node n; 445 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var); 446 return (tree) n->value; 447} 448 449static inline tree 450maybe_lookup_decl (tree var, omp_context *ctx) 451{ 452 splay_tree_node n; 453 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var); 454 return n ? (tree) n->value : NULL_TREE; 455} 456 457static inline tree 458lookup_field (tree var, omp_context *ctx) 459{ 460 splay_tree_node n; 461 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var); 462 return (tree) n->value; 463} 464 465static inline tree 466maybe_lookup_field (tree var, omp_context *ctx) 467{ 468 splay_tree_node n; 469 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var); 470 return n ? (tree) n->value : NULL_TREE; 471} 472 473/* Return true if DECL should be copied by pointer. SHARED_P is true 474 if DECL is to be shared. */ 475 476static bool 477use_pointer_for_field (tree decl, bool shared_p) 478{ 479 if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) 480 return true; 481 482 /* We can only use copy-in/copy-out semantics for shared variables 483 when we know the value is not accessible from an outer scope. */ 484 if (shared_p) 485 { 486 /* ??? Trivially accessible from anywhere. But why would we even 487 be passing an address in this case? Should we simply assert 488 this to be false, or should we have a cleanup pass that removes 489 these from the list of mappings? */ 490 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) 491 return true; 492 493 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell 494 without analyzing the expression whether or not its location 495 is accessible to anyone else. In the case of nested parallel 496 regions it certainly may be. */ 497 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl)) 498 return true; 499 500 /* Do not use copy-in/copy-out for variables that have their 501 address taken. */ 502 if (TREE_ADDRESSABLE (decl)) 503 return true; 504 } 505 506 return false; 507} 508 509/* Construct a new automatic decl similar to VAR. */ 510 511static tree 512omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) 513{ 514 tree copy = build_decl (VAR_DECL, name, type); 515 516 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var); 517 DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var); 518 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var); 519 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var); 520 TREE_USED (copy) = 1; 521 DECL_CONTEXT (copy) = current_function_decl; 522 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1; 523 524 TREE_CHAIN (copy) = ctx->block_vars; 525 ctx->block_vars = copy; 526 527 return copy; 528} 529 530static tree 531omp_copy_decl_1 (tree var, omp_context *ctx) 532{ 533 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx); 534} 535 536/* Build tree nodes to access the field for VAR on the receiver side. */ 537 538static tree 539build_receiver_ref (tree var, bool by_ref, omp_context *ctx) 540{ 541 tree x, field = lookup_field (var, ctx); 542 543 /* If the receiver record type was remapped in the child function, 544 remap the field into the new record type. */ 545 x = maybe_lookup_field (field, ctx); 546 if (x != NULL) 547 field = x; 548 549 x = build_fold_indirect_ref (ctx->receiver_decl); 550 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL); 551 if (by_ref) 552 x = build_fold_indirect_ref (x); 553 554 return x; 555} 556 557/* Build tree nodes to access VAR in the scope outer to CTX. In the case 558 of a parallel, this is a component reference; for workshare constructs 559 this is some variable. */ 560 561static tree 562build_outer_var_ref (tree var, omp_context *ctx) 563{ 564 tree x; 565 566 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))) 567 x = var; 568 else if (is_variable_sized (var)) 569 { 570 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0); 571 x = build_outer_var_ref (x, ctx); 572 x = build_fold_indirect_ref (x); 573 } 574 else if (is_parallel_ctx (ctx)) 575 { 576 bool by_ref = use_pointer_for_field (var, false); 577 x = build_receiver_ref (var, by_ref, ctx); 578 } 579 else if (ctx->outer) 580 x = lookup_decl (var, ctx->outer); 581 else if (is_reference (var)) 582 /* This can happen with orphaned constructs. If var is reference, it is 583 possible it is shared and as such valid. */ 584 x = var; 585 else 586 gcc_unreachable (); 587 588 if (is_reference (var)) 589 x = build_fold_indirect_ref (x); 590 591 return x; 592} 593 594/* Build tree nodes to access the field for VAR on the sender side. */ 595 596static tree 597build_sender_ref (tree var, omp_context *ctx) 598{ 599 tree field = lookup_field (var, ctx); 600 return build3 (COMPONENT_REF, TREE_TYPE (field), 601 ctx->sender_decl, field, NULL); 602} 603 604/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */ 605 606static void 607install_var_field (tree var, bool by_ref, omp_context *ctx) 608{ 609 tree field, type; 610 611 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var)); 612 613 type = TREE_TYPE (var); 614 if (by_ref) 615 type = build_pointer_type (type); 616 617 field = build_decl (FIELD_DECL, DECL_NAME (var), type); 618 619 /* Remember what variable this field was created for. This does have a 620 side effect of making dwarf2out ignore this member, so for helpful 621 debugging we clear it later in delete_omp_context. */ 622 DECL_ABSTRACT_ORIGIN (field) = var; 623 624 insert_field_into_struct (ctx->record_type, field); 625 626 splay_tree_insert (ctx->field_map, (splay_tree_key) var, 627 (splay_tree_value) field); 628} 629 630static tree 631install_var_local (tree var, omp_context *ctx) 632{ 633 tree new_var = omp_copy_decl_1 (var, ctx); 634 insert_decl_map (&ctx->cb, var, new_var); 635 return new_var; 636} 637 638/* Adjust the replacement for DECL in CTX for the new context. This means 639 copying the DECL_VALUE_EXPR, and fixing up the type. */ 640 641static void 642fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug) 643{ 644 tree new_decl, size; 645 646 new_decl = lookup_decl (decl, ctx); 647 648 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb); 649 650 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug) 651 && DECL_HAS_VALUE_EXPR_P (decl)) 652 { 653 tree ve = DECL_VALUE_EXPR (decl); 654 walk_tree (&ve, copy_body_r, &ctx->cb, NULL); 655 SET_DECL_VALUE_EXPR (new_decl, ve); 656 DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 657 } 658 659 if (!TREE_CONSTANT (DECL_SIZE (new_decl))) 660 { 661 size = remap_decl (DECL_SIZE (decl), &ctx->cb); 662 if (size == error_mark_node) 663 size = TYPE_SIZE (TREE_TYPE (new_decl)); 664 DECL_SIZE (new_decl) = size; 665 666 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb); 667 if (size == error_mark_node) 668 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl)); 669 DECL_SIZE_UNIT (new_decl) = size; 670 } 671} 672 673/* The callback for remap_decl. Search all containing contexts for a 674 mapping of the variable; this avoids having to duplicate the splay 675 tree ahead of time. We know a mapping doesn't already exist in the 676 given context. Create new mappings to implement default semantics. */ 677 678static tree 679omp_copy_decl (tree var, copy_body_data *cb) 680{ 681 omp_context *ctx = (omp_context *) cb; 682 tree new_var; 683 684 if (TREE_CODE (var) == LABEL_DECL) 685 { 686 new_var = create_artificial_label (); 687 DECL_CONTEXT (new_var) = current_function_decl; 688 insert_decl_map (&ctx->cb, var, new_var); 689 return new_var; 690 } 691 692 while (!is_parallel_ctx (ctx)) 693 { 694 ctx = ctx->outer; 695 if (ctx == NULL) 696 return var; 697 new_var = maybe_lookup_decl (var, ctx); 698 if (new_var) 699 return new_var; 700 } 701 702 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn) 703 return var; 704 705 return error_mark_node; 706} 707 708 709/* Return the parallel region associated with STMT. */ 710 711/* Debugging dumps for parallel regions. */ 712void dump_omp_region (FILE *, struct omp_region *, int); 713void debug_omp_region (struct omp_region *); 714void debug_all_omp_regions (void); 715 716/* Dump the parallel region tree rooted at REGION. */ 717 718void 719dump_omp_region (FILE *file, struct omp_region *region, int indent) 720{ 721 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index, 722 tree_code_name[region->type]); 723 724 if (region->inner) 725 dump_omp_region (file, region->inner, indent + 4); 726 727 if (region->cont) 728 { 729 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "", 730 region->cont->index); 731 } 732 733 if (region->exit) 734 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "", 735 region->exit->index); 736 else 737 fprintf (file, "%*s[no exit marker]\n", indent, ""); 738 739 if (region->next) 740 dump_omp_region (file, region->next, indent); 741} 742 743void 744debug_omp_region (struct omp_region *region) 745{ 746 dump_omp_region (stderr, region, 0); 747} 748 749void 750debug_all_omp_regions (void) 751{ 752 dump_omp_region (stderr, root_omp_region, 0); 753} 754 755 756/* Create a new parallel region starting at STMT inside region PARENT. */ 757 758struct omp_region * 759new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent) 760{ 761 struct omp_region *region = xcalloc (1, sizeof (*region)); 762 763 region->outer = parent; 764 region->entry = bb; 765 region->type = type; 766 767 if (parent) 768 { 769 /* This is a nested region. Add it to the list of inner 770 regions in PARENT. */ 771 region->next = parent->inner; 772 parent->inner = region; 773 } 774 else 775 { 776 /* This is a toplevel region. Add it to the list of toplevel 777 regions in ROOT_OMP_REGION. */ 778 region->next = root_omp_region; 779 root_omp_region = region; 780 } 781 782 return region; 783} 784 785/* Release the memory associated with the region tree rooted at REGION. */ 786 787static void 788free_omp_region_1 (struct omp_region *region) 789{ 790 struct omp_region *i, *n; 791 792 for (i = region->inner; i ; i = n) 793 { 794 n = i->next; 795 free_omp_region_1 (i); 796 } 797 798 free (region); 799} 800 801/* Release the memory for the entire omp region tree. */ 802 803void 804free_omp_regions (void) 805{ 806 struct omp_region *r, *n; 807 for (r = root_omp_region; r ; r = n) 808 { 809 n = r->next; 810 free_omp_region_1 (r); 811 } 812 root_omp_region = NULL; 813} 814 815 816/* Create a new context, with OUTER_CTX being the surrounding context. */ 817 818static omp_context * 819new_omp_context (tree stmt, omp_context *outer_ctx) 820{ 821 omp_context *ctx = XCNEW (omp_context); 822 823 splay_tree_insert (all_contexts, (splay_tree_key) stmt, 824 (splay_tree_value) ctx); 825 ctx->stmt = stmt; 826 827 if (outer_ctx) 828 { 829 ctx->outer = outer_ctx; 830 ctx->cb = outer_ctx->cb; 831 ctx->cb.block = NULL; 832 ctx->depth = outer_ctx->depth + 1; 833 } 834 else 835 { 836 ctx->cb.src_fn = current_function_decl; 837 ctx->cb.dst_fn = current_function_decl; 838 ctx->cb.src_node = cgraph_node (current_function_decl); 839 ctx->cb.dst_node = ctx->cb.src_node; 840 ctx->cb.src_cfun = cfun; 841 ctx->cb.copy_decl = omp_copy_decl; 842 ctx->cb.eh_region = -1; 843 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE; 844 ctx->depth = 1; 845 } 846 847 ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 848 849 return ctx; 850} 851 852/* Destroy a omp_context data structures. Called through the splay tree 853 value delete callback. */ 854 855static void 856delete_omp_context (splay_tree_value value) 857{ 858 omp_context *ctx = (omp_context *) value; 859 860 splay_tree_delete (ctx->cb.decl_map); 861 862 if (ctx->field_map) 863 splay_tree_delete (ctx->field_map); 864 865 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before 866 it produces corrupt debug information. */ 867 if (ctx->record_type) 868 { 869 tree t; 870 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t)) 871 DECL_ABSTRACT_ORIGIN (t) = NULL; 872 } 873 874 XDELETE (ctx); 875} 876 877/* Fix up RECEIVER_DECL with a type that has been remapped to the child 878 context. */ 879 880static void 881fixup_child_record_type (omp_context *ctx) 882{ 883 tree f, type = ctx->record_type; 884 885 /* ??? It isn't sufficient to just call remap_type here, because 886 variably_modified_type_p doesn't work the way we expect for 887 record types. Testing each field for whether it needs remapping 888 and creating a new record by hand works, however. */ 889 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f)) 890 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn)) 891 break; 892 if (f) 893 { 894 tree name, new_fields = NULL; 895 896 type = lang_hooks.types.make_type (RECORD_TYPE); 897 name = DECL_NAME (TYPE_NAME (ctx->record_type)); 898 name = build_decl (TYPE_DECL, name, type); 899 TYPE_NAME (type) = name; 900 901 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f)) 902 { 903 tree new_f = copy_node (f); 904 DECL_CONTEXT (new_f) = type; 905 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb); 906 TREE_CHAIN (new_f) = new_fields; 907 new_fields = new_f; 908 909 /* Arrange to be able to look up the receiver field 910 given the sender field. */ 911 splay_tree_insert (ctx->field_map, (splay_tree_key) f, 912 (splay_tree_value) new_f); 913 } 914 TYPE_FIELDS (type) = nreverse (new_fields); 915 layout_type (type); 916 } 917 918 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type); 919} 920 921/* Instantiate decls as necessary in CTX to satisfy the data sharing 922 specified by CLAUSES. */ 923 924static void 925scan_sharing_clauses (tree clauses, omp_context *ctx) 926{ 927 tree c, decl; 928 bool scan_array_reductions = false; 929 930 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 931 { 932 bool by_ref; 933 934 switch (OMP_CLAUSE_CODE (c)) 935 { 936 case OMP_CLAUSE_PRIVATE: 937 decl = OMP_CLAUSE_DECL (c); 938 if (!is_variable_sized (decl)) 939 install_var_local (decl, ctx); 940 break; 941 942 case OMP_CLAUSE_SHARED: 943 gcc_assert (is_parallel_ctx (ctx)); 944 decl = OMP_CLAUSE_DECL (c); 945 gcc_assert (!is_variable_sized (decl)); 946 by_ref = use_pointer_for_field (decl, true); 947 /* Global variables don't need to be copied, 948 the receiver side will use them directly. */ 949 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) 950 break; 951 if (! TREE_READONLY (decl) 952 || TREE_ADDRESSABLE (decl) 953 || by_ref 954 || is_reference (decl)) 955 { 956 install_var_field (decl, by_ref, ctx); 957 install_var_local (decl, ctx); 958 break; 959 } 960 /* We don't need to copy const scalar vars back. */ 961 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE); 962 goto do_private; 963 964 case OMP_CLAUSE_LASTPRIVATE: 965 /* Let the corresponding firstprivate clause create 966 the variable. */ 967 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 968 break; 969 /* FALLTHRU */ 970 971 case OMP_CLAUSE_FIRSTPRIVATE: 972 case OMP_CLAUSE_REDUCTION: 973 decl = OMP_CLAUSE_DECL (c); 974 do_private: 975 if (is_variable_sized (decl)) 976 break; 977 else if (is_parallel_ctx (ctx) 978 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, 979 ctx))) 980 { 981 by_ref = use_pointer_for_field (decl, false); 982 install_var_field (decl, by_ref, ctx); 983 } 984 install_var_local (decl, ctx); 985 break; 986 987 case OMP_CLAUSE_COPYPRIVATE: 988 if (ctx->outer) 989 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer); 990 /* FALLTHRU */ 991 992 case OMP_CLAUSE_COPYIN: 993 decl = OMP_CLAUSE_DECL (c); 994 by_ref = use_pointer_for_field (decl, false); 995 install_var_field (decl, by_ref, ctx); 996 break; 997 998 case OMP_CLAUSE_DEFAULT: 999 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c); 1000 break; 1001 1002 case OMP_CLAUSE_IF: 1003 case OMP_CLAUSE_NUM_THREADS: 1004 case OMP_CLAUSE_SCHEDULE: 1005 if (ctx->outer) 1006 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer); 1007 break; 1008 1009 case OMP_CLAUSE_NOWAIT: 1010 case OMP_CLAUSE_ORDERED: 1011 break; 1012 1013 default: 1014 gcc_unreachable (); 1015 } 1016 } 1017 1018 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 1019 { 1020 switch (OMP_CLAUSE_CODE (c)) 1021 { 1022 case OMP_CLAUSE_LASTPRIVATE: 1023 /* Let the corresponding firstprivate clause create 1024 the variable. */ 1025 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 1026 break; 1027 /* FALLTHRU */ 1028 1029 case OMP_CLAUSE_PRIVATE: 1030 case OMP_CLAUSE_FIRSTPRIVATE: 1031 case OMP_CLAUSE_REDUCTION: 1032 decl = OMP_CLAUSE_DECL (c); 1033 if (is_variable_sized (decl)) 1034 install_var_local (decl, ctx); 1035 fixup_remapped_decl (decl, ctx, 1036 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE 1037 && OMP_CLAUSE_PRIVATE_DEBUG (c)); 1038 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION 1039 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1040 scan_array_reductions = true; 1041 break; 1042 1043 case OMP_CLAUSE_SHARED: 1044 decl = OMP_CLAUSE_DECL (c); 1045 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) 1046 fixup_remapped_decl (decl, ctx, false); 1047 break; 1048 1049 case OMP_CLAUSE_COPYPRIVATE: 1050 case OMP_CLAUSE_COPYIN: 1051 case OMP_CLAUSE_DEFAULT: 1052 case OMP_CLAUSE_IF: 1053 case OMP_CLAUSE_NUM_THREADS: 1054 case OMP_CLAUSE_SCHEDULE: 1055 case OMP_CLAUSE_NOWAIT: 1056 case OMP_CLAUSE_ORDERED: 1057 break; 1058 1059 default: 1060 gcc_unreachable (); 1061 } 1062 } 1063 1064 if (scan_array_reductions) 1065 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 1066 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION 1067 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1068 { 1069 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx); 1070 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx); 1071 } 1072} 1073 1074/* Create a new name for omp child function. Returns an identifier. */ 1075 1076static GTY(()) unsigned int tmp_ompfn_id_num; 1077 1078static tree 1079create_omp_child_function_name (void) 1080{ 1081 tree name = DECL_ASSEMBLER_NAME (current_function_decl); 1082 size_t len = IDENTIFIER_LENGTH (name); 1083 char *tmp_name, *prefix; 1084 1085 prefix = alloca (len + sizeof ("_omp_fn")); 1086 memcpy (prefix, IDENTIFIER_POINTER (name), len); 1087 strcpy (prefix + len, "_omp_fn"); 1088#ifndef NO_DOT_IN_LABEL 1089 prefix[len] = '.'; 1090#elif !defined NO_DOLLAR_IN_LABEL 1091 prefix[len] = '$'; 1092#endif 1093 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++); 1094 return get_identifier (tmp_name); 1095} 1096 1097/* Build a decl for the omp child function. It'll not contain a body 1098 yet, just the bare decl. */ 1099 1100static void 1101create_omp_child_function (omp_context *ctx) 1102{ 1103 tree decl, type, name, t; 1104 1105 name = create_omp_child_function_name (); 1106 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); 1107 1108 decl = build_decl (FUNCTION_DECL, name, type); 1109 decl = lang_hooks.decls.pushdecl (decl); 1110 1111 ctx->cb.dst_fn = decl; 1112 1113 TREE_STATIC (decl) = 1; 1114 TREE_USED (decl) = 1; 1115 DECL_ARTIFICIAL (decl) = 1; 1116 DECL_IGNORED_P (decl) = 0; 1117 TREE_PUBLIC (decl) = 0; 1118 DECL_UNINLINABLE (decl) = 1; 1119 DECL_EXTERNAL (decl) = 0; 1120 DECL_CONTEXT (decl) = NULL_TREE; 1121 DECL_INITIAL (decl) = make_node (BLOCK); 1122 1123 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node); 1124 DECL_ARTIFICIAL (t) = 1; 1125 DECL_IGNORED_P (t) = 1; 1126 DECL_RESULT (decl) = t; 1127 1128 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node); 1129 DECL_ARTIFICIAL (t) = 1; 1130 DECL_ARG_TYPE (t) = ptr_type_node; 1131 DECL_CONTEXT (t) = current_function_decl; 1132 TREE_USED (t) = 1; 1133 DECL_ARGUMENTS (decl) = t; 1134 ctx->receiver_decl = t; 1135 1136 /* Allocate memory for the function structure. The call to 1137 allocate_struct_function clobbers CFUN, so we need to restore 1138 it afterward. */ 1139 allocate_struct_function (decl); 1140 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt); 1141 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt); 1142 cfun = ctx->cb.src_cfun; 1143} 1144 1145 1146/* Scan an OpenMP parallel directive. */ 1147 1148static void 1149scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx) 1150{ 1151 omp_context *ctx; 1152 tree name; 1153 1154 /* Ignore parallel directives with empty bodies, unless there 1155 are copyin clauses. */ 1156 if (optimize > 0 1157 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p)) 1158 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL) 1159 { 1160 *stmt_p = build_empty_stmt (); 1161 return; 1162 } 1163 1164 ctx = new_omp_context (*stmt_p, outer_ctx); 1165 if (parallel_nesting_level > 1) 1166 ctx->is_nested = true; 1167 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 1168 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED; 1169 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE); 1170 name = create_tmp_var_name (".omp_data_s"); 1171 name = build_decl (TYPE_DECL, name, ctx->record_type); 1172 TYPE_NAME (ctx->record_type) = name; 1173 create_omp_child_function (ctx); 1174 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn; 1175 1176 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx); 1177 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx); 1178 1179 if (TYPE_FIELDS (ctx->record_type) == NULL) 1180 ctx->record_type = ctx->receiver_decl = NULL; 1181 else 1182 { 1183 layout_type (ctx->record_type); 1184 fixup_child_record_type (ctx); 1185 } 1186} 1187 1188 1189/* Scan an OpenMP loop directive. */ 1190 1191static void 1192scan_omp_for (tree *stmt_p, omp_context *outer_ctx) 1193{ 1194 omp_context *ctx; 1195 tree stmt; 1196 1197 stmt = *stmt_p; 1198 ctx = new_omp_context (stmt, outer_ctx); 1199 1200 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx); 1201 1202 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx); 1203 scan_omp (&OMP_FOR_INIT (stmt), ctx); 1204 scan_omp (&OMP_FOR_COND (stmt), ctx); 1205 scan_omp (&OMP_FOR_INCR (stmt), ctx); 1206 scan_omp (&OMP_FOR_BODY (stmt), ctx); 1207} 1208 1209/* Scan an OpenMP sections directive. */ 1210 1211static void 1212scan_omp_sections (tree *stmt_p, omp_context *outer_ctx) 1213{ 1214 tree stmt; 1215 omp_context *ctx; 1216 1217 stmt = *stmt_p; 1218 ctx = new_omp_context (stmt, outer_ctx); 1219 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx); 1220 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx); 1221} 1222 1223/* Scan an OpenMP single directive. */ 1224 1225static void 1226scan_omp_single (tree *stmt_p, omp_context *outer_ctx) 1227{ 1228 tree stmt = *stmt_p; 1229 omp_context *ctx; 1230 tree name; 1231 1232 ctx = new_omp_context (stmt, outer_ctx); 1233 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 1234 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE); 1235 name = create_tmp_var_name (".omp_copy_s"); 1236 name = build_decl (TYPE_DECL, name, ctx->record_type); 1237 TYPE_NAME (ctx->record_type) = name; 1238 1239 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx); 1240 scan_omp (&OMP_SINGLE_BODY (stmt), ctx); 1241 1242 if (TYPE_FIELDS (ctx->record_type) == NULL) 1243 ctx->record_type = NULL; 1244 else 1245 layout_type (ctx->record_type); 1246} 1247 1248 1249/* Check OpenMP nesting restrictions. */ 1250static void 1251check_omp_nesting_restrictions (tree t, omp_context *ctx) 1252{ 1253 switch (TREE_CODE (t)) 1254 { 1255 case OMP_FOR: 1256 case OMP_SECTIONS: 1257 case OMP_SINGLE: 1258 for (; ctx != NULL; ctx = ctx->outer) 1259 switch (TREE_CODE (ctx->stmt)) 1260 { 1261 case OMP_FOR: 1262 case OMP_SECTIONS: 1263 case OMP_SINGLE: 1264 case OMP_ORDERED: 1265 case OMP_MASTER: 1266 warning (0, "work-sharing region may not be closely nested inside " 1267 "of work-sharing, critical, ordered or master region"); 1268 return; 1269 case OMP_PARALLEL: 1270 return; 1271 default: 1272 break; 1273 } 1274 break; 1275 case OMP_MASTER: 1276 for (; ctx != NULL; ctx = ctx->outer) 1277 switch (TREE_CODE (ctx->stmt)) 1278 { 1279 case OMP_FOR: 1280 case OMP_SECTIONS: 1281 case OMP_SINGLE: 1282 warning (0, "master region may not be closely nested inside " 1283 "of work-sharing region"); 1284 return; 1285 case OMP_PARALLEL: 1286 return; 1287 default: 1288 break; 1289 } 1290 break; 1291 case OMP_ORDERED: 1292 for (; ctx != NULL; ctx = ctx->outer) 1293 switch (TREE_CODE (ctx->stmt)) 1294 { 1295 case OMP_CRITICAL: 1296 warning (0, "ordered region may not be closely nested inside " 1297 "of critical region"); 1298 return; 1299 case OMP_FOR: 1300 if (find_omp_clause (OMP_CLAUSES (ctx->stmt), 1301 OMP_CLAUSE_ORDERED) == NULL) 1302 warning (0, "ordered region must be closely nested inside " 1303 "a loop region with an ordered clause"); 1304 return; 1305 case OMP_PARALLEL: 1306 return; 1307 default: 1308 break; 1309 } 1310 break; 1311 case OMP_CRITICAL: 1312 for (; ctx != NULL; ctx = ctx->outer) 1313 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL 1314 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt)) 1315 { 1316 warning (0, "critical region may not be nested inside a critical " 1317 "region with the same name"); 1318 return; 1319 } 1320 break; 1321 default: 1322 break; 1323 } 1324} 1325 1326 1327/* Callback for walk_stmts used to scan for OpenMP directives at TP. */ 1328 1329static tree 1330scan_omp_1 (tree *tp, int *walk_subtrees, void *data) 1331{ 1332 struct walk_stmt_info *wi = data; 1333 omp_context *ctx = wi->info; 1334 tree t = *tp; 1335 1336 if (EXPR_HAS_LOCATION (t)) 1337 input_location = EXPR_LOCATION (t); 1338 1339 /* Check the OpenMP nesting restrictions. */ 1340 if (OMP_DIRECTIVE_P (t) && ctx != NULL) 1341 check_omp_nesting_restrictions (t, ctx); 1342 1343 *walk_subtrees = 0; 1344 switch (TREE_CODE (t)) 1345 { 1346 case OMP_PARALLEL: 1347 parallel_nesting_level++; 1348 scan_omp_parallel (tp, ctx); 1349 parallel_nesting_level--; 1350 break; 1351 1352 case OMP_FOR: 1353 scan_omp_for (tp, ctx); 1354 break; 1355 1356 case OMP_SECTIONS: 1357 scan_omp_sections (tp, ctx); 1358 break; 1359 1360 case OMP_SINGLE: 1361 scan_omp_single (tp, ctx); 1362 break; 1363 1364 case OMP_SECTION: 1365 case OMP_MASTER: 1366 case OMP_ORDERED: 1367 case OMP_CRITICAL: 1368 ctx = new_omp_context (*tp, ctx); 1369 scan_omp (&OMP_BODY (*tp), ctx); 1370 break; 1371 1372 case BIND_EXPR: 1373 { 1374 tree var; 1375 *walk_subtrees = 1; 1376 1377 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var)) 1378 insert_decl_map (&ctx->cb, var, var); 1379 } 1380 break; 1381 1382 case VAR_DECL: 1383 case PARM_DECL: 1384 case LABEL_DECL: 1385 case RESULT_DECL: 1386 if (ctx) 1387 *tp = remap_decl (t, &ctx->cb); 1388 break; 1389 1390 default: 1391 if (ctx && TYPE_P (t)) 1392 *tp = remap_type (t, &ctx->cb); 1393 else if (!DECL_P (t)) 1394 *walk_subtrees = 1; 1395 break; 1396 } 1397 1398 return NULL_TREE; 1399} 1400 1401 1402/* Scan all the statements starting at STMT_P. CTX contains context 1403 information about the OpenMP directives and clauses found during 1404 the scan. */ 1405 1406static void 1407scan_omp (tree *stmt_p, omp_context *ctx) 1408{ 1409 location_t saved_location; 1410 struct walk_stmt_info wi; 1411 1412 memset (&wi, 0, sizeof (wi)); 1413 wi.callback = scan_omp_1; 1414 wi.info = ctx; 1415 wi.want_bind_expr = (ctx != NULL); 1416 wi.want_locations = true; 1417 1418 saved_location = input_location; 1419 walk_stmts (&wi, stmt_p); 1420 input_location = saved_location; 1421} 1422 1423/* Re-gimplification and code generation routines. */ 1424 1425/* Build a call to GOMP_barrier. */ 1426 1427static void 1428build_omp_barrier (tree *stmt_list) 1429{ 1430 tree t; 1431 1432 t = built_in_decls[BUILT_IN_GOMP_BARRIER]; 1433 t = build_function_call_expr (t, NULL); 1434 gimplify_and_add (t, stmt_list); 1435} 1436 1437/* If a context was created for STMT when it was scanned, return it. */ 1438 1439static omp_context * 1440maybe_lookup_ctx (tree stmt) 1441{ 1442 splay_tree_node n; 1443 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt); 1444 return n ? (omp_context *) n->value : NULL; 1445} 1446 1447 1448/* Find the mapping for DECL in CTX or the immediately enclosing 1449 context that has a mapping for DECL. 1450 1451 If CTX is a nested parallel directive, we may have to use the decl 1452 mappings created in CTX's parent context. Suppose that we have the 1453 following parallel nesting (variable UIDs showed for clarity): 1454 1455 iD.1562 = 0; 1456 #omp parallel shared(iD.1562) -> outer parallel 1457 iD.1562 = iD.1562 + 1; 1458 1459 #omp parallel shared (iD.1562) -> inner parallel 1460 iD.1562 = iD.1562 - 1; 1461 1462 Each parallel structure will create a distinct .omp_data_s structure 1463 for copying iD.1562 in/out of the directive: 1464 1465 outer parallel .omp_data_s.1.i -> iD.1562 1466 inner parallel .omp_data_s.2.i -> iD.1562 1467 1468 A shared variable mapping will produce a copy-out operation before 1469 the parallel directive and a copy-in operation after it. So, in 1470 this case we would have: 1471 1472 iD.1562 = 0; 1473 .omp_data_o.1.i = iD.1562; 1474 #omp parallel shared(iD.1562) -> outer parallel 1475 .omp_data_i.1 = &.omp_data_o.1 1476 .omp_data_i.1->i = .omp_data_i.1->i + 1; 1477 1478 .omp_data_o.2.i = iD.1562; -> ** 1479 #omp parallel shared(iD.1562) -> inner parallel 1480 .omp_data_i.2 = &.omp_data_o.2 1481 .omp_data_i.2->i = .omp_data_i.2->i - 1; 1482 1483 1484 ** This is a problem. The symbol iD.1562 cannot be referenced 1485 inside the body of the outer parallel region. But since we are 1486 emitting this copy operation while expanding the inner parallel 1487 directive, we need to access the CTX structure of the outer 1488 parallel directive to get the correct mapping: 1489 1490 .omp_data_o.2.i = .omp_data_i.1->i 1491 1492 Since there may be other workshare or parallel directives enclosing 1493 the parallel directive, it may be necessary to walk up the context 1494 parent chain. This is not a problem in general because nested 1495 parallelism happens only rarely. */ 1496 1497static tree 1498lookup_decl_in_outer_ctx (tree decl, omp_context *ctx) 1499{ 1500 tree t; 1501 omp_context *up; 1502 1503 gcc_assert (ctx->is_nested); 1504 1505 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer) 1506 t = maybe_lookup_decl (decl, up); 1507 1508 gcc_assert (t); 1509 1510 return t; 1511} 1512 1513 1514/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found 1515 in outer contexts. */ 1516 1517static tree 1518maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx) 1519{ 1520 tree t = NULL; 1521 omp_context *up; 1522 1523 if (ctx->is_nested) 1524 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer) 1525 t = maybe_lookup_decl (decl, up); 1526 1527 return t ? t : decl; 1528} 1529 1530 1531/* Construct the initialization value for reduction CLAUSE. */ 1532 1533tree 1534omp_reduction_init (tree clause, tree type) 1535{ 1536 switch (OMP_CLAUSE_REDUCTION_CODE (clause)) 1537 { 1538 case PLUS_EXPR: 1539 case MINUS_EXPR: 1540 case BIT_IOR_EXPR: 1541 case BIT_XOR_EXPR: 1542 case TRUTH_OR_EXPR: 1543 case TRUTH_ORIF_EXPR: 1544 case TRUTH_XOR_EXPR: 1545 case NE_EXPR: 1546 return fold_convert (type, integer_zero_node); 1547 1548 case MULT_EXPR: 1549 case TRUTH_AND_EXPR: 1550 case TRUTH_ANDIF_EXPR: 1551 case EQ_EXPR: 1552 return fold_convert (type, integer_one_node); 1553 1554 case BIT_AND_EXPR: 1555 return fold_convert (type, integer_minus_one_node); 1556 1557 case MAX_EXPR: 1558 if (SCALAR_FLOAT_TYPE_P (type)) 1559 { 1560 REAL_VALUE_TYPE max, min; 1561 if (HONOR_INFINITIES (TYPE_MODE (type))) 1562 { 1563 real_inf (&max); 1564 real_arithmetic (&min, NEGATE_EXPR, &max, NULL); 1565 } 1566 else 1567 real_maxval (&min, 1, TYPE_MODE (type)); 1568 return build_real (type, min); 1569 } 1570 else 1571 { 1572 gcc_assert (INTEGRAL_TYPE_P (type)); 1573 return TYPE_MIN_VALUE (type); 1574 } 1575 1576 case MIN_EXPR: 1577 if (SCALAR_FLOAT_TYPE_P (type)) 1578 { 1579 REAL_VALUE_TYPE max; 1580 if (HONOR_INFINITIES (TYPE_MODE (type))) 1581 real_inf (&max); 1582 else 1583 real_maxval (&max, 0, TYPE_MODE (type)); 1584 return build_real (type, max); 1585 } 1586 else 1587 { 1588 gcc_assert (INTEGRAL_TYPE_P (type)); 1589 return TYPE_MAX_VALUE (type); 1590 } 1591 1592 default: 1593 gcc_unreachable (); 1594 } 1595} 1596 1597/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN, 1598 from the receiver (aka child) side and initializers for REFERENCE_TYPE 1599 private variables. Initialization statements go in ILIST, while calls 1600 to destructors go in DLIST. */ 1601 1602static void 1603lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist, 1604 omp_context *ctx) 1605{ 1606 tree_stmt_iterator diter; 1607 tree c, dtor, copyin_seq, x, args, ptr; 1608 bool copyin_by_ref = false; 1609 bool lastprivate_firstprivate = false; 1610 int pass; 1611 1612 *dlist = alloc_stmt_list (); 1613 diter = tsi_start (*dlist); 1614 copyin_seq = NULL; 1615 1616 /* Do all the fixed sized types in the first pass, and the variable sized 1617 types in the second pass. This makes sure that the scalar arguments to 1618 the variable sized types are processed before we use them in the 1619 variable sized operations. */ 1620 for (pass = 0; pass < 2; ++pass) 1621 { 1622 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 1623 { 1624 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c); 1625 tree var, new_var; 1626 bool by_ref; 1627 1628 switch (c_kind) 1629 { 1630 case OMP_CLAUSE_PRIVATE: 1631 if (OMP_CLAUSE_PRIVATE_DEBUG (c)) 1632 continue; 1633 break; 1634 case OMP_CLAUSE_SHARED: 1635 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL) 1636 { 1637 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c))); 1638 continue; 1639 } 1640 case OMP_CLAUSE_FIRSTPRIVATE: 1641 case OMP_CLAUSE_COPYIN: 1642 case OMP_CLAUSE_REDUCTION: 1643 break; 1644 case OMP_CLAUSE_LASTPRIVATE: 1645 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 1646 { 1647 lastprivate_firstprivate = true; 1648 if (pass != 0) 1649 continue; 1650 } 1651 break; 1652 default: 1653 continue; 1654 } 1655 1656 new_var = var = OMP_CLAUSE_DECL (c); 1657 if (c_kind != OMP_CLAUSE_COPYIN) 1658 new_var = lookup_decl (var, ctx); 1659 1660 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN) 1661 { 1662 if (pass != 0) 1663 continue; 1664 } 1665 else if (is_variable_sized (var)) 1666 { 1667 /* For variable sized types, we need to allocate the 1668 actual storage here. Call alloca and store the 1669 result in the pointer decl that we created elsewhere. */ 1670 if (pass == 0) 1671 continue; 1672 1673 ptr = DECL_VALUE_EXPR (new_var); 1674 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF); 1675 ptr = TREE_OPERAND (ptr, 0); 1676 gcc_assert (DECL_P (ptr)); 1677 1678 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var)); 1679 args = tree_cons (NULL, x, NULL); 1680 x = built_in_decls[BUILT_IN_ALLOCA]; 1681 x = build_function_call_expr (x, args); 1682 x = fold_convert (TREE_TYPE (ptr), x); 1683 x = build2 (MODIFY_EXPR, void_type_node, ptr, x); 1684 gimplify_and_add (x, ilist); 1685 } 1686 else if (is_reference (var)) 1687 { 1688 /* For references that are being privatized for Fortran, 1689 allocate new backing storage for the new pointer 1690 variable. This allows us to avoid changing all the 1691 code that expects a pointer to something that expects 1692 a direct variable. Note that this doesn't apply to 1693 C++, since reference types are disallowed in data 1694 sharing clauses there, except for NRV optimized 1695 return values. */ 1696 if (pass == 0) 1697 continue; 1698 1699 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var))); 1700 if (TREE_CONSTANT (x)) 1701 { 1702 const char *name = NULL; 1703 if (DECL_NAME (var)) 1704 name = IDENTIFIER_POINTER (DECL_NAME (new_var)); 1705 1706 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)), 1707 name); 1708 gimple_add_tmp_var (x); 1709 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var)); 1710 } 1711 else 1712 { 1713 args = tree_cons (NULL, x, NULL); 1714 x = built_in_decls[BUILT_IN_ALLOCA]; 1715 x = build_function_call_expr (x, args); 1716 x = fold_convert (TREE_TYPE (new_var), x); 1717 } 1718 1719 x = build2 (MODIFY_EXPR, void_type_node, new_var, x); 1720 gimplify_and_add (x, ilist); 1721 1722 new_var = build_fold_indirect_ref (new_var); 1723 } 1724 else if (c_kind == OMP_CLAUSE_REDUCTION 1725 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1726 { 1727 if (pass == 0) 1728 continue; 1729 } 1730 else if (pass != 0) 1731 continue; 1732 1733 switch (OMP_CLAUSE_CODE (c)) 1734 { 1735 case OMP_CLAUSE_SHARED: 1736 /* Shared global vars are just accessed directly. */ 1737 if (is_global_var (new_var)) 1738 break; 1739 /* Set up the DECL_VALUE_EXPR for shared variables now. This 1740 needs to be delayed until after fixup_child_record_type so 1741 that we get the correct type during the dereference. */ 1742 by_ref = use_pointer_for_field (var, true); 1743 x = build_receiver_ref (var, by_ref, ctx); 1744 SET_DECL_VALUE_EXPR (new_var, x); 1745 DECL_HAS_VALUE_EXPR_P (new_var) = 1; 1746 1747 /* ??? If VAR is not passed by reference, and the variable 1748 hasn't been initialized yet, then we'll get a warning for 1749 the store into the omp_data_s structure. Ideally, we'd be 1750 able to notice this and not store anything at all, but 1751 we're generating code too early. Suppress the warning. */ 1752 if (!by_ref) 1753 TREE_NO_WARNING (var) = 1; 1754 break; 1755 1756 case OMP_CLAUSE_LASTPRIVATE: 1757 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 1758 break; 1759 /* FALLTHRU */ 1760 1761 case OMP_CLAUSE_PRIVATE: 1762 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var); 1763 if (x) 1764 gimplify_and_add (x, ilist); 1765 /* FALLTHRU */ 1766 1767 do_dtor: 1768 x = lang_hooks.decls.omp_clause_dtor (c, new_var); 1769 if (x) 1770 { 1771 dtor = x; 1772 gimplify_stmt (&dtor); 1773 tsi_link_before (&diter, dtor, TSI_SAME_STMT); 1774 } 1775 break; 1776 1777 case OMP_CLAUSE_FIRSTPRIVATE: 1778 x = build_outer_var_ref (var, ctx); 1779 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x); 1780 gimplify_and_add (x, ilist); 1781 goto do_dtor; 1782 break; 1783 1784 case OMP_CLAUSE_COPYIN: 1785 by_ref = use_pointer_for_field (var, false); 1786 x = build_receiver_ref (var, by_ref, ctx); 1787 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x); 1788 append_to_statement_list (x, ©in_seq); 1789 copyin_by_ref |= by_ref; 1790 break; 1791 1792 case OMP_CLAUSE_REDUCTION: 1793 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1794 { 1795 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist); 1796 OMP_CLAUSE_REDUCTION_INIT (c) = NULL; 1797 } 1798 else 1799 { 1800 x = omp_reduction_init (c, TREE_TYPE (new_var)); 1801 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE); 1802 x = build2 (MODIFY_EXPR, void_type_node, new_var, x); 1803 gimplify_and_add (x, ilist); 1804 } 1805 break; 1806 1807 default: 1808 gcc_unreachable (); 1809 } 1810 } 1811 } 1812 1813 /* The copyin sequence is not to be executed by the main thread, since 1814 that would result in self-copies. Perhaps not visible to scalars, 1815 but it certainly is to C++ operator=. */ 1816 if (copyin_seq) 1817 { 1818 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; 1819 x = build_function_call_expr (x, NULL); 1820 x = build2 (NE_EXPR, boolean_type_node, x, 1821 build_int_cst (TREE_TYPE (x), 0)); 1822 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL); 1823 gimplify_and_add (x, ilist); 1824 } 1825 1826 /* If any copyin variable is passed by reference, we must ensure the 1827 master thread doesn't modify it before it is copied over in all 1828 threads. Similarly for variables in both firstprivate and 1829 lastprivate clauses we need to ensure the lastprivate copying 1830 happens after firstprivate copying in all threads. */ 1831 if (copyin_by_ref || lastprivate_firstprivate) 1832 build_omp_barrier (ilist); 1833} 1834 1835 1836/* Generate code to implement the LASTPRIVATE clauses. This is used for 1837 both parallel and workshare constructs. PREDICATE may be NULL if it's 1838 always true. */ 1839 1840static void 1841lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list, 1842 omp_context *ctx) 1843{ 1844 tree sub_list, x, c; 1845 1846 /* Early exit if there are no lastprivate clauses. */ 1847 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE); 1848 if (clauses == NULL) 1849 { 1850 /* If this was a workshare clause, see if it had been combined 1851 with its parallel. In that case, look for the clauses on the 1852 parallel statement itself. */ 1853 if (is_parallel_ctx (ctx)) 1854 return; 1855 1856 ctx = ctx->outer; 1857 if (ctx == NULL || !is_parallel_ctx (ctx)) 1858 return; 1859 1860 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt), 1861 OMP_CLAUSE_LASTPRIVATE); 1862 if (clauses == NULL) 1863 return; 1864 } 1865 1866 sub_list = alloc_stmt_list (); 1867 1868 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 1869 { 1870 tree var, new_var; 1871 1872 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE) 1873 continue; 1874 1875 var = OMP_CLAUSE_DECL (c); 1876 new_var = lookup_decl (var, ctx); 1877 1878 x = build_outer_var_ref (var, ctx); 1879 if (is_reference (var)) 1880 new_var = build_fold_indirect_ref (new_var); 1881 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var); 1882 append_to_statement_list (x, &sub_list); 1883 } 1884 1885 if (predicate) 1886 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL); 1887 else 1888 x = sub_list; 1889 1890 gimplify_and_add (x, stmt_list); 1891} 1892 1893 1894/* Generate code to implement the REDUCTION clauses. */ 1895 1896static void 1897lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx) 1898{ 1899 tree sub_list = NULL, x, c; 1900 int count = 0; 1901 1902 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC 1903 update in that case, otherwise use a lock. */ 1904 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c)) 1905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) 1906 { 1907 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1908 { 1909 /* Never use OMP_ATOMIC for array reductions. */ 1910 count = -1; 1911 break; 1912 } 1913 count++; 1914 } 1915 1916 if (count == 0) 1917 return; 1918 1919 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 1920 { 1921 tree var, ref, new_var; 1922 enum tree_code code; 1923 1924 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) 1925 continue; 1926 1927 var = OMP_CLAUSE_DECL (c); 1928 new_var = lookup_decl (var, ctx); 1929 if (is_reference (var)) 1930 new_var = build_fold_indirect_ref (new_var); 1931 ref = build_outer_var_ref (var, ctx); 1932 code = OMP_CLAUSE_REDUCTION_CODE (c); 1933 1934 /* reduction(-:var) sums up the partial results, so it acts 1935 identically to reduction(+:var). */ 1936 if (code == MINUS_EXPR) 1937 code = PLUS_EXPR; 1938 1939 if (count == 1) 1940 { 1941 tree addr = build_fold_addr_expr (ref); 1942 1943 addr = save_expr (addr); 1944 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr); 1945 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var); 1946 x = build2 (OMP_ATOMIC, void_type_node, addr, x); 1947 gimplify_and_add (x, stmt_list); 1948 return; 1949 } 1950 1951 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1952 { 1953 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); 1954 1955 if (is_reference (var)) 1956 ref = build_fold_addr_expr (ref); 1957 SET_DECL_VALUE_EXPR (placeholder, ref); 1958 DECL_HAS_VALUE_EXPR_P (placeholder) = 1; 1959 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list); 1960 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL; 1961 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL; 1962 } 1963 else 1964 { 1965 x = build2 (code, TREE_TYPE (ref), ref, new_var); 1966 ref = build_outer_var_ref (var, ctx); 1967 x = build2 (MODIFY_EXPR, void_type_node, ref, x); 1968 append_to_statement_list (x, &sub_list); 1969 } 1970 } 1971 1972 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START]; 1973 x = build_function_call_expr (x, NULL); 1974 gimplify_and_add (x, stmt_list); 1975 1976 gimplify_and_add (sub_list, stmt_list); 1977 1978 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END]; 1979 x = build_function_call_expr (x, NULL); 1980 gimplify_and_add (x, stmt_list); 1981} 1982 1983 1984/* Generate code to implement the COPYPRIVATE clauses. */ 1985 1986static void 1987lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist, 1988 omp_context *ctx) 1989{ 1990 tree c; 1991 1992 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 1993 { 1994 tree var, ref, x; 1995 bool by_ref; 1996 1997 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE) 1998 continue; 1999 2000 var = OMP_CLAUSE_DECL (c); 2001 by_ref = use_pointer_for_field (var, false); 2002 2003 ref = build_sender_ref (var, ctx); 2004 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var; 2005 x = by_ref ? build_fold_addr_expr (x) : x; 2006 x = build2 (MODIFY_EXPR, void_type_node, ref, x); 2007 gimplify_and_add (x, slist); 2008 2009 ref = build_receiver_ref (var, by_ref, ctx); 2010 if (is_reference (var)) 2011 { 2012 ref = build_fold_indirect_ref (ref); 2013 var = build_fold_indirect_ref (var); 2014 } 2015 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref); 2016 gimplify_and_add (x, rlist); 2017 } 2018} 2019 2020 2021/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE, 2022 and REDUCTION from the sender (aka parent) side. */ 2023 2024static void 2025lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx) 2026{ 2027 tree c; 2028 2029 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 2030 { 2031 tree val, ref, x, var; 2032 bool by_ref, do_in = false, do_out = false; 2033 2034 switch (OMP_CLAUSE_CODE (c)) 2035 { 2036 case OMP_CLAUSE_FIRSTPRIVATE: 2037 case OMP_CLAUSE_COPYIN: 2038 case OMP_CLAUSE_LASTPRIVATE: 2039 case OMP_CLAUSE_REDUCTION: 2040 break; 2041 default: 2042 continue; 2043 } 2044 2045 var = val = OMP_CLAUSE_DECL (c); 2046 if (ctx->is_nested) 2047 var = lookup_decl_in_outer_ctx (val, ctx); 2048 2049 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN 2050 && is_global_var (var)) 2051 continue; 2052 if (is_variable_sized (val)) 2053 continue; 2054 by_ref = use_pointer_for_field (val, false); 2055 2056 switch (OMP_CLAUSE_CODE (c)) 2057 { 2058 case OMP_CLAUSE_FIRSTPRIVATE: 2059 case OMP_CLAUSE_COPYIN: 2060 do_in = true; 2061 break; 2062 2063 case OMP_CLAUSE_LASTPRIVATE: 2064 if (by_ref || is_reference (val)) 2065 { 2066 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 2067 continue; 2068 do_in = true; 2069 } 2070 else 2071 do_out = true; 2072 break; 2073 2074 case OMP_CLAUSE_REDUCTION: 2075 do_in = true; 2076 do_out = !(by_ref || is_reference (val)); 2077 break; 2078 2079 default: 2080 gcc_unreachable (); 2081 } 2082 2083 if (do_in) 2084 { 2085 ref = build_sender_ref (val, ctx); 2086 x = by_ref ? build_fold_addr_expr (var) : var; 2087 x = build2 (MODIFY_EXPR, void_type_node, ref, x); 2088 gimplify_and_add (x, ilist); 2089 } 2090 2091 if (do_out) 2092 { 2093 ref = build_sender_ref (val, ctx); 2094 x = build2 (MODIFY_EXPR, void_type_node, var, ref); 2095 gimplify_and_add (x, olist); 2096 } 2097 } 2098} 2099 2100/* Generate code to implement SHARED from the sender (aka parent) side. 2101 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that 2102 got automatically shared. */ 2103 2104static void 2105lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx) 2106{ 2107 tree var, ovar, nvar, f, x; 2108 2109 if (ctx->record_type == NULL) 2110 return; 2111 2112 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f)) 2113 { 2114 ovar = DECL_ABSTRACT_ORIGIN (f); 2115 nvar = maybe_lookup_decl (ovar, ctx); 2116 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar)) 2117 continue; 2118 2119 var = ovar; 2120 2121 /* If CTX is a nested parallel directive. Find the immediately 2122 enclosing parallel or workshare construct that contains a 2123 mapping for OVAR. */ 2124 if (ctx->is_nested) 2125 var = lookup_decl_in_outer_ctx (ovar, ctx); 2126 2127 if (use_pointer_for_field (ovar, true)) 2128 { 2129 x = build_sender_ref (ovar, ctx); 2130 var = build_fold_addr_expr (var); 2131 x = build2 (MODIFY_EXPR, void_type_node, x, var); 2132 gimplify_and_add (x, ilist); 2133 } 2134 else 2135 { 2136 x = build_sender_ref (ovar, ctx); 2137 x = build2 (MODIFY_EXPR, void_type_node, x, var); 2138 gimplify_and_add (x, ilist); 2139 2140 x = build_sender_ref (ovar, ctx); 2141 x = build2 (MODIFY_EXPR, void_type_node, var, x); 2142 gimplify_and_add (x, olist); 2143 } 2144 } 2145} 2146 2147/* Build the function calls to GOMP_parallel_start etc to actually 2148 generate the parallel operation. REGION is the parallel region 2149 being expanded. BB is the block where to insert the code. WS_ARGS 2150 will be set if this is a call to a combined parallel+workshare 2151 construct, it contains the list of additional arguments needed by 2152 the workshare construct. */ 2153 2154static void 2155expand_parallel_call (struct omp_region *region, basic_block bb, 2156 tree entry_stmt, tree ws_args) 2157{ 2158 tree t, args, val, cond, c, list, clauses; 2159 block_stmt_iterator si; 2160 int start_ix; 2161 2162 clauses = OMP_PARALLEL_CLAUSES (entry_stmt); 2163 push_gimplify_context (); 2164 2165 /* Determine what flavor of GOMP_parallel_start we will be 2166 emitting. */ 2167 start_ix = BUILT_IN_GOMP_PARALLEL_START; 2168 if (is_combined_parallel (region)) 2169 { 2170 switch (region->inner->type) 2171 { 2172 case OMP_FOR: 2173 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START 2174 + region->inner->sched_kind; 2175 break; 2176 case OMP_SECTIONS: 2177 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START; 2178 break; 2179 default: 2180 gcc_unreachable (); 2181 } 2182 } 2183 2184 /* By default, the value of NUM_THREADS is zero (selected at run time) 2185 and there is no conditional. */ 2186 cond = NULL_TREE; 2187 val = build_int_cst (unsigned_type_node, 0); 2188 2189 c = find_omp_clause (clauses, OMP_CLAUSE_IF); 2190 if (c) 2191 cond = OMP_CLAUSE_IF_EXPR (c); 2192 2193 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS); 2194 if (c) 2195 val = OMP_CLAUSE_NUM_THREADS_EXPR (c); 2196 2197 /* Ensure 'val' is of the correct type. */ 2198 val = fold_convert (unsigned_type_node, val); 2199 2200 /* If we found the clause 'if (cond)', build either 2201 (cond != 0) or (cond ? val : 1u). */ 2202 if (cond) 2203 { 2204 block_stmt_iterator si; 2205 2206 cond = gimple_boolify (cond); 2207 2208 if (integer_zerop (val)) 2209 val = build2 (EQ_EXPR, unsigned_type_node, cond, 2210 build_int_cst (TREE_TYPE (cond), 0)); 2211 else 2212 { 2213 basic_block cond_bb, then_bb, else_bb; 2214 edge e; 2215 tree t, then_lab, else_lab, tmp; 2216 2217 tmp = create_tmp_var (TREE_TYPE (val), NULL); 2218 e = split_block (bb, NULL); 2219 cond_bb = e->src; 2220 bb = e->dest; 2221 remove_edge (e); 2222 2223 then_bb = create_empty_bb (cond_bb); 2224 else_bb = create_empty_bb (then_bb); 2225 then_lab = create_artificial_label (); 2226 else_lab = create_artificial_label (); 2227 2228 t = build3 (COND_EXPR, void_type_node, 2229 cond, 2230 build_and_jump (&then_lab), 2231 build_and_jump (&else_lab)); 2232 2233 si = bsi_start (cond_bb); 2234 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 2235 2236 si = bsi_start (then_bb); 2237 t = build1 (LABEL_EXPR, void_type_node, then_lab); 2238 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 2239 t = build2 (MODIFY_EXPR, void_type_node, tmp, val); 2240 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 2241 2242 si = bsi_start (else_bb); 2243 t = build1 (LABEL_EXPR, void_type_node, else_lab); 2244 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 2245 t = build2 (MODIFY_EXPR, void_type_node, tmp, 2246 build_int_cst (unsigned_type_node, 1)); 2247 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 2248 2249 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); 2250 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE); 2251 make_edge (then_bb, bb, EDGE_FALLTHRU); 2252 make_edge (else_bb, bb, EDGE_FALLTHRU); 2253 2254 val = tmp; 2255 } 2256 2257 list = NULL_TREE; 2258 val = get_formal_tmp_var (val, &list); 2259 si = bsi_start (bb); 2260 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 2261 } 2262 2263 list = NULL_TREE; 2264 args = tree_cons (NULL, val, NULL); 2265 t = OMP_PARALLEL_DATA_ARG (entry_stmt); 2266 if (t == NULL) 2267 t = null_pointer_node; 2268 else 2269 t = build_fold_addr_expr (t); 2270 args = tree_cons (NULL, t, args); 2271 t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt)); 2272 args = tree_cons (NULL, t, args); 2273 2274 if (ws_args) 2275 args = chainon (args, ws_args); 2276 2277 t = built_in_decls[start_ix]; 2278 t = build_function_call_expr (t, args); 2279 gimplify_and_add (t, &list); 2280 2281 t = OMP_PARALLEL_DATA_ARG (entry_stmt); 2282 if (t == NULL) 2283 t = null_pointer_node; 2284 else 2285 t = build_fold_addr_expr (t); 2286 args = tree_cons (NULL, t, NULL); 2287 t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args); 2288 gimplify_and_add (t, &list); 2289 2290 t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END]; 2291 t = build_function_call_expr (t, NULL); 2292 gimplify_and_add (t, &list); 2293 2294 si = bsi_last (bb); 2295 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 2296 2297 pop_gimplify_context (NULL_TREE); 2298} 2299 2300 2301/* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch 2302 handler. This prevents programs from violating the structured 2303 block semantics with throws. */ 2304 2305static void 2306maybe_catch_exception (tree *stmt_p) 2307{ 2308 tree f, t; 2309 2310 if (!flag_exceptions) 2311 return; 2312 2313 if (lang_protect_cleanup_actions) 2314 t = lang_protect_cleanup_actions (); 2315 else 2316 { 2317 t = built_in_decls[BUILT_IN_TRAP]; 2318 t = build_function_call_expr (t, NULL); 2319 } 2320 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL); 2321 EH_FILTER_MUST_NOT_THROW (f) = 1; 2322 gimplify_and_add (t, &EH_FILTER_FAILURE (f)); 2323 2324 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL); 2325 append_to_statement_list (f, &TREE_OPERAND (t, 1)); 2326 2327 *stmt_p = NULL; 2328 append_to_statement_list (t, stmt_p); 2329} 2330 2331/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */ 2332 2333static tree 2334list2chain (tree list) 2335{ 2336 tree t; 2337 2338 for (t = list; t; t = TREE_CHAIN (t)) 2339 { 2340 tree var = TREE_VALUE (t); 2341 if (TREE_CHAIN (t)) 2342 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t)); 2343 else 2344 TREE_CHAIN (var) = NULL_TREE; 2345 } 2346 2347 return list ? TREE_VALUE (list) : NULL_TREE; 2348} 2349 2350 2351/* Remove barriers in REGION->EXIT's block. Note that this is only 2352 valid for OMP_PARALLEL regions. Since the end of a parallel region 2353 is an implicit barrier, any workshare inside the OMP_PARALLEL that 2354 left a barrier at the end of the OMP_PARALLEL region can now be 2355 removed. */ 2356 2357static void 2358remove_exit_barrier (struct omp_region *region) 2359{ 2360 block_stmt_iterator si; 2361 basic_block exit_bb; 2362 edge_iterator ei; 2363 edge e; 2364 tree t; 2365 2366 exit_bb = region->exit; 2367 2368 /* If the parallel region doesn't return, we don't have REGION->EXIT 2369 block at all. */ 2370 if (! exit_bb) 2371 return; 2372 2373 /* The last insn in the block will be the parallel's OMP_RETURN. The 2374 workshare's OMP_RETURN will be in a preceding block. The kinds of 2375 statements that can appear in between are extremely limited -- no 2376 memory operations at all. Here, we allow nothing at all, so the 2377 only thing we allow to precede this OMP_RETURN is a label. */ 2378 si = bsi_last (exit_bb); 2379 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); 2380 bsi_prev (&si); 2381 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR) 2382 return; 2383 2384 FOR_EACH_EDGE (e, ei, exit_bb->preds) 2385 { 2386 si = bsi_last (e->src); 2387 if (bsi_end_p (si)) 2388 continue; 2389 t = bsi_stmt (si); 2390 if (TREE_CODE (t) == OMP_RETURN) 2391 OMP_RETURN_NOWAIT (t) = 1; 2392 } 2393} 2394 2395static void 2396remove_exit_barriers (struct omp_region *region) 2397{ 2398 if (region->type == OMP_PARALLEL) 2399 remove_exit_barrier (region); 2400 2401 if (region->inner) 2402 { 2403 region = region->inner; 2404 remove_exit_barriers (region); 2405 while (region->next) 2406 { 2407 region = region->next; 2408 remove_exit_barriers (region); 2409 } 2410 } 2411} 2412 2413/* Expand the OpenMP parallel directive starting at REGION. */ 2414 2415static void 2416expand_omp_parallel (struct omp_region *region) 2417{ 2418 basic_block entry_bb, exit_bb, new_bb; 2419 struct function *child_cfun, *saved_cfun; 2420 tree child_fn, block, t, ws_args; 2421 block_stmt_iterator si; 2422 tree entry_stmt; 2423 edge e; 2424 bool do_cleanup_cfg = false; 2425 2426 entry_stmt = last_stmt (region->entry); 2427 child_fn = OMP_PARALLEL_FN (entry_stmt); 2428 child_cfun = DECL_STRUCT_FUNCTION (child_fn); 2429 saved_cfun = cfun; 2430 2431 entry_bb = region->entry; 2432 exit_bb = region->exit; 2433 2434 if (is_combined_parallel (region)) 2435 ws_args = region->ws_args; 2436 else 2437 ws_args = NULL_TREE; 2438 2439 if (child_cfun->cfg) 2440 { 2441 /* Due to inlining, it may happen that we have already outlined 2442 the region, in which case all we need to do is make the 2443 sub-graph unreachable and emit the parallel call. */ 2444 edge entry_succ_e, exit_succ_e; 2445 block_stmt_iterator si; 2446 2447 entry_succ_e = single_succ_edge (entry_bb); 2448 2449 si = bsi_last (entry_bb); 2450 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL); 2451 bsi_remove (&si, true); 2452 2453 new_bb = entry_bb; 2454 remove_edge (entry_succ_e); 2455 if (exit_bb) 2456 { 2457 exit_succ_e = single_succ_edge (exit_bb); 2458 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU); 2459 } 2460 do_cleanup_cfg = true; 2461 } 2462 else 2463 { 2464 /* If the parallel region needs data sent from the parent 2465 function, then the very first statement (except possible 2466 tree profile counter updates) of the parallel body 2467 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since 2468 &.OMP_DATA_O is passed as an argument to the child function, 2469 we need to replace it with the argument as seen by the child 2470 function. 2471 2472 In most cases, this will end up being the identity assignment 2473 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had 2474 a function call that has been inlined, the original PARM_DECL 2475 .OMP_DATA_I may have been converted into a different local 2476 variable. In which case, we need to keep the assignment. */ 2477 if (OMP_PARALLEL_DATA_ARG (entry_stmt)) 2478 { 2479 basic_block entry_succ_bb = single_succ (entry_bb); 2480 block_stmt_iterator si; 2481 2482 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si)) 2483 { 2484 tree stmt, arg; 2485 2486 gcc_assert (!bsi_end_p (si)); 2487 stmt = bsi_stmt (si); 2488 if (TREE_CODE (stmt) != MODIFY_EXPR) 2489 continue; 2490 2491 arg = TREE_OPERAND (stmt, 1); 2492 STRIP_NOPS (arg); 2493 if (TREE_CODE (arg) == ADDR_EXPR 2494 && TREE_OPERAND (arg, 0) 2495 == OMP_PARALLEL_DATA_ARG (entry_stmt)) 2496 { 2497 if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn)) 2498 bsi_remove (&si, true); 2499 else 2500 TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn); 2501 break; 2502 } 2503 } 2504 } 2505 2506 /* Declare local variables needed in CHILD_CFUN. */ 2507 block = DECL_INITIAL (child_fn); 2508 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list); 2509 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list; 2510 2511 /* Reset DECL_CONTEXT on locals and function arguments. */ 2512 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t)) 2513 DECL_CONTEXT (t) = child_fn; 2514 2515 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t)) 2516 DECL_CONTEXT (t) = child_fn; 2517 2518 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the 2519 child function. */ 2520 si = bsi_last (entry_bb); 2521 t = bsi_stmt (si); 2522 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL); 2523 bsi_remove (&si, true); 2524 e = split_block (entry_bb, t); 2525 entry_bb = e->dest; 2526 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 2527 2528 /* Move the parallel region into CHILD_CFUN. We need to reset 2529 dominance information because the expansion of the inner 2530 regions has invalidated it. */ 2531 free_dominance_info (CDI_DOMINATORS); 2532 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb); 2533 if (exit_bb) 2534 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU; 2535 cgraph_add_new_function (child_fn); 2536 2537 /* Convert OMP_RETURN into a RETURN_EXPR. */ 2538 if (exit_bb) 2539 { 2540 si = bsi_last (exit_bb); 2541 gcc_assert (!bsi_end_p (si) 2542 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN); 2543 t = build1 (RETURN_EXPR, void_type_node, NULL); 2544 bsi_insert_after (&si, t, BSI_SAME_STMT); 2545 bsi_remove (&si, true); 2546 } 2547 } 2548 2549 /* Emit a library call to launch the children threads. */ 2550 expand_parallel_call (region, new_bb, entry_stmt, ws_args); 2551 2552 if (do_cleanup_cfg) 2553 { 2554 /* Clean up the unreachable sub-graph we created above. */ 2555 free_dominance_info (CDI_DOMINATORS); 2556 free_dominance_info (CDI_POST_DOMINATORS); 2557 cleanup_tree_cfg (); 2558 } 2559} 2560 2561 2562/* A subroutine of expand_omp_for. Generate code for a parallel 2563 loop with any schedule. Given parameters: 2564 2565 for (V = N1; V cond N2; V += STEP) BODY; 2566 2567 where COND is "<" or ">", we generate pseudocode 2568 2569 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0); 2570 if (more) goto L0; else goto L3; 2571 L0: 2572 V = istart0; 2573 iend = iend0; 2574 L1: 2575 BODY; 2576 V += STEP; 2577 if (V cond iend) goto L1; else goto L2; 2578 L2: 2579 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3; 2580 L3: 2581 2582 If this is a combined omp parallel loop, instead of the call to 2583 GOMP_loop_foo_start, we emit 'goto L3'. */ 2584 2585static void 2586expand_omp_for_generic (struct omp_region *region, 2587 struct omp_for_data *fd, 2588 enum built_in_function start_fn, 2589 enum built_in_function next_fn) 2590{ 2591 tree l0, l1, l2 = NULL, l3 = NULL; 2592 tree type, istart0, iend0, iend; 2593 tree t, args, list; 2594 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb; 2595 basic_block l2_bb = NULL, l3_bb = NULL; 2596 block_stmt_iterator si; 2597 bool in_combined_parallel = is_combined_parallel (region); 2598 2599 type = TREE_TYPE (fd->v); 2600 2601 istart0 = create_tmp_var (long_integer_type_node, ".istart0"); 2602 iend0 = create_tmp_var (long_integer_type_node, ".iend0"); 2603 iend = create_tmp_var (type, NULL); 2604 TREE_ADDRESSABLE (istart0) = 1; 2605 TREE_ADDRESSABLE (iend0) = 1; 2606 2607 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL)); 2608 2609 entry_bb = region->entry; 2610 l0_bb = create_empty_bb (entry_bb); 2611 l1_bb = single_succ (entry_bb); 2612 2613 l0 = tree_block_label (l0_bb); 2614 l1 = tree_block_label (l1_bb); 2615 2616 cont_bb = region->cont; 2617 exit_bb = region->exit; 2618 if (cont_bb) 2619 { 2620 l2_bb = create_empty_bb (cont_bb); 2621 l3_bb = single_succ (cont_bb); 2622 2623 l2 = tree_block_label (l2_bb); 2624 l3 = tree_block_label (l3_bb); 2625 } 2626 2627 si = bsi_last (entry_bb); 2628 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR); 2629 if (!in_combined_parallel) 2630 { 2631 /* If this is not a combined parallel loop, emit a call to 2632 GOMP_loop_foo_start in ENTRY_BB. */ 2633 list = alloc_stmt_list (); 2634 t = build_fold_addr_expr (iend0); 2635 args = tree_cons (NULL, t, NULL); 2636 t = build_fold_addr_expr (istart0); 2637 args = tree_cons (NULL, t, args); 2638 if (fd->chunk_size) 2639 { 2640 t = fold_convert (long_integer_type_node, fd->chunk_size); 2641 args = tree_cons (NULL, t, args); 2642 } 2643 t = fold_convert (long_integer_type_node, fd->step); 2644 args = tree_cons (NULL, t, args); 2645 t = fold_convert (long_integer_type_node, fd->n2); 2646 args = tree_cons (NULL, t, args); 2647 t = fold_convert (long_integer_type_node, fd->n1); 2648 args = tree_cons (NULL, t, args); 2649 t = build_function_call_expr (built_in_decls[start_fn], args); 2650 t = get_formal_tmp_var (t, &list); 2651 if (cont_bb) 2652 { 2653 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0), 2654 build_and_jump (&l3)); 2655 append_to_statement_list (t, &list); 2656 } 2657 bsi_insert_after (&si, list, BSI_SAME_STMT); 2658 } 2659 bsi_remove (&si, true); 2660 2661 /* Iteration setup for sequential loop goes in L0_BB. */ 2662 list = alloc_stmt_list (); 2663 t = fold_convert (type, istart0); 2664 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 2665 gimplify_and_add (t, &list); 2666 2667 t = fold_convert (type, iend0); 2668 t = build2 (MODIFY_EXPR, void_type_node, iend, t); 2669 gimplify_and_add (t, &list); 2670 2671 si = bsi_start (l0_bb); 2672 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 2673 2674 /* Handle the rare case where BODY doesn't ever return. */ 2675 if (cont_bb == NULL) 2676 { 2677 remove_edge (single_succ_edge (entry_bb)); 2678 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU); 2679 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU); 2680 return; 2681 } 2682 2683 /* Code to control the increment and predicate for the sequential 2684 loop goes in the first half of EXIT_BB (we split EXIT_BB so 2685 that we can inherit all the edges going out of the loop 2686 body). */ 2687 list = alloc_stmt_list (); 2688 2689 t = build2 (PLUS_EXPR, type, fd->v, fd->step); 2690 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 2691 gimplify_and_add (t, &list); 2692 2693 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend); 2694 t = get_formal_tmp_var (t, &list); 2695 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1), 2696 build_and_jump (&l2)); 2697 append_to_statement_list (t, &list); 2698 2699 si = bsi_last (cont_bb); 2700 bsi_insert_after (&si, list, BSI_SAME_STMT); 2701 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); 2702 bsi_remove (&si, true); 2703 2704 /* Emit code to get the next parallel iteration in L2_BB. */ 2705 list = alloc_stmt_list (); 2706 2707 t = build_fold_addr_expr (iend0); 2708 args = tree_cons (NULL, t, NULL); 2709 t = build_fold_addr_expr (istart0); 2710 args = tree_cons (NULL, t, args); 2711 t = build_function_call_expr (built_in_decls[next_fn], args); 2712 t = get_formal_tmp_var (t, &list); 2713 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0), 2714 build_and_jump (&l3)); 2715 append_to_statement_list (t, &list); 2716 2717 si = bsi_start (l2_bb); 2718 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 2719 2720 /* Add the loop cleanup function. */ 2721 si = bsi_last (exit_bb); 2722 if (OMP_RETURN_NOWAIT (bsi_stmt (si))) 2723 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT]; 2724 else 2725 t = built_in_decls[BUILT_IN_GOMP_LOOP_END]; 2726 t = build_function_call_expr (t, NULL); 2727 bsi_insert_after (&si, t, BSI_SAME_STMT); 2728 bsi_remove (&si, true); 2729 2730 /* Connect the new blocks. */ 2731 remove_edge (single_succ_edge (entry_bb)); 2732 if (in_combined_parallel) 2733 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU); 2734 else 2735 { 2736 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE); 2737 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE); 2738 } 2739 2740 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU); 2741 2742 remove_edge (single_succ_edge (cont_bb)); 2743 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE); 2744 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE); 2745 2746 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE); 2747 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE); 2748} 2749 2750 2751/* A subroutine of expand_omp_for. Generate code for a parallel 2752 loop with static schedule and no specified chunk size. Given 2753 parameters: 2754 2755 for (V = N1; V cond N2; V += STEP) BODY; 2756 2757 where COND is "<" or ">", we generate pseudocode 2758 2759 if (cond is <) 2760 adj = STEP - 1; 2761 else 2762 adj = STEP + 1; 2763 n = (adj + N2 - N1) / STEP; 2764 q = n / nthreads; 2765 q += (q * nthreads != n); 2766 s0 = q * threadid; 2767 e0 = min(s0 + q, n); 2768 if (s0 >= e0) goto L2; else goto L0; 2769 L0: 2770 V = s0 * STEP + N1; 2771 e = e0 * STEP + N1; 2772 L1: 2773 BODY; 2774 V += STEP; 2775 if (V cond e) goto L1; 2776 L2: 2777*/ 2778 2779static void 2780expand_omp_for_static_nochunk (struct omp_region *region, 2781 struct omp_for_data *fd) 2782{ 2783 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid; 2784 tree type, list; 2785 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb; 2786 basic_block fin_bb; 2787 block_stmt_iterator si; 2788 2789 type = TREE_TYPE (fd->v); 2790 2791 entry_bb = region->entry; 2792 seq_start_bb = create_empty_bb (entry_bb); 2793 body_bb = single_succ (entry_bb); 2794 cont_bb = region->cont; 2795 fin_bb = single_succ (cont_bb); 2796 exit_bb = region->exit; 2797 2798 l0 = tree_block_label (seq_start_bb); 2799 l1 = tree_block_label (body_bb); 2800 l2 = tree_block_label (fin_bb); 2801 2802 /* Iteration space partitioning goes in ENTRY_BB. */ 2803 list = alloc_stmt_list (); 2804 2805 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS]; 2806 t = build_function_call_expr (t, NULL); 2807 t = fold_convert (type, t); 2808 nthreads = get_formal_tmp_var (t, &list); 2809 2810 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; 2811 t = build_function_call_expr (t, NULL); 2812 t = fold_convert (type, t); 2813 threadid = get_formal_tmp_var (t, &list); 2814 2815 fd->n1 = fold_convert (type, fd->n1); 2816 if (!is_gimple_val (fd->n1)) 2817 fd->n1 = get_formal_tmp_var (fd->n1, &list); 2818 2819 fd->n2 = fold_convert (type, fd->n2); 2820 if (!is_gimple_val (fd->n2)) 2821 fd->n2 = get_formal_tmp_var (fd->n2, &list); 2822 2823 fd->step = fold_convert (type, fd->step); 2824 if (!is_gimple_val (fd->step)) 2825 fd->step = get_formal_tmp_var (fd->step, &list); 2826 2827 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1)); 2828 t = fold_build2 (PLUS_EXPR, type, fd->step, t); 2829 t = fold_build2 (PLUS_EXPR, type, t, fd->n2); 2830 t = fold_build2 (MINUS_EXPR, type, t, fd->n1); 2831 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step); 2832 t = fold_convert (type, t); 2833 if (is_gimple_val (t)) 2834 n = t; 2835 else 2836 n = get_formal_tmp_var (t, &list); 2837 2838 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads); 2839 q = get_formal_tmp_var (t, &list); 2840 2841 t = build2 (MULT_EXPR, type, q, nthreads); 2842 t = build2 (NE_EXPR, type, t, n); 2843 t = build2 (PLUS_EXPR, type, q, t); 2844 q = get_formal_tmp_var (t, &list); 2845 2846 t = build2 (MULT_EXPR, type, q, threadid); 2847 s0 = get_formal_tmp_var (t, &list); 2848 2849 t = build2 (PLUS_EXPR, type, s0, q); 2850 t = build2 (MIN_EXPR, type, t, n); 2851 e0 = get_formal_tmp_var (t, &list); 2852 2853 t = build2 (GE_EXPR, boolean_type_node, s0, e0); 2854 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2), 2855 build_and_jump (&l0)); 2856 append_to_statement_list (t, &list); 2857 2858 si = bsi_last (entry_bb); 2859 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR); 2860 bsi_insert_after (&si, list, BSI_SAME_STMT); 2861 bsi_remove (&si, true); 2862 2863 /* Setup code for sequential iteration goes in SEQ_START_BB. */ 2864 list = alloc_stmt_list (); 2865 2866 t = fold_convert (type, s0); 2867 t = build2 (MULT_EXPR, type, t, fd->step); 2868 t = build2 (PLUS_EXPR, type, t, fd->n1); 2869 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 2870 gimplify_and_add (t, &list); 2871 2872 t = fold_convert (type, e0); 2873 t = build2 (MULT_EXPR, type, t, fd->step); 2874 t = build2 (PLUS_EXPR, type, t, fd->n1); 2875 e = get_formal_tmp_var (t, &list); 2876 2877 si = bsi_start (seq_start_bb); 2878 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 2879 2880 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */ 2881 list = alloc_stmt_list (); 2882 2883 t = build2 (PLUS_EXPR, type, fd->v, fd->step); 2884 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 2885 gimplify_and_add (t, &list); 2886 2887 t = build2 (fd->cond_code, boolean_type_node, fd->v, e); 2888 t = get_formal_tmp_var (t, &list); 2889 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1), 2890 build_and_jump (&l2)); 2891 append_to_statement_list (t, &list); 2892 2893 si = bsi_last (cont_bb); 2894 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); 2895 bsi_insert_after (&si, list, BSI_SAME_STMT); 2896 bsi_remove (&si, true); 2897 2898 /* Replace the OMP_RETURN with a barrier, or nothing. */ 2899 si = bsi_last (exit_bb); 2900 if (!OMP_RETURN_NOWAIT (bsi_stmt (si))) 2901 { 2902 list = alloc_stmt_list (); 2903 build_omp_barrier (&list); 2904 bsi_insert_after (&si, list, BSI_SAME_STMT); 2905 } 2906 bsi_remove (&si, true); 2907 2908 /* Connect all the blocks. */ 2909 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU); 2910 2911 remove_edge (single_succ_edge (entry_bb)); 2912 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE); 2913 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE); 2914 2915 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE); 2916 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE; 2917} 2918 2919 2920/* A subroutine of expand_omp_for. Generate code for a parallel 2921 loop with static schedule and a specified chunk size. Given 2922 parameters: 2923 2924 for (V = N1; V cond N2; V += STEP) BODY; 2925 2926 where COND is "<" or ">", we generate pseudocode 2927 2928 if (cond is <) 2929 adj = STEP - 1; 2930 else 2931 adj = STEP + 1; 2932 n = (adj + N2 - N1) / STEP; 2933 trip = 0; 2934 L0: 2935 s0 = (trip * nthreads + threadid) * CHUNK; 2936 e0 = min(s0 + CHUNK, n); 2937 if (s0 < n) goto L1; else goto L4; 2938 L1: 2939 V = s0 * STEP + N1; 2940 e = e0 * STEP + N1; 2941 L2: 2942 BODY; 2943 V += STEP; 2944 if (V cond e) goto L2; else goto L3; 2945 L3: 2946 trip += 1; 2947 goto L0; 2948 L4: 2949*/ 2950 2951static void 2952expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd) 2953{ 2954 tree l0, l1, l2, l3, l4, n, s0, e0, e, t; 2955 tree trip, nthreads, threadid; 2956 tree type; 2957 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb; 2958 basic_block trip_update_bb, cont_bb, fin_bb; 2959 tree list; 2960 block_stmt_iterator si; 2961 2962 type = TREE_TYPE (fd->v); 2963 2964 entry_bb = region->entry; 2965 iter_part_bb = create_empty_bb (entry_bb); 2966 seq_start_bb = create_empty_bb (iter_part_bb); 2967 body_bb = single_succ (entry_bb); 2968 cont_bb = region->cont; 2969 trip_update_bb = create_empty_bb (cont_bb); 2970 fin_bb = single_succ (cont_bb); 2971 exit_bb = region->exit; 2972 2973 l0 = tree_block_label (iter_part_bb); 2974 l1 = tree_block_label (seq_start_bb); 2975 l2 = tree_block_label (body_bb); 2976 l3 = tree_block_label (trip_update_bb); 2977 l4 = tree_block_label (fin_bb); 2978 2979 /* Trip and adjustment setup goes in ENTRY_BB. */ 2980 list = alloc_stmt_list (); 2981 2982 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS]; 2983 t = build_function_call_expr (t, NULL); 2984 t = fold_convert (type, t); 2985 nthreads = get_formal_tmp_var (t, &list); 2986 2987 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; 2988 t = build_function_call_expr (t, NULL); 2989 t = fold_convert (type, t); 2990 threadid = get_formal_tmp_var (t, &list); 2991 2992 fd->n1 = fold_convert (type, fd->n1); 2993 if (!is_gimple_val (fd->n1)) 2994 fd->n1 = get_formal_tmp_var (fd->n1, &list); 2995 2996 fd->n2 = fold_convert (type, fd->n2); 2997 if (!is_gimple_val (fd->n2)) 2998 fd->n2 = get_formal_tmp_var (fd->n2, &list); 2999 3000 fd->step = fold_convert (type, fd->step); 3001 if (!is_gimple_val (fd->step)) 3002 fd->step = get_formal_tmp_var (fd->step, &list); 3003 3004 fd->chunk_size = fold_convert (type, fd->chunk_size); 3005 if (!is_gimple_val (fd->chunk_size)) 3006 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list); 3007 3008 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1)); 3009 t = fold_build2 (PLUS_EXPR, type, fd->step, t); 3010 t = fold_build2 (PLUS_EXPR, type, t, fd->n2); 3011 t = fold_build2 (MINUS_EXPR, type, t, fd->n1); 3012 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step); 3013 t = fold_convert (type, t); 3014 if (is_gimple_val (t)) 3015 n = t; 3016 else 3017 n = get_formal_tmp_var (t, &list); 3018 3019 t = build_int_cst (type, 0); 3020 trip = get_initialized_tmp_var (t, &list, NULL); 3021 3022 si = bsi_last (entry_bb); 3023 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR); 3024 bsi_insert_after (&si, list, BSI_SAME_STMT); 3025 bsi_remove (&si, true); 3026 3027 /* Iteration space partitioning goes in ITER_PART_BB. */ 3028 list = alloc_stmt_list (); 3029 3030 t = build2 (MULT_EXPR, type, trip, nthreads); 3031 t = build2 (PLUS_EXPR, type, t, threadid); 3032 t = build2 (MULT_EXPR, type, t, fd->chunk_size); 3033 s0 = get_formal_tmp_var (t, &list); 3034 3035 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size); 3036 t = build2 (MIN_EXPR, type, t, n); 3037 e0 = get_formal_tmp_var (t, &list); 3038 3039 t = build2 (LT_EXPR, boolean_type_node, s0, n); 3040 t = build3 (COND_EXPR, void_type_node, t, 3041 build_and_jump (&l1), build_and_jump (&l4)); 3042 append_to_statement_list (t, &list); 3043 3044 si = bsi_start (iter_part_bb); 3045 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 3046 3047 /* Setup code for sequential iteration goes in SEQ_START_BB. */ 3048 list = alloc_stmt_list (); 3049 3050 t = fold_convert (type, s0); 3051 t = build2 (MULT_EXPR, type, t, fd->step); 3052 t = build2 (PLUS_EXPR, type, t, fd->n1); 3053 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 3054 gimplify_and_add (t, &list); 3055 3056 t = fold_convert (type, e0); 3057 t = build2 (MULT_EXPR, type, t, fd->step); 3058 t = build2 (PLUS_EXPR, type, t, fd->n1); 3059 e = get_formal_tmp_var (t, &list); 3060 3061 si = bsi_start (seq_start_bb); 3062 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 3063 3064 /* The code controlling the sequential loop goes in CONT_BB, 3065 replacing the OMP_CONTINUE. */ 3066 list = alloc_stmt_list (); 3067 3068 t = build2 (PLUS_EXPR, type, fd->v, fd->step); 3069 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t); 3070 gimplify_and_add (t, &list); 3071 3072 t = build2 (fd->cond_code, boolean_type_node, fd->v, e); 3073 t = get_formal_tmp_var (t, &list); 3074 t = build3 (COND_EXPR, void_type_node, t, 3075 build_and_jump (&l2), build_and_jump (&l3)); 3076 append_to_statement_list (t, &list); 3077 3078 si = bsi_last (cont_bb); 3079 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); 3080 bsi_insert_after (&si, list, BSI_SAME_STMT); 3081 bsi_remove (&si, true); 3082 3083 /* Trip update code goes into TRIP_UPDATE_BB. */ 3084 list = alloc_stmt_list (); 3085 3086 t = build_int_cst (type, 1); 3087 t = build2 (PLUS_EXPR, type, trip, t); 3088 t = build2 (MODIFY_EXPR, void_type_node, trip, t); 3089 gimplify_and_add (t, &list); 3090 3091 si = bsi_start (trip_update_bb); 3092 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING); 3093 3094 /* Replace the OMP_RETURN with a barrier, or nothing. */ 3095 si = bsi_last (exit_bb); 3096 if (!OMP_RETURN_NOWAIT (bsi_stmt (si))) 3097 { 3098 list = alloc_stmt_list (); 3099 build_omp_barrier (&list); 3100 bsi_insert_after (&si, list, BSI_SAME_STMT); 3101 } 3102 bsi_remove (&si, true); 3103 3104 /* Connect the new blocks. */ 3105 remove_edge (single_succ_edge (entry_bb)); 3106 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU); 3107 3108 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE); 3109 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE); 3110 3111 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU); 3112 3113 remove_edge (single_succ_edge (cont_bb)); 3114 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE); 3115 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE); 3116 3117 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU); 3118} 3119 3120 3121/* Expand the OpenMP loop defined by REGION. */ 3122 3123static void 3124expand_omp_for (struct omp_region *region) 3125{ 3126 struct omp_for_data fd; 3127 3128 push_gimplify_context (); 3129 3130 extract_omp_for_data (last_stmt (region->entry), &fd); 3131 region->sched_kind = fd.sched_kind; 3132 3133 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC 3134 && !fd.have_ordered 3135 && region->cont 3136 && region->exit) 3137 { 3138 if (fd.chunk_size == NULL) 3139 expand_omp_for_static_nochunk (region, &fd); 3140 else 3141 expand_omp_for_static_chunk (region, &fd); 3142 } 3143 else 3144 { 3145 int fn_index = fd.sched_kind + fd.have_ordered * 4; 3146 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index; 3147 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index; 3148 expand_omp_for_generic (region, &fd, start_ix, next_ix); 3149 } 3150 3151 pop_gimplify_context (NULL); 3152} 3153 3154 3155/* Expand code for an OpenMP sections directive. In pseudo code, we generate 3156 3157 v = GOMP_sections_start (n); 3158 L0: 3159 switch (v) 3160 { 3161 case 0: 3162 goto L2; 3163 case 1: 3164 section 1; 3165 goto L1; 3166 case 2: 3167 ... 3168 case n: 3169 ... 3170 default: 3171 abort (); 3172 } 3173 L1: 3174 v = GOMP_sections_next (); 3175 goto L0; 3176 L2: 3177 reduction; 3178 3179 If this is a combined parallel sections, replace the call to 3180 GOMP_sections_start with 'goto L1'. */ 3181 3182static void 3183expand_omp_sections (struct omp_region *region) 3184{ 3185 tree label_vec, l0, l1, l2, t, u, v, sections_stmt; 3186 unsigned i, len; 3187 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb; 3188 block_stmt_iterator si; 3189 struct omp_region *inner; 3190 edge e; 3191 3192 entry_bb = region->entry; 3193 l0_bb = create_empty_bb (entry_bb); 3194 l0 = tree_block_label (l0_bb); 3195 3196 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL)); 3197 l1_bb = region->cont; 3198 if (l1_bb) 3199 { 3200 l2_bb = single_succ (l1_bb); 3201 default_bb = create_empty_bb (l1_bb->prev_bb); 3202 3203 l1 = tree_block_label (l1_bb); 3204 } 3205 else 3206 { 3207 l2_bb = create_empty_bb (l0_bb); 3208 default_bb = l2_bb; 3209 3210 l1 = NULL; 3211 } 3212 l2 = tree_block_label (l2_bb); 3213 3214 exit_bb = region->exit; 3215 3216 v = create_tmp_var (unsigned_type_node, ".section"); 3217 3218 /* We will build a switch() with enough cases for all the 3219 OMP_SECTION regions, a '0' case to handle the end of more work 3220 and a default case to abort if something goes wrong. */ 3221 len = EDGE_COUNT (entry_bb->succs); 3222 label_vec = make_tree_vec (len + 2); 3223 3224 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the 3225 OMP_SECTIONS statement. */ 3226 si = bsi_last (entry_bb); 3227 sections_stmt = bsi_stmt (si); 3228 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS); 3229 if (!is_combined_parallel (region)) 3230 { 3231 /* If we are not inside a combined parallel+sections region, 3232 call GOMP_sections_start. */ 3233 t = build_int_cst (unsigned_type_node, len); 3234 t = tree_cons (NULL, t, NULL); 3235 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START]; 3236 t = build_function_call_expr (u, t); 3237 t = build2 (MODIFY_EXPR, void_type_node, v, t); 3238 bsi_insert_after (&si, t, BSI_SAME_STMT); 3239 } 3240 bsi_remove (&si, true); 3241 3242 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */ 3243 si = bsi_start (l0_bb); 3244 3245 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec); 3246 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 3247 3248 t = build3 (CASE_LABEL_EXPR, void_type_node, 3249 build_int_cst (unsigned_type_node, 0), NULL, l2); 3250 TREE_VEC_ELT (label_vec, 0) = t; 3251 make_edge (l0_bb, l2_bb, 0); 3252 3253 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */ 3254 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i) 3255 { 3256 basic_block s_entry_bb, s_exit_bb; 3257 3258 s_entry_bb = inner->entry; 3259 s_exit_bb = inner->exit; 3260 3261 t = tree_block_label (s_entry_bb); 3262 u = build_int_cst (unsigned_type_node, i); 3263 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t); 3264 TREE_VEC_ELT (label_vec, i) = u; 3265 3266 si = bsi_last (s_entry_bb); 3267 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION); 3268 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si))); 3269 bsi_remove (&si, true); 3270 3271 e = single_pred_edge (s_entry_bb); 3272 e->flags = 0; 3273 redirect_edge_pred (e, l0_bb); 3274 3275 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU; 3276 3277 if (s_exit_bb == NULL) 3278 continue; 3279 3280 si = bsi_last (s_exit_bb); 3281 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); 3282 bsi_remove (&si, true); 3283 3284 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU; 3285 } 3286 3287 /* Error handling code goes in DEFAULT_BB. */ 3288 t = tree_block_label (default_bb); 3289 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t); 3290 TREE_VEC_ELT (label_vec, len + 1) = u; 3291 make_edge (l0_bb, default_bb, 0); 3292 3293 si = bsi_start (default_bb); 3294 t = built_in_decls[BUILT_IN_TRAP]; 3295 t = build_function_call_expr (t, NULL); 3296 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING); 3297 3298 /* Code to get the next section goes in L1_BB. */ 3299 if (l1_bb) 3300 { 3301 si = bsi_last (l1_bb); 3302 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE); 3303 3304 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT]; 3305 t = build_function_call_expr (t, NULL); 3306 t = build2 (MODIFY_EXPR, void_type_node, v, t); 3307 bsi_insert_after (&si, t, BSI_SAME_STMT); 3308 bsi_remove (&si, true); 3309 } 3310 3311 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */ 3312 if (exit_bb) 3313 { 3314 si = bsi_last (exit_bb); 3315 if (OMP_RETURN_NOWAIT (bsi_stmt (si))) 3316 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT]; 3317 else 3318 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END]; 3319 t = build_function_call_expr (t, NULL); 3320 bsi_insert_after (&si, t, BSI_SAME_STMT); 3321 bsi_remove (&si, true); 3322 } 3323 3324 /* Connect the new blocks. */ 3325 if (is_combined_parallel (region)) 3326 { 3327 /* If this was a combined parallel+sections region, we did not 3328 emit a GOMP_sections_start in the entry block, so we just 3329 need to jump to L1_BB to get the next section. */ 3330 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU); 3331 } 3332 else 3333 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU); 3334 3335 if (l1_bb) 3336 { 3337 e = single_succ_edge (l1_bb); 3338 redirect_edge_succ (e, l0_bb); 3339 e->flags = EDGE_FALLTHRU; 3340 } 3341} 3342 3343 3344/* Expand code for an OpenMP single directive. We've already expanded 3345 much of the code, here we simply place the GOMP_barrier call. */ 3346 3347static void 3348expand_omp_single (struct omp_region *region) 3349{ 3350 basic_block entry_bb, exit_bb; 3351 block_stmt_iterator si; 3352 bool need_barrier = false; 3353 3354 entry_bb = region->entry; 3355 exit_bb = region->exit; 3356 3357 si = bsi_last (entry_bb); 3358 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot 3359 be removed. We need to ensure that the thread that entered the single 3360 does not exit before the data is copied out by the other threads. */ 3361 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)), 3362 OMP_CLAUSE_COPYPRIVATE)) 3363 need_barrier = true; 3364 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE); 3365 bsi_remove (&si, true); 3366 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 3367 3368 si = bsi_last (exit_bb); 3369 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier) 3370 { 3371 tree t = alloc_stmt_list (); 3372 build_omp_barrier (&t); 3373 bsi_insert_after (&si, t, BSI_SAME_STMT); 3374 } 3375 bsi_remove (&si, true); 3376 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; 3377} 3378 3379 3380/* Generic expansion for OpenMP synchronization directives: master, 3381 ordered and critical. All we need to do here is remove the entry 3382 and exit markers for REGION. */ 3383 3384static void 3385expand_omp_synch (struct omp_region *region) 3386{ 3387 basic_block entry_bb, exit_bb; 3388 block_stmt_iterator si; 3389 3390 entry_bb = region->entry; 3391 exit_bb = region->exit; 3392 3393 si = bsi_last (entry_bb); 3394 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE 3395 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER 3396 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED 3397 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL); 3398 bsi_remove (&si, true); 3399 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 3400 3401 if (exit_bb) 3402 { 3403 si = bsi_last (exit_bb); 3404 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN); 3405 bsi_remove (&si, true); 3406 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; 3407 } 3408} 3409 3410 3411/* Expand the parallel region tree rooted at REGION. Expansion 3412 proceeds in depth-first order. Innermost regions are expanded 3413 first. This way, parallel regions that require a new function to 3414 be created (e.g., OMP_PARALLEL) can be expanded without having any 3415 internal dependencies in their body. */ 3416 3417static void 3418expand_omp (struct omp_region *region) 3419{ 3420 while (region) 3421 { 3422 if (region->inner) 3423 expand_omp (region->inner); 3424 3425 switch (region->type) 3426 { 3427 case OMP_PARALLEL: 3428 expand_omp_parallel (region); 3429 break; 3430 3431 case OMP_FOR: 3432 expand_omp_for (region); 3433 break; 3434 3435 case OMP_SECTIONS: 3436 expand_omp_sections (region); 3437 break; 3438 3439 case OMP_SECTION: 3440 /* Individual omp sections are handled together with their 3441 parent OMP_SECTIONS region. */ 3442 break; 3443 3444 case OMP_SINGLE: 3445 expand_omp_single (region); 3446 break; 3447 3448 case OMP_MASTER: 3449 case OMP_ORDERED: 3450 case OMP_CRITICAL: 3451 expand_omp_synch (region); 3452 break; 3453 3454 default: 3455 gcc_unreachable (); 3456 } 3457 3458 region = region->next; 3459 } 3460} 3461 3462 3463/* Helper for build_omp_regions. Scan the dominator tree starting at 3464 block BB. PARENT is the region that contains BB. */ 3465 3466static void 3467build_omp_regions_1 (basic_block bb, struct omp_region *parent) 3468{ 3469 block_stmt_iterator si; 3470 tree stmt; 3471 basic_block son; 3472 3473 si = bsi_last (bb); 3474 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si))) 3475 { 3476 struct omp_region *region; 3477 enum tree_code code; 3478 3479 stmt = bsi_stmt (si); 3480 code = TREE_CODE (stmt); 3481 3482 if (code == OMP_RETURN) 3483 { 3484 /* STMT is the return point out of region PARENT. Mark it 3485 as the exit point and make PARENT the immediately 3486 enclosing region. */ 3487 gcc_assert (parent); 3488 region = parent; 3489 region->exit = bb; 3490 parent = parent->outer; 3491 3492 /* If REGION is a parallel region, determine whether it is 3493 a combined parallel+workshare region. */ 3494 if (region->type == OMP_PARALLEL) 3495 determine_parallel_type (region); 3496 } 3497 else if (code == OMP_CONTINUE) 3498 { 3499 gcc_assert (parent); 3500 parent->cont = bb; 3501 } 3502 else 3503 { 3504 /* Otherwise, this directive becomes the parent for a new 3505 region. */ 3506 region = new_omp_region (bb, code, parent); 3507 parent = region; 3508 } 3509 } 3510 3511 for (son = first_dom_son (CDI_DOMINATORS, bb); 3512 son; 3513 son = next_dom_son (CDI_DOMINATORS, son)) 3514 build_omp_regions_1 (son, parent); 3515} 3516 3517 3518/* Scan the CFG and build a tree of OMP regions. Return the root of 3519 the OMP region tree. */ 3520 3521static void 3522build_omp_regions (void) 3523{ 3524 gcc_assert (root_omp_region == NULL); 3525 calculate_dominance_info (CDI_DOMINATORS); 3526 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL); 3527} 3528 3529 3530/* Main entry point for expanding OMP-GIMPLE into runtime calls. */ 3531 3532static unsigned int 3533execute_expand_omp (void) 3534{ 3535 build_omp_regions (); 3536 3537 if (!root_omp_region) 3538 return 0; 3539 3540 if (dump_file) 3541 { 3542 fprintf (dump_file, "\nOMP region tree\n\n"); 3543 dump_omp_region (dump_file, root_omp_region, 0); 3544 fprintf (dump_file, "\n"); 3545 } 3546 3547 remove_exit_barriers (root_omp_region); 3548 3549 expand_omp (root_omp_region); 3550 3551 free_dominance_info (CDI_DOMINATORS); 3552 free_dominance_info (CDI_POST_DOMINATORS); 3553 cleanup_tree_cfg (); 3554 3555 free_omp_regions (); 3556 3557 return 0; 3558} 3559 3560static bool 3561gate_expand_omp (void) 3562{ 3563 return flag_openmp != 0 && errorcount == 0; 3564} 3565 3566struct tree_opt_pass pass_expand_omp = 3567{ 3568 "ompexp", /* name */ 3569 gate_expand_omp, /* gate */ 3570 execute_expand_omp, /* execute */ 3571 NULL, /* sub */ 3572 NULL, /* next */ 3573 0, /* static_pass_number */ 3574 0, /* tv_id */ 3575 PROP_gimple_any, /* properties_required */ 3576 PROP_gimple_lomp, /* properties_provided */ 3577 0, /* properties_destroyed */ 3578 0, /* todo_flags_start */ 3579 TODO_dump_func, /* todo_flags_finish */ 3580 0 /* letter */ 3581}; 3582 3583/* Routines to lower OpenMP directives into OMP-GIMPLE. */ 3584 3585/* Lower the OpenMP sections directive in *STMT_P. */ 3586 3587static void 3588lower_omp_sections (tree *stmt_p, omp_context *ctx) 3589{ 3590 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body; 3591 tree t, dlist; 3592 tree_stmt_iterator tsi; 3593 unsigned i, len; 3594 3595 stmt = *stmt_p; 3596 3597 push_gimplify_context (); 3598 3599 dlist = NULL; 3600 ilist = NULL; 3601 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx); 3602 3603 tsi = tsi_start (OMP_SECTIONS_BODY (stmt)); 3604 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi)) 3605 continue; 3606 3607 tsi = tsi_start (OMP_SECTIONS_BODY (stmt)); 3608 body = alloc_stmt_list (); 3609 for (i = 0; i < len; i++, tsi_next (&tsi)) 3610 { 3611 omp_context *sctx; 3612 tree sec_start, sec_end; 3613 3614 sec_start = tsi_stmt (tsi); 3615 sctx = maybe_lookup_ctx (sec_start); 3616 gcc_assert (sctx); 3617 3618 append_to_statement_list (sec_start, &body); 3619 3620 lower_omp (&OMP_SECTION_BODY (sec_start), sctx); 3621 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body); 3622 OMP_SECTION_BODY (sec_start) = NULL; 3623 3624 if (i == len - 1) 3625 { 3626 tree l = alloc_stmt_list (); 3627 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL, 3628 &l, ctx); 3629 append_to_statement_list (l, &body); 3630 OMP_SECTION_LAST (sec_start) = 1; 3631 } 3632 3633 sec_end = make_node (OMP_RETURN); 3634 append_to_statement_list (sec_end, &body); 3635 } 3636 3637 block = make_node (BLOCK); 3638 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block); 3639 3640 olist = NULL_TREE; 3641 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx); 3642 3643 pop_gimplify_context (NULL_TREE); 3644 record_vars_into (ctx->block_vars, ctx->cb.dst_fn); 3645 3646 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); 3647 TREE_SIDE_EFFECTS (new_stmt) = 1; 3648 3649 new_body = alloc_stmt_list (); 3650 append_to_statement_list (ilist, &new_body); 3651 append_to_statement_list (stmt, &new_body); 3652 append_to_statement_list (bind, &new_body); 3653 3654 t = make_node (OMP_CONTINUE); 3655 append_to_statement_list (t, &new_body); 3656 3657 append_to_statement_list (olist, &new_body); 3658 append_to_statement_list (dlist, &new_body); 3659 3660 maybe_catch_exception (&new_body); 3661 3662 t = make_node (OMP_RETURN); 3663 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt), 3664 OMP_CLAUSE_NOWAIT); 3665 append_to_statement_list (t, &new_body); 3666 3667 BIND_EXPR_BODY (new_stmt) = new_body; 3668 OMP_SECTIONS_BODY (stmt) = NULL; 3669 3670 *stmt_p = new_stmt; 3671} 3672 3673 3674/* A subroutine of lower_omp_single. Expand the simple form of 3675 an OMP_SINGLE, without a copyprivate clause: 3676 3677 if (GOMP_single_start ()) 3678 BODY; 3679 [ GOMP_barrier (); ] -> unless 'nowait' is present. 3680 3681 FIXME. It may be better to delay expanding the logic of this until 3682 pass_expand_omp. The expanded logic may make the job more difficult 3683 to a synchronization analysis pass. */ 3684 3685static void 3686lower_omp_single_simple (tree single_stmt, tree *pre_p) 3687{ 3688 tree t; 3689 3690 t = built_in_decls[BUILT_IN_GOMP_SINGLE_START]; 3691 t = build_function_call_expr (t, NULL); 3692 t = build3 (COND_EXPR, void_type_node, t, 3693 OMP_SINGLE_BODY (single_stmt), NULL); 3694 gimplify_and_add (t, pre_p); 3695} 3696 3697 3698/* A subroutine of lower_omp_single. Expand the simple form of 3699 an OMP_SINGLE, with a copyprivate clause: 3700 3701 #pragma omp single copyprivate (a, b, c) 3702 3703 Create a new structure to hold copies of 'a', 'b' and 'c' and emit: 3704 3705 { 3706 if ((copyout_p = GOMP_single_copy_start ()) == NULL) 3707 { 3708 BODY; 3709 copyout.a = a; 3710 copyout.b = b; 3711 copyout.c = c; 3712 GOMP_single_copy_end (©out); 3713 } 3714 else 3715 { 3716 a = copyout_p->a; 3717 b = copyout_p->b; 3718 c = copyout_p->c; 3719 } 3720 GOMP_barrier (); 3721 } 3722 3723 FIXME. It may be better to delay expanding the logic of this until 3724 pass_expand_omp. The expanded logic may make the job more difficult 3725 to a synchronization analysis pass. */ 3726 3727static void 3728lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx) 3729{ 3730 tree ptr_type, t, args, l0, l1, l2, copyin_seq; 3731 3732 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o"); 3733 3734 ptr_type = build_pointer_type (ctx->record_type); 3735 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i"); 3736 3737 l0 = create_artificial_label (); 3738 l1 = create_artificial_label (); 3739 l2 = create_artificial_label (); 3740 3741 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START]; 3742 t = build_function_call_expr (t, NULL); 3743 t = fold_convert (ptr_type, t); 3744 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t); 3745 gimplify_and_add (t, pre_p); 3746 3747 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl, 3748 build_int_cst (ptr_type, 0)); 3749 t = build3 (COND_EXPR, void_type_node, t, 3750 build_and_jump (&l0), build_and_jump (&l1)); 3751 gimplify_and_add (t, pre_p); 3752 3753 t = build1 (LABEL_EXPR, void_type_node, l0); 3754 gimplify_and_add (t, pre_p); 3755 3756 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p); 3757 3758 copyin_seq = NULL; 3759 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p, 3760 ©in_seq, ctx); 3761 3762 t = build_fold_addr_expr (ctx->sender_decl); 3763 args = tree_cons (NULL, t, NULL); 3764 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END]; 3765 t = build_function_call_expr (t, args); 3766 gimplify_and_add (t, pre_p); 3767 3768 t = build_and_jump (&l2); 3769 gimplify_and_add (t, pre_p); 3770 3771 t = build1 (LABEL_EXPR, void_type_node, l1); 3772 gimplify_and_add (t, pre_p); 3773 3774 append_to_statement_list (copyin_seq, pre_p); 3775 3776 t = build1 (LABEL_EXPR, void_type_node, l2); 3777 gimplify_and_add (t, pre_p); 3778} 3779 3780 3781/* Expand code for an OpenMP single directive. */ 3782 3783static void 3784lower_omp_single (tree *stmt_p, omp_context *ctx) 3785{ 3786 tree t, bind, block, single_stmt = *stmt_p, dlist; 3787 3788 push_gimplify_context (); 3789 3790 block = make_node (BLOCK); 3791 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); 3792 TREE_SIDE_EFFECTS (bind) = 1; 3793 3794 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt), 3795 &BIND_EXPR_BODY (bind), &dlist, ctx); 3796 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx); 3797 3798 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind)); 3799 3800 if (ctx->record_type) 3801 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx); 3802 else 3803 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind)); 3804 3805 OMP_SINGLE_BODY (single_stmt) = NULL; 3806 3807 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind)); 3808 3809 maybe_catch_exception (&BIND_EXPR_BODY (bind)); 3810 3811 t = make_node (OMP_RETURN); 3812 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt), 3813 OMP_CLAUSE_NOWAIT); 3814 append_to_statement_list (t, &BIND_EXPR_BODY (bind)); 3815 3816 pop_gimplify_context (bind); 3817 3818 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); 3819 BLOCK_VARS (block) = BIND_EXPR_VARS (bind); 3820} 3821 3822 3823/* Expand code for an OpenMP master directive. */ 3824 3825static void 3826lower_omp_master (tree *stmt_p, omp_context *ctx) 3827{ 3828 tree bind, block, stmt = *stmt_p, lab = NULL, x; 3829 3830 push_gimplify_context (); 3831 3832 block = make_node (BLOCK); 3833 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); 3834 TREE_SIDE_EFFECTS (bind) = 1; 3835 3836 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); 3837 3838 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM]; 3839 x = build_function_call_expr (x, NULL); 3840 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node); 3841 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab)); 3842 gimplify_and_add (x, &BIND_EXPR_BODY (bind)); 3843 3844 lower_omp (&OMP_MASTER_BODY (stmt), ctx); 3845 maybe_catch_exception (&OMP_MASTER_BODY (stmt)); 3846 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind)); 3847 OMP_MASTER_BODY (stmt) = NULL; 3848 3849 x = build1 (LABEL_EXPR, void_type_node, lab); 3850 gimplify_and_add (x, &BIND_EXPR_BODY (bind)); 3851 3852 x = make_node (OMP_RETURN); 3853 OMP_RETURN_NOWAIT (x) = 1; 3854 append_to_statement_list (x, &BIND_EXPR_BODY (bind)); 3855 3856 pop_gimplify_context (bind); 3857 3858 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); 3859 BLOCK_VARS (block) = BIND_EXPR_VARS (bind); 3860} 3861 3862 3863/* Expand code for an OpenMP ordered directive. */ 3864 3865static void 3866lower_omp_ordered (tree *stmt_p, omp_context *ctx) 3867{ 3868 tree bind, block, stmt = *stmt_p, x; 3869 3870 push_gimplify_context (); 3871 3872 block = make_node (BLOCK); 3873 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); 3874 TREE_SIDE_EFFECTS (bind) = 1; 3875 3876 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); 3877 3878 x = built_in_decls[BUILT_IN_GOMP_ORDERED_START]; 3879 x = build_function_call_expr (x, NULL); 3880 gimplify_and_add (x, &BIND_EXPR_BODY (bind)); 3881 3882 lower_omp (&OMP_ORDERED_BODY (stmt), ctx); 3883 maybe_catch_exception (&OMP_ORDERED_BODY (stmt)); 3884 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind)); 3885 OMP_ORDERED_BODY (stmt) = NULL; 3886 3887 x = built_in_decls[BUILT_IN_GOMP_ORDERED_END]; 3888 x = build_function_call_expr (x, NULL); 3889 gimplify_and_add (x, &BIND_EXPR_BODY (bind)); 3890 3891 x = make_node (OMP_RETURN); 3892 OMP_RETURN_NOWAIT (x) = 1; 3893 append_to_statement_list (x, &BIND_EXPR_BODY (bind)); 3894 3895 pop_gimplify_context (bind); 3896 3897 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); 3898 BLOCK_VARS (block) = BIND_EXPR_VARS (bind); 3899} 3900 3901 3902/* Gimplify an OMP_CRITICAL statement. This is a relatively simple 3903 substitution of a couple of function calls. But in the NAMED case, 3904 requires that languages coordinate a symbol name. It is therefore 3905 best put here in common code. */ 3906 3907static GTY((param1_is (tree), param2_is (tree))) 3908 splay_tree critical_name_mutexes; 3909 3910static void 3911lower_omp_critical (tree *stmt_p, omp_context *ctx) 3912{ 3913 tree bind, block, stmt = *stmt_p; 3914 tree t, lock, unlock, name; 3915 3916 name = OMP_CRITICAL_NAME (stmt); 3917 if (name) 3918 { 3919 tree decl, args; 3920 splay_tree_node n; 3921 3922 if (!critical_name_mutexes) 3923 critical_name_mutexes 3924 = splay_tree_new_ggc (splay_tree_compare_pointers); 3925 3926 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name); 3927 if (n == NULL) 3928 { 3929 char *new_str; 3930 3931 decl = create_tmp_var_raw (ptr_type_node, NULL); 3932 3933 new_str = ACONCAT ((".gomp_critical_user_", 3934 IDENTIFIER_POINTER (name), NULL)); 3935 DECL_NAME (decl) = get_identifier (new_str); 3936 TREE_PUBLIC (decl) = 1; 3937 TREE_STATIC (decl) = 1; 3938 DECL_COMMON (decl) = 1; 3939 DECL_ARTIFICIAL (decl) = 1; 3940 DECL_IGNORED_P (decl) = 1; 3941 cgraph_varpool_finalize_decl (decl); 3942 3943 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name, 3944 (splay_tree_value) decl); 3945 } 3946 else 3947 decl = (tree) n->value; 3948 3949 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL); 3950 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START]; 3951 lock = build_function_call_expr (lock, args); 3952 3953 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL); 3954 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END]; 3955 unlock = build_function_call_expr (unlock, args); 3956 } 3957 else 3958 { 3959 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START]; 3960 lock = build_function_call_expr (lock, NULL); 3961 3962 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END]; 3963 unlock = build_function_call_expr (unlock, NULL); 3964 } 3965 3966 push_gimplify_context (); 3967 3968 block = make_node (BLOCK); 3969 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block); 3970 TREE_SIDE_EFFECTS (bind) = 1; 3971 3972 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); 3973 3974 gimplify_and_add (lock, &BIND_EXPR_BODY (bind)); 3975 3976 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx); 3977 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt)); 3978 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind)); 3979 OMP_CRITICAL_BODY (stmt) = NULL; 3980 3981 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind)); 3982 3983 t = make_node (OMP_RETURN); 3984 OMP_RETURN_NOWAIT (t) = 1; 3985 append_to_statement_list (t, &BIND_EXPR_BODY (bind)); 3986 3987 pop_gimplify_context (bind); 3988 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars); 3989 BLOCK_VARS (block) = BIND_EXPR_VARS (bind); 3990} 3991 3992 3993/* A subroutine of lower_omp_for. Generate code to emit the predicate 3994 for a lastprivate clause. Given a loop control predicate of (V 3995 cond N2), we gate the clause on (!(V cond N2)). The lowered form 3996 is appended to *DLIST, iterator initialization is appended to 3997 *BODY_P. */ 3998 3999static void 4000lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p, 4001 tree *dlist, struct omp_context *ctx) 4002{ 4003 tree clauses, cond, stmts, vinit, t; 4004 enum tree_code cond_code; 4005 4006 cond_code = fd->cond_code; 4007 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR; 4008 4009 /* When possible, use a strict equality expression. This can let VRP 4010 type optimizations deduce the value and remove a copy. */ 4011 if (host_integerp (fd->step, 0)) 4012 { 4013 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step); 4014 if (step == 1 || step == -1) 4015 cond_code = EQ_EXPR; 4016 } 4017 4018 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2); 4019 4020 clauses = OMP_FOR_CLAUSES (fd->for_stmt); 4021 stmts = NULL; 4022 lower_lastprivate_clauses (clauses, cond, &stmts, ctx); 4023 if (stmts != NULL) 4024 { 4025 append_to_statement_list (stmts, dlist); 4026 4027 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */ 4028 vinit = fd->n1; 4029 if (cond_code == EQ_EXPR 4030 && host_integerp (fd->n2, 0) 4031 && ! integer_zerop (fd->n2)) 4032 vinit = build_int_cst (TREE_TYPE (fd->v), 0); 4033 4034 /* Initialize the iterator variable, so that threads that don't execute 4035 any iterations don't execute the lastprivate clauses by accident. */ 4036 t = build2 (MODIFY_EXPR, void_type_node, fd->v, vinit); 4037 gimplify_and_add (t, body_p); 4038 } 4039} 4040 4041 4042/* Lower code for an OpenMP loop directive. */ 4043 4044static void 4045lower_omp_for (tree *stmt_p, omp_context *ctx) 4046{ 4047 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p; 4048 struct omp_for_data fd; 4049 4050 stmt = *stmt_p; 4051 4052 push_gimplify_context (); 4053 4054 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx); 4055 lower_omp (&OMP_FOR_BODY (stmt), ctx); 4056 4057 /* Move declaration of temporaries in the loop body before we make 4058 it go away. */ 4059 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR) 4060 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn); 4061 4062 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); 4063 TREE_SIDE_EFFECTS (new_stmt) = 1; 4064 body_p = &BIND_EXPR_BODY (new_stmt); 4065 4066 /* The pre-body and input clauses go before the lowered OMP_FOR. */ 4067 ilist = NULL; 4068 dlist = NULL; 4069 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p); 4070 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx); 4071 4072 /* Lower the header expressions. At this point, we can assume that 4073 the header is of the form: 4074 4075 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3) 4076 4077 We just need to make sure that VAL1, VAL2 and VAL3 are lowered 4078 using the .omp_data_s mapping, if needed. */ 4079 rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1); 4080 if (!is_gimple_min_invariant (*rhs_p)) 4081 *rhs_p = get_formal_tmp_var (*rhs_p, body_p); 4082 4083 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1); 4084 if (!is_gimple_min_invariant (*rhs_p)) 4085 *rhs_p = get_formal_tmp_var (*rhs_p, body_p); 4086 4087 rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1); 4088 if (!is_gimple_min_invariant (*rhs_p)) 4089 *rhs_p = get_formal_tmp_var (*rhs_p, body_p); 4090 4091 /* Once lowered, extract the bounds and clauses. */ 4092 extract_omp_for_data (stmt, &fd); 4093 4094 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx); 4095 4096 append_to_statement_list (stmt, body_p); 4097 4098 append_to_statement_list (OMP_FOR_BODY (stmt), body_p); 4099 4100 t = make_node (OMP_CONTINUE); 4101 append_to_statement_list (t, body_p); 4102 4103 /* After the loop, add exit clauses. */ 4104 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx); 4105 append_to_statement_list (dlist, body_p); 4106 4107 maybe_catch_exception (body_p); 4108 4109 /* Region exit marker goes at the end of the loop body. */ 4110 t = make_node (OMP_RETURN); 4111 OMP_RETURN_NOWAIT (t) = fd.have_nowait; 4112 append_to_statement_list (t, body_p); 4113 4114 pop_gimplify_context (NULL_TREE); 4115 record_vars_into (ctx->block_vars, ctx->cb.dst_fn); 4116 4117 OMP_FOR_BODY (stmt) = NULL_TREE; 4118 OMP_FOR_PRE_BODY (stmt) = NULL_TREE; 4119 *stmt_p = new_stmt; 4120} 4121 4122 4123/* Lower the OpenMP parallel directive in *STMT_P. CTX holds context 4124 information for the directive. */ 4125 4126static void 4127lower_omp_parallel (tree *stmt_p, omp_context *ctx) 4128{ 4129 tree clauses, par_bind, par_body, new_body, bind; 4130 tree olist, ilist, par_olist, par_ilist; 4131 tree stmt, child_fn, t; 4132 4133 stmt = *stmt_p; 4134 4135 clauses = OMP_PARALLEL_CLAUSES (stmt); 4136 par_bind = OMP_PARALLEL_BODY (stmt); 4137 par_body = BIND_EXPR_BODY (par_bind); 4138 child_fn = ctx->cb.dst_fn; 4139 4140 push_gimplify_context (); 4141 4142 par_olist = NULL_TREE; 4143 par_ilist = NULL_TREE; 4144 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx); 4145 lower_omp (&par_body, ctx); 4146 lower_reduction_clauses (clauses, &par_olist, ctx); 4147 4148 /* Declare all the variables created by mapping and the variables 4149 declared in the scope of the parallel body. */ 4150 record_vars_into (ctx->block_vars, child_fn); 4151 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn); 4152 4153 if (ctx->record_type) 4154 { 4155 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o"); 4156 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl; 4157 } 4158 4159 olist = NULL_TREE; 4160 ilist = NULL_TREE; 4161 lower_send_clauses (clauses, &ilist, &olist, ctx); 4162 lower_send_shared_vars (&ilist, &olist, ctx); 4163 4164 /* Once all the expansions are done, sequence all the different 4165 fragments inside OMP_PARALLEL_BODY. */ 4166 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); 4167 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind)); 4168 4169 new_body = alloc_stmt_list (); 4170 4171 if (ctx->record_type) 4172 { 4173 t = build_fold_addr_expr (ctx->sender_decl); 4174 /* fixup_child_record_type might have changed receiver_decl's type. */ 4175 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t); 4176 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t); 4177 append_to_statement_list (t, &new_body); 4178 } 4179 4180 append_to_statement_list (par_ilist, &new_body); 4181 append_to_statement_list (par_body, &new_body); 4182 append_to_statement_list (par_olist, &new_body); 4183 maybe_catch_exception (&new_body); 4184 t = make_node (OMP_RETURN); 4185 append_to_statement_list (t, &new_body); 4186 OMP_PARALLEL_BODY (stmt) = new_body; 4187 4188 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind)); 4189 append_to_statement_list (olist, &BIND_EXPR_BODY (bind)); 4190 4191 *stmt_p = bind; 4192 4193 pop_gimplify_context (NULL_TREE); 4194} 4195 4196 4197/* Pass *TP back through the gimplifier within the context determined by WI. 4198 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the 4199 flags on ADDR_EXPR. */ 4200 4201static void 4202lower_regimplify (tree *tp, struct walk_stmt_info *wi) 4203{ 4204 enum gimplify_status gs; 4205 tree pre = NULL; 4206 4207 if (wi->is_lhs) 4208 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue); 4209 else if (wi->val_only) 4210 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue); 4211 else 4212 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue); 4213 gcc_assert (gs == GS_ALL_DONE); 4214 4215 if (pre) 4216 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT); 4217} 4218 4219/* Copy EXP into a temporary. Insert the initialization statement before TSI. */ 4220 4221static tree 4222init_tmp_var (tree exp, tree_stmt_iterator *tsi) 4223{ 4224 tree t, stmt; 4225 4226 t = create_tmp_var (TREE_TYPE (exp), NULL); 4227 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) 4228 DECL_COMPLEX_GIMPLE_REG_P (t) = 1; 4229 stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp); 4230 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi))); 4231 tsi_link_before (tsi, stmt, TSI_SAME_STMT); 4232 4233 return t; 4234} 4235 4236/* Similarly, but copy from the temporary and insert the statement 4237 after the iterator. */ 4238 4239static tree 4240save_tmp_var (tree exp, tree_stmt_iterator *tsi) 4241{ 4242 tree t, stmt; 4243 4244 t = create_tmp_var (TREE_TYPE (exp), NULL); 4245 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE) 4246 DECL_COMPLEX_GIMPLE_REG_P (t) = 1; 4247 stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t); 4248 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi))); 4249 tsi_link_after (tsi, stmt, TSI_SAME_STMT); 4250 4251 return t; 4252} 4253 4254/* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */ 4255 4256static tree 4257lower_omp_1 (tree *tp, int *walk_subtrees, void *data) 4258{ 4259 struct walk_stmt_info *wi = data; 4260 omp_context *ctx = wi->info; 4261 tree t = *tp; 4262 4263 /* If we have issued syntax errors, avoid doing any heavy lifting. 4264 Just replace the OpenMP directives with a NOP to avoid 4265 confusing RTL expansion. */ 4266 if (errorcount && OMP_DIRECTIVE_P (*tp)) 4267 { 4268 *tp = build_empty_stmt (); 4269 return NULL_TREE; 4270 } 4271 4272 *walk_subtrees = 0; 4273 switch (TREE_CODE (*tp)) 4274 { 4275 case OMP_PARALLEL: 4276 ctx = maybe_lookup_ctx (t); 4277 lower_omp_parallel (tp, ctx); 4278 break; 4279 4280 case OMP_FOR: 4281 ctx = maybe_lookup_ctx (t); 4282 gcc_assert (ctx); 4283 lower_omp_for (tp, ctx); 4284 break; 4285 4286 case OMP_SECTIONS: 4287 ctx = maybe_lookup_ctx (t); 4288 gcc_assert (ctx); 4289 lower_omp_sections (tp, ctx); 4290 break; 4291 4292 case OMP_SINGLE: 4293 ctx = maybe_lookup_ctx (t); 4294 gcc_assert (ctx); 4295 lower_omp_single (tp, ctx); 4296 break; 4297 4298 case OMP_MASTER: 4299 ctx = maybe_lookup_ctx (t); 4300 gcc_assert (ctx); 4301 lower_omp_master (tp, ctx); 4302 break; 4303 4304 case OMP_ORDERED: 4305 ctx = maybe_lookup_ctx (t); 4306 gcc_assert (ctx); 4307 lower_omp_ordered (tp, ctx); 4308 break; 4309 4310 case OMP_CRITICAL: 4311 ctx = maybe_lookup_ctx (t); 4312 gcc_assert (ctx); 4313 lower_omp_critical (tp, ctx); 4314 break; 4315 4316 case VAR_DECL: 4317 if (ctx && DECL_HAS_VALUE_EXPR_P (t)) 4318 { 4319 lower_regimplify (&t, wi); 4320 if (wi->val_only) 4321 { 4322 if (wi->is_lhs) 4323 t = save_tmp_var (t, &wi->tsi); 4324 else 4325 t = init_tmp_var (t, &wi->tsi); 4326 } 4327 *tp = t; 4328 } 4329 break; 4330 4331 case ADDR_EXPR: 4332 if (ctx) 4333 lower_regimplify (tp, wi); 4334 break; 4335 4336 case ARRAY_REF: 4337 case ARRAY_RANGE_REF: 4338 case REALPART_EXPR: 4339 case IMAGPART_EXPR: 4340 case COMPONENT_REF: 4341 case VIEW_CONVERT_EXPR: 4342 if (ctx) 4343 lower_regimplify (tp, wi); 4344 break; 4345 4346 case INDIRECT_REF: 4347 if (ctx) 4348 { 4349 wi->is_lhs = false; 4350 wi->val_only = true; 4351 lower_regimplify (&TREE_OPERAND (t, 0), wi); 4352 } 4353 break; 4354 4355 default: 4356 if (!TYPE_P (t) && !DECL_P (t)) 4357 *walk_subtrees = 1; 4358 break; 4359 } 4360 4361 return NULL_TREE; 4362} 4363 4364static void 4365lower_omp (tree *stmt_p, omp_context *ctx) 4366{ 4367 struct walk_stmt_info wi; 4368 4369 memset (&wi, 0, sizeof (wi)); 4370 wi.callback = lower_omp_1; 4371 wi.info = ctx; 4372 wi.val_only = true; 4373 wi.want_locations = true; 4374 4375 walk_stmts (&wi, stmt_p); 4376} 4377 4378/* Main entry point. */ 4379 4380static unsigned int 4381execute_lower_omp (void) 4382{ 4383 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0, 4384 delete_omp_context); 4385 4386 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL); 4387 gcc_assert (parallel_nesting_level == 0); 4388 4389 if (all_contexts->root) 4390 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL); 4391 4392 if (all_contexts) 4393 { 4394 splay_tree_delete (all_contexts); 4395 all_contexts = NULL; 4396 } 4397 return 0; 4398} 4399 4400static bool 4401gate_lower_omp (void) 4402{ 4403 return flag_openmp != 0; 4404} 4405 4406struct tree_opt_pass pass_lower_omp = 4407{ 4408 "omplower", /* name */ 4409 gate_lower_omp, /* gate */ 4410 execute_lower_omp, /* execute */ 4411 NULL, /* sub */ 4412 NULL, /* next */ 4413 0, /* static_pass_number */ 4414 0, /* tv_id */ 4415 PROP_gimple_any, /* properties_required */ 4416 PROP_gimple_lomp, /* properties_provided */ 4417 0, /* properties_destroyed */ 4418 0, /* todo_flags_start */ 4419 TODO_dump_func, /* todo_flags_finish */ 4420 0 /* letter */ 4421}; 4422 4423/* The following is a utility to diagnose OpenMP structured block violations. 4424 It is not part of the "omplower" pass, as that's invoked too late. It 4425 should be invoked by the respective front ends after gimplification. */ 4426 4427static splay_tree all_labels; 4428 4429/* Check for mismatched contexts and generate an error if needed. Return 4430 true if an error is detected. */ 4431 4432static bool 4433diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx) 4434{ 4435 bool exit_p = true; 4436 4437 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx) 4438 return false; 4439 4440 /* Try to avoid confusing the user by producing and error message 4441 with correct "exit" or "enter" verbage. We prefer "exit" 4442 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */ 4443 if (branch_ctx == NULL) 4444 exit_p = false; 4445 else 4446 { 4447 while (label_ctx) 4448 { 4449 if (TREE_VALUE (label_ctx) == branch_ctx) 4450 { 4451 exit_p = false; 4452 break; 4453 } 4454 label_ctx = TREE_CHAIN (label_ctx); 4455 } 4456 } 4457 4458 if (exit_p) 4459 error ("invalid exit from OpenMP structured block"); 4460 else 4461 error ("invalid entry to OpenMP structured block"); 4462 4463 *stmt_p = build_empty_stmt (); 4464 return true; 4465} 4466 4467/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record 4468 where in the tree each label is found. */ 4469 4470static tree 4471diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data) 4472{ 4473 struct walk_stmt_info *wi = data; 4474 tree context = (tree) wi->info; 4475 tree inner_context; 4476 tree t = *tp; 4477 4478 *walk_subtrees = 0; 4479 switch (TREE_CODE (t)) 4480 { 4481 case OMP_PARALLEL: 4482 case OMP_SECTIONS: 4483 case OMP_SINGLE: 4484 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL); 4485 /* FALLTHRU */ 4486 case OMP_SECTION: 4487 case OMP_MASTER: 4488 case OMP_ORDERED: 4489 case OMP_CRITICAL: 4490 /* The minimal context here is just a tree of statements. */ 4491 inner_context = tree_cons (NULL, t, context); 4492 wi->info = inner_context; 4493 walk_stmts (wi, &OMP_BODY (t)); 4494 wi->info = context; 4495 break; 4496 4497 case OMP_FOR: 4498 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL); 4499 inner_context = tree_cons (NULL, t, context); 4500 wi->info = inner_context; 4501 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL); 4502 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL); 4503 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL); 4504 walk_stmts (wi, &OMP_FOR_PRE_BODY (t)); 4505 walk_stmts (wi, &OMP_FOR_BODY (t)); 4506 wi->info = context; 4507 break; 4508 4509 case LABEL_EXPR: 4510 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t), 4511 (splay_tree_value) context); 4512 break; 4513 4514 default: 4515 break; 4516 } 4517 4518 return NULL_TREE; 4519} 4520 4521/* Pass 2: Check each branch and see if its context differs from that of 4522 the destination label's context. */ 4523 4524static tree 4525diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data) 4526{ 4527 struct walk_stmt_info *wi = data; 4528 tree context = (tree) wi->info; 4529 splay_tree_node n; 4530 tree t = *tp; 4531 4532 *walk_subtrees = 0; 4533 switch (TREE_CODE (t)) 4534 { 4535 case OMP_PARALLEL: 4536 case OMP_SECTIONS: 4537 case OMP_SINGLE: 4538 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL); 4539 /* FALLTHRU */ 4540 case OMP_SECTION: 4541 case OMP_MASTER: 4542 case OMP_ORDERED: 4543 case OMP_CRITICAL: 4544 wi->info = t; 4545 walk_stmts (wi, &OMP_BODY (t)); 4546 wi->info = context; 4547 break; 4548 4549 case OMP_FOR: 4550 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL); 4551 wi->info = t; 4552 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL); 4553 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL); 4554 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL); 4555 walk_stmts (wi, &OMP_FOR_PRE_BODY (t)); 4556 walk_stmts (wi, &OMP_FOR_BODY (t)); 4557 wi->info = context; 4558 break; 4559 4560 case GOTO_EXPR: 4561 { 4562 tree lab = GOTO_DESTINATION (t); 4563 if (TREE_CODE (lab) != LABEL_DECL) 4564 break; 4565 4566 n = splay_tree_lookup (all_labels, (splay_tree_key) lab); 4567 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE); 4568 } 4569 break; 4570 4571 case SWITCH_EXPR: 4572 { 4573 tree vec = SWITCH_LABELS (t); 4574 int i, len = TREE_VEC_LENGTH (vec); 4575 for (i = 0; i < len; ++i) 4576 { 4577 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i)); 4578 n = splay_tree_lookup (all_labels, (splay_tree_key) lab); 4579 if (diagnose_sb_0 (tp, context, (tree) n->value)) 4580 break; 4581 } 4582 } 4583 break; 4584 4585 case RETURN_EXPR: 4586 diagnose_sb_0 (tp, context, NULL_TREE); 4587 break; 4588 4589 default: 4590 break; 4591 } 4592 4593 return NULL_TREE; 4594} 4595 4596void 4597diagnose_omp_structured_block_errors (tree fndecl) 4598{ 4599 tree save_current = current_function_decl; 4600 struct walk_stmt_info wi; 4601 4602 current_function_decl = fndecl; 4603 4604 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0); 4605 4606 memset (&wi, 0, sizeof (wi)); 4607 wi.callback = diagnose_sb_1; 4608 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl)); 4609 4610 memset (&wi, 0, sizeof (wi)); 4611 wi.callback = diagnose_sb_2; 4612 wi.want_locations = true; 4613 wi.want_return_expr = true; 4614 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl)); 4615 4616 splay_tree_delete (all_labels); 4617 all_labels = NULL; 4618 4619 current_function_decl = save_current; 4620} 4621 4622#include "gt-omp-low.h" 4623