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