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, 2007, 2008, 2009, 2010 7 Free Software Foundation, Inc. 8 9This file is part of GCC. 10 11GCC is free software; you can redistribute it and/or modify it under 12the terms of the GNU General Public License as published by the Free 13Software Foundation; either version 3, or (at your option) any later 14version. 15 16GCC is distributed in the hope that it will be useful, but WITHOUT ANY 17WARRANTY; without even the implied warranty of MERCHANTABILITY or 18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19for more details. 20 21You should have received a copy of the GNU General Public License 22along with GCC; see the file COPYING3. If not see 23<http://www.gnu.org/licenses/>. */ 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 "gimple.h" 32#include "tree-iterator.h" 33#include "tree-inline.h" 34#include "langhooks.h" 35#include "diagnostic.h" 36#include "tree-flow.h" 37#include "timevar.h" 38#include "flags.h" 39#include "function.h" 40#include "expr.h" 41#include "toplev.h" 42#include "tree-pass.h" 43#include "ggc.h" 44#include "except.h" 45#include "splay-tree.h" 46#include "optabs.h" 47#include "cfgloop.h" 48 49 50/* Lowering of OpenMP parallel and workshare constructs proceeds in two 51 phases. The first phase scans the function looking for OMP statements 52 and then for variables that must be replaced to satisfy data sharing 53 clauses. The second phase expands code for the constructs, as well as 54 re-gimplifying things when variables have been replaced with complex 55 expressions. 56 57 Final code generation is done by pass_expand_omp. The flowgraph is 58 scanned for parallel regions which are then moved to a new 59 function, to be invoked by the thread library. */ 60 61/* Context structure. Used to store information about each parallel 62 directive in the code. */ 63 64typedef struct omp_context 65{ 66 /* This field must be at the beginning, as we do "inheritance": Some 67 callback functions for tree-inline.c (e.g., omp_copy_decl) 68 receive a copy_body_data pointer that is up-casted to an 69 omp_context pointer. */ 70 copy_body_data cb; 71 72 /* The tree of contexts corresponding to the encountered constructs. */ 73 struct omp_context *outer; 74 gimple stmt; 75 76 /* Map variables to fields in a structure that allows communication 77 between sending and receiving threads. */ 78 splay_tree field_map; 79 tree record_type; 80 tree sender_decl; 81 tree receiver_decl; 82 83 /* These are used just by task contexts, if task firstprivate fn is 84 needed. srecord_type is used to communicate from the thread 85 that encountered the task construct to task firstprivate fn, 86 record_type is allocated by GOMP_task, initialized by task firstprivate 87 fn and passed to the task body fn. */ 88 splay_tree sfield_map; 89 tree srecord_type; 90 91 /* A chain of variables to add to the top-level block surrounding the 92 construct. In the case of a parallel, this is in the child function. */ 93 tree block_vars; 94 95 /* What to do with variables with implicitly determined sharing 96 attributes. */ 97 enum omp_clause_default_kind default_kind; 98 99 /* Nesting depth of this context. Used to beautify error messages re 100 invalid gotos. The outermost ctx is depth 1, with depth 0 being 101 reserved for the main body of the function. */ 102 int depth; 103 104 /* True if this parallel directive is nested within another. */ 105 bool is_nested; 106} omp_context; 107 108 109struct omp_for_data_loop 110{ 111 tree v, n1, n2, step; 112 enum tree_code cond_code; 113}; 114 115/* A structure describing the main elements of a parallel loop. */ 116 117struct omp_for_data 118{ 119 struct omp_for_data_loop loop; 120 tree chunk_size; 121 gimple for_stmt; 122 tree pre, iter_type; 123 int collapse; 124 bool have_nowait, have_ordered; 125 enum omp_clause_schedule_kind sched_kind; 126 struct omp_for_data_loop *loops; 127}; 128 129 130static splay_tree all_contexts; 131static int taskreg_nesting_level; 132struct omp_region *root_omp_region; 133static bitmap task_shared_vars; 134 135static void scan_omp (gimple_seq, omp_context *); 136static tree scan_omp_1_op (tree *, int *, void *); 137 138#define WALK_SUBSTMTS \ 139 case GIMPLE_BIND: \ 140 case GIMPLE_TRY: \ 141 case GIMPLE_CATCH: \ 142 case GIMPLE_EH_FILTER: \ 143 /* The sub-statements for these should be walked. */ \ 144 *handled_ops_p = false; \ 145 break; 146 147/* Convenience function for calling scan_omp_1_op on tree operands. */ 148 149static inline tree 150scan_omp_op (tree *tp, omp_context *ctx) 151{ 152 struct walk_stmt_info wi; 153 154 memset (&wi, 0, sizeof (wi)); 155 wi.info = ctx; 156 wi.want_locations = true; 157 158 return walk_tree (tp, scan_omp_1_op, &wi, NULL); 159} 160 161static void lower_omp (gimple_seq, omp_context *); 162static tree lookup_decl_in_outer_ctx (tree, omp_context *); 163static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *); 164 165/* Find an OpenMP clause of type KIND within CLAUSES. */ 166 167tree 168find_omp_clause (tree clauses, enum omp_clause_code kind) 169{ 170 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses)) 171 if (OMP_CLAUSE_CODE (clauses) == kind) 172 return clauses; 173 174 return NULL_TREE; 175} 176 177/* Return true if CTX is for an omp parallel. */ 178 179static inline bool 180is_parallel_ctx (omp_context *ctx) 181{ 182 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL; 183} 184 185 186/* Return true if CTX is for an omp task. */ 187 188static inline bool 189is_task_ctx (omp_context *ctx) 190{ 191 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK; 192} 193 194 195/* Return true if CTX is for an omp parallel or omp task. */ 196 197static inline bool 198is_taskreg_ctx (omp_context *ctx) 199{ 200 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL 201 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK; 202} 203 204 205/* Return true if REGION is a combined parallel+workshare region. */ 206 207static inline bool 208is_combined_parallel (struct omp_region *region) 209{ 210 return region->is_combined_parallel; 211} 212 213 214/* Extract the header elements of parallel loop FOR_STMT and store 215 them into *FD. */ 216 217static void 218extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd, 219 struct omp_for_data_loop *loops) 220{ 221 tree t, var, *collapse_iter, *collapse_count; 222 tree count = NULL_TREE, iter_type = long_integer_type_node; 223 struct omp_for_data_loop *loop; 224 int i; 225 struct omp_for_data_loop dummy_loop; 226 location_t loc = gimple_location (for_stmt); 227 228 fd->for_stmt = for_stmt; 229 fd->pre = NULL; 230 fd->collapse = gimple_omp_for_collapse (for_stmt); 231 if (fd->collapse > 1) 232 fd->loops = loops; 233 else 234 fd->loops = &fd->loop; 235 236 fd->have_nowait = fd->have_ordered = false; 237 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC; 238 fd->chunk_size = NULL_TREE; 239 collapse_iter = NULL; 240 collapse_count = NULL; 241 242 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t)) 243 switch (OMP_CLAUSE_CODE (t)) 244 { 245 case OMP_CLAUSE_NOWAIT: 246 fd->have_nowait = true; 247 break; 248 case OMP_CLAUSE_ORDERED: 249 fd->have_ordered = true; 250 break; 251 case OMP_CLAUSE_SCHEDULE: 252 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t); 253 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t); 254 break; 255 case OMP_CLAUSE_COLLAPSE: 256 if (fd->collapse > 1) 257 { 258 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t); 259 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t); 260 } 261 default: 262 break; 263 } 264 265 /* FIXME: for now map schedule(auto) to schedule(static). 266 There should be analysis to determine whether all iterations 267 are approximately the same amount of work (then schedule(static) 268 is best) or if it varies (then schedule(dynamic,N) is better). */ 269 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO) 270 { 271 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC; 272 gcc_assert (fd->chunk_size == NULL); 273 } 274 gcc_assert (fd->collapse == 1 || collapse_iter != NULL); 275 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME) 276 gcc_assert (fd->chunk_size == NULL); 277 else if (fd->chunk_size == NULL) 278 { 279 /* We only need to compute a default chunk size for ordered 280 static loops and dynamic loops. */ 281 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC 282 || fd->have_ordered 283 || fd->collapse > 1) 284 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC) 285 ? integer_zero_node : integer_one_node; 286 } 287 288 for (i = 0; i < fd->collapse; i++) 289 { 290 if (fd->collapse == 1) 291 loop = &fd->loop; 292 else if (loops != NULL) 293 loop = loops + i; 294 else 295 loop = &dummy_loop; 296 297 298 loop->v = gimple_omp_for_index (for_stmt, i); 299 gcc_assert (SSA_VAR_P (loop->v)); 300 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE 301 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE); 302 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v; 303 loop->n1 = gimple_omp_for_initial (for_stmt, i); 304 305 loop->cond_code = gimple_omp_for_cond (for_stmt, i); 306 loop->n2 = gimple_omp_for_final (for_stmt, i); 307 switch (loop->cond_code) 308 { 309 case LT_EXPR: 310 case GT_EXPR: 311 break; 312 case LE_EXPR: 313 if (POINTER_TYPE_P (TREE_TYPE (loop->n2))) 314 loop->n2 = fold_build2_loc (loc, 315 POINTER_PLUS_EXPR, TREE_TYPE (loop->n2), 316 loop->n2, size_one_node); 317 else 318 loop->n2 = fold_build2_loc (loc, 319 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2, 320 build_int_cst (TREE_TYPE (loop->n2), 1)); 321 loop->cond_code = LT_EXPR; 322 break; 323 case GE_EXPR: 324 if (POINTER_TYPE_P (TREE_TYPE (loop->n2))) 325 loop->n2 = fold_build2_loc (loc, 326 POINTER_PLUS_EXPR, TREE_TYPE (loop->n2), 327 loop->n2, size_int (-1)); 328 else 329 loop->n2 = fold_build2_loc (loc, 330 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2, 331 build_int_cst (TREE_TYPE (loop->n2), 1)); 332 loop->cond_code = GT_EXPR; 333 break; 334 default: 335 gcc_unreachable (); 336 } 337 338 t = gimple_omp_for_incr (for_stmt, i); 339 gcc_assert (TREE_OPERAND (t, 0) == var); 340 switch (TREE_CODE (t)) 341 { 342 case PLUS_EXPR: 343 case POINTER_PLUS_EXPR: 344 loop->step = TREE_OPERAND (t, 1); 345 break; 346 case MINUS_EXPR: 347 loop->step = TREE_OPERAND (t, 1); 348 loop->step = fold_build1_loc (loc, 349 NEGATE_EXPR, TREE_TYPE (loop->step), 350 loop->step); 351 break; 352 default: 353 gcc_unreachable (); 354 } 355 356 if (iter_type != long_long_unsigned_type_node) 357 { 358 if (POINTER_TYPE_P (TREE_TYPE (loop->v))) 359 iter_type = long_long_unsigned_type_node; 360 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v)) 361 && TYPE_PRECISION (TREE_TYPE (loop->v)) 362 >= TYPE_PRECISION (iter_type)) 363 { 364 tree n; 365 366 if (loop->cond_code == LT_EXPR) 367 n = fold_build2_loc (loc, 368 PLUS_EXPR, TREE_TYPE (loop->v), 369 loop->n2, loop->step); 370 else 371 n = loop->n1; 372 if (TREE_CODE (n) != INTEGER_CST 373 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n)) 374 iter_type = long_long_unsigned_type_node; 375 } 376 else if (TYPE_PRECISION (TREE_TYPE (loop->v)) 377 > TYPE_PRECISION (iter_type)) 378 { 379 tree n1, n2; 380 381 if (loop->cond_code == LT_EXPR) 382 { 383 n1 = loop->n1; 384 n2 = fold_build2_loc (loc, 385 PLUS_EXPR, TREE_TYPE (loop->v), 386 loop->n2, loop->step); 387 } 388 else 389 { 390 n1 = fold_build2_loc (loc, 391 MINUS_EXPR, TREE_TYPE (loop->v), 392 loop->n2, loop->step); 393 n2 = loop->n1; 394 } 395 if (TREE_CODE (n1) != INTEGER_CST 396 || TREE_CODE (n2) != INTEGER_CST 397 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1) 398 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type))) 399 iter_type = long_long_unsigned_type_node; 400 } 401 } 402 403 if (collapse_count && *collapse_count == NULL) 404 { 405 if ((i == 0 || count != NULL_TREE) 406 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE 407 && TREE_CONSTANT (loop->n1) 408 && TREE_CONSTANT (loop->n2) 409 && TREE_CODE (loop->step) == INTEGER_CST) 410 { 411 tree itype = TREE_TYPE (loop->v); 412 413 if (POINTER_TYPE_P (itype)) 414 itype 415 = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0); 416 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1)); 417 t = fold_build2_loc (loc, 418 PLUS_EXPR, itype, 419 fold_convert_loc (loc, itype, loop->step), t); 420 t = fold_build2_loc (loc, PLUS_EXPR, itype, t, 421 fold_convert_loc (loc, itype, loop->n2)); 422 t = fold_build2_loc (loc, MINUS_EXPR, itype, t, 423 fold_convert_loc (loc, itype, loop->n1)); 424 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR) 425 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, 426 fold_build1_loc (loc, NEGATE_EXPR, itype, t), 427 fold_build1_loc (loc, NEGATE_EXPR, itype, 428 fold_convert_loc (loc, itype, 429 loop->step))); 430 else 431 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t, 432 fold_convert_loc (loc, itype, loop->step)); 433 t = fold_convert_loc (loc, long_long_unsigned_type_node, t); 434 if (count != NULL_TREE) 435 count = fold_build2_loc (loc, 436 MULT_EXPR, long_long_unsigned_type_node, 437 count, t); 438 else 439 count = t; 440 if (TREE_CODE (count) != INTEGER_CST) 441 count = NULL_TREE; 442 } 443 else 444 count = NULL_TREE; 445 } 446 } 447 448 if (count) 449 { 450 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node))) 451 iter_type = long_long_unsigned_type_node; 452 else 453 iter_type = long_integer_type_node; 454 } 455 else if (collapse_iter && *collapse_iter != NULL) 456 iter_type = TREE_TYPE (*collapse_iter); 457 fd->iter_type = iter_type; 458 if (collapse_iter && *collapse_iter == NULL) 459 *collapse_iter = create_tmp_var (iter_type, ".iter"); 460 if (collapse_count && *collapse_count == NULL) 461 { 462 if (count) 463 *collapse_count = fold_convert_loc (loc, iter_type, count); 464 else 465 *collapse_count = create_tmp_var (iter_type, ".count"); 466 } 467 468 if (fd->collapse > 1) 469 { 470 fd->loop.v = *collapse_iter; 471 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0); 472 fd->loop.n2 = *collapse_count; 473 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1); 474 fd->loop.cond_code = LT_EXPR; 475 } 476} 477 478 479/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB 480 is the immediate dominator of PAR_ENTRY_BB, return true if there 481 are no data dependencies that would prevent expanding the parallel 482 directive at PAR_ENTRY_BB as a combined parallel+workshare region. 483 484 When expanding a combined parallel+workshare region, the call to 485 the child function may need additional arguments in the case of 486 GIMPLE_OMP_FOR regions. In some cases, these arguments are 487 computed out of variables passed in from the parent to the child 488 via 'struct .omp_data_s'. For instance: 489 490 #pragma omp parallel for schedule (guided, i * 4) 491 for (j ...) 492 493 Is lowered into: 494 495 # BLOCK 2 (PAR_ENTRY_BB) 496 .omp_data_o.i = i; 497 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598) 498 499 # BLOCK 3 (WS_ENTRY_BB) 500 .omp_data_i = &.omp_data_o; 501 D.1667 = .omp_data_i->i; 502 D.1598 = D.1667 * 4; 503 #pragma omp for schedule (guided, D.1598) 504 505 When we outline the parallel region, the call to the child function 506 'bar.omp_fn.0' will need the value D.1598 in its argument list, but 507 that value is computed *after* the call site. So, in principle we 508 cannot do the transformation. 509 510 To see whether the code in WS_ENTRY_BB blocks the combined 511 parallel+workshare call, we collect all the variables used in the 512 GIMPLE_OMP_FOR header check whether they appear on the LHS of any 513 statement in WS_ENTRY_BB. If so, then we cannot emit the combined 514 call. 515 516 FIXME. If we had the SSA form built at this point, we could merely 517 hoist the code in block 3 into block 2 and be done with it. But at 518 this point we don't have dataflow information and though we could 519 hack something up here, it is really not worth the aggravation. */ 520 521static bool 522workshare_safe_to_combine_p (basic_block ws_entry_bb) 523{ 524 struct omp_for_data fd; 525 gimple ws_stmt = last_stmt (ws_entry_bb); 526 527 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS) 528 return true; 529 530 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR); 531 532 extract_omp_for_data (ws_stmt, &fd, NULL); 533 534 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST) 535 return false; 536 if (fd.iter_type != long_integer_type_node) 537 return false; 538 539 /* FIXME. We give up too easily here. If any of these arguments 540 are not constants, they will likely involve variables that have 541 been mapped into fields of .omp_data_s for sharing with the child 542 function. With appropriate data flow, it would be possible to 543 see through this. */ 544 if (!is_gimple_min_invariant (fd.loop.n1) 545 || !is_gimple_min_invariant (fd.loop.n2) 546 || !is_gimple_min_invariant (fd.loop.step) 547 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size))) 548 return false; 549 550 return true; 551} 552 553 554/* Collect additional arguments needed to emit a combined 555 parallel+workshare call. WS_STMT is the workshare directive being 556 expanded. */ 557 558static tree 559get_ws_args_for (gimple ws_stmt) 560{ 561 tree t; 562 location_t loc = gimple_location (ws_stmt); 563 564 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR) 565 { 566 struct omp_for_data fd; 567 tree ws_args; 568 569 extract_omp_for_data (ws_stmt, &fd, NULL); 570 571 ws_args = NULL_TREE; 572 if (fd.chunk_size) 573 { 574 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size); 575 ws_args = tree_cons (NULL, t, ws_args); 576 } 577 578 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step); 579 ws_args = tree_cons (NULL, t, ws_args); 580 581 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2); 582 ws_args = tree_cons (NULL, t, ws_args); 583 584 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1); 585 ws_args = tree_cons (NULL, t, ws_args); 586 587 return ws_args; 588 } 589 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS) 590 { 591 /* Number of sections is equal to the number of edges from the 592 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to 593 the exit of the sections region. */ 594 basic_block bb = single_succ (gimple_bb (ws_stmt)); 595 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1); 596 t = tree_cons (NULL, t, NULL); 597 return t; 598 } 599 600 gcc_unreachable (); 601} 602 603 604/* Discover whether REGION is a combined parallel+workshare region. */ 605 606static void 607determine_parallel_type (struct omp_region *region) 608{ 609 basic_block par_entry_bb, par_exit_bb; 610 basic_block ws_entry_bb, ws_exit_bb; 611 612 if (region == NULL || region->inner == NULL 613 || region->exit == NULL || region->inner->exit == NULL 614 || region->inner->cont == NULL) 615 return; 616 617 /* We only support parallel+for and parallel+sections. */ 618 if (region->type != GIMPLE_OMP_PARALLEL 619 || (region->inner->type != GIMPLE_OMP_FOR 620 && region->inner->type != GIMPLE_OMP_SECTIONS)) 621 return; 622 623 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and 624 WS_EXIT_BB -> PAR_EXIT_BB. */ 625 par_entry_bb = region->entry; 626 par_exit_bb = region->exit; 627 ws_entry_bb = region->inner->entry; 628 ws_exit_bb = region->inner->exit; 629 630 if (single_succ (par_entry_bb) == ws_entry_bb 631 && single_succ (ws_exit_bb) == par_exit_bb 632 && workshare_safe_to_combine_p (ws_entry_bb) 633 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb)) 634 || (last_and_only_stmt (ws_entry_bb) 635 && last_and_only_stmt (par_exit_bb)))) 636 { 637 gimple ws_stmt = last_stmt (ws_entry_bb); 638 639 if (region->inner->type == GIMPLE_OMP_FOR) 640 { 641 /* If this is a combined parallel loop, we need to determine 642 whether or not to use the combined library calls. There 643 are two cases where we do not apply the transformation: 644 static loops and any kind of ordered loop. In the first 645 case, we already open code the loop so there is no need 646 to do anything else. In the latter case, the combined 647 parallel loop call would still need extra synchronization 648 to implement ordered semantics, so there would not be any 649 gain in using the combined call. */ 650 tree clauses = gimple_omp_for_clauses (ws_stmt); 651 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE); 652 if (c == NULL 653 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC 654 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED)) 655 { 656 region->is_combined_parallel = false; 657 region->inner->is_combined_parallel = false; 658 return; 659 } 660 } 661 662 region->is_combined_parallel = true; 663 region->inner->is_combined_parallel = true; 664 region->ws_args = get_ws_args_for (ws_stmt); 665 } 666} 667 668 669/* Return true if EXPR is variable sized. */ 670 671static inline bool 672is_variable_sized (const_tree expr) 673{ 674 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr))); 675} 676 677/* Return true if DECL is a reference type. */ 678 679static inline bool 680is_reference (tree decl) 681{ 682 return lang_hooks.decls.omp_privatize_by_reference (decl); 683} 684 685/* Lookup variables in the decl or field splay trees. The "maybe" form 686 allows for the variable form to not have been entered, otherwise we 687 assert that the variable must have been entered. */ 688 689static inline tree 690lookup_decl (tree var, omp_context *ctx) 691{ 692 tree *n; 693 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var); 694 return *n; 695} 696 697static inline tree 698maybe_lookup_decl (const_tree var, omp_context *ctx) 699{ 700 tree *n; 701 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var); 702 return n ? *n : NULL_TREE; 703} 704 705static inline tree 706lookup_field (tree var, omp_context *ctx) 707{ 708 splay_tree_node n; 709 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var); 710 return (tree) n->value; 711} 712 713static inline tree 714lookup_sfield (tree var, omp_context *ctx) 715{ 716 splay_tree_node n; 717 n = splay_tree_lookup (ctx->sfield_map 718 ? ctx->sfield_map : ctx->field_map, 719 (splay_tree_key) var); 720 return (tree) n->value; 721} 722 723static inline tree 724maybe_lookup_field (tree var, omp_context *ctx) 725{ 726 splay_tree_node n; 727 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var); 728 return n ? (tree) n->value : NULL_TREE; 729} 730 731/* Return true if DECL should be copied by pointer. SHARED_CTX is 732 the parallel context if DECL is to be shared. */ 733 734static bool 735use_pointer_for_field (tree decl, omp_context *shared_ctx) 736{ 737 if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) 738 return true; 739 740 /* We can only use copy-in/copy-out semantics for shared variables 741 when we know the value is not accessible from an outer scope. */ 742 if (shared_ctx) 743 { 744 /* ??? Trivially accessible from anywhere. But why would we even 745 be passing an address in this case? Should we simply assert 746 this to be false, or should we have a cleanup pass that removes 747 these from the list of mappings? */ 748 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) 749 return true; 750 751 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell 752 without analyzing the expression whether or not its location 753 is accessible to anyone else. In the case of nested parallel 754 regions it certainly may be. */ 755 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl)) 756 return true; 757 758 /* Do not use copy-in/copy-out for variables that have their 759 address taken. */ 760 if (TREE_ADDRESSABLE (decl)) 761 return true; 762 763 /* Disallow copy-in/out in nested parallel if 764 decl is shared in outer parallel, otherwise 765 each thread could store the shared variable 766 in its own copy-in location, making the 767 variable no longer really shared. */ 768 if (!TREE_READONLY (decl) && shared_ctx->is_nested) 769 { 770 omp_context *up; 771 772 for (up = shared_ctx->outer; up; up = up->outer) 773 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up)) 774 break; 775 776 if (up) 777 { 778 tree c; 779 780 for (c = gimple_omp_taskreg_clauses (up->stmt); 781 c; c = OMP_CLAUSE_CHAIN (c)) 782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED 783 && OMP_CLAUSE_DECL (c) == decl) 784 break; 785 786 if (c) 787 return true; 788 } 789 } 790 791 /* For tasks avoid using copy-in/out, unless they are readonly 792 (in which case just copy-in is used). As tasks can be 793 deferred or executed in different thread, when GOMP_task 794 returns, the task hasn't necessarily terminated. */ 795 if (!TREE_READONLY (decl) && is_task_ctx (shared_ctx)) 796 { 797 tree outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx); 798 if (is_gimple_reg (outer)) 799 { 800 /* Taking address of OUTER in lower_send_shared_vars 801 might need regimplification of everything that uses the 802 variable. */ 803 if (!task_shared_vars) 804 task_shared_vars = BITMAP_ALLOC (NULL); 805 bitmap_set_bit (task_shared_vars, DECL_UID (outer)); 806 TREE_ADDRESSABLE (outer) = 1; 807 } 808 return true; 809 } 810 } 811 812 return false; 813} 814 815/* Create a new VAR_DECL and copy information from VAR to it. */ 816 817tree 818copy_var_decl (tree var, tree name, tree type) 819{ 820 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type); 821 822 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var); 823 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var); 824 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var); 825 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var); 826 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var); 827 DECL_CONTEXT (copy) = DECL_CONTEXT (var); 828 TREE_USED (copy) = 1; 829 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1; 830 831 return copy; 832} 833 834/* Construct a new automatic decl similar to VAR. */ 835 836static tree 837omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx) 838{ 839 tree copy = copy_var_decl (var, name, type); 840 841 DECL_CONTEXT (copy) = current_function_decl; 842 TREE_CHAIN (copy) = ctx->block_vars; 843 ctx->block_vars = copy; 844 845 return copy; 846} 847 848static tree 849omp_copy_decl_1 (tree var, omp_context *ctx) 850{ 851 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx); 852} 853 854/* Build tree nodes to access the field for VAR on the receiver side. */ 855 856static tree 857build_receiver_ref (tree var, bool by_ref, omp_context *ctx) 858{ 859 tree x, field = lookup_field (var, ctx); 860 861 /* If the receiver record type was remapped in the child function, 862 remap the field into the new record type. */ 863 x = maybe_lookup_field (field, ctx); 864 if (x != NULL) 865 field = x; 866 867 x = build_fold_indirect_ref (ctx->receiver_decl); 868 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL); 869 if (by_ref) 870 x = build_fold_indirect_ref (x); 871 872 return x; 873} 874 875/* Build tree nodes to access VAR in the scope outer to CTX. In the case 876 of a parallel, this is a component reference; for workshare constructs 877 this is some variable. */ 878 879static tree 880build_outer_var_ref (tree var, omp_context *ctx) 881{ 882 tree x; 883 884 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))) 885 x = var; 886 else if (is_variable_sized (var)) 887 { 888 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0); 889 x = build_outer_var_ref (x, ctx); 890 x = build_fold_indirect_ref (x); 891 } 892 else if (is_taskreg_ctx (ctx)) 893 { 894 bool by_ref = use_pointer_for_field (var, NULL); 895 x = build_receiver_ref (var, by_ref, ctx); 896 } 897 else if (ctx->outer) 898 x = lookup_decl (var, ctx->outer); 899 else if (is_reference (var)) 900 /* This can happen with orphaned constructs. If var is reference, it is 901 possible it is shared and as such valid. */ 902 x = var; 903 else 904 gcc_unreachable (); 905 906 if (is_reference (var)) 907 x = build_fold_indirect_ref (x); 908 909 return x; 910} 911 912/* Build tree nodes to access the field for VAR on the sender side. */ 913 914static tree 915build_sender_ref (tree var, omp_context *ctx) 916{ 917 tree field = lookup_sfield (var, ctx); 918 return build3 (COMPONENT_REF, TREE_TYPE (field), 919 ctx->sender_decl, field, NULL); 920} 921 922/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */ 923 924static void 925install_var_field (tree var, bool by_ref, int mask, omp_context *ctx) 926{ 927 tree field, type, sfield = NULL_TREE; 928 929 gcc_assert ((mask & 1) == 0 930 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var)); 931 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map 932 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var)); 933 934 type = TREE_TYPE (var); 935 if (by_ref) 936 type = build_pointer_type (type); 937 else if ((mask & 3) == 1 && is_reference (var)) 938 type = TREE_TYPE (type); 939 940 field = build_decl (DECL_SOURCE_LOCATION (var), 941 FIELD_DECL, DECL_NAME (var), type); 942 943 /* Remember what variable this field was created for. This does have a 944 side effect of making dwarf2out ignore this member, so for helpful 945 debugging we clear it later in delete_omp_context. */ 946 DECL_ABSTRACT_ORIGIN (field) = var; 947 if (type == TREE_TYPE (var)) 948 { 949 DECL_ALIGN (field) = DECL_ALIGN (var); 950 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var); 951 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var); 952 } 953 else 954 DECL_ALIGN (field) = TYPE_ALIGN (type); 955 956 if ((mask & 3) == 3) 957 { 958 insert_field_into_struct (ctx->record_type, field); 959 if (ctx->srecord_type) 960 { 961 sfield = build_decl (DECL_SOURCE_LOCATION (var), 962 FIELD_DECL, DECL_NAME (var), type); 963 DECL_ABSTRACT_ORIGIN (sfield) = var; 964 DECL_ALIGN (sfield) = DECL_ALIGN (field); 965 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field); 966 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field); 967 insert_field_into_struct (ctx->srecord_type, sfield); 968 } 969 } 970 else 971 { 972 if (ctx->srecord_type == NULL_TREE) 973 { 974 tree t; 975 976 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE); 977 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 978 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t)) 979 { 980 sfield = build_decl (DECL_SOURCE_LOCATION (var), 981 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t)); 982 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t); 983 insert_field_into_struct (ctx->srecord_type, sfield); 984 splay_tree_insert (ctx->sfield_map, 985 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t), 986 (splay_tree_value) sfield); 987 } 988 } 989 sfield = field; 990 insert_field_into_struct ((mask & 1) ? ctx->record_type 991 : ctx->srecord_type, field); 992 } 993 994 if (mask & 1) 995 splay_tree_insert (ctx->field_map, (splay_tree_key) var, 996 (splay_tree_value) field); 997 if ((mask & 2) && ctx->sfield_map) 998 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var, 999 (splay_tree_value) sfield); 1000} 1001 1002static tree 1003install_var_local (tree var, omp_context *ctx) 1004{ 1005 tree new_var = omp_copy_decl_1 (var, ctx); 1006 insert_decl_map (&ctx->cb, var, new_var); 1007 return new_var; 1008} 1009 1010/* Adjust the replacement for DECL in CTX for the new context. This means 1011 copying the DECL_VALUE_EXPR, and fixing up the type. */ 1012 1013static void 1014fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug) 1015{ 1016 tree new_decl, size; 1017 1018 new_decl = lookup_decl (decl, ctx); 1019 1020 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb); 1021 1022 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug) 1023 && DECL_HAS_VALUE_EXPR_P (decl)) 1024 { 1025 tree ve = DECL_VALUE_EXPR (decl); 1026 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL); 1027 SET_DECL_VALUE_EXPR (new_decl, ve); 1028 DECL_HAS_VALUE_EXPR_P (new_decl) = 1; 1029 } 1030 1031 if (!TREE_CONSTANT (DECL_SIZE (new_decl))) 1032 { 1033 size = remap_decl (DECL_SIZE (decl), &ctx->cb); 1034 if (size == error_mark_node) 1035 size = TYPE_SIZE (TREE_TYPE (new_decl)); 1036 DECL_SIZE (new_decl) = size; 1037 1038 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb); 1039 if (size == error_mark_node) 1040 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl)); 1041 DECL_SIZE_UNIT (new_decl) = size; 1042 } 1043} 1044 1045/* The callback for remap_decl. Search all containing contexts for a 1046 mapping of the variable; this avoids having to duplicate the splay 1047 tree ahead of time. We know a mapping doesn't already exist in the 1048 given context. Create new mappings to implement default semantics. */ 1049 1050static tree 1051omp_copy_decl (tree var, copy_body_data *cb) 1052{ 1053 omp_context *ctx = (omp_context *) cb; 1054 tree new_var; 1055 1056 if (TREE_CODE (var) == LABEL_DECL) 1057 { 1058 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var)); 1059 DECL_CONTEXT (new_var) = current_function_decl; 1060 insert_decl_map (&ctx->cb, var, new_var); 1061 return new_var; 1062 } 1063 1064 while (!is_taskreg_ctx (ctx)) 1065 { 1066 ctx = ctx->outer; 1067 if (ctx == NULL) 1068 return var; 1069 new_var = maybe_lookup_decl (var, ctx); 1070 if (new_var) 1071 return new_var; 1072 } 1073 1074 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn) 1075 return var; 1076 1077 return error_mark_node; 1078} 1079 1080 1081/* Return the parallel region associated with STMT. */ 1082 1083/* Debugging dumps for parallel regions. */ 1084void dump_omp_region (FILE *, struct omp_region *, int); 1085void debug_omp_region (struct omp_region *); 1086void debug_all_omp_regions (void); 1087 1088/* Dump the parallel region tree rooted at REGION. */ 1089 1090void 1091dump_omp_region (FILE *file, struct omp_region *region, int indent) 1092{ 1093 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index, 1094 gimple_code_name[region->type]); 1095 1096 if (region->inner) 1097 dump_omp_region (file, region->inner, indent + 4); 1098 1099 if (region->cont) 1100 { 1101 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "", 1102 region->cont->index); 1103 } 1104 1105 if (region->exit) 1106 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "", 1107 region->exit->index); 1108 else 1109 fprintf (file, "%*s[no exit marker]\n", indent, ""); 1110 1111 if (region->next) 1112 dump_omp_region (file, region->next, indent); 1113} 1114 1115void 1116debug_omp_region (struct omp_region *region) 1117{ 1118 dump_omp_region (stderr, region, 0); 1119} 1120 1121void 1122debug_all_omp_regions (void) 1123{ 1124 dump_omp_region (stderr, root_omp_region, 0); 1125} 1126 1127 1128/* Create a new parallel region starting at STMT inside region PARENT. */ 1129 1130struct omp_region * 1131new_omp_region (basic_block bb, enum gimple_code type, 1132 struct omp_region *parent) 1133{ 1134 struct omp_region *region = XCNEW (struct omp_region); 1135 1136 region->outer = parent; 1137 region->entry = bb; 1138 region->type = type; 1139 1140 if (parent) 1141 { 1142 /* This is a nested region. Add it to the list of inner 1143 regions in PARENT. */ 1144 region->next = parent->inner; 1145 parent->inner = region; 1146 } 1147 else 1148 { 1149 /* This is a toplevel region. Add it to the list of toplevel 1150 regions in ROOT_OMP_REGION. */ 1151 region->next = root_omp_region; 1152 root_omp_region = region; 1153 } 1154 1155 return region; 1156} 1157 1158/* Release the memory associated with the region tree rooted at REGION. */ 1159 1160static void 1161free_omp_region_1 (struct omp_region *region) 1162{ 1163 struct omp_region *i, *n; 1164 1165 for (i = region->inner; i ; i = n) 1166 { 1167 n = i->next; 1168 free_omp_region_1 (i); 1169 } 1170 1171 free (region); 1172} 1173 1174/* Release the memory for the entire omp region tree. */ 1175 1176void 1177free_omp_regions (void) 1178{ 1179 struct omp_region *r, *n; 1180 for (r = root_omp_region; r ; r = n) 1181 { 1182 n = r->next; 1183 free_omp_region_1 (r); 1184 } 1185 root_omp_region = NULL; 1186} 1187 1188 1189/* Create a new context, with OUTER_CTX being the surrounding context. */ 1190 1191static omp_context * 1192new_omp_context (gimple stmt, omp_context *outer_ctx) 1193{ 1194 omp_context *ctx = XCNEW (omp_context); 1195 1196 splay_tree_insert (all_contexts, (splay_tree_key) stmt, 1197 (splay_tree_value) ctx); 1198 ctx->stmt = stmt; 1199 1200 if (outer_ctx) 1201 { 1202 ctx->outer = outer_ctx; 1203 ctx->cb = outer_ctx->cb; 1204 ctx->cb.block = NULL; 1205 ctx->depth = outer_ctx->depth + 1; 1206 } 1207 else 1208 { 1209 ctx->cb.src_fn = current_function_decl; 1210 ctx->cb.dst_fn = current_function_decl; 1211 ctx->cb.src_node = cgraph_node (current_function_decl); 1212 ctx->cb.dst_node = ctx->cb.src_node; 1213 ctx->cb.src_cfun = cfun; 1214 ctx->cb.copy_decl = omp_copy_decl; 1215 ctx->cb.eh_lp_nr = 0; 1216 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE; 1217 ctx->depth = 1; 1218 } 1219 1220 ctx->cb.decl_map = pointer_map_create (); 1221 1222 return ctx; 1223} 1224 1225static gimple_seq maybe_catch_exception (gimple_seq); 1226 1227/* Finalize task copyfn. */ 1228 1229static void 1230finalize_task_copyfn (gimple task_stmt) 1231{ 1232 struct function *child_cfun; 1233 tree child_fn, old_fn; 1234 gimple_seq seq, new_seq; 1235 gimple bind; 1236 1237 child_fn = gimple_omp_task_copy_fn (task_stmt); 1238 if (child_fn == NULL_TREE) 1239 return; 1240 1241 child_cfun = DECL_STRUCT_FUNCTION (child_fn); 1242 1243 /* Inform the callgraph about the new function. */ 1244 DECL_STRUCT_FUNCTION (child_fn)->curr_properties 1245 = cfun->curr_properties; 1246 1247 old_fn = current_function_decl; 1248 push_cfun (child_cfun); 1249 current_function_decl = child_fn; 1250 bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false); 1251 seq = gimple_seq_alloc (); 1252 gimple_seq_add_stmt (&seq, bind); 1253 new_seq = maybe_catch_exception (seq); 1254 if (new_seq != seq) 1255 { 1256 bind = gimple_build_bind (NULL, new_seq, NULL); 1257 seq = gimple_seq_alloc (); 1258 gimple_seq_add_stmt (&seq, bind); 1259 } 1260 gimple_set_body (child_fn, seq); 1261 pop_cfun (); 1262 current_function_decl = old_fn; 1263 1264 cgraph_add_new_function (child_fn, false); 1265} 1266 1267/* Destroy a omp_context data structures. Called through the splay tree 1268 value delete callback. */ 1269 1270static void 1271delete_omp_context (splay_tree_value value) 1272{ 1273 omp_context *ctx = (omp_context *) value; 1274 1275 pointer_map_destroy (ctx->cb.decl_map); 1276 1277 if (ctx->field_map) 1278 splay_tree_delete (ctx->field_map); 1279 if (ctx->sfield_map) 1280 splay_tree_delete (ctx->sfield_map); 1281 1282 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before 1283 it produces corrupt debug information. */ 1284 if (ctx->record_type) 1285 { 1286 tree t; 1287 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t)) 1288 DECL_ABSTRACT_ORIGIN (t) = NULL; 1289 } 1290 if (ctx->srecord_type) 1291 { 1292 tree t; 1293 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = TREE_CHAIN (t)) 1294 DECL_ABSTRACT_ORIGIN (t) = NULL; 1295 } 1296 1297 if (is_task_ctx (ctx)) 1298 finalize_task_copyfn (ctx->stmt); 1299 1300 XDELETE (ctx); 1301} 1302 1303/* Fix up RECEIVER_DECL with a type that has been remapped to the child 1304 context. */ 1305 1306static void 1307fixup_child_record_type (omp_context *ctx) 1308{ 1309 tree f, type = ctx->record_type; 1310 1311 /* ??? It isn't sufficient to just call remap_type here, because 1312 variably_modified_type_p doesn't work the way we expect for 1313 record types. Testing each field for whether it needs remapping 1314 and creating a new record by hand works, however. */ 1315 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f)) 1316 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn)) 1317 break; 1318 if (f) 1319 { 1320 tree name, new_fields = NULL; 1321 1322 type = lang_hooks.types.make_type (RECORD_TYPE); 1323 name = DECL_NAME (TYPE_NAME (ctx->record_type)); 1324 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl), 1325 TYPE_DECL, name, type); 1326 TYPE_NAME (type) = name; 1327 1328 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f)) 1329 { 1330 tree new_f = copy_node (f); 1331 DECL_CONTEXT (new_f) = type; 1332 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb); 1333 TREE_CHAIN (new_f) = new_fields; 1334 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL); 1335 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, 1336 &ctx->cb, NULL); 1337 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r, 1338 &ctx->cb, NULL); 1339 new_fields = new_f; 1340 1341 /* Arrange to be able to look up the receiver field 1342 given the sender field. */ 1343 splay_tree_insert (ctx->field_map, (splay_tree_key) f, 1344 (splay_tree_value) new_f); 1345 } 1346 TYPE_FIELDS (type) = nreverse (new_fields); 1347 layout_type (type); 1348 } 1349 1350 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type); 1351} 1352 1353/* Instantiate decls as necessary in CTX to satisfy the data sharing 1354 specified by CLAUSES. */ 1355 1356static void 1357scan_sharing_clauses (tree clauses, omp_context *ctx) 1358{ 1359 tree c, decl; 1360 bool scan_array_reductions = false; 1361 1362 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 1363 { 1364 bool by_ref; 1365 1366 switch (OMP_CLAUSE_CODE (c)) 1367 { 1368 case OMP_CLAUSE_PRIVATE: 1369 decl = OMP_CLAUSE_DECL (c); 1370 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c)) 1371 goto do_private; 1372 else if (!is_variable_sized (decl)) 1373 install_var_local (decl, ctx); 1374 break; 1375 1376 case OMP_CLAUSE_SHARED: 1377 gcc_assert (is_taskreg_ctx (ctx)); 1378 decl = OMP_CLAUSE_DECL (c); 1379 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl)) 1380 || !is_variable_sized (decl)); 1381 /* Global variables don't need to be copied, 1382 the receiver side will use them directly. */ 1383 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) 1384 break; 1385 by_ref = use_pointer_for_field (decl, ctx); 1386 if (! TREE_READONLY (decl) 1387 || TREE_ADDRESSABLE (decl) 1388 || by_ref 1389 || is_reference (decl)) 1390 { 1391 install_var_field (decl, by_ref, 3, ctx); 1392 install_var_local (decl, ctx); 1393 break; 1394 } 1395 /* We don't need to copy const scalar vars back. */ 1396 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE); 1397 goto do_private; 1398 1399 case OMP_CLAUSE_LASTPRIVATE: 1400 /* Let the corresponding firstprivate clause create 1401 the variable. */ 1402 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 1403 break; 1404 /* FALLTHRU */ 1405 1406 case OMP_CLAUSE_FIRSTPRIVATE: 1407 case OMP_CLAUSE_REDUCTION: 1408 decl = OMP_CLAUSE_DECL (c); 1409 do_private: 1410 if (is_variable_sized (decl)) 1411 { 1412 if (is_task_ctx (ctx)) 1413 install_var_field (decl, false, 1, ctx); 1414 break; 1415 } 1416 else if (is_taskreg_ctx (ctx)) 1417 { 1418 bool global 1419 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)); 1420 by_ref = use_pointer_for_field (decl, NULL); 1421 1422 if (is_task_ctx (ctx) 1423 && (global || by_ref || is_reference (decl))) 1424 { 1425 install_var_field (decl, false, 1, ctx); 1426 if (!global) 1427 install_var_field (decl, by_ref, 2, ctx); 1428 } 1429 else if (!global) 1430 install_var_field (decl, by_ref, 3, ctx); 1431 } 1432 install_var_local (decl, ctx); 1433 break; 1434 1435 case OMP_CLAUSE_COPYPRIVATE: 1436 case OMP_CLAUSE_COPYIN: 1437 decl = OMP_CLAUSE_DECL (c); 1438 by_ref = use_pointer_for_field (decl, NULL); 1439 install_var_field (decl, by_ref, 3, ctx); 1440 break; 1441 1442 case OMP_CLAUSE_DEFAULT: 1443 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c); 1444 break; 1445 1446 case OMP_CLAUSE_IF: 1447 case OMP_CLAUSE_NUM_THREADS: 1448 case OMP_CLAUSE_SCHEDULE: 1449 if (ctx->outer) 1450 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer); 1451 break; 1452 1453 case OMP_CLAUSE_NOWAIT: 1454 case OMP_CLAUSE_ORDERED: 1455 case OMP_CLAUSE_COLLAPSE: 1456 case OMP_CLAUSE_UNTIED: 1457 break; 1458 1459 default: 1460 gcc_unreachable (); 1461 } 1462 } 1463 1464 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 1465 { 1466 switch (OMP_CLAUSE_CODE (c)) 1467 { 1468 case OMP_CLAUSE_LASTPRIVATE: 1469 /* Let the corresponding firstprivate clause create 1470 the variable. */ 1471 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) 1472 scan_array_reductions = true; 1473 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 1474 break; 1475 /* FALLTHRU */ 1476 1477 case OMP_CLAUSE_PRIVATE: 1478 case OMP_CLAUSE_FIRSTPRIVATE: 1479 case OMP_CLAUSE_REDUCTION: 1480 decl = OMP_CLAUSE_DECL (c); 1481 if (is_variable_sized (decl)) 1482 install_var_local (decl, ctx); 1483 fixup_remapped_decl (decl, ctx, 1484 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE 1485 && OMP_CLAUSE_PRIVATE_DEBUG (c)); 1486 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION 1487 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1488 scan_array_reductions = true; 1489 break; 1490 1491 case OMP_CLAUSE_SHARED: 1492 decl = OMP_CLAUSE_DECL (c); 1493 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) 1494 fixup_remapped_decl (decl, ctx, false); 1495 break; 1496 1497 case OMP_CLAUSE_COPYPRIVATE: 1498 case OMP_CLAUSE_COPYIN: 1499 case OMP_CLAUSE_DEFAULT: 1500 case OMP_CLAUSE_IF: 1501 case OMP_CLAUSE_NUM_THREADS: 1502 case OMP_CLAUSE_SCHEDULE: 1503 case OMP_CLAUSE_NOWAIT: 1504 case OMP_CLAUSE_ORDERED: 1505 case OMP_CLAUSE_COLLAPSE: 1506 case OMP_CLAUSE_UNTIED: 1507 break; 1508 1509 default: 1510 gcc_unreachable (); 1511 } 1512 } 1513 1514 if (scan_array_reductions) 1515 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) 1516 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION 1517 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 1518 { 1519 scan_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx); 1520 scan_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx); 1521 } 1522 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE 1523 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) 1524 scan_omp (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx); 1525} 1526 1527/* Create a new name for omp child function. Returns an identifier. */ 1528 1529static GTY(()) unsigned int tmp_ompfn_id_num; 1530 1531static tree 1532create_omp_child_function_name (bool task_copy) 1533{ 1534 tree name = DECL_ASSEMBLER_NAME (current_function_decl); 1535 size_t len = IDENTIFIER_LENGTH (name); 1536 char *tmp_name, *prefix; 1537 const char *suffix; 1538 1539 suffix = task_copy ? "_omp_cpyfn" : "_omp_fn"; 1540 prefix = XALLOCAVEC (char, len + strlen (suffix) + 1); 1541 memcpy (prefix, IDENTIFIER_POINTER (name), len); 1542 strcpy (prefix + len, suffix); 1543#ifndef NO_DOT_IN_LABEL 1544 prefix[len] = '.'; 1545#elif !defined NO_DOLLAR_IN_LABEL 1546 prefix[len] = '$'; 1547#endif 1548 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++); 1549 return get_identifier (tmp_name); 1550} 1551 1552/* Build a decl for the omp child function. It'll not contain a body 1553 yet, just the bare decl. */ 1554 1555static void 1556create_omp_child_function (omp_context *ctx, bool task_copy) 1557{ 1558 tree decl, type, name, t; 1559 1560 name = create_omp_child_function_name (task_copy); 1561 if (task_copy) 1562 type = build_function_type_list (void_type_node, ptr_type_node, 1563 ptr_type_node, NULL_TREE); 1564 else 1565 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); 1566 1567 decl = build_decl (gimple_location (ctx->stmt), 1568 FUNCTION_DECL, name, type); 1569 1570 if (!task_copy) 1571 ctx->cb.dst_fn = decl; 1572 else 1573 gimple_omp_task_set_copy_fn (ctx->stmt, decl); 1574 1575 TREE_STATIC (decl) = 1; 1576 TREE_USED (decl) = 1; 1577 DECL_ARTIFICIAL (decl) = 1; 1578 DECL_IGNORED_P (decl) = 0; 1579 TREE_PUBLIC (decl) = 0; 1580 DECL_UNINLINABLE (decl) = 1; 1581 DECL_EXTERNAL (decl) = 0; 1582 DECL_CONTEXT (decl) = NULL_TREE; 1583 DECL_INITIAL (decl) = make_node (BLOCK); 1584 1585 t = build_decl (DECL_SOURCE_LOCATION (decl), 1586 RESULT_DECL, NULL_TREE, void_type_node); 1587 DECL_ARTIFICIAL (t) = 1; 1588 DECL_IGNORED_P (t) = 1; 1589 DECL_CONTEXT (t) = decl; 1590 DECL_RESULT (decl) = t; 1591 1592 t = build_decl (DECL_SOURCE_LOCATION (decl), 1593 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node); 1594 DECL_ARTIFICIAL (t) = 1; 1595 DECL_ARG_TYPE (t) = ptr_type_node; 1596 DECL_CONTEXT (t) = current_function_decl; 1597 TREE_USED (t) = 1; 1598 DECL_ARGUMENTS (decl) = t; 1599 if (!task_copy) 1600 ctx->receiver_decl = t; 1601 else 1602 { 1603 t = build_decl (DECL_SOURCE_LOCATION (decl), 1604 PARM_DECL, get_identifier (".omp_data_o"), 1605 ptr_type_node); 1606 DECL_ARTIFICIAL (t) = 1; 1607 DECL_ARG_TYPE (t) = ptr_type_node; 1608 DECL_CONTEXT (t) = current_function_decl; 1609 TREE_USED (t) = 1; 1610 TREE_ADDRESSABLE (t) = 1; 1611 TREE_CHAIN (t) = DECL_ARGUMENTS (decl); 1612 DECL_ARGUMENTS (decl) = t; 1613 } 1614 1615 /* Allocate memory for the function structure. The call to 1616 allocate_struct_function clobbers CFUN, so we need to restore 1617 it afterward. */ 1618 push_struct_function (decl); 1619 cfun->function_end_locus = gimple_location (ctx->stmt); 1620 pop_cfun (); 1621} 1622 1623 1624/* Scan an OpenMP parallel directive. */ 1625 1626static void 1627scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx) 1628{ 1629 omp_context *ctx; 1630 tree name; 1631 gimple stmt = gsi_stmt (*gsi); 1632 1633 /* Ignore parallel directives with empty bodies, unless there 1634 are copyin clauses. */ 1635 if (optimize > 0 1636 && empty_body_p (gimple_omp_body (stmt)) 1637 && find_omp_clause (gimple_omp_parallel_clauses (stmt), 1638 OMP_CLAUSE_COPYIN) == NULL) 1639 { 1640 gsi_replace (gsi, gimple_build_nop (), false); 1641 return; 1642 } 1643 1644 ctx = new_omp_context (stmt, outer_ctx); 1645 if (taskreg_nesting_level > 1) 1646 ctx->is_nested = true; 1647 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 1648 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED; 1649 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE); 1650 name = create_tmp_var_name (".omp_data_s"); 1651 name = build_decl (gimple_location (stmt), 1652 TYPE_DECL, name, ctx->record_type); 1653 TYPE_NAME (ctx->record_type) = name; 1654 create_omp_child_function (ctx, false); 1655 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn); 1656 1657 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx); 1658 scan_omp (gimple_omp_body (stmt), ctx); 1659 1660 if (TYPE_FIELDS (ctx->record_type) == NULL) 1661 ctx->record_type = ctx->receiver_decl = NULL; 1662 else 1663 { 1664 layout_type (ctx->record_type); 1665 fixup_child_record_type (ctx); 1666 } 1667} 1668 1669/* Scan an OpenMP task directive. */ 1670 1671static void 1672scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx) 1673{ 1674 omp_context *ctx; 1675 tree name, t; 1676 gimple stmt = gsi_stmt (*gsi); 1677 location_t loc = gimple_location (stmt); 1678 1679 /* Ignore task directives with empty bodies. */ 1680 if (optimize > 0 1681 && empty_body_p (gimple_omp_body (stmt))) 1682 { 1683 gsi_replace (gsi, gimple_build_nop (), false); 1684 return; 1685 } 1686 1687 ctx = new_omp_context (stmt, outer_ctx); 1688 if (taskreg_nesting_level > 1) 1689 ctx->is_nested = true; 1690 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 1691 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED; 1692 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE); 1693 name = create_tmp_var_name (".omp_data_s"); 1694 name = build_decl (gimple_location (stmt), 1695 TYPE_DECL, name, ctx->record_type); 1696 TYPE_NAME (ctx->record_type) = name; 1697 create_omp_child_function (ctx, false); 1698 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn); 1699 1700 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx); 1701 1702 if (ctx->srecord_type) 1703 { 1704 name = create_tmp_var_name (".omp_data_a"); 1705 name = build_decl (gimple_location (stmt), 1706 TYPE_DECL, name, ctx->srecord_type); 1707 TYPE_NAME (ctx->srecord_type) = name; 1708 create_omp_child_function (ctx, true); 1709 } 1710 1711 scan_omp (gimple_omp_body (stmt), ctx); 1712 1713 if (TYPE_FIELDS (ctx->record_type) == NULL) 1714 { 1715 ctx->record_type = ctx->receiver_decl = NULL; 1716 t = build_int_cst (long_integer_type_node, 0); 1717 gimple_omp_task_set_arg_size (stmt, t); 1718 t = build_int_cst (long_integer_type_node, 1); 1719 gimple_omp_task_set_arg_align (stmt, t); 1720 } 1721 else 1722 { 1723 tree *p, vla_fields = NULL_TREE, *q = &vla_fields; 1724 /* Move VLA fields to the end. */ 1725 p = &TYPE_FIELDS (ctx->record_type); 1726 while (*p) 1727 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p)) 1728 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p)))) 1729 { 1730 *q = *p; 1731 *p = TREE_CHAIN (*p); 1732 TREE_CHAIN (*q) = NULL_TREE; 1733 q = &TREE_CHAIN (*q); 1734 } 1735 else 1736 p = &TREE_CHAIN (*p); 1737 *p = vla_fields; 1738 layout_type (ctx->record_type); 1739 fixup_child_record_type (ctx); 1740 if (ctx->srecord_type) 1741 layout_type (ctx->srecord_type); 1742 t = fold_convert_loc (loc, long_integer_type_node, 1743 TYPE_SIZE_UNIT (ctx->record_type)); 1744 gimple_omp_task_set_arg_size (stmt, t); 1745 t = build_int_cst (long_integer_type_node, 1746 TYPE_ALIGN_UNIT (ctx->record_type)); 1747 gimple_omp_task_set_arg_align (stmt, t); 1748 } 1749} 1750 1751 1752/* Scan an OpenMP loop directive. */ 1753 1754static void 1755scan_omp_for (gimple stmt, omp_context *outer_ctx) 1756{ 1757 omp_context *ctx; 1758 size_t i; 1759 1760 ctx = new_omp_context (stmt, outer_ctx); 1761 1762 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx); 1763 1764 scan_omp (gimple_omp_for_pre_body (stmt), ctx); 1765 for (i = 0; i < gimple_omp_for_collapse (stmt); i++) 1766 { 1767 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx); 1768 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx); 1769 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx); 1770 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx); 1771 } 1772 scan_omp (gimple_omp_body (stmt), ctx); 1773} 1774 1775/* Scan an OpenMP sections directive. */ 1776 1777static void 1778scan_omp_sections (gimple stmt, omp_context *outer_ctx) 1779{ 1780 omp_context *ctx; 1781 1782 ctx = new_omp_context (stmt, outer_ctx); 1783 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx); 1784 scan_omp (gimple_omp_body (stmt), ctx); 1785} 1786 1787/* Scan an OpenMP single directive. */ 1788 1789static void 1790scan_omp_single (gimple stmt, omp_context *outer_ctx) 1791{ 1792 omp_context *ctx; 1793 tree name; 1794 1795 ctx = new_omp_context (stmt, outer_ctx); 1796 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); 1797 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE); 1798 name = create_tmp_var_name (".omp_copy_s"); 1799 name = build_decl (gimple_location (stmt), 1800 TYPE_DECL, name, ctx->record_type); 1801 TYPE_NAME (ctx->record_type) = name; 1802 1803 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx); 1804 scan_omp (gimple_omp_body (stmt), ctx); 1805 1806 if (TYPE_FIELDS (ctx->record_type) == NULL) 1807 ctx->record_type = NULL; 1808 else 1809 layout_type (ctx->record_type); 1810} 1811 1812 1813/* Check OpenMP nesting restrictions. */ 1814static void 1815check_omp_nesting_restrictions (gimple stmt, omp_context *ctx) 1816{ 1817 switch (gimple_code (stmt)) 1818 { 1819 case GIMPLE_OMP_FOR: 1820 case GIMPLE_OMP_SECTIONS: 1821 case GIMPLE_OMP_SINGLE: 1822 case GIMPLE_CALL: 1823 for (; ctx != NULL; ctx = ctx->outer) 1824 switch (gimple_code (ctx->stmt)) 1825 { 1826 case GIMPLE_OMP_FOR: 1827 case GIMPLE_OMP_SECTIONS: 1828 case GIMPLE_OMP_SINGLE: 1829 case GIMPLE_OMP_ORDERED: 1830 case GIMPLE_OMP_MASTER: 1831 case GIMPLE_OMP_TASK: 1832 if (is_gimple_call (stmt)) 1833 { 1834 warning (0, "barrier region may not be closely nested inside " 1835 "of work-sharing, critical, ordered, master or " 1836 "explicit task region"); 1837 return; 1838 } 1839 warning (0, "work-sharing region may not be closely nested inside " 1840 "of work-sharing, critical, ordered, master or explicit " 1841 "task region"); 1842 return; 1843 case GIMPLE_OMP_PARALLEL: 1844 return; 1845 default: 1846 break; 1847 } 1848 break; 1849 case GIMPLE_OMP_MASTER: 1850 for (; ctx != NULL; ctx = ctx->outer) 1851 switch (gimple_code (ctx->stmt)) 1852 { 1853 case GIMPLE_OMP_FOR: 1854 case GIMPLE_OMP_SECTIONS: 1855 case GIMPLE_OMP_SINGLE: 1856 case GIMPLE_OMP_TASK: 1857 warning (0, "master region may not be closely nested inside " 1858 "of work-sharing or explicit task region"); 1859 return; 1860 case GIMPLE_OMP_PARALLEL: 1861 return; 1862 default: 1863 break; 1864 } 1865 break; 1866 case GIMPLE_OMP_ORDERED: 1867 for (; ctx != NULL; ctx = ctx->outer) 1868 switch (gimple_code (ctx->stmt)) 1869 { 1870 case GIMPLE_OMP_CRITICAL: 1871 case GIMPLE_OMP_TASK: 1872 warning (0, "ordered region may not be closely nested inside " 1873 "of critical or explicit task region"); 1874 return; 1875 case GIMPLE_OMP_FOR: 1876 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt), 1877 OMP_CLAUSE_ORDERED) == NULL) 1878 warning (0, "ordered region must be closely nested inside " 1879 "a loop region with an ordered clause"); 1880 return; 1881 case GIMPLE_OMP_PARALLEL: 1882 return; 1883 default: 1884 break; 1885 } 1886 break; 1887 case GIMPLE_OMP_CRITICAL: 1888 for (; ctx != NULL; ctx = ctx->outer) 1889 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL 1890 && (gimple_omp_critical_name (stmt) 1891 == gimple_omp_critical_name (ctx->stmt))) 1892 { 1893 warning (0, "critical region may not be nested inside a critical " 1894 "region with the same name"); 1895 return; 1896 } 1897 break; 1898 default: 1899 break; 1900 } 1901} 1902 1903 1904/* Helper function scan_omp. 1905 1906 Callback for walk_tree or operators in walk_gimple_stmt used to 1907 scan for OpenMP directives in TP. */ 1908 1909static tree 1910scan_omp_1_op (tree *tp, int *walk_subtrees, void *data) 1911{ 1912 struct walk_stmt_info *wi = (struct walk_stmt_info *) data; 1913 omp_context *ctx = (omp_context *) wi->info; 1914 tree t = *tp; 1915 1916 switch (TREE_CODE (t)) 1917 { 1918 case VAR_DECL: 1919 case PARM_DECL: 1920 case LABEL_DECL: 1921 case RESULT_DECL: 1922 if (ctx) 1923 *tp = remap_decl (t, &ctx->cb); 1924 break; 1925 1926 default: 1927 if (ctx && TYPE_P (t)) 1928 *tp = remap_type (t, &ctx->cb); 1929 else if (!DECL_P (t)) 1930 { 1931 *walk_subtrees = 1; 1932 if (ctx) 1933 { 1934 tree tem = remap_type (TREE_TYPE (t), &ctx->cb); 1935 if (tem != TREE_TYPE (t)) 1936 { 1937 if (TREE_CODE (t) == INTEGER_CST) 1938 *tp = build_int_cst_wide (tem, 1939 TREE_INT_CST_LOW (t), 1940 TREE_INT_CST_HIGH (t)); 1941 else 1942 TREE_TYPE (t) = tem; 1943 } 1944 } 1945 } 1946 break; 1947 } 1948 1949 return NULL_TREE; 1950} 1951 1952 1953/* Helper function for scan_omp. 1954 1955 Callback for walk_gimple_stmt used to scan for OpenMP directives in 1956 the current statement in GSI. */ 1957 1958static tree 1959scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, 1960 struct walk_stmt_info *wi) 1961{ 1962 gimple stmt = gsi_stmt (*gsi); 1963 omp_context *ctx = (omp_context *) wi->info; 1964 1965 if (gimple_has_location (stmt)) 1966 input_location = gimple_location (stmt); 1967 1968 /* Check the OpenMP nesting restrictions. */ 1969 if (ctx != NULL) 1970 { 1971 if (is_gimple_omp (stmt)) 1972 check_omp_nesting_restrictions (stmt, ctx); 1973 else if (is_gimple_call (stmt)) 1974 { 1975 tree fndecl = gimple_call_fndecl (stmt); 1976 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL 1977 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER) 1978 check_omp_nesting_restrictions (stmt, ctx); 1979 } 1980 } 1981 1982 *handled_ops_p = true; 1983 1984 switch (gimple_code (stmt)) 1985 { 1986 case GIMPLE_OMP_PARALLEL: 1987 taskreg_nesting_level++; 1988 scan_omp_parallel (gsi, ctx); 1989 taskreg_nesting_level--; 1990 break; 1991 1992 case GIMPLE_OMP_TASK: 1993 taskreg_nesting_level++; 1994 scan_omp_task (gsi, ctx); 1995 taskreg_nesting_level--; 1996 break; 1997 1998 case GIMPLE_OMP_FOR: 1999 scan_omp_for (stmt, ctx); 2000 break; 2001 2002 case GIMPLE_OMP_SECTIONS: 2003 scan_omp_sections (stmt, ctx); 2004 break; 2005 2006 case GIMPLE_OMP_SINGLE: 2007 scan_omp_single (stmt, ctx); 2008 break; 2009 2010 case GIMPLE_OMP_SECTION: 2011 case GIMPLE_OMP_MASTER: 2012 case GIMPLE_OMP_ORDERED: 2013 case GIMPLE_OMP_CRITICAL: 2014 ctx = new_omp_context (stmt, ctx); 2015 scan_omp (gimple_omp_body (stmt), ctx); 2016 break; 2017 2018 case GIMPLE_BIND: 2019 { 2020 tree var; 2021 2022 *handled_ops_p = false; 2023 if (ctx) 2024 for (var = gimple_bind_vars (stmt); var ; var = TREE_CHAIN (var)) 2025 insert_decl_map (&ctx->cb, var, var); 2026 } 2027 break; 2028 default: 2029 *handled_ops_p = false; 2030 break; 2031 } 2032 2033 return NULL_TREE; 2034} 2035 2036 2037/* Scan all the statements starting at the current statement. CTX 2038 contains context information about the OpenMP directives and 2039 clauses found during the scan. */ 2040 2041static void 2042scan_omp (gimple_seq body, omp_context *ctx) 2043{ 2044 location_t saved_location; 2045 struct walk_stmt_info wi; 2046 2047 memset (&wi, 0, sizeof (wi)); 2048 wi.info = ctx; 2049 wi.want_locations = true; 2050 2051 saved_location = input_location; 2052 walk_gimple_seq (body, scan_omp_1_stmt, scan_omp_1_op, &wi); 2053 input_location = saved_location; 2054} 2055 2056/* Re-gimplification and code generation routines. */ 2057 2058/* Build a call to GOMP_barrier. */ 2059 2060static tree 2061build_omp_barrier (void) 2062{ 2063 return build_call_expr (built_in_decls[BUILT_IN_GOMP_BARRIER], 0); 2064} 2065 2066/* If a context was created for STMT when it was scanned, return it. */ 2067 2068static omp_context * 2069maybe_lookup_ctx (gimple stmt) 2070{ 2071 splay_tree_node n; 2072 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt); 2073 return n ? (omp_context *) n->value : NULL; 2074} 2075 2076 2077/* Find the mapping for DECL in CTX or the immediately enclosing 2078 context that has a mapping for DECL. 2079 2080 If CTX is a nested parallel directive, we may have to use the decl 2081 mappings created in CTX's parent context. Suppose that we have the 2082 following parallel nesting (variable UIDs showed for clarity): 2083 2084 iD.1562 = 0; 2085 #omp parallel shared(iD.1562) -> outer parallel 2086 iD.1562 = iD.1562 + 1; 2087 2088 #omp parallel shared (iD.1562) -> inner parallel 2089 iD.1562 = iD.1562 - 1; 2090 2091 Each parallel structure will create a distinct .omp_data_s structure 2092 for copying iD.1562 in/out of the directive: 2093 2094 outer parallel .omp_data_s.1.i -> iD.1562 2095 inner parallel .omp_data_s.2.i -> iD.1562 2096 2097 A shared variable mapping will produce a copy-out operation before 2098 the parallel directive and a copy-in operation after it. So, in 2099 this case we would have: 2100 2101 iD.1562 = 0; 2102 .omp_data_o.1.i = iD.1562; 2103 #omp parallel shared(iD.1562) -> outer parallel 2104 .omp_data_i.1 = &.omp_data_o.1 2105 .omp_data_i.1->i = .omp_data_i.1->i + 1; 2106 2107 .omp_data_o.2.i = iD.1562; -> ** 2108 #omp parallel shared(iD.1562) -> inner parallel 2109 .omp_data_i.2 = &.omp_data_o.2 2110 .omp_data_i.2->i = .omp_data_i.2->i - 1; 2111 2112 2113 ** This is a problem. The symbol iD.1562 cannot be referenced 2114 inside the body of the outer parallel region. But since we are 2115 emitting this copy operation while expanding the inner parallel 2116 directive, we need to access the CTX structure of the outer 2117 parallel directive to get the correct mapping: 2118 2119 .omp_data_o.2.i = .omp_data_i.1->i 2120 2121 Since there may be other workshare or parallel directives enclosing 2122 the parallel directive, it may be necessary to walk up the context 2123 parent chain. This is not a problem in general because nested 2124 parallelism happens only rarely. */ 2125 2126static tree 2127lookup_decl_in_outer_ctx (tree decl, omp_context *ctx) 2128{ 2129 tree t; 2130 omp_context *up; 2131 2132 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer) 2133 t = maybe_lookup_decl (decl, up); 2134 2135 gcc_assert (!ctx->is_nested || t || is_global_var (decl)); 2136 2137 return t ? t : decl; 2138} 2139 2140 2141/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found 2142 in outer contexts. */ 2143 2144static tree 2145maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx) 2146{ 2147 tree t = NULL; 2148 omp_context *up; 2149 2150 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer) 2151 t = maybe_lookup_decl (decl, up); 2152 2153 return t ? t : decl; 2154} 2155 2156 2157/* Construct the initialization value for reduction CLAUSE. */ 2158 2159tree 2160omp_reduction_init (tree clause, tree type) 2161{ 2162 location_t loc = OMP_CLAUSE_LOCATION (clause); 2163 switch (OMP_CLAUSE_REDUCTION_CODE (clause)) 2164 { 2165 case PLUS_EXPR: 2166 case MINUS_EXPR: 2167 case BIT_IOR_EXPR: 2168 case BIT_XOR_EXPR: 2169 case TRUTH_OR_EXPR: 2170 case TRUTH_ORIF_EXPR: 2171 case TRUTH_XOR_EXPR: 2172 case NE_EXPR: 2173 return fold_convert_loc (loc, type, integer_zero_node); 2174 2175 case MULT_EXPR: 2176 case TRUTH_AND_EXPR: 2177 case TRUTH_ANDIF_EXPR: 2178 case EQ_EXPR: 2179 return fold_convert_loc (loc, type, integer_one_node); 2180 2181 case BIT_AND_EXPR: 2182 return fold_convert_loc (loc, type, integer_minus_one_node); 2183 2184 case MAX_EXPR: 2185 if (SCALAR_FLOAT_TYPE_P (type)) 2186 { 2187 REAL_VALUE_TYPE max, min; 2188 if (HONOR_INFINITIES (TYPE_MODE (type))) 2189 { 2190 real_inf (&max); 2191 real_arithmetic (&min, NEGATE_EXPR, &max, NULL); 2192 } 2193 else 2194 real_maxval (&min, 1, TYPE_MODE (type)); 2195 return build_real (type, min); 2196 } 2197 else 2198 { 2199 gcc_assert (INTEGRAL_TYPE_P (type)); 2200 return TYPE_MIN_VALUE (type); 2201 } 2202 2203 case MIN_EXPR: 2204 if (SCALAR_FLOAT_TYPE_P (type)) 2205 { 2206 REAL_VALUE_TYPE max; 2207 if (HONOR_INFINITIES (TYPE_MODE (type))) 2208 real_inf (&max); 2209 else 2210 real_maxval (&max, 0, TYPE_MODE (type)); 2211 return build_real (type, max); 2212 } 2213 else 2214 { 2215 gcc_assert (INTEGRAL_TYPE_P (type)); 2216 return TYPE_MAX_VALUE (type); 2217 } 2218 2219 default: 2220 gcc_unreachable (); 2221 } 2222} 2223 2224/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN, 2225 from the receiver (aka child) side and initializers for REFERENCE_TYPE 2226 private variables. Initialization statements go in ILIST, while calls 2227 to destructors go in DLIST. */ 2228 2229static void 2230lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, 2231 omp_context *ctx) 2232{ 2233 gimple_stmt_iterator diter; 2234 tree c, dtor, copyin_seq, x, ptr; 2235 bool copyin_by_ref = false; 2236 bool lastprivate_firstprivate = false; 2237 int pass; 2238 2239 *dlist = gimple_seq_alloc (); 2240 diter = gsi_start (*dlist); 2241 copyin_seq = NULL; 2242 2243 /* Do all the fixed sized types in the first pass, and the variable sized 2244 types in the second pass. This makes sure that the scalar arguments to 2245 the variable sized types are processed before we use them in the 2246 variable sized operations. */ 2247 for (pass = 0; pass < 2; ++pass) 2248 { 2249 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 2250 { 2251 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c); 2252 tree var, new_var; 2253 bool by_ref; 2254 location_t clause_loc = OMP_CLAUSE_LOCATION (c); 2255 2256 switch (c_kind) 2257 { 2258 case OMP_CLAUSE_PRIVATE: 2259 if (OMP_CLAUSE_PRIVATE_DEBUG (c)) 2260 continue; 2261 break; 2262 case OMP_CLAUSE_SHARED: 2263 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL) 2264 { 2265 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c))); 2266 continue; 2267 } 2268 case OMP_CLAUSE_FIRSTPRIVATE: 2269 case OMP_CLAUSE_COPYIN: 2270 case OMP_CLAUSE_REDUCTION: 2271 break; 2272 case OMP_CLAUSE_LASTPRIVATE: 2273 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 2274 { 2275 lastprivate_firstprivate = true; 2276 if (pass != 0) 2277 continue; 2278 } 2279 break; 2280 default: 2281 continue; 2282 } 2283 2284 new_var = var = OMP_CLAUSE_DECL (c); 2285 if (c_kind != OMP_CLAUSE_COPYIN) 2286 new_var = lookup_decl (var, ctx); 2287 2288 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN) 2289 { 2290 if (pass != 0) 2291 continue; 2292 } 2293 else if (is_variable_sized (var)) 2294 { 2295 /* For variable sized types, we need to allocate the 2296 actual storage here. Call alloca and store the 2297 result in the pointer decl that we created elsewhere. */ 2298 if (pass == 0) 2299 continue; 2300 2301 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx)) 2302 { 2303 gimple stmt; 2304 tree tmp; 2305 2306 ptr = DECL_VALUE_EXPR (new_var); 2307 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF); 2308 ptr = TREE_OPERAND (ptr, 0); 2309 gcc_assert (DECL_P (ptr)); 2310 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var)); 2311 2312 /* void *tmp = __builtin_alloca */ 2313 stmt 2314 = gimple_build_call (built_in_decls[BUILT_IN_ALLOCA], 1, x); 2315 tmp = create_tmp_var_raw (ptr_type_node, NULL); 2316 gimple_add_tmp_var (tmp); 2317 gimple_call_set_lhs (stmt, tmp); 2318 2319 gimple_seq_add_stmt (ilist, stmt); 2320 2321 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp); 2322 gimplify_assign (ptr, x, ilist); 2323 } 2324 } 2325 else if (is_reference (var)) 2326 { 2327 /* For references that are being privatized for Fortran, 2328 allocate new backing storage for the new pointer 2329 variable. This allows us to avoid changing all the 2330 code that expects a pointer to something that expects 2331 a direct variable. Note that this doesn't apply to 2332 C++, since reference types are disallowed in data 2333 sharing clauses there, except for NRV optimized 2334 return values. */ 2335 if (pass == 0) 2336 continue; 2337 2338 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var))); 2339 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx)) 2340 { 2341 x = build_receiver_ref (var, false, ctx); 2342 x = build_fold_addr_expr_loc (clause_loc, x); 2343 } 2344 else if (TREE_CONSTANT (x)) 2345 { 2346 const char *name = NULL; 2347 if (DECL_NAME (var)) 2348 name = IDENTIFIER_POINTER (DECL_NAME (new_var)); 2349 2350 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)), 2351 name); 2352 gimple_add_tmp_var (x); 2353 TREE_ADDRESSABLE (x) = 1; 2354 x = build_fold_addr_expr_loc (clause_loc, x); 2355 } 2356 else 2357 { 2358 x = build_call_expr_loc (clause_loc, 2359 built_in_decls[BUILT_IN_ALLOCA], 1, x); 2360 } 2361 2362 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x); 2363 gimplify_assign (new_var, x, ilist); 2364 2365 new_var = build_fold_indirect_ref_loc (clause_loc, new_var); 2366 } 2367 else if (c_kind == OMP_CLAUSE_REDUCTION 2368 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 2369 { 2370 if (pass == 0) 2371 continue; 2372 } 2373 else if (pass != 0) 2374 continue; 2375 2376 switch (OMP_CLAUSE_CODE (c)) 2377 { 2378 case OMP_CLAUSE_SHARED: 2379 /* Shared global vars are just accessed directly. */ 2380 if (is_global_var (new_var)) 2381 break; 2382 /* Set up the DECL_VALUE_EXPR for shared variables now. This 2383 needs to be delayed until after fixup_child_record_type so 2384 that we get the correct type during the dereference. */ 2385 by_ref = use_pointer_for_field (var, ctx); 2386 x = build_receiver_ref (var, by_ref, ctx); 2387 SET_DECL_VALUE_EXPR (new_var, x); 2388 DECL_HAS_VALUE_EXPR_P (new_var) = 1; 2389 2390 /* ??? If VAR is not passed by reference, and the variable 2391 hasn't been initialized yet, then we'll get a warning for 2392 the store into the omp_data_s structure. Ideally, we'd be 2393 able to notice this and not store anything at all, but 2394 we're generating code too early. Suppress the warning. */ 2395 if (!by_ref) 2396 TREE_NO_WARNING (var) = 1; 2397 break; 2398 2399 case OMP_CLAUSE_LASTPRIVATE: 2400 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 2401 break; 2402 /* FALLTHRU */ 2403 2404 case OMP_CLAUSE_PRIVATE: 2405 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE) 2406 x = build_outer_var_ref (var, ctx); 2407 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c)) 2408 { 2409 if (is_task_ctx (ctx)) 2410 x = build_receiver_ref (var, false, ctx); 2411 else 2412 x = build_outer_var_ref (var, ctx); 2413 } 2414 else 2415 x = NULL; 2416 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x); 2417 if (x) 2418 gimplify_and_add (x, ilist); 2419 /* FALLTHRU */ 2420 2421 do_dtor: 2422 x = lang_hooks.decls.omp_clause_dtor (c, new_var); 2423 if (x) 2424 { 2425 gimple_seq tseq = NULL; 2426 2427 dtor = x; 2428 gimplify_stmt (&dtor, &tseq); 2429 gsi_insert_seq_before (&diter, tseq, GSI_SAME_STMT); 2430 } 2431 break; 2432 2433 case OMP_CLAUSE_FIRSTPRIVATE: 2434 if (is_task_ctx (ctx)) 2435 { 2436 if (is_reference (var) || is_variable_sized (var)) 2437 goto do_dtor; 2438 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, 2439 ctx)) 2440 || use_pointer_for_field (var, NULL)) 2441 { 2442 x = build_receiver_ref (var, false, ctx); 2443 SET_DECL_VALUE_EXPR (new_var, x); 2444 DECL_HAS_VALUE_EXPR_P (new_var) = 1; 2445 goto do_dtor; 2446 } 2447 } 2448 x = build_outer_var_ref (var, ctx); 2449 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x); 2450 gimplify_and_add (x, ilist); 2451 goto do_dtor; 2452 break; 2453 2454 case OMP_CLAUSE_COPYIN: 2455 by_ref = use_pointer_for_field (var, NULL); 2456 x = build_receiver_ref (var, by_ref, ctx); 2457 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x); 2458 append_to_statement_list (x, ©in_seq); 2459 copyin_by_ref |= by_ref; 2460 break; 2461 2462 case OMP_CLAUSE_REDUCTION: 2463 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 2464 { 2465 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); 2466 x = build_outer_var_ref (var, ctx); 2467 2468 if (is_reference (var)) 2469 x = build_fold_addr_expr_loc (clause_loc, x); 2470 SET_DECL_VALUE_EXPR (placeholder, x); 2471 DECL_HAS_VALUE_EXPR_P (placeholder) = 1; 2472 lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx); 2473 gimple_seq_add_seq (ilist, 2474 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)); 2475 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL; 2476 DECL_HAS_VALUE_EXPR_P (placeholder) = 0; 2477 } 2478 else 2479 { 2480 x = omp_reduction_init (c, TREE_TYPE (new_var)); 2481 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE); 2482 gimplify_assign (new_var, x, ilist); 2483 } 2484 break; 2485 2486 default: 2487 gcc_unreachable (); 2488 } 2489 } 2490 } 2491 2492 /* The copyin sequence is not to be executed by the main thread, since 2493 that would result in self-copies. Perhaps not visible to scalars, 2494 but it certainly is to C++ operator=. */ 2495 if (copyin_seq) 2496 { 2497 x = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); 2498 x = build2 (NE_EXPR, boolean_type_node, x, 2499 build_int_cst (TREE_TYPE (x), 0)); 2500 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL); 2501 gimplify_and_add (x, ilist); 2502 } 2503 2504 /* If any copyin variable is passed by reference, we must ensure the 2505 master thread doesn't modify it before it is copied over in all 2506 threads. Similarly for variables in both firstprivate and 2507 lastprivate clauses we need to ensure the lastprivate copying 2508 happens after firstprivate copying in all threads. */ 2509 if (copyin_by_ref || lastprivate_firstprivate) 2510 gimplify_and_add (build_omp_barrier (), ilist); 2511} 2512 2513 2514/* Generate code to implement the LASTPRIVATE clauses. This is used for 2515 both parallel and workshare constructs. PREDICATE may be NULL if it's 2516 always true. */ 2517 2518static void 2519lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list, 2520 omp_context *ctx) 2521{ 2522 tree x, c, label = NULL; 2523 bool par_clauses = false; 2524 2525 /* Early exit if there are no lastprivate clauses. */ 2526 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE); 2527 if (clauses == NULL) 2528 { 2529 /* If this was a workshare clause, see if it had been combined 2530 with its parallel. In that case, look for the clauses on the 2531 parallel statement itself. */ 2532 if (is_parallel_ctx (ctx)) 2533 return; 2534 2535 ctx = ctx->outer; 2536 if (ctx == NULL || !is_parallel_ctx (ctx)) 2537 return; 2538 2539 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt), 2540 OMP_CLAUSE_LASTPRIVATE); 2541 if (clauses == NULL) 2542 return; 2543 par_clauses = true; 2544 } 2545 2546 if (predicate) 2547 { 2548 gimple stmt; 2549 tree label_true, arm1, arm2; 2550 2551 label = create_artificial_label (UNKNOWN_LOCATION); 2552 label_true = create_artificial_label (UNKNOWN_LOCATION); 2553 arm1 = TREE_OPERAND (predicate, 0); 2554 arm2 = TREE_OPERAND (predicate, 1); 2555 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue); 2556 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue); 2557 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2, 2558 label_true, label); 2559 gimple_seq_add_stmt (stmt_list, stmt); 2560 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true)); 2561 } 2562 2563 for (c = clauses; c ;) 2564 { 2565 tree var, new_var; 2566 location_t clause_loc = OMP_CLAUSE_LOCATION (c); 2567 2568 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) 2569 { 2570 var = OMP_CLAUSE_DECL (c); 2571 new_var = lookup_decl (var, ctx); 2572 2573 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)) 2574 { 2575 lower_omp (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx); 2576 gimple_seq_add_seq (stmt_list, 2577 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)); 2578 } 2579 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL; 2580 2581 x = build_outer_var_ref (var, ctx); 2582 if (is_reference (var)) 2583 new_var = build_fold_indirect_ref_loc (clause_loc, new_var); 2584 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var); 2585 gimplify_and_add (x, stmt_list); 2586 } 2587 c = OMP_CLAUSE_CHAIN (c); 2588 if (c == NULL && !par_clauses) 2589 { 2590 /* If this was a workshare clause, see if it had been combined 2591 with its parallel. In that case, continue looking for the 2592 clauses also on the parallel statement itself. */ 2593 if (is_parallel_ctx (ctx)) 2594 break; 2595 2596 ctx = ctx->outer; 2597 if (ctx == NULL || !is_parallel_ctx (ctx)) 2598 break; 2599 2600 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt), 2601 OMP_CLAUSE_LASTPRIVATE); 2602 par_clauses = true; 2603 } 2604 } 2605 2606 if (label) 2607 gimple_seq_add_stmt (stmt_list, gimple_build_label (label)); 2608} 2609 2610 2611/* Generate code to implement the REDUCTION clauses. */ 2612 2613static void 2614lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx) 2615{ 2616 gimple_seq sub_seq = NULL; 2617 gimple stmt; 2618 tree x, c; 2619 int count = 0; 2620 2621 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC 2622 update in that case, otherwise use a lock. */ 2623 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c)) 2624 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) 2625 { 2626 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 2627 { 2628 /* Never use OMP_ATOMIC for array reductions. */ 2629 count = -1; 2630 break; 2631 } 2632 count++; 2633 } 2634 2635 if (count == 0) 2636 return; 2637 2638 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 2639 { 2640 tree var, ref, new_var; 2641 enum tree_code code; 2642 location_t clause_loc = OMP_CLAUSE_LOCATION (c); 2643 2644 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION) 2645 continue; 2646 2647 var = OMP_CLAUSE_DECL (c); 2648 new_var = lookup_decl (var, ctx); 2649 if (is_reference (var)) 2650 new_var = build_fold_indirect_ref_loc (clause_loc, new_var); 2651 ref = build_outer_var_ref (var, ctx); 2652 code = OMP_CLAUSE_REDUCTION_CODE (c); 2653 2654 /* reduction(-:var) sums up the partial results, so it acts 2655 identically to reduction(+:var). */ 2656 if (code == MINUS_EXPR) 2657 code = PLUS_EXPR; 2658 2659 if (count == 1) 2660 { 2661 tree addr = build_fold_addr_expr_loc (clause_loc, ref); 2662 2663 addr = save_expr (addr); 2664 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr); 2665 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var); 2666 x = build2 (OMP_ATOMIC, void_type_node, addr, x); 2667 gimplify_and_add (x, stmt_seqp); 2668 return; 2669 } 2670 2671 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) 2672 { 2673 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); 2674 2675 if (is_reference (var)) 2676 ref = build_fold_addr_expr_loc (clause_loc, ref); 2677 SET_DECL_VALUE_EXPR (placeholder, ref); 2678 DECL_HAS_VALUE_EXPR_P (placeholder) = 1; 2679 lower_omp (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx); 2680 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)); 2681 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL; 2682 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL; 2683 } 2684 else 2685 { 2686 x = build2 (code, TREE_TYPE (ref), ref, new_var); 2687 ref = build_outer_var_ref (var, ctx); 2688 gimplify_assign (ref, x, &sub_seq); 2689 } 2690 } 2691 2692 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_START], 0); 2693 gimple_seq_add_stmt (stmt_seqp, stmt); 2694 2695 gimple_seq_add_seq (stmt_seqp, sub_seq); 2696 2697 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ATOMIC_END], 0); 2698 gimple_seq_add_stmt (stmt_seqp, stmt); 2699} 2700 2701 2702/* Generate code to implement the COPYPRIVATE clauses. */ 2703 2704static void 2705lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist, 2706 omp_context *ctx) 2707{ 2708 tree c; 2709 2710 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 2711 { 2712 tree var, new_var, ref, x; 2713 bool by_ref; 2714 location_t clause_loc = OMP_CLAUSE_LOCATION (c); 2715 2716 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE) 2717 continue; 2718 2719 var = OMP_CLAUSE_DECL (c); 2720 by_ref = use_pointer_for_field (var, NULL); 2721 2722 ref = build_sender_ref (var, ctx); 2723 x = new_var = lookup_decl_in_outer_ctx (var, ctx); 2724 if (by_ref) 2725 { 2726 x = build_fold_addr_expr_loc (clause_loc, new_var); 2727 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x); 2728 } 2729 gimplify_assign (ref, x, slist); 2730 2731 ref = build_receiver_ref (var, false, ctx); 2732 if (by_ref) 2733 { 2734 ref = fold_convert_loc (clause_loc, 2735 build_pointer_type (TREE_TYPE (new_var)), 2736 ref); 2737 ref = build_fold_indirect_ref_loc (clause_loc, ref); 2738 } 2739 if (is_reference (var)) 2740 { 2741 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref); 2742 ref = build_fold_indirect_ref_loc (clause_loc, ref); 2743 new_var = build_fold_indirect_ref_loc (clause_loc, new_var); 2744 } 2745 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref); 2746 gimplify_and_add (x, rlist); 2747 } 2748} 2749 2750 2751/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE, 2752 and REDUCTION from the sender (aka parent) side. */ 2753 2754static void 2755lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist, 2756 omp_context *ctx) 2757{ 2758 tree c; 2759 2760 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) 2761 { 2762 tree val, ref, x, var; 2763 bool by_ref, do_in = false, do_out = false; 2764 location_t clause_loc = OMP_CLAUSE_LOCATION (c); 2765 2766 switch (OMP_CLAUSE_CODE (c)) 2767 { 2768 case OMP_CLAUSE_PRIVATE: 2769 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c)) 2770 break; 2771 continue; 2772 case OMP_CLAUSE_FIRSTPRIVATE: 2773 case OMP_CLAUSE_COPYIN: 2774 case OMP_CLAUSE_LASTPRIVATE: 2775 case OMP_CLAUSE_REDUCTION: 2776 break; 2777 default: 2778 continue; 2779 } 2780 2781 val = OMP_CLAUSE_DECL (c); 2782 var = lookup_decl_in_outer_ctx (val, ctx); 2783 2784 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN 2785 && is_global_var (var)) 2786 continue; 2787 if (is_variable_sized (val)) 2788 continue; 2789 by_ref = use_pointer_for_field (val, NULL); 2790 2791 switch (OMP_CLAUSE_CODE (c)) 2792 { 2793 case OMP_CLAUSE_PRIVATE: 2794 case OMP_CLAUSE_FIRSTPRIVATE: 2795 case OMP_CLAUSE_COPYIN: 2796 do_in = true; 2797 break; 2798 2799 case OMP_CLAUSE_LASTPRIVATE: 2800 if (by_ref || is_reference (val)) 2801 { 2802 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)) 2803 continue; 2804 do_in = true; 2805 } 2806 else 2807 { 2808 do_out = true; 2809 if (lang_hooks.decls.omp_private_outer_ref (val)) 2810 do_in = true; 2811 } 2812 break; 2813 2814 case OMP_CLAUSE_REDUCTION: 2815 do_in = true; 2816 do_out = !(by_ref || is_reference (val)); 2817 break; 2818 2819 default: 2820 gcc_unreachable (); 2821 } 2822 2823 if (do_in) 2824 { 2825 ref = build_sender_ref (val, ctx); 2826 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var; 2827 gimplify_assign (ref, x, ilist); 2828 if (is_task_ctx (ctx)) 2829 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL; 2830 } 2831 2832 if (do_out) 2833 { 2834 ref = build_sender_ref (val, ctx); 2835 gimplify_assign (var, ref, olist); 2836 } 2837 } 2838} 2839 2840/* Generate code to implement SHARED from the sender (aka parent) 2841 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't 2842 list things that got automatically shared. */ 2843 2844static void 2845lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx) 2846{ 2847 tree var, ovar, nvar, f, x, record_type; 2848 2849 if (ctx->record_type == NULL) 2850 return; 2851 2852 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type; 2853 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f)) 2854 { 2855 ovar = DECL_ABSTRACT_ORIGIN (f); 2856 nvar = maybe_lookup_decl (ovar, ctx); 2857 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar)) 2858 continue; 2859 2860 /* If CTX is a nested parallel directive. Find the immediately 2861 enclosing parallel or workshare construct that contains a 2862 mapping for OVAR. */ 2863 var = lookup_decl_in_outer_ctx (ovar, ctx); 2864 2865 if (use_pointer_for_field (ovar, ctx)) 2866 { 2867 x = build_sender_ref (ovar, ctx); 2868 var = build_fold_addr_expr (var); 2869 gimplify_assign (x, var, ilist); 2870 } 2871 else 2872 { 2873 x = build_sender_ref (ovar, ctx); 2874 gimplify_assign (x, var, ilist); 2875 2876 if (!TREE_READONLY (var) 2877 /* We don't need to receive a new reference to a result 2878 or parm decl. In fact we may not store to it as we will 2879 invalidate any pending RSO and generate wrong gimple 2880 during inlining. */ 2881 && !((TREE_CODE (var) == RESULT_DECL 2882 || TREE_CODE (var) == PARM_DECL) 2883 && DECL_BY_REFERENCE (var))) 2884 { 2885 x = build_sender_ref (ovar, ctx); 2886 gimplify_assign (var, x, olist); 2887 } 2888 } 2889 } 2890} 2891 2892 2893/* A convenience function to build an empty GIMPLE_COND with just the 2894 condition. */ 2895 2896static gimple 2897gimple_build_cond_empty (tree cond) 2898{ 2899 enum tree_code pred_code; 2900 tree lhs, rhs; 2901 2902 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs); 2903 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE); 2904} 2905 2906 2907/* Build the function calls to GOMP_parallel_start etc to actually 2908 generate the parallel operation. REGION is the parallel region 2909 being expanded. BB is the block where to insert the code. WS_ARGS 2910 will be set if this is a call to a combined parallel+workshare 2911 construct, it contains the list of additional arguments needed by 2912 the workshare construct. */ 2913 2914static void 2915expand_parallel_call (struct omp_region *region, basic_block bb, 2916 gimple entry_stmt, tree ws_args) 2917{ 2918 tree t, t1, t2, val, cond, c, clauses; 2919 gimple_stmt_iterator gsi; 2920 gimple stmt; 2921 int start_ix; 2922 location_t clause_loc; 2923 2924 clauses = gimple_omp_parallel_clauses (entry_stmt); 2925 2926 /* Determine what flavor of GOMP_parallel_start we will be 2927 emitting. */ 2928 start_ix = BUILT_IN_GOMP_PARALLEL_START; 2929 if (is_combined_parallel (region)) 2930 { 2931 switch (region->inner->type) 2932 { 2933 case GIMPLE_OMP_FOR: 2934 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO); 2935 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START 2936 + (region->inner->sched_kind 2937 == OMP_CLAUSE_SCHEDULE_RUNTIME 2938 ? 3 : region->inner->sched_kind); 2939 break; 2940 case GIMPLE_OMP_SECTIONS: 2941 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START; 2942 break; 2943 default: 2944 gcc_unreachable (); 2945 } 2946 } 2947 2948 /* By default, the value of NUM_THREADS is zero (selected at run time) 2949 and there is no conditional. */ 2950 cond = NULL_TREE; 2951 val = build_int_cst (unsigned_type_node, 0); 2952 2953 c = find_omp_clause (clauses, OMP_CLAUSE_IF); 2954 if (c) 2955 cond = OMP_CLAUSE_IF_EXPR (c); 2956 2957 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS); 2958 if (c) 2959 { 2960 val = OMP_CLAUSE_NUM_THREADS_EXPR (c); 2961 clause_loc = OMP_CLAUSE_LOCATION (c); 2962 } 2963 else 2964 clause_loc = gimple_location (entry_stmt); 2965 2966 /* Ensure 'val' is of the correct type. */ 2967 val = fold_convert_loc (clause_loc, unsigned_type_node, val); 2968 2969 /* If we found the clause 'if (cond)', build either 2970 (cond != 0) or (cond ? val : 1u). */ 2971 if (cond) 2972 { 2973 gimple_stmt_iterator gsi; 2974 2975 cond = gimple_boolify (cond); 2976 2977 if (integer_zerop (val)) 2978 val = fold_build2_loc (clause_loc, 2979 EQ_EXPR, unsigned_type_node, cond, 2980 build_int_cst (TREE_TYPE (cond), 0)); 2981 else 2982 { 2983 basic_block cond_bb, then_bb, else_bb; 2984 edge e, e_then, e_else; 2985 tree tmp_then, tmp_else, tmp_join, tmp_var; 2986 2987 tmp_var = create_tmp_var (TREE_TYPE (val), NULL); 2988 if (gimple_in_ssa_p (cfun)) 2989 { 2990 tmp_then = make_ssa_name (tmp_var, NULL); 2991 tmp_else = make_ssa_name (tmp_var, NULL); 2992 tmp_join = make_ssa_name (tmp_var, NULL); 2993 } 2994 else 2995 { 2996 tmp_then = tmp_var; 2997 tmp_else = tmp_var; 2998 tmp_join = tmp_var; 2999 } 3000 3001 e = split_block (bb, NULL); 3002 cond_bb = e->src; 3003 bb = e->dest; 3004 remove_edge (e); 3005 3006 then_bb = create_empty_bb (cond_bb); 3007 else_bb = create_empty_bb (then_bb); 3008 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb); 3009 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb); 3010 3011 stmt = gimple_build_cond_empty (cond); 3012 gsi = gsi_start_bb (cond_bb); 3013 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3014 3015 gsi = gsi_start_bb (then_bb); 3016 stmt = gimple_build_assign (tmp_then, val); 3017 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3018 3019 gsi = gsi_start_bb (else_bb); 3020 stmt = gimple_build_assign 3021 (tmp_else, build_int_cst (unsigned_type_node, 1)); 3022 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3023 3024 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); 3025 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE); 3026 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU); 3027 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU); 3028 3029 if (gimple_in_ssa_p (cfun)) 3030 { 3031 gimple phi = create_phi_node (tmp_join, bb); 3032 SSA_NAME_DEF_STMT (tmp_join) = phi; 3033 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION); 3034 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION); 3035 } 3036 3037 val = tmp_join; 3038 } 3039 3040 gsi = gsi_start_bb (bb); 3041 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE, 3042 false, GSI_CONTINUE_LINKING); 3043 } 3044 3045 gsi = gsi_last_bb (bb); 3046 t = gimple_omp_parallel_data_arg (entry_stmt); 3047 if (t == NULL) 3048 t1 = null_pointer_node; 3049 else 3050 t1 = build_fold_addr_expr (t); 3051 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt)); 3052 3053 if (ws_args) 3054 { 3055 tree args = tree_cons (NULL, t2, 3056 tree_cons (NULL, t1, 3057 tree_cons (NULL, val, ws_args))); 3058 t = build_function_call_expr (UNKNOWN_LOCATION, 3059 built_in_decls[start_ix], args); 3060 } 3061 else 3062 t = build_call_expr (built_in_decls[start_ix], 3, t2, t1, val); 3063 3064 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3065 false, GSI_CONTINUE_LINKING); 3066 3067 t = gimple_omp_parallel_data_arg (entry_stmt); 3068 if (t == NULL) 3069 t = null_pointer_node; 3070 else 3071 t = build_fold_addr_expr (t); 3072 t = build_call_expr_loc (gimple_location (entry_stmt), 3073 gimple_omp_parallel_child_fn (entry_stmt), 1, t); 3074 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3075 false, GSI_CONTINUE_LINKING); 3076 3077 t = build_call_expr_loc (gimple_location (entry_stmt), 3078 built_in_decls[BUILT_IN_GOMP_PARALLEL_END], 0); 3079 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3080 false, GSI_CONTINUE_LINKING); 3081} 3082 3083 3084/* Build the function call to GOMP_task to actually 3085 generate the task operation. BB is the block where to insert the code. */ 3086 3087static void 3088expand_task_call (basic_block bb, gimple entry_stmt) 3089{ 3090 tree t, t1, t2, t3, flags, cond, c, clauses; 3091 gimple_stmt_iterator gsi; 3092 location_t loc = gimple_location (entry_stmt); 3093 3094 clauses = gimple_omp_task_clauses (entry_stmt); 3095 3096 c = find_omp_clause (clauses, OMP_CLAUSE_IF); 3097 if (c) 3098 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c)); 3099 else 3100 cond = boolean_true_node; 3101 3102 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED); 3103 flags = build_int_cst (unsigned_type_node, (c ? 1 : 0)); 3104 3105 gsi = gsi_last_bb (bb); 3106 t = gimple_omp_task_data_arg (entry_stmt); 3107 if (t == NULL) 3108 t2 = null_pointer_node; 3109 else 3110 t2 = build_fold_addr_expr_loc (loc, t); 3111 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt)); 3112 t = gimple_omp_task_copy_fn (entry_stmt); 3113 if (t == NULL) 3114 t3 = null_pointer_node; 3115 else 3116 t3 = build_fold_addr_expr_loc (loc, t); 3117 3118 t = build_call_expr (built_in_decls[BUILT_IN_GOMP_TASK], 7, t1, t2, t3, 3119 gimple_omp_task_arg_size (entry_stmt), 3120 gimple_omp_task_arg_align (entry_stmt), cond, flags); 3121 3122 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3123 false, GSI_CONTINUE_LINKING); 3124} 3125 3126 3127/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW 3128 catch handler and return it. This prevents programs from violating the 3129 structured block semantics with throws. */ 3130 3131static gimple_seq 3132maybe_catch_exception (gimple_seq body) 3133{ 3134 gimple g; 3135 tree decl; 3136 3137 if (!flag_exceptions) 3138 return body; 3139 3140 if (lang_protect_cleanup_actions) 3141 decl = lang_protect_cleanup_actions (); 3142 else 3143 decl = built_in_decls[BUILT_IN_TRAP]; 3144 3145 g = gimple_build_eh_must_not_throw (decl); 3146 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g), 3147 GIMPLE_TRY_CATCH); 3148 3149 return gimple_seq_alloc_with_stmt (g); 3150} 3151 3152/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */ 3153 3154static tree 3155list2chain (tree list) 3156{ 3157 tree t; 3158 3159 for (t = list; t; t = TREE_CHAIN (t)) 3160 { 3161 tree var = TREE_VALUE (t); 3162 if (TREE_CHAIN (t)) 3163 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t)); 3164 else 3165 TREE_CHAIN (var) = NULL_TREE; 3166 } 3167 3168 return list ? TREE_VALUE (list) : NULL_TREE; 3169} 3170 3171 3172/* Remove barriers in REGION->EXIT's block. Note that this is only 3173 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region 3174 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that 3175 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be 3176 removed. */ 3177 3178static void 3179remove_exit_barrier (struct omp_region *region) 3180{ 3181 gimple_stmt_iterator gsi; 3182 basic_block exit_bb; 3183 edge_iterator ei; 3184 edge e; 3185 gimple stmt; 3186 int any_addressable_vars = -1; 3187 3188 exit_bb = region->exit; 3189 3190 /* If the parallel region doesn't return, we don't have REGION->EXIT 3191 block at all. */ 3192 if (! exit_bb) 3193 return; 3194 3195 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The 3196 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of 3197 statements that can appear in between are extremely limited -- no 3198 memory operations at all. Here, we allow nothing at all, so the 3199 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */ 3200 gsi = gsi_last_bb (exit_bb); 3201 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); 3202 gsi_prev (&gsi); 3203 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL) 3204 return; 3205 3206 FOR_EACH_EDGE (e, ei, exit_bb->preds) 3207 { 3208 gsi = gsi_last_bb (e->src); 3209 if (gsi_end_p (gsi)) 3210 continue; 3211 stmt = gsi_stmt (gsi); 3212 if (gimple_code (stmt) == GIMPLE_OMP_RETURN 3213 && !gimple_omp_return_nowait_p (stmt)) 3214 { 3215 /* OpenMP 3.0 tasks unfortunately prevent this optimization 3216 in many cases. If there could be tasks queued, the barrier 3217 might be needed to let the tasks run before some local 3218 variable of the parallel that the task uses as shared 3219 runs out of scope. The task can be spawned either 3220 from within current function (this would be easy to check) 3221 or from some function it calls and gets passed an address 3222 of such a variable. */ 3223 if (any_addressable_vars < 0) 3224 { 3225 gimple parallel_stmt = last_stmt (region->entry); 3226 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt); 3227 tree local_decls = DECL_STRUCT_FUNCTION (child_fun)->local_decls; 3228 tree block; 3229 3230 any_addressable_vars = 0; 3231 for (; local_decls; local_decls = TREE_CHAIN (local_decls)) 3232 if (TREE_ADDRESSABLE (TREE_VALUE (local_decls))) 3233 { 3234 any_addressable_vars = 1; 3235 break; 3236 } 3237 for (block = gimple_block (stmt); 3238 !any_addressable_vars 3239 && block 3240 && TREE_CODE (block) == BLOCK; 3241 block = BLOCK_SUPERCONTEXT (block)) 3242 { 3243 for (local_decls = BLOCK_VARS (block); 3244 local_decls; 3245 local_decls = TREE_CHAIN (local_decls)) 3246 if (TREE_ADDRESSABLE (local_decls)) 3247 { 3248 any_addressable_vars = 1; 3249 break; 3250 } 3251 if (block == gimple_block (parallel_stmt)) 3252 break; 3253 } 3254 } 3255 if (!any_addressable_vars) 3256 gimple_omp_return_set_nowait (stmt); 3257 } 3258 } 3259} 3260 3261static void 3262remove_exit_barriers (struct omp_region *region) 3263{ 3264 if (region->type == GIMPLE_OMP_PARALLEL) 3265 remove_exit_barrier (region); 3266 3267 if (region->inner) 3268 { 3269 region = region->inner; 3270 remove_exit_barriers (region); 3271 while (region->next) 3272 { 3273 region = region->next; 3274 remove_exit_barriers (region); 3275 } 3276 } 3277} 3278 3279/* Optimize omp_get_thread_num () and omp_get_num_threads () 3280 calls. These can't be declared as const functions, but 3281 within one parallel body they are constant, so they can be 3282 transformed there into __builtin_omp_get_{thread_num,num_threads} () 3283 which are declared const. Similarly for task body, except 3284 that in untied task omp_get_thread_num () can change at any task 3285 scheduling point. */ 3286 3287static void 3288optimize_omp_library_calls (gimple entry_stmt) 3289{ 3290 basic_block bb; 3291 gimple_stmt_iterator gsi; 3292 tree thr_num_id 3293 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]); 3294 tree num_thr_id 3295 = DECL_ASSEMBLER_NAME (built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]); 3296 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK 3297 && find_omp_clause (gimple_omp_task_clauses (entry_stmt), 3298 OMP_CLAUSE_UNTIED) != NULL); 3299 3300 FOR_EACH_BB (bb) 3301 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 3302 { 3303 gimple call = gsi_stmt (gsi); 3304 tree decl; 3305 3306 if (is_gimple_call (call) 3307 && (decl = gimple_call_fndecl (call)) 3308 && DECL_EXTERNAL (decl) 3309 && TREE_PUBLIC (decl) 3310 && DECL_INITIAL (decl) == NULL) 3311 { 3312 tree built_in; 3313 3314 if (DECL_NAME (decl) == thr_num_id) 3315 { 3316 /* In #pragma omp task untied omp_get_thread_num () can change 3317 during the execution of the task region. */ 3318 if (untied_task) 3319 continue; 3320 built_in = built_in_decls [BUILT_IN_OMP_GET_THREAD_NUM]; 3321 } 3322 else if (DECL_NAME (decl) == num_thr_id) 3323 built_in = built_in_decls [BUILT_IN_OMP_GET_NUM_THREADS]; 3324 else 3325 continue; 3326 3327 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in) 3328 || gimple_call_num_args (call) != 0) 3329 continue; 3330 3331 if (flag_exceptions && !TREE_NOTHROW (decl)) 3332 continue; 3333 3334 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE 3335 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)), 3336 TREE_TYPE (TREE_TYPE (built_in)))) 3337 continue; 3338 3339 gimple_call_set_fndecl (call, built_in); 3340 } 3341 } 3342} 3343 3344/* Expand the OpenMP parallel or task directive starting at REGION. */ 3345 3346static void 3347expand_omp_taskreg (struct omp_region *region) 3348{ 3349 basic_block entry_bb, exit_bb, new_bb; 3350 struct function *child_cfun; 3351 tree child_fn, block, t, ws_args, *tp; 3352 tree save_current; 3353 gimple_stmt_iterator gsi; 3354 gimple entry_stmt, stmt; 3355 edge e; 3356 3357 entry_stmt = last_stmt (region->entry); 3358 child_fn = gimple_omp_taskreg_child_fn (entry_stmt); 3359 child_cfun = DECL_STRUCT_FUNCTION (child_fn); 3360 /* If this function has been already instrumented, make sure 3361 the child function isn't instrumented again. */ 3362 child_cfun->after_tree_profile = cfun->after_tree_profile; 3363 3364 entry_bb = region->entry; 3365 exit_bb = region->exit; 3366 3367 if (is_combined_parallel (region)) 3368 ws_args = region->ws_args; 3369 else 3370 ws_args = NULL_TREE; 3371 3372 if (child_cfun->cfg) 3373 { 3374 /* Due to inlining, it may happen that we have already outlined 3375 the region, in which case all we need to do is make the 3376 sub-graph unreachable and emit the parallel call. */ 3377 edge entry_succ_e, exit_succ_e; 3378 gimple_stmt_iterator gsi; 3379 3380 entry_succ_e = single_succ_edge (entry_bb); 3381 3382 gsi = gsi_last_bb (entry_bb); 3383 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL 3384 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK); 3385 gsi_remove (&gsi, true); 3386 3387 new_bb = entry_bb; 3388 if (exit_bb) 3389 { 3390 exit_succ_e = single_succ_edge (exit_bb); 3391 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU); 3392 } 3393 remove_edge_and_dominated_blocks (entry_succ_e); 3394 } 3395 else 3396 { 3397 /* If the parallel region needs data sent from the parent 3398 function, then the very first statement (except possible 3399 tree profile counter updates) of the parallel body 3400 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since 3401 &.OMP_DATA_O is passed as an argument to the child function, 3402 we need to replace it with the argument as seen by the child 3403 function. 3404 3405 In most cases, this will end up being the identity assignment 3406 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had 3407 a function call that has been inlined, the original PARM_DECL 3408 .OMP_DATA_I may have been converted into a different local 3409 variable. In which case, we need to keep the assignment. */ 3410 if (gimple_omp_taskreg_data_arg (entry_stmt)) 3411 { 3412 basic_block entry_succ_bb = single_succ (entry_bb); 3413 gimple_stmt_iterator gsi; 3414 tree arg, narg; 3415 gimple parcopy_stmt = NULL; 3416 3417 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi)) 3418 { 3419 gimple stmt; 3420 3421 gcc_assert (!gsi_end_p (gsi)); 3422 stmt = gsi_stmt (gsi); 3423 if (gimple_code (stmt) != GIMPLE_ASSIGN) 3424 continue; 3425 3426 if (gimple_num_ops (stmt) == 2) 3427 { 3428 tree arg = gimple_assign_rhs1 (stmt); 3429 3430 /* We're ignore the subcode because we're 3431 effectively doing a STRIP_NOPS. */ 3432 3433 if (TREE_CODE (arg) == ADDR_EXPR 3434 && TREE_OPERAND (arg, 0) 3435 == gimple_omp_taskreg_data_arg (entry_stmt)) 3436 { 3437 parcopy_stmt = stmt; 3438 break; 3439 } 3440 } 3441 } 3442 3443 gcc_assert (parcopy_stmt != NULL); 3444 arg = DECL_ARGUMENTS (child_fn); 3445 3446 if (!gimple_in_ssa_p (cfun)) 3447 { 3448 if (gimple_assign_lhs (parcopy_stmt) == arg) 3449 gsi_remove (&gsi, true); 3450 else 3451 { 3452 /* ?? Is setting the subcode really necessary ?? */ 3453 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg)); 3454 gimple_assign_set_rhs1 (parcopy_stmt, arg); 3455 } 3456 } 3457 else 3458 { 3459 /* If we are in ssa form, we must load the value from the default 3460 definition of the argument. That should not be defined now, 3461 since the argument is not used uninitialized. */ 3462 gcc_assert (gimple_default_def (cfun, arg) == NULL); 3463 narg = make_ssa_name (arg, gimple_build_nop ()); 3464 set_default_def (arg, narg); 3465 /* ?? Is setting the subcode really necessary ?? */ 3466 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg)); 3467 gimple_assign_set_rhs1 (parcopy_stmt, narg); 3468 update_stmt (parcopy_stmt); 3469 } 3470 } 3471 3472 /* Declare local variables needed in CHILD_CFUN. */ 3473 block = DECL_INITIAL (child_fn); 3474 BLOCK_VARS (block) = list2chain (child_cfun->local_decls); 3475 /* The gimplifier could record temporaries in parallel/task block 3476 rather than in containing function's local_decls chain, 3477 which would mean cgraph missed finalizing them. Do it now. */ 3478 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t)) 3479 if (TREE_CODE (t) == VAR_DECL 3480 && TREE_STATIC (t) 3481 && !DECL_EXTERNAL (t)) 3482 varpool_finalize_decl (t); 3483 DECL_SAVED_TREE (child_fn) = NULL; 3484 gimple_set_body (child_fn, bb_seq (single_succ (entry_bb))); 3485 TREE_USED (block) = 1; 3486 3487 /* Reset DECL_CONTEXT on function arguments. */ 3488 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t)) 3489 DECL_CONTEXT (t) = child_fn; 3490 3491 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK, 3492 so that it can be moved to the child function. */ 3493 gsi = gsi_last_bb (entry_bb); 3494 stmt = gsi_stmt (gsi); 3495 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL 3496 || gimple_code (stmt) == GIMPLE_OMP_TASK)); 3497 gsi_remove (&gsi, true); 3498 e = split_block (entry_bb, stmt); 3499 entry_bb = e->dest; 3500 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 3501 3502 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */ 3503 if (exit_bb) 3504 { 3505 gsi = gsi_last_bb (exit_bb); 3506 gcc_assert (!gsi_end_p (gsi) 3507 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN); 3508 stmt = gimple_build_return (NULL); 3509 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); 3510 gsi_remove (&gsi, true); 3511 } 3512 3513 /* Move the parallel region into CHILD_CFUN. */ 3514 3515 if (gimple_in_ssa_p (cfun)) 3516 { 3517 push_cfun (child_cfun); 3518 init_tree_ssa (child_cfun); 3519 init_ssa_operands (); 3520 cfun->gimple_df->in_ssa_p = true; 3521 pop_cfun (); 3522 block = NULL_TREE; 3523 } 3524 else 3525 block = gimple_block (entry_stmt); 3526 3527 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block); 3528 if (exit_bb) 3529 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU; 3530 3531 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */ 3532 for (tp = &child_cfun->local_decls; *tp; ) 3533 if (DECL_CONTEXT (TREE_VALUE (*tp)) != cfun->decl) 3534 tp = &TREE_CHAIN (*tp); 3535 else 3536 *tp = TREE_CHAIN (*tp); 3537 3538 /* Inform the callgraph about the new function. */ 3539 DECL_STRUCT_FUNCTION (child_fn)->curr_properties 3540 = cfun->curr_properties; 3541 cgraph_add_new_function (child_fn, true); 3542 3543 /* Fix the callgraph edges for child_cfun. Those for cfun will be 3544 fixed in a following pass. */ 3545 push_cfun (child_cfun); 3546 save_current = current_function_decl; 3547 current_function_decl = child_fn; 3548 if (optimize) 3549 optimize_omp_library_calls (entry_stmt); 3550 rebuild_cgraph_edges (); 3551 3552 /* Some EH regions might become dead, see PR34608. If 3553 pass_cleanup_cfg isn't the first pass to happen with the 3554 new child, these dead EH edges might cause problems. 3555 Clean them up now. */ 3556 if (flag_exceptions) 3557 { 3558 basic_block bb; 3559 bool changed = false; 3560 3561 FOR_EACH_BB (bb) 3562 changed |= gimple_purge_dead_eh_edges (bb); 3563 if (changed) 3564 cleanup_tree_cfg (); 3565 } 3566 if (gimple_in_ssa_p (cfun)) 3567 update_ssa (TODO_update_ssa); 3568 current_function_decl = save_current; 3569 pop_cfun (); 3570 } 3571 3572 /* Emit a library call to launch the children threads. */ 3573 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL) 3574 expand_parallel_call (region, new_bb, entry_stmt, ws_args); 3575 else 3576 expand_task_call (new_bb, entry_stmt); 3577 update_ssa (TODO_update_ssa_only_virtuals); 3578} 3579 3580 3581/* A subroutine of expand_omp_for. Generate code for a parallel 3582 loop with any schedule. Given parameters: 3583 3584 for (V = N1; V cond N2; V += STEP) BODY; 3585 3586 where COND is "<" or ">", we generate pseudocode 3587 3588 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0); 3589 if (more) goto L0; else goto L3; 3590 L0: 3591 V = istart0; 3592 iend = iend0; 3593 L1: 3594 BODY; 3595 V += STEP; 3596 if (V cond iend) goto L1; else goto L2; 3597 L2: 3598 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3; 3599 L3: 3600 3601 If this is a combined omp parallel loop, instead of the call to 3602 GOMP_loop_foo_start, we call GOMP_loop_foo_next. 3603 3604 For collapsed loops, given parameters: 3605 collapse(3) 3606 for (V1 = N11; V1 cond1 N12; V1 += STEP1) 3607 for (V2 = N21; V2 cond2 N22; V2 += STEP2) 3608 for (V3 = N31; V3 cond3 N32; V3 += STEP3) 3609 BODY; 3610 3611 we generate pseudocode 3612 3613 if (cond3 is <) 3614 adj = STEP3 - 1; 3615 else 3616 adj = STEP3 + 1; 3617 count3 = (adj + N32 - N31) / STEP3; 3618 if (cond2 is <) 3619 adj = STEP2 - 1; 3620 else 3621 adj = STEP2 + 1; 3622 count2 = (adj + N22 - N21) / STEP2; 3623 if (cond1 is <) 3624 adj = STEP1 - 1; 3625 else 3626 adj = STEP1 + 1; 3627 count1 = (adj + N12 - N11) / STEP1; 3628 count = count1 * count2 * count3; 3629 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0); 3630 if (more) goto L0; else goto L3; 3631 L0: 3632 V = istart0; 3633 T = V; 3634 V3 = N31 + (T % count3) * STEP3; 3635 T = T / count3; 3636 V2 = N21 + (T % count2) * STEP2; 3637 T = T / count2; 3638 V1 = N11 + T * STEP1; 3639 iend = iend0; 3640 L1: 3641 BODY; 3642 V += 1; 3643 if (V < iend) goto L10; else goto L2; 3644 L10: 3645 V3 += STEP3; 3646 if (V3 cond3 N32) goto L1; else goto L11; 3647 L11: 3648 V3 = N31; 3649 V2 += STEP2; 3650 if (V2 cond2 N22) goto L1; else goto L12; 3651 L12: 3652 V2 = N21; 3653 V1 += STEP1; 3654 goto L1; 3655 L2: 3656 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3; 3657 L3: 3658 3659 */ 3660 3661static void 3662expand_omp_for_generic (struct omp_region *region, 3663 struct omp_for_data *fd, 3664 enum built_in_function start_fn, 3665 enum built_in_function next_fn) 3666{ 3667 tree type, istart0, iend0, iend; 3668 tree t, vmain, vback, bias = NULL_TREE; 3669 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb; 3670 basic_block l2_bb = NULL, l3_bb = NULL; 3671 gimple_stmt_iterator gsi; 3672 gimple stmt; 3673 bool in_combined_parallel = is_combined_parallel (region); 3674 bool broken_loop = region->cont == NULL; 3675 edge e, ne; 3676 tree *counts = NULL; 3677 int i; 3678 3679 gcc_assert (!broken_loop || !in_combined_parallel); 3680 gcc_assert (fd->iter_type == long_integer_type_node 3681 || !in_combined_parallel); 3682 3683 type = TREE_TYPE (fd->loop.v); 3684 istart0 = create_tmp_var (fd->iter_type, ".istart0"); 3685 iend0 = create_tmp_var (fd->iter_type, ".iend0"); 3686 TREE_ADDRESSABLE (istart0) = 1; 3687 TREE_ADDRESSABLE (iend0) = 1; 3688 if (gimple_in_ssa_p (cfun)) 3689 { 3690 add_referenced_var (istart0); 3691 add_referenced_var (iend0); 3692 } 3693 3694 /* See if we need to bias by LLONG_MIN. */ 3695 if (fd->iter_type == long_long_unsigned_type_node 3696 && TREE_CODE (type) == INTEGER_TYPE 3697 && !TYPE_UNSIGNED (type)) 3698 { 3699 tree n1, n2; 3700 3701 if (fd->loop.cond_code == LT_EXPR) 3702 { 3703 n1 = fd->loop.n1; 3704 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step); 3705 } 3706 else 3707 { 3708 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step); 3709 n2 = fd->loop.n1; 3710 } 3711 if (TREE_CODE (n1) != INTEGER_CST 3712 || TREE_CODE (n2) != INTEGER_CST 3713 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0))) 3714 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type)); 3715 } 3716 3717 entry_bb = region->entry; 3718 cont_bb = region->cont; 3719 collapse_bb = NULL; 3720 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2); 3721 gcc_assert (broken_loop 3722 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest); 3723 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb)); 3724 l1_bb = single_succ (l0_bb); 3725 if (!broken_loop) 3726 { 3727 l2_bb = create_empty_bb (cont_bb); 3728 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb); 3729 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); 3730 } 3731 else 3732 l2_bb = NULL; 3733 l3_bb = BRANCH_EDGE (entry_bb)->dest; 3734 exit_bb = region->exit; 3735 3736 gsi = gsi_last_bb (entry_bb); 3737 3738 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); 3739 if (fd->collapse > 1) 3740 { 3741 /* collapsed loops need work for expansion in SSA form. */ 3742 gcc_assert (!gimple_in_ssa_p (cfun)); 3743 counts = (tree *) alloca (fd->collapse * sizeof (tree)); 3744 for (i = 0; i < fd->collapse; i++) 3745 { 3746 tree itype = TREE_TYPE (fd->loops[i].v); 3747 3748 if (POINTER_TYPE_P (itype)) 3749 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0); 3750 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR 3751 ? -1 : 1)); 3752 t = fold_build2 (PLUS_EXPR, itype, 3753 fold_convert (itype, fd->loops[i].step), t); 3754 t = fold_build2 (PLUS_EXPR, itype, t, 3755 fold_convert (itype, fd->loops[i].n2)); 3756 t = fold_build2 (MINUS_EXPR, itype, t, 3757 fold_convert (itype, fd->loops[i].n1)); 3758 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR) 3759 t = fold_build2 (TRUNC_DIV_EXPR, itype, 3760 fold_build1 (NEGATE_EXPR, itype, t), 3761 fold_build1 (NEGATE_EXPR, itype, 3762 fold_convert (itype, 3763 fd->loops[i].step))); 3764 else 3765 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, 3766 fold_convert (itype, fd->loops[i].step)); 3767 t = fold_convert (type, t); 3768 if (TREE_CODE (t) == INTEGER_CST) 3769 counts[i] = t; 3770 else 3771 { 3772 counts[i] = create_tmp_var (type, ".count"); 3773 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3774 true, GSI_SAME_STMT); 3775 stmt = gimple_build_assign (counts[i], t); 3776 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3777 } 3778 if (SSA_VAR_P (fd->loop.n2)) 3779 { 3780 if (i == 0) 3781 t = counts[0]; 3782 else 3783 { 3784 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]); 3785 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3786 true, GSI_SAME_STMT); 3787 } 3788 stmt = gimple_build_assign (fd->loop.n2, t); 3789 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3790 } 3791 } 3792 } 3793 if (in_combined_parallel) 3794 { 3795 /* In a combined parallel loop, emit a call to 3796 GOMP_loop_foo_next. */ 3797 t = build_call_expr (built_in_decls[next_fn], 2, 3798 build_fold_addr_expr (istart0), 3799 build_fold_addr_expr (iend0)); 3800 } 3801 else 3802 { 3803 tree t0, t1, t2, t3, t4; 3804 /* If this is not a combined parallel loop, emit a call to 3805 GOMP_loop_foo_start in ENTRY_BB. */ 3806 t4 = build_fold_addr_expr (iend0); 3807 t3 = build_fold_addr_expr (istart0); 3808 t2 = fold_convert (fd->iter_type, fd->loop.step); 3809 if (POINTER_TYPE_P (type) 3810 && TYPE_PRECISION (type) != TYPE_PRECISION (fd->iter_type)) 3811 { 3812 /* Avoid casting pointers to integer of a different size. */ 3813 tree itype 3814 = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0); 3815 t1 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n2)); 3816 t0 = fold_convert (fd->iter_type, fold_convert (itype, fd->loop.n1)); 3817 } 3818 else 3819 { 3820 t1 = fold_convert (fd->iter_type, fd->loop.n2); 3821 t0 = fold_convert (fd->iter_type, fd->loop.n1); 3822 } 3823 if (bias) 3824 { 3825 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias); 3826 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias); 3827 } 3828 if (fd->iter_type == long_integer_type_node) 3829 { 3830 if (fd->chunk_size) 3831 { 3832 t = fold_convert (fd->iter_type, fd->chunk_size); 3833 t = build_call_expr (built_in_decls[start_fn], 6, 3834 t0, t1, t2, t, t3, t4); 3835 } 3836 else 3837 t = build_call_expr (built_in_decls[start_fn], 5, 3838 t0, t1, t2, t3, t4); 3839 } 3840 else 3841 { 3842 tree t5; 3843 tree c_bool_type; 3844 3845 /* The GOMP_loop_ull_*start functions have additional boolean 3846 argument, true for < loops and false for > loops. 3847 In Fortran, the C bool type can be different from 3848 boolean_type_node. */ 3849 c_bool_type = TREE_TYPE (TREE_TYPE (built_in_decls[start_fn])); 3850 t5 = build_int_cst (c_bool_type, 3851 fd->loop.cond_code == LT_EXPR ? 1 : 0); 3852 if (fd->chunk_size) 3853 { 3854 t = fold_convert (fd->iter_type, fd->chunk_size); 3855 t = build_call_expr (built_in_decls[start_fn], 7, 3856 t5, t0, t1, t2, t, t3, t4); 3857 } 3858 else 3859 t = build_call_expr (built_in_decls[start_fn], 6, 3860 t5, t0, t1, t2, t3, t4); 3861 } 3862 } 3863 if (TREE_TYPE (t) != boolean_type_node) 3864 t = fold_build2 (NE_EXPR, boolean_type_node, 3865 t, build_int_cst (TREE_TYPE (t), 0)); 3866 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3867 true, GSI_SAME_STMT); 3868 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT); 3869 3870 /* Remove the GIMPLE_OMP_FOR statement. */ 3871 gsi_remove (&gsi, true); 3872 3873 /* Iteration setup for sequential loop goes in L0_BB. */ 3874 gsi = gsi_start_bb (l0_bb); 3875 t = istart0; 3876 if (bias) 3877 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias); 3878 if (POINTER_TYPE_P (type)) 3879 t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type), 3880 0), t); 3881 t = fold_convert (type, t); 3882 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3883 false, GSI_CONTINUE_LINKING); 3884 stmt = gimple_build_assign (fd->loop.v, t); 3885 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3886 3887 t = iend0; 3888 if (bias) 3889 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias); 3890 if (POINTER_TYPE_P (type)) 3891 t = fold_convert (lang_hooks.types.type_for_size (TYPE_PRECISION (type), 3892 0), t); 3893 t = fold_convert (type, t); 3894 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 3895 false, GSI_CONTINUE_LINKING); 3896 if (fd->collapse > 1) 3897 { 3898 tree tem = create_tmp_var (type, ".tem"); 3899 3900 stmt = gimple_build_assign (tem, fd->loop.v); 3901 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3902 for (i = fd->collapse - 1; i >= 0; i--) 3903 { 3904 tree vtype = TREE_TYPE (fd->loops[i].v), itype; 3905 itype = vtype; 3906 if (POINTER_TYPE_P (vtype)) 3907 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (vtype), 0); 3908 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]); 3909 t = fold_convert (itype, t); 3910 t = fold_build2 (MULT_EXPR, itype, t, 3911 fold_convert (itype, fd->loops[i].step)); 3912 if (POINTER_TYPE_P (vtype)) 3913 t = fold_build2 (POINTER_PLUS_EXPR, vtype, 3914 fd->loops[i].n1, fold_convert (sizetype, t)); 3915 else 3916 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t); 3917 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3918 false, GSI_CONTINUE_LINKING); 3919 stmt = gimple_build_assign (fd->loops[i].v, t); 3920 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3921 if (i != 0) 3922 { 3923 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]); 3924 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3925 false, GSI_CONTINUE_LINKING); 3926 stmt = gimple_build_assign (tem, t); 3927 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3928 } 3929 } 3930 } 3931 3932 if (!broken_loop) 3933 { 3934 /* Code to control the increment and predicate for the sequential 3935 loop goes in the CONT_BB. */ 3936 gsi = gsi_last_bb (cont_bb); 3937 stmt = gsi_stmt (gsi); 3938 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); 3939 vmain = gimple_omp_continue_control_use (stmt); 3940 vback = gimple_omp_continue_control_def (stmt); 3941 3942 if (POINTER_TYPE_P (type)) 3943 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain, 3944 fold_convert (sizetype, fd->loop.step)); 3945 else 3946 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step); 3947 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3948 true, GSI_SAME_STMT); 3949 stmt = gimple_build_assign (vback, t); 3950 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3951 3952 t = build2 (fd->loop.cond_code, boolean_type_node, vback, iend); 3953 stmt = gimple_build_cond_empty (t); 3954 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 3955 3956 /* Remove GIMPLE_OMP_CONTINUE. */ 3957 gsi_remove (&gsi, true); 3958 3959 if (fd->collapse > 1) 3960 { 3961 basic_block last_bb, bb; 3962 3963 last_bb = cont_bb; 3964 for (i = fd->collapse - 1; i >= 0; i--) 3965 { 3966 tree vtype = TREE_TYPE (fd->loops[i].v); 3967 3968 bb = create_empty_bb (last_bb); 3969 gsi = gsi_start_bb (bb); 3970 3971 if (i < fd->collapse - 1) 3972 { 3973 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE); 3974 e->probability = REG_BR_PROB_BASE / 8; 3975 3976 t = fd->loops[i + 1].n1; 3977 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3978 false, GSI_CONTINUE_LINKING); 3979 stmt = gimple_build_assign (fd->loops[i + 1].v, t); 3980 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3981 } 3982 else 3983 collapse_bb = bb; 3984 3985 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb); 3986 3987 if (POINTER_TYPE_P (vtype)) 3988 t = fold_build2 (POINTER_PLUS_EXPR, vtype, 3989 fd->loops[i].v, 3990 fold_convert (sizetype, fd->loops[i].step)); 3991 else 3992 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, 3993 fd->loops[i].step); 3994 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 3995 false, GSI_CONTINUE_LINKING); 3996 stmt = gimple_build_assign (fd->loops[i].v, t); 3997 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 3998 3999 if (i > 0) 4000 { 4001 t = fd->loops[i].n2; 4002 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 4003 false, GSI_CONTINUE_LINKING); 4004 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, 4005 fd->loops[i].v, t); 4006 stmt = gimple_build_cond_empty (t); 4007 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 4008 e = make_edge (bb, l1_bb, EDGE_TRUE_VALUE); 4009 e->probability = REG_BR_PROB_BASE * 7 / 8; 4010 } 4011 else 4012 make_edge (bb, l1_bb, EDGE_FALLTHRU); 4013 last_bb = bb; 4014 } 4015 } 4016 4017 /* Emit code to get the next parallel iteration in L2_BB. */ 4018 gsi = gsi_start_bb (l2_bb); 4019 4020 t = build_call_expr (built_in_decls[next_fn], 2, 4021 build_fold_addr_expr (istart0), 4022 build_fold_addr_expr (iend0)); 4023 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 4024 false, GSI_CONTINUE_LINKING); 4025 if (TREE_TYPE (t) != boolean_type_node) 4026 t = fold_build2 (NE_EXPR, boolean_type_node, 4027 t, build_int_cst (TREE_TYPE (t), 0)); 4028 stmt = gimple_build_cond_empty (t); 4029 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 4030 } 4031 4032 /* Add the loop cleanup function. */ 4033 gsi = gsi_last_bb (exit_bb); 4034 if (gimple_omp_return_nowait_p (gsi_stmt (gsi))) 4035 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT]; 4036 else 4037 t = built_in_decls[BUILT_IN_GOMP_LOOP_END]; 4038 stmt = gimple_build_call (t, 0); 4039 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); 4040 gsi_remove (&gsi, true); 4041 4042 /* Connect the new blocks. */ 4043 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE; 4044 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE; 4045 4046 if (!broken_loop) 4047 { 4048 gimple_seq phis; 4049 4050 e = find_edge (cont_bb, l3_bb); 4051 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE); 4052 4053 phis = phi_nodes (l3_bb); 4054 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi)) 4055 { 4056 gimple phi = gsi_stmt (gsi); 4057 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne), 4058 PHI_ARG_DEF_FROM_EDGE (phi, e)); 4059 } 4060 remove_edge (e); 4061 4062 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE); 4063 if (fd->collapse > 1) 4064 { 4065 e = find_edge (cont_bb, l1_bb); 4066 remove_edge (e); 4067 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE); 4068 } 4069 else 4070 { 4071 e = find_edge (cont_bb, l1_bb); 4072 e->flags = EDGE_TRUE_VALUE; 4073 } 4074 e->probability = REG_BR_PROB_BASE * 7 / 8; 4075 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8; 4076 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE); 4077 4078 set_immediate_dominator (CDI_DOMINATORS, l2_bb, 4079 recompute_dominator (CDI_DOMINATORS, l2_bb)); 4080 set_immediate_dominator (CDI_DOMINATORS, l3_bb, 4081 recompute_dominator (CDI_DOMINATORS, l3_bb)); 4082 set_immediate_dominator (CDI_DOMINATORS, l0_bb, 4083 recompute_dominator (CDI_DOMINATORS, l0_bb)); 4084 set_immediate_dominator (CDI_DOMINATORS, l1_bb, 4085 recompute_dominator (CDI_DOMINATORS, l1_bb)); 4086 } 4087} 4088 4089 4090/* A subroutine of expand_omp_for. Generate code for a parallel 4091 loop with static schedule and no specified chunk size. Given 4092 parameters: 4093 4094 for (V = N1; V cond N2; V += STEP) BODY; 4095 4096 where COND is "<" or ">", we generate pseudocode 4097 4098 if (cond is <) 4099 adj = STEP - 1; 4100 else 4101 adj = STEP + 1; 4102 if ((__typeof (V)) -1 > 0 && cond is >) 4103 n = -(adj + N2 - N1) / -STEP; 4104 else 4105 n = (adj + N2 - N1) / STEP; 4106 q = n / nthreads; 4107 q += (q * nthreads != n); 4108 s0 = q * threadid; 4109 e0 = min(s0 + q, n); 4110 V = s0 * STEP + N1; 4111 if (s0 >= e0) goto L2; else goto L0; 4112 L0: 4113 e = e0 * STEP + N1; 4114 L1: 4115 BODY; 4116 V += STEP; 4117 if (V cond e) goto L1; 4118 L2: 4119*/ 4120 4121static void 4122expand_omp_for_static_nochunk (struct omp_region *region, 4123 struct omp_for_data *fd) 4124{ 4125 tree n, q, s0, e0, e, t, nthreads, threadid; 4126 tree type, itype, vmain, vback; 4127 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb; 4128 basic_block fin_bb; 4129 gimple_stmt_iterator gsi; 4130 gimple stmt; 4131 4132 itype = type = TREE_TYPE (fd->loop.v); 4133 if (POINTER_TYPE_P (type)) 4134 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0); 4135 4136 entry_bb = region->entry; 4137 cont_bb = region->cont; 4138 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2); 4139 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest); 4140 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb)); 4141 body_bb = single_succ (seq_start_bb); 4142 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb); 4143 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); 4144 fin_bb = FALLTHRU_EDGE (cont_bb)->dest; 4145 exit_bb = region->exit; 4146 4147 /* Iteration space partitioning goes in ENTRY_BB. */ 4148 gsi = gsi_last_bb (entry_bb); 4149 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); 4150 4151 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0); 4152 t = fold_convert (itype, t); 4153 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 4154 true, GSI_SAME_STMT); 4155 4156 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); 4157 t = fold_convert (itype, t); 4158 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 4159 true, GSI_SAME_STMT); 4160 4161 fd->loop.n1 4162 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1), 4163 true, NULL_TREE, true, GSI_SAME_STMT); 4164 fd->loop.n2 4165 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2), 4166 true, NULL_TREE, true, GSI_SAME_STMT); 4167 fd->loop.step 4168 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step), 4169 true, NULL_TREE, true, GSI_SAME_STMT); 4170 4171 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1)); 4172 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t); 4173 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2); 4174 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1)); 4175 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR) 4176 t = fold_build2 (TRUNC_DIV_EXPR, itype, 4177 fold_build1 (NEGATE_EXPR, itype, t), 4178 fold_build1 (NEGATE_EXPR, itype, fd->loop.step)); 4179 else 4180 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step); 4181 t = fold_convert (itype, t); 4182 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); 4183 4184 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads); 4185 q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); 4186 4187 t = fold_build2 (MULT_EXPR, itype, q, nthreads); 4188 t = fold_build2 (NE_EXPR, itype, t, n); 4189 t = fold_build2 (PLUS_EXPR, itype, q, t); 4190 q = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); 4191 4192 t = build2 (MULT_EXPR, itype, q, threadid); 4193 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); 4194 4195 t = fold_build2 (PLUS_EXPR, itype, s0, q); 4196 t = fold_build2 (MIN_EXPR, itype, t, n); 4197 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); 4198 4199 t = build2 (GE_EXPR, boolean_type_node, s0, e0); 4200 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT); 4201 4202 /* Remove the GIMPLE_OMP_FOR statement. */ 4203 gsi_remove (&gsi, true); 4204 4205 /* Setup code for sequential iteration goes in SEQ_START_BB. */ 4206 gsi = gsi_start_bb (seq_start_bb); 4207 4208 t = fold_convert (itype, s0); 4209 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step); 4210 if (POINTER_TYPE_P (type)) 4211 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1, 4212 fold_convert (sizetype, t)); 4213 else 4214 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1); 4215 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 4216 false, GSI_CONTINUE_LINKING); 4217 stmt = gimple_build_assign (fd->loop.v, t); 4218 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); 4219 4220 t = fold_convert (itype, e0); 4221 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step); 4222 if (POINTER_TYPE_P (type)) 4223 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1, 4224 fold_convert (sizetype, t)); 4225 else 4226 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1); 4227 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, 4228 false, GSI_CONTINUE_LINKING); 4229 4230 /* The code controlling the sequential loop replaces the 4231 GIMPLE_OMP_CONTINUE. */ 4232 gsi = gsi_last_bb (cont_bb); 4233 stmt = gsi_stmt (gsi); 4234 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); 4235 vmain = gimple_omp_continue_control_use (stmt); 4236 vback = gimple_omp_continue_control_def (stmt); 4237 4238 if (POINTER_TYPE_P (type)) 4239 t = fold_build2 (POINTER_PLUS_EXPR, type, vmain, 4240 fold_convert (sizetype, fd->loop.step)); 4241 else 4242 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step); 4243 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, 4244 true, GSI_SAME_STMT); 4245 stmt = gimple_build_assign (vback, t); 4246 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); 4247 4248 t = build2 (fd->loop.cond_code, boolean_type_node, vback, e); 4249 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT); 4250 4251 /* Remove the GIMPLE_OMP_CONTINUE statement. */ 4252 gsi_remove (&gsi, true); 4253 4254 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */ 4255 gsi = gsi_last_bb (exit_bb); 4256 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi))) 4257 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE, 4258 false, GSI_SAME_STMT); 4259 gsi_remove (&gsi, true); 4260 4261 /* Connect all the blocks. */ 4262 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE; 4263 find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE; 4264 4265 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE; 4266 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE; 4267 4268 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb); 4269 set_immediate_dominator (CDI_DOMINATORS, body_bb, 4270 recompute_dominator (CDI_DOMINATORS, body_bb)); 4271 set_immediate_dominator (CDI_DOMINATORS, fin_bb, 4272 recompute_dominator (CDI_DOMINATORS, fin_bb)); 4273} 4274 4275 4276/* A subroutine of expand_omp_for. Generate code for a parallel 4277 loop with static schedule and a specified chunk size. Given 4278 parameters: 4279 4280 for (V = N1; V cond N2; V += STEP) BODY; 4281 4282 where COND is "<" or ">", we generate pseudocode 4283 4284 if (cond is <) 4285 adj = STEP - 1; 4286 else 4287 adj = STEP + 1; 4288 if ((__typeof (V)) -1 > 0 && cond is >) 4289 n = -(adj + N2 - N1) / -STEP; 4290 else 4291 n = (adj + N2 - N1) / STEP; 4292 trip = 0; 4293 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is 4294 here so that V is defined 4295 if the loop is not entered 4296 L0: 4297 s0 = (trip * nthreads + threadid) * CHUNK; 4298 e0 = min(s0 + CHUNK, n); 4299 if (s0 < n) goto L1; else goto L4; 4300 L1: 4301 V = s0 * STEP + N1; 4302 e = e0 * STEP + N1; 4303 L2: 4304 BODY; 4305 V += STEP; 4306 if (V cond e) goto L2; else goto L3; 4307 L3: 4308 trip += 1; 4309 goto L0; 4310 L4: 4311*/ 4312 4313static void 4314expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd) 4315{ 4316 tree n, s0, e0, e, t; 4317 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid; 4318 tree type, itype, v_main, v_back, v_extra; 4319 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb; 4320 basic_block trip_update_bb, cont_bb, fin_bb; 4321 gimple_stmt_iterator si; 4322 gimple stmt; 4323 edge se; 4324 4325 itype = type = TREE_TYPE (fd->loop.v); 4326 if (POINTER_TYPE_P (type)) 4327 itype = lang_hooks.types.type_for_size (TYPE_PRECISION (type), 0); 4328 4329 entry_bb = region->entry; 4330 se = split_block (entry_bb, last_stmt (entry_bb)); 4331 entry_bb = se->src; 4332 iter_part_bb = se->dest; 4333 cont_bb = region->cont; 4334 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2); 4335 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest 4336 == FALLTHRU_EDGE (cont_bb)->dest); 4337 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb)); 4338 body_bb = single_succ (seq_start_bb); 4339 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb); 4340 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); 4341 fin_bb = FALLTHRU_EDGE (cont_bb)->dest; 4342 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb)); 4343 exit_bb = region->exit; 4344 4345 /* Trip and adjustment setup goes in ENTRY_BB. */ 4346 si = gsi_last_bb (entry_bb); 4347 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR); 4348 4349 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS], 0); 4350 t = fold_convert (itype, t); 4351 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4352 true, GSI_SAME_STMT); 4353 4354 t = build_call_expr (built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); 4355 t = fold_convert (itype, t); 4356 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4357 true, GSI_SAME_STMT); 4358 4359 fd->loop.n1 4360 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1), 4361 true, NULL_TREE, true, GSI_SAME_STMT); 4362 fd->loop.n2 4363 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2), 4364 true, NULL_TREE, true, GSI_SAME_STMT); 4365 fd->loop.step 4366 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step), 4367 true, NULL_TREE, true, GSI_SAME_STMT); 4368 fd->chunk_size 4369 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size), 4370 true, NULL_TREE, true, GSI_SAME_STMT); 4371 4372 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1)); 4373 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t); 4374 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2); 4375 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1)); 4376 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR) 4377 t = fold_build2 (TRUNC_DIV_EXPR, itype, 4378 fold_build1 (NEGATE_EXPR, itype, t), 4379 fold_build1 (NEGATE_EXPR, itype, fd->loop.step)); 4380 else 4381 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step); 4382 t = fold_convert (itype, t); 4383 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4384 true, GSI_SAME_STMT); 4385 4386 trip_var = create_tmp_var (itype, ".trip"); 4387 if (gimple_in_ssa_p (cfun)) 4388 { 4389 add_referenced_var (trip_var); 4390 trip_init = make_ssa_name (trip_var, NULL); 4391 trip_main = make_ssa_name (trip_var, NULL); 4392 trip_back = make_ssa_name (trip_var, NULL); 4393 } 4394 else 4395 { 4396 trip_init = trip_var; 4397 trip_main = trip_var; 4398 trip_back = trip_var; 4399 } 4400 4401 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0)); 4402 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 4403 4404 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size); 4405 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step); 4406 if (POINTER_TYPE_P (type)) 4407 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1, 4408 fold_convert (sizetype, t)); 4409 else 4410 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1); 4411 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4412 true, GSI_SAME_STMT); 4413 4414 /* Remove the GIMPLE_OMP_FOR. */ 4415 gsi_remove (&si, true); 4416 4417 /* Iteration space partitioning goes in ITER_PART_BB. */ 4418 si = gsi_last_bb (iter_part_bb); 4419 4420 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads); 4421 t = fold_build2 (PLUS_EXPR, itype, t, threadid); 4422 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size); 4423 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4424 false, GSI_CONTINUE_LINKING); 4425 4426 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size); 4427 t = fold_build2 (MIN_EXPR, itype, t, n); 4428 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4429 false, GSI_CONTINUE_LINKING); 4430 4431 t = build2 (LT_EXPR, boolean_type_node, s0, n); 4432 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING); 4433 4434 /* Setup code for sequential iteration goes in SEQ_START_BB. */ 4435 si = gsi_start_bb (seq_start_bb); 4436 4437 t = fold_convert (itype, s0); 4438 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step); 4439 if (POINTER_TYPE_P (type)) 4440 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1, 4441 fold_convert (sizetype, t)); 4442 else 4443 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1); 4444 t = force_gimple_operand_gsi (&si, t, false, NULL_TREE, 4445 false, GSI_CONTINUE_LINKING); 4446 stmt = gimple_build_assign (fd->loop.v, t); 4447 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING); 4448 4449 t = fold_convert (itype, e0); 4450 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step); 4451 if (POINTER_TYPE_P (type)) 4452 t = fold_build2 (POINTER_PLUS_EXPR, type, fd->loop.n1, 4453 fold_convert (sizetype, t)); 4454 else 4455 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1); 4456 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE, 4457 false, GSI_CONTINUE_LINKING); 4458 4459 /* The code controlling the sequential loop goes in CONT_BB, 4460 replacing the GIMPLE_OMP_CONTINUE. */ 4461 si = gsi_last_bb (cont_bb); 4462 stmt = gsi_stmt (si); 4463 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE); 4464 v_main = gimple_omp_continue_control_use (stmt); 4465 v_back = gimple_omp_continue_control_def (stmt); 4466 4467 if (POINTER_TYPE_P (type)) 4468 t = fold_build2 (POINTER_PLUS_EXPR, type, v_main, 4469 fold_convert (sizetype, fd->loop.step)); 4470 else 4471 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step); 4472 stmt = gimple_build_assign (v_back, t); 4473 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 4474 4475 t = build2 (fd->loop.cond_code, boolean_type_node, v_back, e); 4476 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT); 4477 4478 /* Remove GIMPLE_OMP_CONTINUE. */ 4479 gsi_remove (&si, true); 4480 4481 /* Trip update code goes into TRIP_UPDATE_BB. */ 4482 si = gsi_start_bb (trip_update_bb); 4483 4484 t = build_int_cst (itype, 1); 4485 t = build2 (PLUS_EXPR, itype, trip_main, t); 4486 stmt = gimple_build_assign (trip_back, t); 4487 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING); 4488 4489 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */ 4490 si = gsi_last_bb (exit_bb); 4491 if (!gimple_omp_return_nowait_p (gsi_stmt (si))) 4492 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE, 4493 false, GSI_SAME_STMT); 4494 gsi_remove (&si, true); 4495 4496 /* Connect the new blocks. */ 4497 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE; 4498 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE; 4499 4500 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE; 4501 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE; 4502 4503 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb); 4504 4505 if (gimple_in_ssa_p (cfun)) 4506 { 4507 gimple_stmt_iterator psi; 4508 gimple phi; 4509 edge re, ene; 4510 edge_var_map_vector head; 4511 edge_var_map *vm; 4512 size_t i; 4513 4514 /* When we redirect the edge from trip_update_bb to iter_part_bb, we 4515 remove arguments of the phi nodes in fin_bb. We need to create 4516 appropriate phi nodes in iter_part_bb instead. */ 4517 se = single_pred_edge (fin_bb); 4518 re = single_succ_edge (trip_update_bb); 4519 head = redirect_edge_var_map_vector (re); 4520 ene = single_succ_edge (entry_bb); 4521 4522 psi = gsi_start_phis (fin_bb); 4523 for (i = 0; !gsi_end_p (psi) && VEC_iterate (edge_var_map, head, i, vm); 4524 gsi_next (&psi), ++i) 4525 { 4526 gimple nphi; 4527 source_location locus; 4528 4529 phi = gsi_stmt (psi); 4530 t = gimple_phi_result (phi); 4531 gcc_assert (t == redirect_edge_var_map_result (vm)); 4532 nphi = create_phi_node (t, iter_part_bb); 4533 SSA_NAME_DEF_STMT (t) = nphi; 4534 4535 t = PHI_ARG_DEF_FROM_EDGE (phi, se); 4536 locus = gimple_phi_arg_location_from_edge (phi, se); 4537 4538 /* A special case -- fd->loop.v is not yet computed in 4539 iter_part_bb, we need to use v_extra instead. */ 4540 if (t == fd->loop.v) 4541 t = v_extra; 4542 add_phi_arg (nphi, t, ene, locus); 4543 locus = redirect_edge_var_map_location (vm); 4544 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus); 4545 } 4546 gcc_assert (!gsi_end_p (psi) && i == VEC_length (edge_var_map, head)); 4547 redirect_edge_var_map_clear (re); 4548 while (1) 4549 { 4550 psi = gsi_start_phis (fin_bb); 4551 if (gsi_end_p (psi)) 4552 break; 4553 remove_phi_node (&psi, false); 4554 } 4555 4556 /* Make phi node for trip. */ 4557 phi = create_phi_node (trip_main, iter_part_bb); 4558 SSA_NAME_DEF_STMT (trip_main) = phi; 4559 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb), 4560 UNKNOWN_LOCATION); 4561 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb), 4562 UNKNOWN_LOCATION); 4563 } 4564 4565 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb); 4566 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb, 4567 recompute_dominator (CDI_DOMINATORS, iter_part_bb)); 4568 set_immediate_dominator (CDI_DOMINATORS, fin_bb, 4569 recompute_dominator (CDI_DOMINATORS, fin_bb)); 4570 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, 4571 recompute_dominator (CDI_DOMINATORS, seq_start_bb)); 4572 set_immediate_dominator (CDI_DOMINATORS, body_bb, 4573 recompute_dominator (CDI_DOMINATORS, body_bb)); 4574} 4575 4576 4577/* Expand the OpenMP loop defined by REGION. */ 4578 4579static void 4580expand_omp_for (struct omp_region *region) 4581{ 4582 struct omp_for_data fd; 4583 struct omp_for_data_loop *loops; 4584 4585 loops 4586 = (struct omp_for_data_loop *) 4587 alloca (gimple_omp_for_collapse (last_stmt (region->entry)) 4588 * sizeof (struct omp_for_data_loop)); 4589 extract_omp_for_data (last_stmt (region->entry), &fd, loops); 4590 region->sched_kind = fd.sched_kind; 4591 4592 gcc_assert (EDGE_COUNT (region->entry->succs) == 2); 4593 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL; 4594 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL; 4595 if (region->cont) 4596 { 4597 gcc_assert (EDGE_COUNT (region->cont->succs) == 2); 4598 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL; 4599 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL; 4600 } 4601 4602 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC 4603 && !fd.have_ordered 4604 && fd.collapse == 1 4605 && region->cont != NULL) 4606 { 4607 if (fd.chunk_size == NULL) 4608 expand_omp_for_static_nochunk (region, &fd); 4609 else 4610 expand_omp_for_static_chunk (region, &fd); 4611 } 4612 else 4613 { 4614 int fn_index, start_ix, next_ix; 4615 4616 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO); 4617 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME) 4618 ? 3 : fd.sched_kind; 4619 fn_index += fd.have_ordered * 4; 4620 start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index; 4621 next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index; 4622 if (fd.iter_type == long_long_unsigned_type_node) 4623 { 4624 start_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_START 4625 - BUILT_IN_GOMP_LOOP_STATIC_START; 4626 next_ix += BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT 4627 - BUILT_IN_GOMP_LOOP_STATIC_NEXT; 4628 } 4629 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix, 4630 (enum built_in_function) next_ix); 4631 } 4632 4633 update_ssa (TODO_update_ssa_only_virtuals); 4634} 4635 4636 4637/* Expand code for an OpenMP sections directive. In pseudo code, we generate 4638 4639 v = GOMP_sections_start (n); 4640 L0: 4641 switch (v) 4642 { 4643 case 0: 4644 goto L2; 4645 case 1: 4646 section 1; 4647 goto L1; 4648 case 2: 4649 ... 4650 case n: 4651 ... 4652 default: 4653 abort (); 4654 } 4655 L1: 4656 v = GOMP_sections_next (); 4657 goto L0; 4658 L2: 4659 reduction; 4660 4661 If this is a combined parallel sections, replace the call to 4662 GOMP_sections_start with call to GOMP_sections_next. */ 4663 4664static void 4665expand_omp_sections (struct omp_region *region) 4666{ 4667 tree t, u, vin = NULL, vmain, vnext, l2; 4668 VEC (tree,heap) *label_vec; 4669 unsigned len; 4670 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb; 4671 gimple_stmt_iterator si, switch_si; 4672 gimple sections_stmt, stmt, cont; 4673 edge_iterator ei; 4674 edge e; 4675 struct omp_region *inner; 4676 unsigned i, casei; 4677 bool exit_reachable = region->cont != NULL; 4678 4679 gcc_assert (exit_reachable == (region->exit != NULL)); 4680 entry_bb = region->entry; 4681 l0_bb = single_succ (entry_bb); 4682 l1_bb = region->cont; 4683 l2_bb = region->exit; 4684 if (exit_reachable) 4685 { 4686 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb) 4687 l2 = gimple_block_label (l2_bb); 4688 else 4689 { 4690 /* This can happen if there are reductions. */ 4691 len = EDGE_COUNT (l0_bb->succs); 4692 gcc_assert (len > 0); 4693 e = EDGE_SUCC (l0_bb, len - 1); 4694 si = gsi_last_bb (e->dest); 4695 l2 = NULL_TREE; 4696 if (gsi_end_p (si) 4697 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION) 4698 l2 = gimple_block_label (e->dest); 4699 else 4700 FOR_EACH_EDGE (e, ei, l0_bb->succs) 4701 { 4702 si = gsi_last_bb (e->dest); 4703 if (gsi_end_p (si) 4704 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION) 4705 { 4706 l2 = gimple_block_label (e->dest); 4707 break; 4708 } 4709 } 4710 } 4711 default_bb = create_empty_bb (l1_bb->prev_bb); 4712 } 4713 else 4714 { 4715 default_bb = create_empty_bb (l0_bb); 4716 l2 = gimple_block_label (default_bb); 4717 } 4718 4719 /* We will build a switch() with enough cases for all the 4720 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work 4721 and a default case to abort if something goes wrong. */ 4722 len = EDGE_COUNT (l0_bb->succs); 4723 4724 /* Use VEC_quick_push on label_vec throughout, since we know the size 4725 in advance. */ 4726 label_vec = VEC_alloc (tree, heap, len); 4727 4728 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the 4729 GIMPLE_OMP_SECTIONS statement. */ 4730 si = gsi_last_bb (entry_bb); 4731 sections_stmt = gsi_stmt (si); 4732 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS); 4733 vin = gimple_omp_sections_control (sections_stmt); 4734 if (!is_combined_parallel (region)) 4735 { 4736 /* If we are not inside a combined parallel+sections region, 4737 call GOMP_sections_start. */ 4738 t = build_int_cst (unsigned_type_node, 4739 exit_reachable ? len - 1 : len); 4740 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START]; 4741 stmt = gimple_build_call (u, 1, t); 4742 } 4743 else 4744 { 4745 /* Otherwise, call GOMP_sections_next. */ 4746 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT]; 4747 stmt = gimple_build_call (u, 0); 4748 } 4749 gimple_call_set_lhs (stmt, vin); 4750 gsi_insert_after (&si, stmt, GSI_SAME_STMT); 4751 gsi_remove (&si, true); 4752 4753 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in 4754 L0_BB. */ 4755 switch_si = gsi_last_bb (l0_bb); 4756 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH); 4757 if (exit_reachable) 4758 { 4759 cont = last_stmt (l1_bb); 4760 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE); 4761 vmain = gimple_omp_continue_control_use (cont); 4762 vnext = gimple_omp_continue_control_def (cont); 4763 } 4764 else 4765 { 4766 vmain = vin; 4767 vnext = NULL_TREE; 4768 } 4769 4770 i = 0; 4771 if (exit_reachable) 4772 { 4773 t = build3 (CASE_LABEL_EXPR, void_type_node, 4774 build_int_cst (unsigned_type_node, 0), NULL, l2); 4775 VEC_quick_push (tree, label_vec, t); 4776 i++; 4777 } 4778 4779 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */ 4780 for (inner = region->inner, casei = 1; 4781 inner; 4782 inner = inner->next, i++, casei++) 4783 { 4784 basic_block s_entry_bb, s_exit_bb; 4785 4786 /* Skip optional reduction region. */ 4787 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD) 4788 { 4789 --i; 4790 --casei; 4791 continue; 4792 } 4793 4794 s_entry_bb = inner->entry; 4795 s_exit_bb = inner->exit; 4796 4797 t = gimple_block_label (s_entry_bb); 4798 u = build_int_cst (unsigned_type_node, casei); 4799 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t); 4800 VEC_quick_push (tree, label_vec, u); 4801 4802 si = gsi_last_bb (s_entry_bb); 4803 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION); 4804 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si))); 4805 gsi_remove (&si, true); 4806 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU; 4807 4808 if (s_exit_bb == NULL) 4809 continue; 4810 4811 si = gsi_last_bb (s_exit_bb); 4812 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN); 4813 gsi_remove (&si, true); 4814 4815 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU; 4816 } 4817 4818 /* Error handling code goes in DEFAULT_BB. */ 4819 t = gimple_block_label (default_bb); 4820 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t); 4821 make_edge (l0_bb, default_bb, 0); 4822 4823 stmt = gimple_build_switch_vec (vmain, u, label_vec); 4824 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT); 4825 gsi_remove (&switch_si, true); 4826 VEC_free (tree, heap, label_vec); 4827 4828 si = gsi_start_bb (default_bb); 4829 stmt = gimple_build_call (built_in_decls[BUILT_IN_TRAP], 0); 4830 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING); 4831 4832 if (exit_reachable) 4833 { 4834 /* Code to get the next section goes in L1_BB. */ 4835 si = gsi_last_bb (l1_bb); 4836 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE); 4837 4838 stmt = gimple_build_call (built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT], 0); 4839 gimple_call_set_lhs (stmt, vnext); 4840 gsi_insert_after (&si, stmt, GSI_SAME_STMT); 4841 gsi_remove (&si, true); 4842 4843 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU; 4844 4845 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */ 4846 si = gsi_last_bb (l2_bb); 4847 if (gimple_omp_return_nowait_p (gsi_stmt (si))) 4848 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT]; 4849 else 4850 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END]; 4851 stmt = gimple_build_call (t, 0); 4852 gsi_insert_after (&si, stmt, GSI_SAME_STMT); 4853 gsi_remove (&si, true); 4854 } 4855 4856 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb); 4857} 4858 4859 4860/* Expand code for an OpenMP single directive. We've already expanded 4861 much of the code, here we simply place the GOMP_barrier call. */ 4862 4863static void 4864expand_omp_single (struct omp_region *region) 4865{ 4866 basic_block entry_bb, exit_bb; 4867 gimple_stmt_iterator si; 4868 bool need_barrier = false; 4869 4870 entry_bb = region->entry; 4871 exit_bb = region->exit; 4872 4873 si = gsi_last_bb (entry_bb); 4874 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot 4875 be removed. We need to ensure that the thread that entered the single 4876 does not exit before the data is copied out by the other threads. */ 4877 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)), 4878 OMP_CLAUSE_COPYPRIVATE)) 4879 need_barrier = true; 4880 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE); 4881 gsi_remove (&si, true); 4882 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 4883 4884 si = gsi_last_bb (exit_bb); 4885 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier) 4886 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE, 4887 false, GSI_SAME_STMT); 4888 gsi_remove (&si, true); 4889 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; 4890} 4891 4892 4893/* Generic expansion for OpenMP synchronization directives: master, 4894 ordered and critical. All we need to do here is remove the entry 4895 and exit markers for REGION. */ 4896 4897static void 4898expand_omp_synch (struct omp_region *region) 4899{ 4900 basic_block entry_bb, exit_bb; 4901 gimple_stmt_iterator si; 4902 4903 entry_bb = region->entry; 4904 exit_bb = region->exit; 4905 4906 si = gsi_last_bb (entry_bb); 4907 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE 4908 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER 4909 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED 4910 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL); 4911 gsi_remove (&si, true); 4912 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU; 4913 4914 if (exit_bb) 4915 { 4916 si = gsi_last_bb (exit_bb); 4917 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN); 4918 gsi_remove (&si, true); 4919 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU; 4920 } 4921} 4922 4923/* A subroutine of expand_omp_atomic. Attempt to implement the atomic 4924 operation as a __sync_fetch_and_op builtin. INDEX is log2 of the 4925 size of the data type, and thus usable to find the index of the builtin 4926 decl. Returns false if the expression is not of the proper form. */ 4927 4928static bool 4929expand_omp_atomic_fetch_op (basic_block load_bb, 4930 tree addr, tree loaded_val, 4931 tree stored_val, int index) 4932{ 4933 enum built_in_function base; 4934 tree decl, itype, call; 4935 enum insn_code *optab; 4936 tree rhs; 4937 basic_block store_bb = single_succ (load_bb); 4938 gimple_stmt_iterator gsi; 4939 gimple stmt; 4940 location_t loc; 4941 4942 /* We expect to find the following sequences: 4943 4944 load_bb: 4945 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem) 4946 4947 store_bb: 4948 val = tmp OP something; (or: something OP tmp) 4949 GIMPLE_OMP_STORE (val) 4950 4951 ???FIXME: Allow a more flexible sequence. 4952 Perhaps use data flow to pick the statements. 4953 4954 */ 4955 4956 gsi = gsi_after_labels (store_bb); 4957 stmt = gsi_stmt (gsi); 4958 loc = gimple_location (stmt); 4959 if (!is_gimple_assign (stmt)) 4960 return false; 4961 gsi_next (&gsi); 4962 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE) 4963 return false; 4964 4965 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0)) 4966 return false; 4967 4968 /* Check for one of the supported fetch-op operations. */ 4969 switch (gimple_assign_rhs_code (stmt)) 4970 { 4971 case PLUS_EXPR: 4972 case POINTER_PLUS_EXPR: 4973 base = BUILT_IN_FETCH_AND_ADD_N; 4974 optab = sync_add_optab; 4975 break; 4976 case MINUS_EXPR: 4977 base = BUILT_IN_FETCH_AND_SUB_N; 4978 optab = sync_add_optab; 4979 break; 4980 case BIT_AND_EXPR: 4981 base = BUILT_IN_FETCH_AND_AND_N; 4982 optab = sync_and_optab; 4983 break; 4984 case BIT_IOR_EXPR: 4985 base = BUILT_IN_FETCH_AND_OR_N; 4986 optab = sync_ior_optab; 4987 break; 4988 case BIT_XOR_EXPR: 4989 base = BUILT_IN_FETCH_AND_XOR_N; 4990 optab = sync_xor_optab; 4991 break; 4992 default: 4993 return false; 4994 } 4995 /* Make sure the expression is of the proper form. */ 4996 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0)) 4997 rhs = gimple_assign_rhs2 (stmt); 4998 else if (commutative_tree_code (gimple_assign_rhs_code (stmt)) 4999 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0)) 5000 rhs = gimple_assign_rhs1 (stmt); 5001 else 5002 return false; 5003 5004 decl = built_in_decls[base + index + 1]; 5005 itype = TREE_TYPE (TREE_TYPE (decl)); 5006 5007 if (optab[TYPE_MODE (itype)] == CODE_FOR_nothing) 5008 return false; 5009 5010 gsi = gsi_last_bb (load_bb); 5011 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD); 5012 call = build_call_expr_loc (loc, 5013 decl, 2, addr, 5014 fold_convert_loc (loc, itype, rhs)); 5015 call = fold_convert_loc (loc, void_type_node, call); 5016 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT); 5017 gsi_remove (&gsi, true); 5018 5019 gsi = gsi_last_bb (store_bb); 5020 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE); 5021 gsi_remove (&gsi, true); 5022 gsi = gsi_last_bb (store_bb); 5023 gsi_remove (&gsi, true); 5024 5025 if (gimple_in_ssa_p (cfun)) 5026 update_ssa (TODO_update_ssa_no_phi); 5027 5028 return true; 5029} 5030 5031/* A subroutine of expand_omp_atomic. Implement the atomic operation as: 5032 5033 oldval = *addr; 5034 repeat: 5035 newval = rhs; // with oldval replacing *addr in rhs 5036 oldval = __sync_val_compare_and_swap (addr, oldval, newval); 5037 if (oldval != newval) 5038 goto repeat; 5039 5040 INDEX is log2 of the size of the data type, and thus usable to find the 5041 index of the builtin decl. */ 5042 5043static bool 5044expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, 5045 tree addr, tree loaded_val, tree stored_val, 5046 int index) 5047{ 5048 tree loadedi, storedi, initial, new_storedi, old_vali; 5049 tree type, itype, cmpxchg, iaddr; 5050 gimple_stmt_iterator si; 5051 basic_block loop_header = single_succ (load_bb); 5052 gimple phi, stmt; 5053 edge e; 5054 5055 cmpxchg = built_in_decls[BUILT_IN_VAL_COMPARE_AND_SWAP_N + index + 1]; 5056 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr))); 5057 itype = TREE_TYPE (TREE_TYPE (cmpxchg)); 5058 5059 if (sync_compare_and_swap[TYPE_MODE (itype)] == CODE_FOR_nothing) 5060 return false; 5061 5062 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */ 5063 si = gsi_last_bb (load_bb); 5064 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD); 5065 5066 /* For floating-point values, we'll need to view-convert them to integers 5067 so that we can perform the atomic compare and swap. Simplify the 5068 following code by always setting up the "i"ntegral variables. */ 5069 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) 5070 { 5071 tree iaddr_val; 5072 5073 iaddr = create_tmp_var (build_pointer_type_for_mode (itype, ptr_mode, 5074 true), NULL); 5075 iaddr_val 5076 = force_gimple_operand_gsi (&si, 5077 fold_convert (TREE_TYPE (iaddr), addr), 5078 false, NULL_TREE, true, GSI_SAME_STMT); 5079 stmt = gimple_build_assign (iaddr, iaddr_val); 5080 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5081 loadedi = create_tmp_var (itype, NULL); 5082 if (gimple_in_ssa_p (cfun)) 5083 { 5084 add_referenced_var (iaddr); 5085 add_referenced_var (loadedi); 5086 loadedi = make_ssa_name (loadedi, NULL); 5087 } 5088 } 5089 else 5090 { 5091 iaddr = addr; 5092 loadedi = loaded_val; 5093 } 5094 5095 initial = force_gimple_operand_gsi (&si, build_fold_indirect_ref (iaddr), 5096 true, NULL_TREE, true, GSI_SAME_STMT); 5097 5098 /* Move the value to the LOADEDI temporary. */ 5099 if (gimple_in_ssa_p (cfun)) 5100 { 5101 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header))); 5102 phi = create_phi_node (loadedi, loop_header); 5103 SSA_NAME_DEF_STMT (loadedi) = phi; 5104 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)), 5105 initial); 5106 } 5107 else 5108 gsi_insert_before (&si, 5109 gimple_build_assign (loadedi, initial), 5110 GSI_SAME_STMT); 5111 if (loadedi != loaded_val) 5112 { 5113 gimple_stmt_iterator gsi2; 5114 tree x; 5115 5116 x = build1 (VIEW_CONVERT_EXPR, type, loadedi); 5117 gsi2 = gsi_start_bb (loop_header); 5118 if (gimple_in_ssa_p (cfun)) 5119 { 5120 gimple stmt; 5121 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE, 5122 true, GSI_SAME_STMT); 5123 stmt = gimple_build_assign (loaded_val, x); 5124 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT); 5125 } 5126 else 5127 { 5128 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x); 5129 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE, 5130 true, GSI_SAME_STMT); 5131 } 5132 } 5133 gsi_remove (&si, true); 5134 5135 si = gsi_last_bb (store_bb); 5136 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE); 5137 5138 if (iaddr == addr) 5139 storedi = stored_val; 5140 else 5141 storedi = 5142 force_gimple_operand_gsi (&si, 5143 build1 (VIEW_CONVERT_EXPR, itype, 5144 stored_val), true, NULL_TREE, true, 5145 GSI_SAME_STMT); 5146 5147 /* Build the compare&swap statement. */ 5148 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi); 5149 new_storedi = force_gimple_operand_gsi (&si, 5150 fold_convert (TREE_TYPE (loadedi), 5151 new_storedi), 5152 true, NULL_TREE, 5153 true, GSI_SAME_STMT); 5154 5155 if (gimple_in_ssa_p (cfun)) 5156 old_vali = loadedi; 5157 else 5158 { 5159 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL); 5160 if (gimple_in_ssa_p (cfun)) 5161 add_referenced_var (old_vali); 5162 stmt = gimple_build_assign (old_vali, loadedi); 5163 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5164 5165 stmt = gimple_build_assign (loadedi, new_storedi); 5166 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5167 } 5168 5169 /* Note that we always perform the comparison as an integer, even for 5170 floating point. This allows the atomic operation to properly 5171 succeed even with NaNs and -0.0. */ 5172 stmt = gimple_build_cond_empty 5173 (build2 (NE_EXPR, boolean_type_node, 5174 new_storedi, old_vali)); 5175 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5176 5177 /* Update cfg. */ 5178 e = single_succ_edge (store_bb); 5179 e->flags &= ~EDGE_FALLTHRU; 5180 e->flags |= EDGE_FALSE_VALUE; 5181 5182 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE); 5183 5184 /* Copy the new value to loadedi (we already did that before the condition 5185 if we are not in SSA). */ 5186 if (gimple_in_ssa_p (cfun)) 5187 { 5188 phi = gimple_seq_first_stmt (phi_nodes (loop_header)); 5189 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi); 5190 } 5191 5192 /* Remove GIMPLE_OMP_ATOMIC_STORE. */ 5193 gsi_remove (&si, true); 5194 5195 if (gimple_in_ssa_p (cfun)) 5196 update_ssa (TODO_update_ssa_no_phi); 5197 5198 return true; 5199} 5200 5201/* A subroutine of expand_omp_atomic. Implement the atomic operation as: 5202 5203 GOMP_atomic_start (); 5204 *addr = rhs; 5205 GOMP_atomic_end (); 5206 5207 The result is not globally atomic, but works so long as all parallel 5208 references are within #pragma omp atomic directives. According to 5209 responses received from omp@openmp.org, appears to be within spec. 5210 Which makes sense, since that's how several other compilers handle 5211 this situation as well. 5212 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're 5213 expanding. STORED_VAL is the operand of the matching 5214 GIMPLE_OMP_ATOMIC_STORE. 5215 5216 We replace 5217 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with 5218 loaded_val = *addr; 5219 5220 and replace 5221 GIMPLE_OMP_ATOMIC_ATORE (stored_val) with 5222 *addr = stored_val; 5223*/ 5224 5225static bool 5226expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb, 5227 tree addr, tree loaded_val, tree stored_val) 5228{ 5229 gimple_stmt_iterator si; 5230 gimple stmt; 5231 tree t; 5232 5233 si = gsi_last_bb (load_bb); 5234 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD); 5235 5236 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_START]; 5237 t = build_function_call_expr (UNKNOWN_LOCATION, t, 0); 5238 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT); 5239 5240 stmt = gimple_build_assign (loaded_val, build_fold_indirect_ref (addr)); 5241 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5242 gsi_remove (&si, true); 5243 5244 si = gsi_last_bb (store_bb); 5245 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE); 5246 5247 stmt = gimple_build_assign (build_fold_indirect_ref (unshare_expr (addr)), 5248 stored_val); 5249 gsi_insert_before (&si, stmt, GSI_SAME_STMT); 5250 5251 t = built_in_decls[BUILT_IN_GOMP_ATOMIC_END]; 5252 t = build_function_call_expr (UNKNOWN_LOCATION, t, 0); 5253 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT); 5254 gsi_remove (&si, true); 5255 5256 if (gimple_in_ssa_p (cfun)) 5257 update_ssa (TODO_update_ssa_no_phi); 5258 return true; 5259} 5260 5261/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand 5262 using expand_omp_atomic_fetch_op. If it failed, we try to 5263 call expand_omp_atomic_pipeline, and if it fails too, the 5264 ultimate fallback is wrapping the operation in a mutex 5265 (expand_omp_atomic_mutex). REGION is the atomic region built 5266 by build_omp_regions_1(). */ 5267 5268static void 5269expand_omp_atomic (struct omp_region *region) 5270{ 5271 basic_block load_bb = region->entry, store_bb = region->exit; 5272 gimple load = last_stmt (load_bb), store = last_stmt (store_bb); 5273 tree loaded_val = gimple_omp_atomic_load_lhs (load); 5274 tree addr = gimple_omp_atomic_load_rhs (load); 5275 tree stored_val = gimple_omp_atomic_store_val (store); 5276 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr))); 5277 HOST_WIDE_INT index; 5278 5279 /* Make sure the type is one of the supported sizes. */ 5280 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1); 5281 index = exact_log2 (index); 5282 if (index >= 0 && index <= 4) 5283 { 5284 unsigned int align = TYPE_ALIGN_UNIT (type); 5285 5286 /* __sync builtins require strict data alignment. */ 5287 if (exact_log2 (align) >= index) 5288 { 5289 /* When possible, use specialized atomic update functions. */ 5290 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)) 5291 && store_bb == single_succ (load_bb)) 5292 { 5293 if (expand_omp_atomic_fetch_op (load_bb, addr, 5294 loaded_val, stored_val, index)) 5295 return; 5296 } 5297 5298 /* If we don't have specialized __sync builtins, try and implement 5299 as a compare and swap loop. */ 5300 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr, 5301 loaded_val, stored_val, index)) 5302 return; 5303 } 5304 } 5305 5306 /* The ultimate fallback is wrapping the operation in a mutex. */ 5307 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val); 5308} 5309 5310 5311/* Expand the parallel region tree rooted at REGION. Expansion 5312 proceeds in depth-first order. Innermost regions are expanded 5313 first. This way, parallel regions that require a new function to 5314 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any 5315 internal dependencies in their body. */ 5316 5317static void 5318expand_omp (struct omp_region *region) 5319{ 5320 while (region) 5321 { 5322 location_t saved_location; 5323 5324 /* First, determine whether this is a combined parallel+workshare 5325 region. */ 5326 if (region->type == GIMPLE_OMP_PARALLEL) 5327 determine_parallel_type (region); 5328 5329 if (region->inner) 5330 expand_omp (region->inner); 5331 5332 saved_location = input_location; 5333 if (gimple_has_location (last_stmt (region->entry))) 5334 input_location = gimple_location (last_stmt (region->entry)); 5335 5336 switch (region->type) 5337 { 5338 case GIMPLE_OMP_PARALLEL: 5339 case GIMPLE_OMP_TASK: 5340 expand_omp_taskreg (region); 5341 break; 5342 5343 case GIMPLE_OMP_FOR: 5344 expand_omp_for (region); 5345 break; 5346 5347 case GIMPLE_OMP_SECTIONS: 5348 expand_omp_sections (region); 5349 break; 5350 5351 case GIMPLE_OMP_SECTION: 5352 /* Individual omp sections are handled together with their 5353 parent GIMPLE_OMP_SECTIONS region. */ 5354 break; 5355 5356 case GIMPLE_OMP_SINGLE: 5357 expand_omp_single (region); 5358 break; 5359 5360 case GIMPLE_OMP_MASTER: 5361 case GIMPLE_OMP_ORDERED: 5362 case GIMPLE_OMP_CRITICAL: 5363 expand_omp_synch (region); 5364 break; 5365 5366 case GIMPLE_OMP_ATOMIC_LOAD: 5367 expand_omp_atomic (region); 5368 break; 5369 5370 default: 5371 gcc_unreachable (); 5372 } 5373 5374 input_location = saved_location; 5375 region = region->next; 5376 } 5377} 5378 5379 5380/* Helper for build_omp_regions. Scan the dominator tree starting at 5381 block BB. PARENT is the region that contains BB. If SINGLE_TREE is 5382 true, the function ends once a single tree is built (otherwise, whole 5383 forest of OMP constructs may be built). */ 5384 5385static void 5386build_omp_regions_1 (basic_block bb, struct omp_region *parent, 5387 bool single_tree) 5388{ 5389 gimple_stmt_iterator gsi; 5390 gimple stmt; 5391 basic_block son; 5392 5393 gsi = gsi_last_bb (bb); 5394 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi))) 5395 { 5396 struct omp_region *region; 5397 enum gimple_code code; 5398 5399 stmt = gsi_stmt (gsi); 5400 code = gimple_code (stmt); 5401 if (code == GIMPLE_OMP_RETURN) 5402 { 5403 /* STMT is the return point out of region PARENT. Mark it 5404 as the exit point and make PARENT the immediately 5405 enclosing region. */ 5406 gcc_assert (parent); 5407 region = parent; 5408 region->exit = bb; 5409 parent = parent->outer; 5410 } 5411 else if (code == GIMPLE_OMP_ATOMIC_STORE) 5412 { 5413 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to 5414 GIMPLE_OMP_RETURN, but matches with 5415 GIMPLE_OMP_ATOMIC_LOAD. */ 5416 gcc_assert (parent); 5417 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD); 5418 region = parent; 5419 region->exit = bb; 5420 parent = parent->outer; 5421 } 5422 5423 else if (code == GIMPLE_OMP_CONTINUE) 5424 { 5425 gcc_assert (parent); 5426 parent->cont = bb; 5427 } 5428 else if (code == GIMPLE_OMP_SECTIONS_SWITCH) 5429 { 5430 /* GIMPLE_OMP_SECTIONS_SWITCH is part of 5431 GIMPLE_OMP_SECTIONS, and we do nothing for it. */ 5432 ; 5433 } 5434 else 5435 { 5436 /* Otherwise, this directive becomes the parent for a new 5437 region. */ 5438 region = new_omp_region (bb, code, parent); 5439 parent = region; 5440 } 5441 } 5442 5443 if (single_tree && !parent) 5444 return; 5445 5446 for (son = first_dom_son (CDI_DOMINATORS, bb); 5447 son; 5448 son = next_dom_son (CDI_DOMINATORS, son)) 5449 build_omp_regions_1 (son, parent, single_tree); 5450} 5451 5452/* Builds the tree of OMP regions rooted at ROOT, storing it to 5453 root_omp_region. */ 5454 5455static void 5456build_omp_regions_root (basic_block root) 5457{ 5458 gcc_assert (root_omp_region == NULL); 5459 build_omp_regions_1 (root, NULL, true); 5460 gcc_assert (root_omp_region != NULL); 5461} 5462 5463/* Expands omp construct (and its subconstructs) starting in HEAD. */ 5464 5465void 5466omp_expand_local (basic_block head) 5467{ 5468 build_omp_regions_root (head); 5469 if (dump_file && (dump_flags & TDF_DETAILS)) 5470 { 5471 fprintf (dump_file, "\nOMP region tree\n\n"); 5472 dump_omp_region (dump_file, root_omp_region, 0); 5473 fprintf (dump_file, "\n"); 5474 } 5475 5476 remove_exit_barriers (root_omp_region); 5477 expand_omp (root_omp_region); 5478 5479 free_omp_regions (); 5480} 5481 5482/* Scan the CFG and build a tree of OMP regions. Return the root of 5483 the OMP region tree. */ 5484 5485static void 5486build_omp_regions (void) 5487{ 5488 gcc_assert (root_omp_region == NULL); 5489 calculate_dominance_info (CDI_DOMINATORS); 5490 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false); 5491} 5492 5493/* Main entry point for expanding OMP-GIMPLE into runtime calls. */ 5494 5495static unsigned int 5496execute_expand_omp (void) 5497{ 5498 build_omp_regions (); 5499 5500 if (!root_omp_region) 5501 return 0; 5502 5503 if (dump_file) 5504 { 5505 fprintf (dump_file, "\nOMP region tree\n\n"); 5506 dump_omp_region (dump_file, root_omp_region, 0); 5507 fprintf (dump_file, "\n"); 5508 } 5509 5510 remove_exit_barriers (root_omp_region); 5511 5512 expand_omp (root_omp_region); 5513 5514 cleanup_tree_cfg (); 5515 5516 free_omp_regions (); 5517 5518 return 0; 5519} 5520 5521/* OMP expansion -- the default pass, run before creation of SSA form. */ 5522 5523static bool 5524gate_expand_omp (void) 5525{ 5526 return (flag_openmp != 0 && errorcount == 0); 5527} 5528 5529struct gimple_opt_pass pass_expand_omp = 5530{ 5531 { 5532 GIMPLE_PASS, 5533 "ompexp", /* name */ 5534 gate_expand_omp, /* gate */ 5535 execute_expand_omp, /* execute */ 5536 NULL, /* sub */ 5537 NULL, /* next */ 5538 0, /* static_pass_number */ 5539 TV_NONE, /* tv_id */ 5540 PROP_gimple_any, /* properties_required */ 5541 0, /* properties_provided */ 5542 0, /* properties_destroyed */ 5543 0, /* todo_flags_start */ 5544 TODO_dump_func /* todo_flags_finish */ 5545 } 5546}; 5547 5548/* Routines to lower OpenMP directives into OMP-GIMPLE. */ 5549 5550/* Lower the OpenMP sections directive in the current statement in GSI_P. 5551 CTX is the enclosing OMP context for the current statement. */ 5552 5553static void 5554lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx) 5555{ 5556 tree block, control; 5557 gimple_stmt_iterator tgsi; 5558 unsigned i, len; 5559 gimple stmt, new_stmt, bind, t; 5560 gimple_seq ilist, dlist, olist, new_body, body; 5561 struct gimplify_ctx gctx; 5562 5563 stmt = gsi_stmt (*gsi_p); 5564 5565 push_gimplify_context (&gctx); 5566 5567 dlist = NULL; 5568 ilist = NULL; 5569 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt), 5570 &ilist, &dlist, ctx); 5571 5572 tgsi = gsi_start (gimple_omp_body (stmt)); 5573 for (len = 0; !gsi_end_p (tgsi); len++, gsi_next (&tgsi)) 5574 continue; 5575 5576 tgsi = gsi_start (gimple_omp_body (stmt)); 5577 body = NULL; 5578 for (i = 0; i < len; i++, gsi_next (&tgsi)) 5579 { 5580 omp_context *sctx; 5581 gimple sec_start; 5582 5583 sec_start = gsi_stmt (tgsi); 5584 sctx = maybe_lookup_ctx (sec_start); 5585 gcc_assert (sctx); 5586 5587 gimple_seq_add_stmt (&body, sec_start); 5588 5589 lower_omp (gimple_omp_body (sec_start), sctx); 5590 gimple_seq_add_seq (&body, gimple_omp_body (sec_start)); 5591 gimple_omp_set_body (sec_start, NULL); 5592 5593 if (i == len - 1) 5594 { 5595 gimple_seq l = NULL; 5596 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL, 5597 &l, ctx); 5598 gimple_seq_add_seq (&body, l); 5599 gimple_omp_section_set_last (sec_start); 5600 } 5601 5602 gimple_seq_add_stmt (&body, gimple_build_omp_return (false)); 5603 } 5604 5605 block = make_node (BLOCK); 5606 bind = gimple_build_bind (NULL, body, block); 5607 5608 olist = NULL; 5609 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx); 5610 5611 block = make_node (BLOCK); 5612 new_stmt = gimple_build_bind (NULL, NULL, block); 5613 5614 pop_gimplify_context (new_stmt); 5615 gimple_bind_append_vars (new_stmt, ctx->block_vars); 5616 BLOCK_VARS (block) = gimple_bind_vars (bind); 5617 if (BLOCK_VARS (block)) 5618 TREE_USED (block) = 1; 5619 5620 new_body = NULL; 5621 gimple_seq_add_seq (&new_body, ilist); 5622 gimple_seq_add_stmt (&new_body, stmt); 5623 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ()); 5624 gimple_seq_add_stmt (&new_body, bind); 5625 5626 control = create_tmp_var (unsigned_type_node, ".section"); 5627 t = gimple_build_omp_continue (control, control); 5628 gimple_omp_sections_set_control (stmt, control); 5629 gimple_seq_add_stmt (&new_body, t); 5630 5631 gimple_seq_add_seq (&new_body, olist); 5632 gimple_seq_add_seq (&new_body, dlist); 5633 5634 new_body = maybe_catch_exception (new_body); 5635 5636 t = gimple_build_omp_return 5637 (!!find_omp_clause (gimple_omp_sections_clauses (stmt), 5638 OMP_CLAUSE_NOWAIT)); 5639 gimple_seq_add_stmt (&new_body, t); 5640 5641 gimple_bind_set_body (new_stmt, new_body); 5642 gimple_omp_set_body (stmt, NULL); 5643 5644 gsi_replace (gsi_p, new_stmt, true); 5645} 5646 5647 5648/* A subroutine of lower_omp_single. Expand the simple form of 5649 a GIMPLE_OMP_SINGLE, without a copyprivate clause: 5650 5651 if (GOMP_single_start ()) 5652 BODY; 5653 [ GOMP_barrier (); ] -> unless 'nowait' is present. 5654 5655 FIXME. It may be better to delay expanding the logic of this until 5656 pass_expand_omp. The expanded logic may make the job more difficult 5657 to a synchronization analysis pass. */ 5658 5659static void 5660lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p) 5661{ 5662 location_t loc = gimple_location (single_stmt); 5663 tree tlabel = create_artificial_label (loc); 5664 tree flabel = create_artificial_label (loc); 5665 gimple call, cond; 5666 tree lhs, decl; 5667 5668 decl = built_in_decls[BUILT_IN_GOMP_SINGLE_START]; 5669 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL); 5670 call = gimple_build_call (decl, 0); 5671 gimple_call_set_lhs (call, lhs); 5672 gimple_seq_add_stmt (pre_p, call); 5673 5674 cond = gimple_build_cond (EQ_EXPR, lhs, 5675 fold_convert_loc (loc, TREE_TYPE (lhs), 5676 boolean_true_node), 5677 tlabel, flabel); 5678 gimple_seq_add_stmt (pre_p, cond); 5679 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel)); 5680 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt)); 5681 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel)); 5682} 5683 5684 5685/* A subroutine of lower_omp_single. Expand the simple form of 5686 a GIMPLE_OMP_SINGLE, with a copyprivate clause: 5687 5688 #pragma omp single copyprivate (a, b, c) 5689 5690 Create a new structure to hold copies of 'a', 'b' and 'c' and emit: 5691 5692 { 5693 if ((copyout_p = GOMP_single_copy_start ()) == NULL) 5694 { 5695 BODY; 5696 copyout.a = a; 5697 copyout.b = b; 5698 copyout.c = c; 5699 GOMP_single_copy_end (©out); 5700 } 5701 else 5702 { 5703 a = copyout_p->a; 5704 b = copyout_p->b; 5705 c = copyout_p->c; 5706 } 5707 GOMP_barrier (); 5708 } 5709 5710 FIXME. It may be better to delay expanding the logic of this until 5711 pass_expand_omp. The expanded logic may make the job more difficult 5712 to a synchronization analysis pass. */ 5713 5714static void 5715lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx) 5716{ 5717 tree ptr_type, t, l0, l1, l2; 5718 gimple_seq copyin_seq; 5719 location_t loc = gimple_location (single_stmt); 5720 5721 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o"); 5722 5723 ptr_type = build_pointer_type (ctx->record_type); 5724 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i"); 5725 5726 l0 = create_artificial_label (loc); 5727 l1 = create_artificial_label (loc); 5728 l2 = create_artificial_label (loc); 5729 5730 t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START], 0); 5731 t = fold_convert_loc (loc, ptr_type, t); 5732 gimplify_assign (ctx->receiver_decl, t, pre_p); 5733 5734 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl, 5735 build_int_cst (ptr_type, 0)); 5736 t = build3 (COND_EXPR, void_type_node, t, 5737 build_and_jump (&l0), build_and_jump (&l1)); 5738 gimplify_and_add (t, pre_p); 5739 5740 gimple_seq_add_stmt (pre_p, gimple_build_label (l0)); 5741 5742 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt)); 5743 5744 copyin_seq = NULL; 5745 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p, 5746 ©in_seq, ctx); 5747 5748 t = build_fold_addr_expr_loc (loc, ctx->sender_decl); 5749 t = build_call_expr_loc (loc, built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END], 5750 1, t); 5751 gimplify_and_add (t, pre_p); 5752 5753 t = build_and_jump (&l2); 5754 gimplify_and_add (t, pre_p); 5755 5756 gimple_seq_add_stmt (pre_p, gimple_build_label (l1)); 5757 5758 gimple_seq_add_seq (pre_p, copyin_seq); 5759 5760 gimple_seq_add_stmt (pre_p, gimple_build_label (l2)); 5761} 5762 5763 5764/* Expand code for an OpenMP single directive. */ 5765 5766static void 5767lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx) 5768{ 5769 tree block; 5770 gimple t, bind, single_stmt = gsi_stmt (*gsi_p); 5771 gimple_seq bind_body, dlist; 5772 struct gimplify_ctx gctx; 5773 5774 push_gimplify_context (&gctx); 5775 5776 bind_body = NULL; 5777 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt), 5778 &bind_body, &dlist, ctx); 5779 lower_omp (gimple_omp_body (single_stmt), ctx); 5780 5781 gimple_seq_add_stmt (&bind_body, single_stmt); 5782 5783 if (ctx->record_type) 5784 lower_omp_single_copy (single_stmt, &bind_body, ctx); 5785 else 5786 lower_omp_single_simple (single_stmt, &bind_body); 5787 5788 gimple_omp_set_body (single_stmt, NULL); 5789 5790 gimple_seq_add_seq (&bind_body, dlist); 5791 5792 bind_body = maybe_catch_exception (bind_body); 5793 5794 t = gimple_build_omp_return 5795 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt), 5796 OMP_CLAUSE_NOWAIT)); 5797 gimple_seq_add_stmt (&bind_body, t); 5798 5799 block = make_node (BLOCK); 5800 bind = gimple_build_bind (NULL, bind_body, block); 5801 5802 pop_gimplify_context (bind); 5803 5804 gimple_bind_append_vars (bind, ctx->block_vars); 5805 BLOCK_VARS (block) = ctx->block_vars; 5806 gsi_replace (gsi_p, bind, true); 5807 if (BLOCK_VARS (block)) 5808 TREE_USED (block) = 1; 5809} 5810 5811 5812/* Expand code for an OpenMP master directive. */ 5813 5814static void 5815lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx) 5816{ 5817 tree block, lab = NULL, x; 5818 gimple stmt = gsi_stmt (*gsi_p), bind; 5819 location_t loc = gimple_location (stmt); 5820 gimple_seq tseq; 5821 struct gimplify_ctx gctx; 5822 5823 push_gimplify_context (&gctx); 5824 5825 block = make_node (BLOCK); 5826 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt), 5827 block); 5828 5829 x = build_call_expr_loc (loc, built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM], 0); 5830 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node); 5831 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab)); 5832 tseq = NULL; 5833 gimplify_and_add (x, &tseq); 5834 gimple_bind_add_seq (bind, tseq); 5835 5836 lower_omp (gimple_omp_body (stmt), ctx); 5837 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt))); 5838 gimple_bind_add_seq (bind, gimple_omp_body (stmt)); 5839 gimple_omp_set_body (stmt, NULL); 5840 5841 gimple_bind_add_stmt (bind, gimple_build_label (lab)); 5842 5843 gimple_bind_add_stmt (bind, gimple_build_omp_return (true)); 5844 5845 pop_gimplify_context (bind); 5846 5847 gimple_bind_append_vars (bind, ctx->block_vars); 5848 BLOCK_VARS (block) = ctx->block_vars; 5849 gsi_replace (gsi_p, bind, true); 5850} 5851 5852 5853/* Expand code for an OpenMP ordered directive. */ 5854 5855static void 5856lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx) 5857{ 5858 tree block; 5859 gimple stmt = gsi_stmt (*gsi_p), bind, x; 5860 struct gimplify_ctx gctx; 5861 5862 push_gimplify_context (&gctx); 5863 5864 block = make_node (BLOCK); 5865 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt), 5866 block); 5867 5868 x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0); 5869 gimple_bind_add_stmt (bind, x); 5870 5871 lower_omp (gimple_omp_body (stmt), ctx); 5872 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt))); 5873 gimple_bind_add_seq (bind, gimple_omp_body (stmt)); 5874 gimple_omp_set_body (stmt, NULL); 5875 5876 x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0); 5877 gimple_bind_add_stmt (bind, x); 5878 5879 gimple_bind_add_stmt (bind, gimple_build_omp_return (true)); 5880 5881 pop_gimplify_context (bind); 5882 5883 gimple_bind_append_vars (bind, ctx->block_vars); 5884 BLOCK_VARS (block) = gimple_bind_vars (bind); 5885 gsi_replace (gsi_p, bind, true); 5886} 5887 5888 5889/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple 5890 substitution of a couple of function calls. But in the NAMED case, 5891 requires that languages coordinate a symbol name. It is therefore 5892 best put here in common code. */ 5893 5894static GTY((param1_is (tree), param2_is (tree))) 5895 splay_tree critical_name_mutexes; 5896 5897static void 5898lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx) 5899{ 5900 tree block; 5901 tree name, lock, unlock; 5902 gimple stmt = gsi_stmt (*gsi_p), bind; 5903 location_t loc = gimple_location (stmt); 5904 gimple_seq tbody; 5905 struct gimplify_ctx gctx; 5906 5907 name = gimple_omp_critical_name (stmt); 5908 if (name) 5909 { 5910 tree decl; 5911 splay_tree_node n; 5912 5913 if (!critical_name_mutexes) 5914 critical_name_mutexes 5915 = splay_tree_new_ggc (splay_tree_compare_pointers); 5916 5917 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name); 5918 if (n == NULL) 5919 { 5920 char *new_str; 5921 5922 decl = create_tmp_var_raw (ptr_type_node, NULL); 5923 5924 new_str = ACONCAT ((".gomp_critical_user_", 5925 IDENTIFIER_POINTER (name), NULL)); 5926 DECL_NAME (decl) = get_identifier (new_str); 5927 TREE_PUBLIC (decl) = 1; 5928 TREE_STATIC (decl) = 1; 5929 DECL_COMMON (decl) = 1; 5930 DECL_ARTIFICIAL (decl) = 1; 5931 DECL_IGNORED_P (decl) = 1; 5932 varpool_finalize_decl (decl); 5933 5934 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name, 5935 (splay_tree_value) decl); 5936 } 5937 else 5938 decl = (tree) n->value; 5939 5940 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START]; 5941 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl)); 5942 5943 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END]; 5944 unlock = build_call_expr_loc (loc, unlock, 1, 5945 build_fold_addr_expr_loc (loc, decl)); 5946 } 5947 else 5948 { 5949 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START]; 5950 lock = build_call_expr_loc (loc, lock, 0); 5951 5952 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END]; 5953 unlock = build_call_expr_loc (loc, unlock, 0); 5954 } 5955 5956 push_gimplify_context (&gctx); 5957 5958 block = make_node (BLOCK); 5959 bind = gimple_build_bind (NULL, gimple_seq_alloc_with_stmt (stmt), block); 5960 5961 tbody = gimple_bind_body (bind); 5962 gimplify_and_add (lock, &tbody); 5963 gimple_bind_set_body (bind, tbody); 5964 5965 lower_omp (gimple_omp_body (stmt), ctx); 5966 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt))); 5967 gimple_bind_add_seq (bind, gimple_omp_body (stmt)); 5968 gimple_omp_set_body (stmt, NULL); 5969 5970 tbody = gimple_bind_body (bind); 5971 gimplify_and_add (unlock, &tbody); 5972 gimple_bind_set_body (bind, tbody); 5973 5974 gimple_bind_add_stmt (bind, gimple_build_omp_return (true)); 5975 5976 pop_gimplify_context (bind); 5977 gimple_bind_append_vars (bind, ctx->block_vars); 5978 BLOCK_VARS (block) = gimple_bind_vars (bind); 5979 gsi_replace (gsi_p, bind, true); 5980} 5981 5982 5983/* A subroutine of lower_omp_for. Generate code to emit the predicate 5984 for a lastprivate clause. Given a loop control predicate of (V 5985 cond N2), we gate the clause on (!(V cond N2)). The lowered form 5986 is appended to *DLIST, iterator initialization is appended to 5987 *BODY_P. */ 5988 5989static void 5990lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p, 5991 gimple_seq *dlist, struct omp_context *ctx) 5992{ 5993 tree clauses, cond, vinit; 5994 enum tree_code cond_code; 5995 gimple_seq stmts; 5996 5997 cond_code = fd->loop.cond_code; 5998 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR; 5999 6000 /* When possible, use a strict equality expression. This can let VRP 6001 type optimizations deduce the value and remove a copy. */ 6002 if (host_integerp (fd->loop.step, 0)) 6003 { 6004 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step); 6005 if (step == 1 || step == -1) 6006 cond_code = EQ_EXPR; 6007 } 6008 6009 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2); 6010 6011 clauses = gimple_omp_for_clauses (fd->for_stmt); 6012 stmts = NULL; 6013 lower_lastprivate_clauses (clauses, cond, &stmts, ctx); 6014 if (!gimple_seq_empty_p (stmts)) 6015 { 6016 gimple_seq_add_seq (&stmts, *dlist); 6017 *dlist = stmts; 6018 6019 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */ 6020 vinit = fd->loop.n1; 6021 if (cond_code == EQ_EXPR 6022 && host_integerp (fd->loop.n2, 0) 6023 && ! integer_zerop (fd->loop.n2)) 6024 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0); 6025 6026 /* Initialize the iterator variable, so that threads that don't execute 6027 any iterations don't execute the lastprivate clauses by accident. */ 6028 gimplify_assign (fd->loop.v, vinit, body_p); 6029 } 6030} 6031 6032 6033/* Lower code for an OpenMP loop directive. */ 6034 6035static void 6036lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx) 6037{ 6038 tree *rhs_p, block; 6039 struct omp_for_data fd; 6040 gimple stmt = gsi_stmt (*gsi_p), new_stmt; 6041 gimple_seq omp_for_body, body, dlist; 6042 size_t i; 6043 struct gimplify_ctx gctx; 6044 6045 push_gimplify_context (&gctx); 6046 6047 lower_omp (gimple_omp_for_pre_body (stmt), ctx); 6048 lower_omp (gimple_omp_body (stmt), ctx); 6049 6050 block = make_node (BLOCK); 6051 new_stmt = gimple_build_bind (NULL, NULL, block); 6052 6053 /* Move declaration of temporaries in the loop body before we make 6054 it go away. */ 6055 omp_for_body = gimple_omp_body (stmt); 6056 if (!gimple_seq_empty_p (omp_for_body) 6057 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND) 6058 { 6059 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body)); 6060 gimple_bind_append_vars (new_stmt, vars); 6061 } 6062 6063 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */ 6064 dlist = NULL; 6065 body = NULL; 6066 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx); 6067 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt)); 6068 6069 /* Lower the header expressions. At this point, we can assume that 6070 the header is of the form: 6071 6072 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3) 6073 6074 We just need to make sure that VAL1, VAL2 and VAL3 are lowered 6075 using the .omp_data_s mapping, if needed. */ 6076 for (i = 0; i < gimple_omp_for_collapse (stmt); i++) 6077 { 6078 rhs_p = gimple_omp_for_initial_ptr (stmt, i); 6079 if (!is_gimple_min_invariant (*rhs_p)) 6080 *rhs_p = get_formal_tmp_var (*rhs_p, &body); 6081 6082 rhs_p = gimple_omp_for_final_ptr (stmt, i); 6083 if (!is_gimple_min_invariant (*rhs_p)) 6084 *rhs_p = get_formal_tmp_var (*rhs_p, &body); 6085 6086 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1); 6087 if (!is_gimple_min_invariant (*rhs_p)) 6088 *rhs_p = get_formal_tmp_var (*rhs_p, &body); 6089 } 6090 6091 /* Once lowered, extract the bounds and clauses. */ 6092 extract_omp_for_data (stmt, &fd, NULL); 6093 6094 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx); 6095 6096 gimple_seq_add_stmt (&body, stmt); 6097 gimple_seq_add_seq (&body, gimple_omp_body (stmt)); 6098 6099 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v, 6100 fd.loop.v)); 6101 6102 /* After the loop, add exit clauses. */ 6103 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx); 6104 gimple_seq_add_seq (&body, dlist); 6105 6106 body = maybe_catch_exception (body); 6107 6108 /* Region exit marker goes at the end of the loop body. */ 6109 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait)); 6110 6111 pop_gimplify_context (new_stmt); 6112 6113 gimple_bind_append_vars (new_stmt, ctx->block_vars); 6114 BLOCK_VARS (block) = gimple_bind_vars (new_stmt); 6115 if (BLOCK_VARS (block)) 6116 TREE_USED (block) = 1; 6117 6118 gimple_bind_set_body (new_stmt, body); 6119 gimple_omp_set_body (stmt, NULL); 6120 gimple_omp_for_set_pre_body (stmt, NULL); 6121 gsi_replace (gsi_p, new_stmt, true); 6122} 6123 6124/* Callback for walk_stmts. Check if the current statement only contains 6125 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */ 6126 6127static tree 6128check_combined_parallel (gimple_stmt_iterator *gsi_p, 6129 bool *handled_ops_p, 6130 struct walk_stmt_info *wi) 6131{ 6132 int *info = (int *) wi->info; 6133 gimple stmt = gsi_stmt (*gsi_p); 6134 6135 *handled_ops_p = true; 6136 switch (gimple_code (stmt)) 6137 { 6138 WALK_SUBSTMTS; 6139 6140 case GIMPLE_OMP_FOR: 6141 case GIMPLE_OMP_SECTIONS: 6142 *info = *info == 0 ? 1 : -1; 6143 break; 6144 default: 6145 *info = -1; 6146 break; 6147 } 6148 return NULL; 6149} 6150 6151struct omp_taskcopy_context 6152{ 6153 /* This field must be at the beginning, as we do "inheritance": Some 6154 callback functions for tree-inline.c (e.g., omp_copy_decl) 6155 receive a copy_body_data pointer that is up-casted to an 6156 omp_context pointer. */ 6157 copy_body_data cb; 6158 omp_context *ctx; 6159}; 6160 6161static tree 6162task_copyfn_copy_decl (tree var, copy_body_data *cb) 6163{ 6164 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb; 6165 6166 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var)) 6167 return create_tmp_var (TREE_TYPE (var), NULL); 6168 6169 return var; 6170} 6171 6172static tree 6173task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type) 6174{ 6175 tree name, new_fields = NULL, type, f; 6176 6177 type = lang_hooks.types.make_type (RECORD_TYPE); 6178 name = DECL_NAME (TYPE_NAME (orig_type)); 6179 name = build_decl (gimple_location (tcctx->ctx->stmt), 6180 TYPE_DECL, name, type); 6181 TYPE_NAME (type) = name; 6182 6183 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f)) 6184 { 6185 tree new_f = copy_node (f); 6186 DECL_CONTEXT (new_f) = type; 6187 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb); 6188 TREE_CHAIN (new_f) = new_fields; 6189 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL); 6190 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL); 6191 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r, 6192 &tcctx->cb, NULL); 6193 new_fields = new_f; 6194 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f; 6195 } 6196 TYPE_FIELDS (type) = nreverse (new_fields); 6197 layout_type (type); 6198 return type; 6199} 6200 6201/* Create task copyfn. */ 6202 6203static void 6204create_task_copyfn (gimple task_stmt, omp_context *ctx) 6205{ 6206 struct function *child_cfun; 6207 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl; 6208 tree record_type, srecord_type, bind, list; 6209 bool record_needs_remap = false, srecord_needs_remap = false; 6210 splay_tree_node n; 6211 struct omp_taskcopy_context tcctx; 6212 struct gimplify_ctx gctx; 6213 location_t loc = gimple_location (task_stmt); 6214 6215 child_fn = gimple_omp_task_copy_fn (task_stmt); 6216 child_cfun = DECL_STRUCT_FUNCTION (child_fn); 6217 gcc_assert (child_cfun->cfg == NULL); 6218 child_cfun->dont_save_pending_sizes_p = 1; 6219 DECL_SAVED_TREE (child_fn) = alloc_stmt_list (); 6220 6221 /* Reset DECL_CONTEXT on function arguments. */ 6222 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t)) 6223 DECL_CONTEXT (t) = child_fn; 6224 6225 /* Populate the function. */ 6226 push_gimplify_context (&gctx); 6227 current_function_decl = child_fn; 6228 6229 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL); 6230 TREE_SIDE_EFFECTS (bind) = 1; 6231 list = NULL; 6232 DECL_SAVED_TREE (child_fn) = bind; 6233 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt); 6234 6235 /* Remap src and dst argument types if needed. */ 6236 record_type = ctx->record_type; 6237 srecord_type = ctx->srecord_type; 6238 for (f = TYPE_FIELDS (record_type); f ; f = TREE_CHAIN (f)) 6239 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn)) 6240 { 6241 record_needs_remap = true; 6242 break; 6243 } 6244 for (f = TYPE_FIELDS (srecord_type); f ; f = TREE_CHAIN (f)) 6245 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn)) 6246 { 6247 srecord_needs_remap = true; 6248 break; 6249 } 6250 6251 if (record_needs_remap || srecord_needs_remap) 6252 { 6253 memset (&tcctx, '\0', sizeof (tcctx)); 6254 tcctx.cb.src_fn = ctx->cb.src_fn; 6255 tcctx.cb.dst_fn = child_fn; 6256 tcctx.cb.src_node = cgraph_node (tcctx.cb.src_fn); 6257 tcctx.cb.dst_node = tcctx.cb.src_node; 6258 tcctx.cb.src_cfun = ctx->cb.src_cfun; 6259 tcctx.cb.copy_decl = task_copyfn_copy_decl; 6260 tcctx.cb.eh_lp_nr = 0; 6261 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE; 6262 tcctx.cb.decl_map = pointer_map_create (); 6263 tcctx.ctx = ctx; 6264 6265 if (record_needs_remap) 6266 record_type = task_copyfn_remap_type (&tcctx, record_type); 6267 if (srecord_needs_remap) 6268 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type); 6269 } 6270 else 6271 tcctx.cb.decl_map = NULL; 6272 6273 push_cfun (child_cfun); 6274 6275 arg = DECL_ARGUMENTS (child_fn); 6276 TREE_TYPE (arg) = build_pointer_type (record_type); 6277 sarg = TREE_CHAIN (arg); 6278 TREE_TYPE (sarg) = build_pointer_type (srecord_type); 6279 6280 /* First pass: initialize temporaries used in record_type and srecord_type 6281 sizes and field offsets. */ 6282 if (tcctx.cb.decl_map) 6283 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c)) 6284 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) 6285 { 6286 tree *p; 6287 6288 decl = OMP_CLAUSE_DECL (c); 6289 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl); 6290 if (p == NULL) 6291 continue; 6292 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl); 6293 sf = (tree) n->value; 6294 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf); 6295 src = build_fold_indirect_ref_loc (loc, sarg); 6296 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL); 6297 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src); 6298 append_to_statement_list (t, &list); 6299 } 6300 6301 /* Second pass: copy shared var pointers and copy construct non-VLA 6302 firstprivate vars. */ 6303 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c)) 6304 switch (OMP_CLAUSE_CODE (c)) 6305 { 6306 case OMP_CLAUSE_SHARED: 6307 decl = OMP_CLAUSE_DECL (c); 6308 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl); 6309 if (n == NULL) 6310 break; 6311 f = (tree) n->value; 6312 if (tcctx.cb.decl_map) 6313 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f); 6314 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl); 6315 sf = (tree) n->value; 6316 if (tcctx.cb.decl_map) 6317 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf); 6318 src = build_fold_indirect_ref_loc (loc, sarg); 6319 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL); 6320 dst = build_fold_indirect_ref_loc (loc, arg); 6321 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL); 6322 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); 6323 append_to_statement_list (t, &list); 6324 break; 6325 case OMP_CLAUSE_FIRSTPRIVATE: 6326 decl = OMP_CLAUSE_DECL (c); 6327 if (is_variable_sized (decl)) 6328 break; 6329 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl); 6330 if (n == NULL) 6331 break; 6332 f = (tree) n->value; 6333 if (tcctx.cb.decl_map) 6334 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f); 6335 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl); 6336 if (n != NULL) 6337 { 6338 sf = (tree) n->value; 6339 if (tcctx.cb.decl_map) 6340 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf); 6341 src = build_fold_indirect_ref_loc (loc, sarg); 6342 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL); 6343 if (use_pointer_for_field (decl, NULL) || is_reference (decl)) 6344 src = build_fold_indirect_ref_loc (loc, src); 6345 } 6346 else 6347 src = decl; 6348 dst = build_fold_indirect_ref_loc (loc, arg); 6349 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL); 6350 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); 6351 append_to_statement_list (t, &list); 6352 break; 6353 case OMP_CLAUSE_PRIVATE: 6354 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c)) 6355 break; 6356 decl = OMP_CLAUSE_DECL (c); 6357 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl); 6358 f = (tree) n->value; 6359 if (tcctx.cb.decl_map) 6360 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f); 6361 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl); 6362 if (n != NULL) 6363 { 6364 sf = (tree) n->value; 6365 if (tcctx.cb.decl_map) 6366 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf); 6367 src = build_fold_indirect_ref_loc (loc, sarg); 6368 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL); 6369 if (use_pointer_for_field (decl, NULL)) 6370 src = build_fold_indirect_ref_loc (loc, src); 6371 } 6372 else 6373 src = decl; 6374 dst = build_fold_indirect_ref_loc (loc, arg); 6375 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL); 6376 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); 6377 append_to_statement_list (t, &list); 6378 break; 6379 default: 6380 break; 6381 } 6382 6383 /* Last pass: handle VLA firstprivates. */ 6384 if (tcctx.cb.decl_map) 6385 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c)) 6386 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) 6387 { 6388 tree ind, ptr, df; 6389 6390 decl = OMP_CLAUSE_DECL (c); 6391 if (!is_variable_sized (decl)) 6392 continue; 6393 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl); 6394 if (n == NULL) 6395 continue; 6396 f = (tree) n->value; 6397 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f); 6398 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl)); 6399 ind = DECL_VALUE_EXPR (decl); 6400 gcc_assert (TREE_CODE (ind) == INDIRECT_REF); 6401 gcc_assert (DECL_P (TREE_OPERAND (ind, 0))); 6402 n = splay_tree_lookup (ctx->sfield_map, 6403 (splay_tree_key) TREE_OPERAND (ind, 0)); 6404 sf = (tree) n->value; 6405 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf); 6406 src = build_fold_indirect_ref_loc (loc, sarg); 6407 src = build3 (COMPONENT_REF, TREE_TYPE (sf), src, sf, NULL); 6408 src = build_fold_indirect_ref_loc (loc, src); 6409 dst = build_fold_indirect_ref_loc (loc, arg); 6410 dst = build3 (COMPONENT_REF, TREE_TYPE (f), dst, f, NULL); 6411 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); 6412 append_to_statement_list (t, &list); 6413 n = splay_tree_lookup (ctx->field_map, 6414 (splay_tree_key) TREE_OPERAND (ind, 0)); 6415 df = (tree) n->value; 6416 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df); 6417 ptr = build_fold_indirect_ref_loc (loc, arg); 6418 ptr = build3 (COMPONENT_REF, TREE_TYPE (df), ptr, df, NULL); 6419 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr, 6420 build_fold_addr_expr_loc (loc, dst)); 6421 append_to_statement_list (t, &list); 6422 } 6423 6424 t = build1 (RETURN_EXPR, void_type_node, NULL); 6425 append_to_statement_list (t, &list); 6426 6427 if (tcctx.cb.decl_map) 6428 pointer_map_destroy (tcctx.cb.decl_map); 6429 pop_gimplify_context (NULL); 6430 BIND_EXPR_BODY (bind) = list; 6431 pop_cfun (); 6432 current_function_decl = ctx->cb.src_fn; 6433} 6434 6435/* Lower the OpenMP parallel or task directive in the current statement 6436 in GSI_P. CTX holds context information for the directive. */ 6437 6438static void 6439lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx) 6440{ 6441 tree clauses; 6442 tree child_fn, t; 6443 gimple stmt = gsi_stmt (*gsi_p); 6444 gimple par_bind, bind; 6445 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body; 6446 struct gimplify_ctx gctx; 6447 location_t loc = gimple_location (stmt); 6448 6449 clauses = gimple_omp_taskreg_clauses (stmt); 6450 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt)); 6451 par_body = gimple_bind_body (par_bind); 6452 child_fn = ctx->cb.dst_fn; 6453 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL 6454 && !gimple_omp_parallel_combined_p (stmt)) 6455 { 6456 struct walk_stmt_info wi; 6457 int ws_num = 0; 6458 6459 memset (&wi, 0, sizeof (wi)); 6460 wi.info = &ws_num; 6461 wi.val_only = true; 6462 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi); 6463 if (ws_num == 1) 6464 gimple_omp_parallel_set_combined_p (stmt, true); 6465 } 6466 if (ctx->srecord_type) 6467 create_task_copyfn (stmt, ctx); 6468 6469 push_gimplify_context (&gctx); 6470 6471 par_olist = NULL; 6472 par_ilist = NULL; 6473 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx); 6474 lower_omp (par_body, ctx); 6475 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL) 6476 lower_reduction_clauses (clauses, &par_olist, ctx); 6477 6478 /* Declare all the variables created by mapping and the variables 6479 declared in the scope of the parallel body. */ 6480 record_vars_into (ctx->block_vars, child_fn); 6481 record_vars_into (gimple_bind_vars (par_bind), child_fn); 6482 6483 if (ctx->record_type) 6484 { 6485 ctx->sender_decl 6486 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type 6487 : ctx->record_type, ".omp_data_o"); 6488 TREE_ADDRESSABLE (ctx->sender_decl) = 1; 6489 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl); 6490 } 6491 6492 olist = NULL; 6493 ilist = NULL; 6494 lower_send_clauses (clauses, &ilist, &olist, ctx); 6495 lower_send_shared_vars (&ilist, &olist, ctx); 6496 6497 /* Once all the expansions are done, sequence all the different 6498 fragments inside gimple_omp_body. */ 6499 6500 new_body = NULL; 6501 6502 if (ctx->record_type) 6503 { 6504 t = build_fold_addr_expr_loc (loc, ctx->sender_decl); 6505 /* fixup_child_record_type might have changed receiver_decl's type. */ 6506 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t); 6507 gimple_seq_add_stmt (&new_body, 6508 gimple_build_assign (ctx->receiver_decl, t)); 6509 } 6510 6511 gimple_seq_add_seq (&new_body, par_ilist); 6512 gimple_seq_add_seq (&new_body, par_body); 6513 gimple_seq_add_seq (&new_body, par_olist); 6514 new_body = maybe_catch_exception (new_body); 6515 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false)); 6516 gimple_omp_set_body (stmt, new_body); 6517 6518 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind)); 6519 gimple_bind_add_stmt (bind, stmt); 6520 if (ilist || olist) 6521 { 6522 gimple_seq_add_stmt (&ilist, bind); 6523 gimple_seq_add_seq (&ilist, olist); 6524 bind = gimple_build_bind (NULL, ilist, NULL); 6525 } 6526 6527 gsi_replace (gsi_p, bind, true); 6528 6529 pop_gimplify_context (NULL); 6530} 6531 6532/* Callback for lower_omp_1. Return non-NULL if *tp needs to be 6533 regimplified. If DATA is non-NULL, lower_omp_1 is outside 6534 of OpenMP context, but with task_shared_vars set. */ 6535 6536static tree 6537lower_omp_regimplify_p (tree *tp, int *walk_subtrees, 6538 void *data) 6539{ 6540 tree t = *tp; 6541 6542 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */ 6543 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t)) 6544 return t; 6545 6546 if (task_shared_vars 6547 && DECL_P (t) 6548 && bitmap_bit_p (task_shared_vars, DECL_UID (t))) 6549 return t; 6550 6551 /* If a global variable has been privatized, TREE_CONSTANT on 6552 ADDR_EXPR might be wrong. */ 6553 if (data == NULL && TREE_CODE (t) == ADDR_EXPR) 6554 recompute_tree_invariant_for_addr_expr (t); 6555 6556 *walk_subtrees = !TYPE_P (t) && !DECL_P (t); 6557 return NULL_TREE; 6558} 6559 6560static void 6561lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) 6562{ 6563 gimple stmt = gsi_stmt (*gsi_p); 6564 struct walk_stmt_info wi; 6565 6566 if (gimple_has_location (stmt)) 6567 input_location = gimple_location (stmt); 6568 6569 if (task_shared_vars) 6570 memset (&wi, '\0', sizeof (wi)); 6571 6572 /* If we have issued syntax errors, avoid doing any heavy lifting. 6573 Just replace the OpenMP directives with a NOP to avoid 6574 confusing RTL expansion. */ 6575 if (errorcount && is_gimple_omp (stmt)) 6576 { 6577 gsi_replace (gsi_p, gimple_build_nop (), true); 6578 return; 6579 } 6580 6581 switch (gimple_code (stmt)) 6582 { 6583 case GIMPLE_COND: 6584 if ((ctx || task_shared_vars) 6585 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p, 6586 ctx ? NULL : &wi, NULL) 6587 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p, 6588 ctx ? NULL : &wi, NULL))) 6589 gimple_regimplify_operands (stmt, gsi_p); 6590 break; 6591 case GIMPLE_CATCH: 6592 lower_omp (gimple_catch_handler (stmt), ctx); 6593 break; 6594 case GIMPLE_EH_FILTER: 6595 lower_omp (gimple_eh_filter_failure (stmt), ctx); 6596 break; 6597 case GIMPLE_TRY: 6598 lower_omp (gimple_try_eval (stmt), ctx); 6599 lower_omp (gimple_try_cleanup (stmt), ctx); 6600 break; 6601 case GIMPLE_BIND: 6602 lower_omp (gimple_bind_body (stmt), ctx); 6603 break; 6604 case GIMPLE_OMP_PARALLEL: 6605 case GIMPLE_OMP_TASK: 6606 ctx = maybe_lookup_ctx (stmt); 6607 lower_omp_taskreg (gsi_p, ctx); 6608 break; 6609 case GIMPLE_OMP_FOR: 6610 ctx = maybe_lookup_ctx (stmt); 6611 gcc_assert (ctx); 6612 lower_omp_for (gsi_p, ctx); 6613 break; 6614 case GIMPLE_OMP_SECTIONS: 6615 ctx = maybe_lookup_ctx (stmt); 6616 gcc_assert (ctx); 6617 lower_omp_sections (gsi_p, ctx); 6618 break; 6619 case GIMPLE_OMP_SINGLE: 6620 ctx = maybe_lookup_ctx (stmt); 6621 gcc_assert (ctx); 6622 lower_omp_single (gsi_p, ctx); 6623 break; 6624 case GIMPLE_OMP_MASTER: 6625 ctx = maybe_lookup_ctx (stmt); 6626 gcc_assert (ctx); 6627 lower_omp_master (gsi_p, ctx); 6628 break; 6629 case GIMPLE_OMP_ORDERED: 6630 ctx = maybe_lookup_ctx (stmt); 6631 gcc_assert (ctx); 6632 lower_omp_ordered (gsi_p, ctx); 6633 break; 6634 case GIMPLE_OMP_CRITICAL: 6635 ctx = maybe_lookup_ctx (stmt); 6636 gcc_assert (ctx); 6637 lower_omp_critical (gsi_p, ctx); 6638 break; 6639 case GIMPLE_OMP_ATOMIC_LOAD: 6640 if ((ctx || task_shared_vars) 6641 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt), 6642 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL)) 6643 gimple_regimplify_operands (stmt, gsi_p); 6644 break; 6645 default: 6646 if ((ctx || task_shared_vars) 6647 && walk_gimple_op (stmt, lower_omp_regimplify_p, 6648 ctx ? NULL : &wi)) 6649 gimple_regimplify_operands (stmt, gsi_p); 6650 break; 6651 } 6652} 6653 6654static void 6655lower_omp (gimple_seq body, omp_context *ctx) 6656{ 6657 location_t saved_location = input_location; 6658 gimple_stmt_iterator gsi = gsi_start (body); 6659 for (gsi = gsi_start (body); !gsi_end_p (gsi); gsi_next (&gsi)) 6660 lower_omp_1 (&gsi, ctx); 6661 input_location = saved_location; 6662} 6663 6664/* Main entry point. */ 6665 6666static unsigned int 6667execute_lower_omp (void) 6668{ 6669 gimple_seq body; 6670 6671 /* This pass always runs, to provide PROP_gimple_lomp. 6672 But there is nothing to do unless -fopenmp is given. */ 6673 if (flag_openmp == 0) 6674 return 0; 6675 6676 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0, 6677 delete_omp_context); 6678 6679 body = gimple_body (current_function_decl); 6680 scan_omp (body, NULL); 6681 gcc_assert (taskreg_nesting_level == 0); 6682 6683 if (all_contexts->root) 6684 { 6685 struct gimplify_ctx gctx; 6686 6687 if (task_shared_vars) 6688 push_gimplify_context (&gctx); 6689 lower_omp (body, NULL); 6690 if (task_shared_vars) 6691 pop_gimplify_context (NULL); 6692 } 6693 6694 if (all_contexts) 6695 { 6696 splay_tree_delete (all_contexts); 6697 all_contexts = NULL; 6698 } 6699 BITMAP_FREE (task_shared_vars); 6700 return 0; 6701} 6702 6703struct gimple_opt_pass pass_lower_omp = 6704{ 6705 { 6706 GIMPLE_PASS, 6707 "omplower", /* name */ 6708 NULL, /* gate */ 6709 execute_lower_omp, /* execute */ 6710 NULL, /* sub */ 6711 NULL, /* next */ 6712 0, /* static_pass_number */ 6713 TV_NONE, /* tv_id */ 6714 PROP_gimple_any, /* properties_required */ 6715 PROP_gimple_lomp, /* properties_provided */ 6716 0, /* properties_destroyed */ 6717 0, /* todo_flags_start */ 6718 TODO_dump_func /* todo_flags_finish */ 6719 } 6720}; 6721 6722/* The following is a utility to diagnose OpenMP structured block violations. 6723 It is not part of the "omplower" pass, as that's invoked too late. It 6724 should be invoked by the respective front ends after gimplification. */ 6725 6726static splay_tree all_labels; 6727 6728/* Check for mismatched contexts and generate an error if needed. Return 6729 true if an error is detected. */ 6730 6731static bool 6732diagnose_sb_0 (gimple_stmt_iterator *gsi_p, 6733 gimple branch_ctx, gimple label_ctx) 6734{ 6735 if (label_ctx == branch_ctx) 6736 return false; 6737 6738 6739 /* 6740 Previously we kept track of the label's entire context in diagnose_sb_[12] 6741 so we could traverse it and issue a correct "exit" or "enter" error 6742 message upon a structured block violation. 6743 6744 We built the context by building a list with tree_cons'ing, but there is 6745 no easy counterpart in gimple tuples. It seems like far too much work 6746 for issuing exit/enter error messages. If someone really misses the 6747 distinct error message... patches welcome. 6748 */ 6749 6750#if 0 6751 /* Try to avoid confusing the user by producing and error message 6752 with correct "exit" or "enter" verbiage. We prefer "exit" 6753 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */ 6754 if (branch_ctx == NULL) 6755 exit_p = false; 6756 else 6757 { 6758 while (label_ctx) 6759 { 6760 if (TREE_VALUE (label_ctx) == branch_ctx) 6761 { 6762 exit_p = false; 6763 break; 6764 } 6765 label_ctx = TREE_CHAIN (label_ctx); 6766 } 6767 } 6768 6769 if (exit_p) 6770 error ("invalid exit from OpenMP structured block"); 6771 else 6772 error ("invalid entry to OpenMP structured block"); 6773#endif 6774 6775 /* If it's obvious we have an invalid entry, be specific about the error. */ 6776 if (branch_ctx == NULL) 6777 error ("invalid entry to OpenMP structured block"); 6778 else 6779 /* Otherwise, be vague and lazy, but efficient. */ 6780 error ("invalid branch to/from an OpenMP structured block"); 6781 6782 gsi_replace (gsi_p, gimple_build_nop (), false); 6783 return true; 6784} 6785 6786/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record 6787 where each label is found. */ 6788 6789static tree 6790diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, 6791 struct walk_stmt_info *wi) 6792{ 6793 gimple context = (gimple) wi->info; 6794 gimple inner_context; 6795 gimple stmt = gsi_stmt (*gsi_p); 6796 6797 *handled_ops_p = true; 6798 6799 switch (gimple_code (stmt)) 6800 { 6801 WALK_SUBSTMTS; 6802 6803 case GIMPLE_OMP_PARALLEL: 6804 case GIMPLE_OMP_TASK: 6805 case GIMPLE_OMP_SECTIONS: 6806 case GIMPLE_OMP_SINGLE: 6807 case GIMPLE_OMP_SECTION: 6808 case GIMPLE_OMP_MASTER: 6809 case GIMPLE_OMP_ORDERED: 6810 case GIMPLE_OMP_CRITICAL: 6811 /* The minimal context here is just the current OMP construct. */ 6812 inner_context = stmt; 6813 wi->info = inner_context; 6814 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi); 6815 wi->info = context; 6816 break; 6817 6818 case GIMPLE_OMP_FOR: 6819 inner_context = stmt; 6820 wi->info = inner_context; 6821 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to 6822 walk them. */ 6823 walk_gimple_seq (gimple_omp_for_pre_body (stmt), 6824 diagnose_sb_1, NULL, wi); 6825 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi); 6826 wi->info = context; 6827 break; 6828 6829 case GIMPLE_LABEL: 6830 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt), 6831 (splay_tree_value) context); 6832 break; 6833 6834 default: 6835 break; 6836 } 6837 6838 return NULL_TREE; 6839} 6840 6841/* Pass 2: Check each branch and see if its context differs from that of 6842 the destination label's context. */ 6843 6844static tree 6845diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, 6846 struct walk_stmt_info *wi) 6847{ 6848 gimple context = (gimple) wi->info; 6849 splay_tree_node n; 6850 gimple stmt = gsi_stmt (*gsi_p); 6851 6852 *handled_ops_p = true; 6853 6854 switch (gimple_code (stmt)) 6855 { 6856 WALK_SUBSTMTS; 6857 6858 case GIMPLE_OMP_PARALLEL: 6859 case GIMPLE_OMP_TASK: 6860 case GIMPLE_OMP_SECTIONS: 6861 case GIMPLE_OMP_SINGLE: 6862 case GIMPLE_OMP_SECTION: 6863 case GIMPLE_OMP_MASTER: 6864 case GIMPLE_OMP_ORDERED: 6865 case GIMPLE_OMP_CRITICAL: 6866 wi->info = stmt; 6867 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi); 6868 wi->info = context; 6869 break; 6870 6871 case GIMPLE_OMP_FOR: 6872 wi->info = stmt; 6873 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to 6874 walk them. */ 6875 walk_gimple_seq (gimple_omp_for_pre_body (stmt), 6876 diagnose_sb_2, NULL, wi); 6877 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi); 6878 wi->info = context; 6879 break; 6880 6881 case GIMPLE_COND: 6882 { 6883 tree lab = gimple_cond_true_label (stmt); 6884 if (lab) 6885 { 6886 n = splay_tree_lookup (all_labels, 6887 (splay_tree_key) lab); 6888 diagnose_sb_0 (gsi_p, context, 6889 n ? (gimple) n->value : NULL); 6890 } 6891 lab = gimple_cond_false_label (stmt); 6892 if (lab) 6893 { 6894 n = splay_tree_lookup (all_labels, 6895 (splay_tree_key) lab); 6896 diagnose_sb_0 (gsi_p, context, 6897 n ? (gimple) n->value : NULL); 6898 } 6899 } 6900 break; 6901 6902 case GIMPLE_GOTO: 6903 { 6904 tree lab = gimple_goto_dest (stmt); 6905 if (TREE_CODE (lab) != LABEL_DECL) 6906 break; 6907 6908 n = splay_tree_lookup (all_labels, (splay_tree_key) lab); 6909 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL); 6910 } 6911 break; 6912 6913 case GIMPLE_SWITCH: 6914 { 6915 unsigned int i; 6916 for (i = 0; i < gimple_switch_num_labels (stmt); ++i) 6917 { 6918 tree lab = CASE_LABEL (gimple_switch_label (stmt, i)); 6919 n = splay_tree_lookup (all_labels, (splay_tree_key) lab); 6920 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value)) 6921 break; 6922 } 6923 } 6924 break; 6925 6926 case GIMPLE_RETURN: 6927 diagnose_sb_0 (gsi_p, context, NULL); 6928 break; 6929 6930 default: 6931 break; 6932 } 6933 6934 return NULL_TREE; 6935} 6936 6937static unsigned int 6938diagnose_omp_structured_block_errors (void) 6939{ 6940 struct walk_stmt_info wi; 6941 gimple_seq body = gimple_body (current_function_decl); 6942 6943 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0); 6944 6945 memset (&wi, 0, sizeof (wi)); 6946 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi); 6947 6948 memset (&wi, 0, sizeof (wi)); 6949 wi.want_locations = true; 6950 walk_gimple_seq (body, diagnose_sb_2, NULL, &wi); 6951 6952 splay_tree_delete (all_labels); 6953 all_labels = NULL; 6954 6955 return 0; 6956} 6957 6958static bool 6959gate_diagnose_omp_blocks (void) 6960{ 6961 return flag_openmp != 0; 6962} 6963 6964struct gimple_opt_pass pass_diagnose_omp_blocks = 6965{ 6966 { 6967 GIMPLE_PASS, 6968 "*diagnose_omp_blocks", /* name */ 6969 gate_diagnose_omp_blocks, /* gate */ 6970 diagnose_omp_structured_block_errors, /* execute */ 6971 NULL, /* sub */ 6972 NULL, /* next */ 6973 0, /* static_pass_number */ 6974 TV_NONE, /* tv_id */ 6975 PROP_gimple_any, /* properties_required */ 6976 0, /* properties_provided */ 6977 0, /* properties_destroyed */ 6978 0, /* todo_flags_start */ 6979 0, /* todo_flags_finish */ 6980 } 6981}; 6982 6983#include "gt-omp-low.h" 6984