00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "config.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "tree.h"
00030 #include "rtl.h"
00031 #include "tree-gimple.h"
00032 #include "tree-inline.h"
00033 #include "langhooks.h"
00034 #include "diagnostic.h"
00035 #include "tree-flow.h"
00036 #include "timevar.h"
00037 #include "flags.h"
00038 #include "function.h"
00039 #include "expr.h"
00040 #include "toplev.h"
00041 #include "tree-pass.h"
00042 #include "ggc.h"
00043 #include "except.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 typedef struct omp_context
00061 {
00062
00063
00064
00065
00066 copy_body_data cb;
00067
00068
00069 struct omp_context *outer;
00070 tree stmt;
00071
00072
00073
00074 splay_tree field_map;
00075 tree record_type;
00076 tree sender_decl;
00077 tree receiver_decl;
00078
00079
00080
00081 tree block_vars;
00082
00083
00084
00085 enum omp_clause_default_kind default_kind;
00086
00087
00088
00089
00090 int depth;
00091
00092
00093 bool is_nested;
00094 } omp_context;
00095
00096
00097
00098
00099 struct omp_for_data
00100 {
00101 tree v, n1, n2, step, chunk_size, for_stmt;
00102 enum tree_code cond_code;
00103 tree pre;
00104 bool have_nowait, have_ordered;
00105 enum omp_clause_schedule_kind sched_kind;
00106 };
00107
00108
00109 static splay_tree all_contexts;
00110 static int parallel_nesting_level;
00111 struct omp_region *root_omp_region;
00112
00113 static void scan_omp (tree *, omp_context *);
00114 static void lower_omp (tree *, omp_context *);
00115 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
00116 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
00117
00118
00119
00120 static tree
00121 find_omp_clause (tree clauses, enum tree_code kind)
00122 {
00123 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
00124 if (OMP_CLAUSE_CODE (clauses) == kind)
00125 return clauses;
00126
00127 return NULL_TREE;
00128 }
00129
00130
00131
00132 static inline bool
00133 is_parallel_ctx (omp_context *ctx)
00134 {
00135 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
00136 }
00137
00138
00139
00140
00141 static inline bool
00142 is_combined_parallel (struct omp_region *region)
00143 {
00144 return region->is_combined_parallel;
00145 }
00146
00147
00148
00149
00150
00151 static void
00152 extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
00153 {
00154 tree t;
00155
00156 fd->for_stmt = for_stmt;
00157 fd->pre = NULL;
00158
00159 t = OMP_FOR_INIT (for_stmt);
00160 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
00161 fd->v = TREE_OPERAND (t, 0);
00162 gcc_assert (DECL_P (fd->v));
00163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
00164 fd->n1 = TREE_OPERAND (t, 1);
00165
00166 t = OMP_FOR_COND (for_stmt);
00167 fd->cond_code = TREE_CODE (t);
00168 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
00169 fd->n2 = TREE_OPERAND (t, 1);
00170 switch (fd->cond_code)
00171 {
00172 case LT_EXPR:
00173 case GT_EXPR:
00174 break;
00175 case LE_EXPR:
00176 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
00177 build_int_cst (TREE_TYPE (fd->n2), 1));
00178 fd->cond_code = LT_EXPR;
00179 break;
00180 case GE_EXPR:
00181 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
00182 build_int_cst (TREE_TYPE (fd->n2), 1));
00183 fd->cond_code = GT_EXPR;
00184 break;
00185 default:
00186 gcc_unreachable ();
00187 }
00188
00189 t = OMP_FOR_INCR (fd->for_stmt);
00190 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
00191 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
00192 t = TREE_OPERAND (t, 1);
00193 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
00194 switch (TREE_CODE (t))
00195 {
00196 case PLUS_EXPR:
00197 fd->step = TREE_OPERAND (t, 1);
00198 break;
00199 case MINUS_EXPR:
00200 fd->step = TREE_OPERAND (t, 1);
00201 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
00202 break;
00203 default:
00204 gcc_unreachable ();
00205 }
00206
00207 fd->have_nowait = fd->have_ordered = false;
00208 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
00209 fd->chunk_size = NULL_TREE;
00210
00211 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
00212 switch (OMP_CLAUSE_CODE (t))
00213 {
00214 case OMP_CLAUSE_NOWAIT:
00215 fd->have_nowait = true;
00216 break;
00217 case OMP_CLAUSE_ORDERED:
00218 fd->have_ordered = true;
00219 break;
00220 case OMP_CLAUSE_SCHEDULE:
00221 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
00222 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
00223 break;
00224 default:
00225 break;
00226 }
00227
00228 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
00229 gcc_assert (fd->chunk_size == NULL);
00230 else if (fd->chunk_size == NULL)
00231 {
00232
00233
00234 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
00235 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
00236 ? integer_zero_node : integer_one_node;
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 static bool
00284 workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
00285 {
00286 struct omp_for_data fd;
00287 tree par_stmt, ws_stmt;
00288
00289 par_stmt = last_stmt (par_entry_bb);
00290 ws_stmt = last_stmt (ws_entry_bb);
00291
00292 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
00293 return true;
00294
00295 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
00296
00297 extract_omp_for_data (ws_stmt, &fd);
00298
00299
00300
00301
00302
00303
00304 if (!is_gimple_min_invariant (fd.n1)
00305 || !is_gimple_min_invariant (fd.n2)
00306 || !is_gimple_min_invariant (fd.step)
00307 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
00308 return false;
00309
00310 return true;
00311 }
00312
00313
00314
00315
00316
00317
00318 static tree
00319 get_ws_args_for (tree ws_stmt)
00320 {
00321 tree t;
00322
00323 if (TREE_CODE (ws_stmt) == OMP_FOR)
00324 {
00325 struct omp_for_data fd;
00326 tree ws_args;
00327
00328 extract_omp_for_data (ws_stmt, &fd);
00329
00330 ws_args = NULL_TREE;
00331 if (fd.chunk_size)
00332 {
00333 t = fold_convert (long_integer_type_node, fd.chunk_size);
00334 ws_args = tree_cons (NULL, t, ws_args);
00335 }
00336
00337 t = fold_convert (long_integer_type_node, fd.step);
00338 ws_args = tree_cons (NULL, t, ws_args);
00339
00340 t = fold_convert (long_integer_type_node, fd.n2);
00341 ws_args = tree_cons (NULL, t, ws_args);
00342
00343 t = fold_convert (long_integer_type_node, fd.n1);
00344 ws_args = tree_cons (NULL, t, ws_args);
00345
00346 return ws_args;
00347 }
00348 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
00349 {
00350 basic_block bb = bb_for_stmt (ws_stmt);
00351 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
00352 t = tree_cons (NULL, t, NULL);
00353 return t;
00354 }
00355
00356 gcc_unreachable ();
00357 }
00358
00359
00360
00361
00362 static void
00363 determine_parallel_type (struct omp_region *region)
00364 {
00365 basic_block par_entry_bb, par_exit_bb;
00366 basic_block ws_entry_bb, ws_exit_bb;
00367
00368 if (region == NULL || region->inner == NULL
00369 || region->exit == NULL || region->inner->exit == NULL)
00370 return;
00371
00372
00373 if (region->type != OMP_PARALLEL
00374 || (region->inner->type != OMP_FOR
00375 && region->inner->type != OMP_SECTIONS))
00376 return;
00377
00378
00379
00380 par_entry_bb = region->entry;
00381 par_exit_bb = region->exit;
00382 ws_entry_bb = region->inner->entry;
00383 ws_exit_bb = region->inner->exit;
00384
00385 if (single_succ (par_entry_bb) == ws_entry_bb
00386 && single_succ (ws_exit_bb) == par_exit_bb
00387 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
00388 {
00389 tree ws_stmt = last_stmt (region->inner->entry);
00390
00391 if (region->inner->type == OMP_FOR)
00392 {
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
00403 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
00404 if (c == NULL
00405 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
00406 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
00407 {
00408 region->is_combined_parallel = false;
00409 region->inner->is_combined_parallel = false;
00410 return;
00411 }
00412 }
00413
00414 region->is_combined_parallel = true;
00415 region->inner->is_combined_parallel = true;
00416 region->ws_args = get_ws_args_for (ws_stmt);
00417 }
00418 }
00419
00420
00421
00422
00423 static inline bool
00424 is_variable_sized (tree expr)
00425 {
00426 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
00427 }
00428
00429
00430
00431 static inline bool
00432 is_reference (tree decl)
00433 {
00434 return lang_hooks.decls.omp_privatize_by_reference (decl);
00435 }
00436
00437
00438
00439
00440
00441 static inline tree
00442 lookup_decl (tree var, omp_context *ctx)
00443 {
00444 splay_tree_node n;
00445 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
00446 return (tree) n->value;
00447 }
00448
00449 static inline tree
00450 maybe_lookup_decl (tree var, omp_context *ctx)
00451 {
00452 splay_tree_node n;
00453 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
00454 return n ? (tree) n->value : NULL_TREE;
00455 }
00456
00457 static inline tree
00458 lookup_field (tree var, omp_context *ctx)
00459 {
00460 splay_tree_node n;
00461 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
00462 return (tree) n->value;
00463 }
00464
00465 static inline tree
00466 maybe_lookup_field (tree var, omp_context *ctx)
00467 {
00468 splay_tree_node n;
00469 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
00470 return n ? (tree) n->value : NULL_TREE;
00471 }
00472
00473
00474
00475
00476 static bool
00477 use_pointer_for_field (tree decl, bool shared_p)
00478 {
00479 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
00480 return true;
00481
00482
00483
00484 if (shared_p)
00485 {
00486
00487
00488
00489
00490 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
00491 return true;
00492
00493
00494
00495
00496
00497 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
00498 return true;
00499
00500
00501
00502 if (TREE_ADDRESSABLE (decl))
00503 return true;
00504 }
00505
00506 return false;
00507 }
00508
00509
00510
00511 static tree
00512 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
00513 {
00514 tree copy = build_decl (VAR_DECL, name, type);
00515
00516 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
00517 DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
00518 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
00519 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
00520 TREE_USED (copy) = 1;
00521 DECL_CONTEXT (copy) = current_function_decl;
00522 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
00523
00524 TREE_CHAIN (copy) = ctx->block_vars;
00525 ctx->block_vars = copy;
00526
00527 return copy;
00528 }
00529
00530 static tree
00531 omp_copy_decl_1 (tree var, omp_context *ctx)
00532 {
00533 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
00534 }
00535
00536
00537
00538 static tree
00539 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
00540 {
00541 tree x, field = lookup_field (var, ctx);
00542
00543
00544
00545 x = maybe_lookup_field (field, ctx);
00546 if (x != NULL)
00547 field = x;
00548
00549 x = build_fold_indirect_ref (ctx->receiver_decl);
00550 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
00551 if (by_ref)
00552 x = build_fold_indirect_ref (x);
00553
00554 return x;
00555 }
00556
00557
00558
00559
00560
00561 static tree
00562 build_outer_var_ref (tree var, omp_context *ctx)
00563 {
00564 tree x;
00565
00566 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
00567 x = var;
00568 else if (is_variable_sized (var))
00569 {
00570 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
00571 x = build_outer_var_ref (x, ctx);
00572 x = build_fold_indirect_ref (x);
00573 }
00574 else if (is_parallel_ctx (ctx))
00575 {
00576 bool by_ref = use_pointer_for_field (var, false);
00577 x = build_receiver_ref (var, by_ref, ctx);
00578 }
00579 else if (ctx->outer)
00580 x = lookup_decl (var, ctx->outer);
00581 else if (is_reference (var))
00582
00583
00584 x = var;
00585 else
00586 gcc_unreachable ();
00587
00588 if (is_reference (var))
00589 x = build_fold_indirect_ref (x);
00590
00591 return x;
00592 }
00593
00594
00595
00596 static tree
00597 build_sender_ref (tree var, omp_context *ctx)
00598 {
00599 tree field = lookup_field (var, ctx);
00600 return build3 (COMPONENT_REF, TREE_TYPE (field),
00601 ctx->sender_decl, field, NULL);
00602 }
00603
00604
00605
00606 static void
00607 install_var_field (tree var, bool by_ref, omp_context *ctx)
00608 {
00609 tree field, type;
00610
00611 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
00612
00613 type = TREE_TYPE (var);
00614 if (by_ref)
00615 type = build_pointer_type (type);
00616
00617 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
00618
00619
00620
00621
00622 DECL_ABSTRACT_ORIGIN (field) = var;
00623
00624 insert_field_into_struct (ctx->record_type, field);
00625
00626 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
00627 (splay_tree_value) field);
00628 }
00629
00630 static tree
00631 install_var_local (tree var, omp_context *ctx)
00632 {
00633 tree new_var = omp_copy_decl_1 (var, ctx);
00634 insert_decl_map (&ctx->cb, var, new_var);
00635 return new_var;
00636 }
00637
00638
00639
00640
00641 static void
00642 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
00643 {
00644 tree new_decl, size;
00645
00646 new_decl = lookup_decl (decl, ctx);
00647
00648 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
00649
00650 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
00651 && DECL_HAS_VALUE_EXPR_P (decl))
00652 {
00653 tree ve = DECL_VALUE_EXPR (decl);
00654 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
00655 SET_DECL_VALUE_EXPR (new_decl, ve);
00656 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
00657 }
00658
00659 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
00660 {
00661 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
00662 if (size == error_mark_node)
00663 size = TYPE_SIZE (TREE_TYPE (new_decl));
00664 DECL_SIZE (new_decl) = size;
00665
00666 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
00667 if (size == error_mark_node)
00668 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
00669 DECL_SIZE_UNIT (new_decl) = size;
00670 }
00671 }
00672
00673
00674
00675
00676
00677
00678 static tree
00679 omp_copy_decl (tree var, copy_body_data *cb)
00680 {
00681 omp_context *ctx = (omp_context *) cb;
00682 tree new_var;
00683
00684 if (TREE_CODE (var) == LABEL_DECL)
00685 {
00686 new_var = create_artificial_label ();
00687 DECL_CONTEXT (new_var) = current_function_decl;
00688 insert_decl_map (&ctx->cb, var, new_var);
00689 return new_var;
00690 }
00691
00692 while (!is_parallel_ctx (ctx))
00693 {
00694 ctx = ctx->outer;
00695 if (ctx == NULL)
00696 return var;
00697 new_var = maybe_lookup_decl (var, ctx);
00698 if (new_var)
00699 return new_var;
00700 }
00701
00702 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
00703 return var;
00704
00705 return error_mark_node;
00706 }
00707
00708
00709
00710
00711
00712 void dump_omp_region (FILE *, struct omp_region *, int);
00713 void debug_omp_region (struct omp_region *);
00714 void debug_all_omp_regions (void);
00715
00716
00717
00718 void
00719 dump_omp_region (FILE *file, struct omp_region *region, int indent)
00720 {
00721 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
00722 tree_code_name[region->type]);
00723
00724 if (region->inner)
00725 dump_omp_region (file, region->inner, indent + 4);
00726
00727 if (region->cont)
00728 {
00729 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
00730 region->cont->index);
00731 }
00732
00733 if (region->exit)
00734 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
00735 region->exit->index);
00736 else
00737 fprintf (file, "%*s[no exit marker]\n", indent, "");
00738
00739 if (region->next)
00740 dump_omp_region (file, region->next, indent);
00741 }
00742
00743 void
00744 debug_omp_region (struct omp_region *region)
00745 {
00746 dump_omp_region (stderr, region, 0);
00747 }
00748
00749 void
00750 debug_all_omp_regions (void)
00751 {
00752 dump_omp_region (stderr, root_omp_region, 0);
00753 }
00754
00755
00756
00757
00758 struct omp_region *
00759 new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
00760 {
00761 struct omp_region *region = xcalloc (1, sizeof (*region));
00762
00763 region->outer = parent;
00764 region->entry = bb;
00765 region->type = type;
00766
00767 if (parent)
00768 {
00769
00770
00771 region->next = parent->inner;
00772 parent->inner = region;
00773 }
00774 else
00775 {
00776
00777
00778 region->next = root_omp_region;
00779 root_omp_region = region;
00780 }
00781
00782 return region;
00783 }
00784
00785
00786
00787 static void
00788 free_omp_region_1 (struct omp_region *region)
00789 {
00790 struct omp_region *i, *n;
00791
00792 for (i = region->inner; i ; i = n)
00793 {
00794 n = i->next;
00795 free_omp_region_1 (i);
00796 }
00797
00798 free (region);
00799 }
00800
00801
00802
00803 void
00804 free_omp_regions (void)
00805 {
00806 struct omp_region *r, *n;
00807 for (r = root_omp_region; r ; r = n)
00808 {
00809 n = r->next;
00810 free_omp_region_1 (r);
00811 }
00812 root_omp_region = NULL;
00813 }
00814
00815
00816
00817
00818 static omp_context *
00819 new_omp_context (tree stmt, omp_context *outer_ctx)
00820 {
00821 omp_context *ctx = XCNEW (omp_context);
00822
00823 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
00824 (splay_tree_value) ctx);
00825 ctx->stmt = stmt;
00826
00827 if (outer_ctx)
00828 {
00829 ctx->outer = outer_ctx;
00830 ctx->cb = outer_ctx->cb;
00831 ctx->cb.block = NULL;
00832 ctx->depth = outer_ctx->depth + 1;
00833 }
00834 else
00835 {
00836 ctx->cb.src_fn = current_function_decl;
00837 ctx->cb.dst_fn = current_function_decl;
00838 ctx->cb.src_node = cgraph_node (current_function_decl);
00839 ctx->cb.dst_node = ctx->cb.src_node;
00840 ctx->cb.src_cfun = cfun;
00841 ctx->cb.copy_decl = omp_copy_decl;
00842 ctx->cb.eh_region = -1;
00843 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
00844 ctx->depth = 1;
00845 }
00846
00847 ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
00848
00849 return ctx;
00850 }
00851
00852
00853
00854
00855 static void
00856 delete_omp_context (splay_tree_value value)
00857 {
00858 omp_context *ctx = (omp_context *) value;
00859
00860 splay_tree_delete (ctx->cb.decl_map);
00861
00862 if (ctx->field_map)
00863 splay_tree_delete (ctx->field_map);
00864
00865
00866
00867 if (ctx->record_type)
00868 {
00869 tree t;
00870 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
00871 DECL_ABSTRACT_ORIGIN (t) = NULL;
00872 }
00873
00874 XDELETE (ctx);
00875 }
00876
00877
00878
00879
00880 static void
00881 fixup_child_record_type (omp_context *ctx)
00882 {
00883 tree f, type = ctx->record_type;
00884
00885
00886
00887
00888
00889 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
00890 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
00891 break;
00892 if (f)
00893 {
00894 tree name, new_fields = NULL;
00895
00896 type = lang_hooks.types.make_type (RECORD_TYPE);
00897 name = DECL_NAME (TYPE_NAME (ctx->record_type));
00898 name = build_decl (TYPE_DECL, name, type);
00899 TYPE_NAME (type) = name;
00900
00901 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
00902 {
00903 tree new_f = copy_node (f);
00904 DECL_CONTEXT (new_f) = type;
00905 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
00906 TREE_CHAIN (new_f) = new_fields;
00907 new_fields = new_f;
00908
00909
00910
00911 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
00912 (splay_tree_value) new_f);
00913 }
00914 TYPE_FIELDS (type) = nreverse (new_fields);
00915 layout_type (type);
00916 }
00917
00918 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
00919 }
00920
00921
00922
00923
00924 static void
00925 scan_sharing_clauses (tree clauses, omp_context *ctx)
00926 {
00927 tree c, decl;
00928 bool scan_array_reductions = false;
00929
00930 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
00931 {
00932 bool by_ref;
00933
00934 switch (OMP_CLAUSE_CODE (c))
00935 {
00936 case OMP_CLAUSE_PRIVATE:
00937 decl = OMP_CLAUSE_DECL (c);
00938 if (!is_variable_sized (decl))
00939 install_var_local (decl, ctx);
00940 break;
00941
00942 case OMP_CLAUSE_SHARED:
00943 gcc_assert (is_parallel_ctx (ctx));
00944 decl = OMP_CLAUSE_DECL (c);
00945 gcc_assert (!is_variable_sized (decl));
00946 by_ref = use_pointer_for_field (decl, true);
00947
00948
00949 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
00950 break;
00951 if (! TREE_READONLY (decl)
00952 || TREE_ADDRESSABLE (decl)
00953 || by_ref
00954 || is_reference (decl))
00955 {
00956 install_var_field (decl, by_ref, ctx);
00957 install_var_local (decl, ctx);
00958 break;
00959 }
00960
00961 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
00962 goto do_private;
00963
00964 case OMP_CLAUSE_LASTPRIVATE:
00965
00966
00967 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
00968 break;
00969
00970
00971 case OMP_CLAUSE_FIRSTPRIVATE:
00972 case OMP_CLAUSE_REDUCTION:
00973 decl = OMP_CLAUSE_DECL (c);
00974 do_private:
00975 if (is_variable_sized (decl))
00976 break;
00977 else if (is_parallel_ctx (ctx)
00978 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
00979 ctx)))
00980 {
00981 by_ref = use_pointer_for_field (decl, false);
00982 install_var_field (decl, by_ref, ctx);
00983 }
00984 install_var_local (decl, ctx);
00985 break;
00986
00987 case OMP_CLAUSE_COPYPRIVATE:
00988 if (ctx->outer)
00989 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
00990
00991
00992 case OMP_CLAUSE_COPYIN:
00993 decl = OMP_CLAUSE_DECL (c);
00994 by_ref = use_pointer_for_field (decl, false);
00995 install_var_field (decl, by_ref, ctx);
00996 break;
00997
00998 case OMP_CLAUSE_DEFAULT:
00999 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
01000 break;
01001
01002 case OMP_CLAUSE_IF:
01003 case OMP_CLAUSE_NUM_THREADS:
01004 case OMP_CLAUSE_SCHEDULE:
01005 if (ctx->outer)
01006 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
01007 break;
01008
01009 case OMP_CLAUSE_NOWAIT:
01010 case OMP_CLAUSE_ORDERED:
01011 break;
01012
01013 default:
01014 gcc_unreachable ();
01015 }
01016 }
01017
01018 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
01019 {
01020 switch (OMP_CLAUSE_CODE (c))
01021 {
01022 case OMP_CLAUSE_LASTPRIVATE:
01023
01024
01025 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
01026 break;
01027
01028
01029 case OMP_CLAUSE_PRIVATE:
01030 case OMP_CLAUSE_FIRSTPRIVATE:
01031 case OMP_CLAUSE_REDUCTION:
01032 decl = OMP_CLAUSE_DECL (c);
01033 if (is_variable_sized (decl))
01034 install_var_local (decl, ctx);
01035 fixup_remapped_decl (decl, ctx,
01036 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
01037 && OMP_CLAUSE_PRIVATE_DEBUG (c));
01038 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
01039 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01040 scan_array_reductions = true;
01041 break;
01042
01043 case OMP_CLAUSE_SHARED:
01044 decl = OMP_CLAUSE_DECL (c);
01045 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
01046 fixup_remapped_decl (decl, ctx, false);
01047 break;
01048
01049 case OMP_CLAUSE_COPYPRIVATE:
01050 case OMP_CLAUSE_COPYIN:
01051 case OMP_CLAUSE_DEFAULT:
01052 case OMP_CLAUSE_IF:
01053 case OMP_CLAUSE_NUM_THREADS:
01054 case OMP_CLAUSE_SCHEDULE:
01055 case OMP_CLAUSE_NOWAIT:
01056 case OMP_CLAUSE_ORDERED:
01057 break;
01058
01059 default:
01060 gcc_unreachable ();
01061 }
01062 }
01063
01064 if (scan_array_reductions)
01065 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
01066 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
01067 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01068 {
01069 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
01070 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
01071 }
01072 }
01073
01074
01075
01076 static GTY(()) unsigned int tmp_ompfn_id_num;
01077
01078 static tree
01079 create_omp_child_function_name (void)
01080 {
01081 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
01082 size_t len = IDENTIFIER_LENGTH (name);
01083 char *tmp_name, *prefix;
01084
01085 prefix = alloca (len + sizeof ("_omp_fn"));
01086 memcpy (prefix, IDENTIFIER_POINTER (name), len);
01087 strcpy (prefix + len, "_omp_fn");
01088 #ifndef NO_DOT_IN_LABEL
01089 prefix[len] = '.';
01090 #elif !defined NO_DOLLAR_IN_LABEL
01091 prefix[len] = '$';
01092 #endif
01093 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
01094 return get_identifier (tmp_name);
01095 }
01096
01097
01098
01099
01100 static void
01101 create_omp_child_function (omp_context *ctx)
01102 {
01103 tree decl, type, name, t;
01104
01105 name = create_omp_child_function_name ();
01106 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
01107
01108 decl = build_decl (FUNCTION_DECL, name, type);
01109 decl = lang_hooks.decls.pushdecl (decl);
01110
01111 ctx->cb.dst_fn = decl;
01112
01113 TREE_STATIC (decl) = 1;
01114 TREE_USED (decl) = 1;
01115 DECL_ARTIFICIAL (decl) = 1;
01116 DECL_IGNORED_P (decl) = 0;
01117 TREE_PUBLIC (decl) = 0;
01118 DECL_UNINLINABLE (decl) = 1;
01119 DECL_EXTERNAL (decl) = 0;
01120 DECL_CONTEXT (decl) = NULL_TREE;
01121 DECL_INITIAL (decl) = make_node (BLOCK);
01122
01123 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
01124 DECL_ARTIFICIAL (t) = 1;
01125 DECL_IGNORED_P (t) = 1;
01126 DECL_RESULT (decl) = t;
01127
01128 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
01129 DECL_ARTIFICIAL (t) = 1;
01130 DECL_ARG_TYPE (t) = ptr_type_node;
01131 DECL_CONTEXT (t) = current_function_decl;
01132 TREE_USED (t) = 1;
01133 DECL_ARGUMENTS (decl) = t;
01134 ctx->receiver_decl = t;
01135
01136
01137
01138
01139 allocate_struct_function (decl);
01140 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
01141 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
01142 cfun = ctx->cb.src_cfun;
01143 }
01144
01145
01146
01147
01148 static void
01149 scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
01150 {
01151 omp_context *ctx;
01152 tree name;
01153
01154
01155
01156 if (optimize > 0
01157 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
01158 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
01159 {
01160 *stmt_p = build_empty_stmt ();
01161 return;
01162 }
01163
01164 ctx = new_omp_context (*stmt_p, outer_ctx);
01165 if (parallel_nesting_level > 1)
01166 ctx->is_nested = true;
01167 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
01168 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
01169 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
01170 name = create_tmp_var_name (".omp_data_s");
01171 name = build_decl (TYPE_DECL, name, ctx->record_type);
01172 TYPE_NAME (ctx->record_type) = name;
01173 create_omp_child_function (ctx);
01174 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
01175
01176 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
01177 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
01178
01179 if (TYPE_FIELDS (ctx->record_type) == NULL)
01180 ctx->record_type = ctx->receiver_decl = NULL;
01181 else
01182 {
01183 layout_type (ctx->record_type);
01184 fixup_child_record_type (ctx);
01185 }
01186 }
01187
01188
01189
01190
01191 static void
01192 scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
01193 {
01194 omp_context *ctx;
01195 tree stmt;
01196
01197 stmt = *stmt_p;
01198 ctx = new_omp_context (stmt, outer_ctx);
01199
01200 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
01201
01202 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
01203 scan_omp (&OMP_FOR_INIT (stmt), ctx);
01204 scan_omp (&OMP_FOR_COND (stmt), ctx);
01205 scan_omp (&OMP_FOR_INCR (stmt), ctx);
01206 scan_omp (&OMP_FOR_BODY (stmt), ctx);
01207 }
01208
01209
01210
01211 static void
01212 scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
01213 {
01214 tree stmt;
01215 omp_context *ctx;
01216
01217 stmt = *stmt_p;
01218 ctx = new_omp_context (stmt, outer_ctx);
01219 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
01220 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
01221 }
01222
01223
01224
01225 static void
01226 scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
01227 {
01228 tree stmt = *stmt_p;
01229 omp_context *ctx;
01230 tree name;
01231
01232 ctx = new_omp_context (stmt, outer_ctx);
01233 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
01234 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
01235 name = create_tmp_var_name (".omp_copy_s");
01236 name = build_decl (TYPE_DECL, name, ctx->record_type);
01237 TYPE_NAME (ctx->record_type) = name;
01238
01239 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
01240 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
01241
01242 if (TYPE_FIELDS (ctx->record_type) == NULL)
01243 ctx->record_type = NULL;
01244 else
01245 layout_type (ctx->record_type);
01246 }
01247
01248
01249
01250 static void
01251 check_omp_nesting_restrictions (tree t, omp_context *ctx)
01252 {
01253 switch (TREE_CODE (t))
01254 {
01255 case OMP_FOR:
01256 case OMP_SECTIONS:
01257 case OMP_SINGLE:
01258 for (; ctx != NULL; ctx = ctx->outer)
01259 switch (TREE_CODE (ctx->stmt))
01260 {
01261 case OMP_FOR:
01262 case OMP_SECTIONS:
01263 case OMP_SINGLE:
01264 case OMP_ORDERED:
01265 case OMP_MASTER:
01266 warning (0, "work-sharing region may not be closely nested inside "
01267 "of work-sharing, critical, ordered or master region");
01268 return;
01269 case OMP_PARALLEL:
01270 return;
01271 default:
01272 break;
01273 }
01274 break;
01275 case OMP_MASTER:
01276 for (; ctx != NULL; ctx = ctx->outer)
01277 switch (TREE_CODE (ctx->stmt))
01278 {
01279 case OMP_FOR:
01280 case OMP_SECTIONS:
01281 case OMP_SINGLE:
01282 warning (0, "master region may not be closely nested inside "
01283 "of work-sharing region");
01284 return;
01285 case OMP_PARALLEL:
01286 return;
01287 default:
01288 break;
01289 }
01290 break;
01291 case OMP_ORDERED:
01292 for (; ctx != NULL; ctx = ctx->outer)
01293 switch (TREE_CODE (ctx->stmt))
01294 {
01295 case OMP_CRITICAL:
01296 warning (0, "ordered region may not be closely nested inside "
01297 "of critical region");
01298 return;
01299 case OMP_FOR:
01300 if (find_omp_clause (OMP_CLAUSES (ctx->stmt),
01301 OMP_CLAUSE_ORDERED) == NULL)
01302 warning (0, "ordered region must be closely nested inside "
01303 "a loop region with an ordered clause");
01304 return;
01305 case OMP_PARALLEL:
01306 return;
01307 default:
01308 break;
01309 }
01310 break;
01311 case OMP_CRITICAL:
01312 for (; ctx != NULL; ctx = ctx->outer)
01313 if (TREE_CODE (ctx->stmt) == OMP_CRITICAL
01314 && OMP_CRITICAL_NAME (t) == OMP_CRITICAL_NAME (ctx->stmt))
01315 {
01316 warning (0, "critical region may not be nested inside a critical "
01317 "region with the same name");
01318 return;
01319 }
01320 break;
01321 default:
01322 break;
01323 }
01324 }
01325
01326
01327
01328
01329 static tree
01330 scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
01331 {
01332 struct walk_stmt_info *wi = data;
01333 omp_context *ctx = wi->info;
01334 tree t = *tp;
01335
01336 if (EXPR_HAS_LOCATION (t))
01337 input_location = EXPR_LOCATION (t);
01338
01339
01340 if (OMP_DIRECTIVE_P (t) && ctx != NULL)
01341 check_omp_nesting_restrictions (t, ctx);
01342
01343 *walk_subtrees = 0;
01344 switch (TREE_CODE (t))
01345 {
01346 case OMP_PARALLEL:
01347 parallel_nesting_level++;
01348 scan_omp_parallel (tp, ctx);
01349 parallel_nesting_level--;
01350 break;
01351
01352 case OMP_FOR:
01353 scan_omp_for (tp, ctx);
01354 break;
01355
01356 case OMP_SECTIONS:
01357 scan_omp_sections (tp, ctx);
01358 break;
01359
01360 case OMP_SINGLE:
01361 scan_omp_single (tp, ctx);
01362 break;
01363
01364 case OMP_SECTION:
01365 case OMP_MASTER:
01366 case OMP_ORDERED:
01367 case OMP_CRITICAL:
01368 ctx = new_omp_context (*tp, ctx);
01369 scan_omp (&OMP_BODY (*tp), ctx);
01370 break;
01371
01372 case BIND_EXPR:
01373 {
01374 tree var;
01375 *walk_subtrees = 1;
01376
01377 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
01378 insert_decl_map (&ctx->cb, var, var);
01379 }
01380 break;
01381
01382 case VAR_DECL:
01383 case PARM_DECL:
01384 case LABEL_DECL:
01385 case RESULT_DECL:
01386 if (ctx)
01387 *tp = remap_decl (t, &ctx->cb);
01388 break;
01389
01390 default:
01391 if (ctx && TYPE_P (t))
01392 *tp = remap_type (t, &ctx->cb);
01393 else if (!DECL_P (t))
01394 *walk_subtrees = 1;
01395 break;
01396 }
01397
01398 return NULL_TREE;
01399 }
01400
01401
01402
01403
01404
01405
01406 static void
01407 scan_omp (tree *stmt_p, omp_context *ctx)
01408 {
01409 location_t saved_location;
01410 struct walk_stmt_info wi;
01411
01412 memset (&wi, 0, sizeof (wi));
01413 wi.callback = scan_omp_1;
01414 wi.info = ctx;
01415 wi.want_bind_expr = (ctx != NULL);
01416 wi.want_locations = true;
01417
01418 saved_location = input_location;
01419 walk_stmts (&wi, stmt_p);
01420 input_location = saved_location;
01421 }
01422
01423
01424
01425
01426
01427 static void
01428 build_omp_barrier (tree *stmt_list)
01429 {
01430 tree t;
01431
01432 t = built_in_decls[BUILT_IN_GOMP_BARRIER];
01433 t = build_function_call_expr (t, NULL);
01434 gimplify_and_add (t, stmt_list);
01435 }
01436
01437
01438
01439 static omp_context *
01440 maybe_lookup_ctx (tree stmt)
01441 {
01442 splay_tree_node n;
01443 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
01444 return n ? (omp_context *) n->value : NULL;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497 static tree
01498 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
01499 {
01500 tree t;
01501 omp_context *up;
01502
01503 gcc_assert (ctx->is_nested);
01504
01505 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
01506 t = maybe_lookup_decl (decl, up);
01507
01508 gcc_assert (t);
01509
01510 return t;
01511 }
01512
01513
01514
01515
01516
01517 static tree
01518 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
01519 {
01520 tree t = NULL;
01521 omp_context *up;
01522
01523 if (ctx->is_nested)
01524 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
01525 t = maybe_lookup_decl (decl, up);
01526
01527 return t ? t : decl;
01528 }
01529
01530
01531
01532
01533 tree
01534 omp_reduction_init (tree clause, tree type)
01535 {
01536 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
01537 {
01538 case PLUS_EXPR:
01539 case MINUS_EXPR:
01540 case BIT_IOR_EXPR:
01541 case BIT_XOR_EXPR:
01542 case TRUTH_OR_EXPR:
01543 case TRUTH_ORIF_EXPR:
01544 case TRUTH_XOR_EXPR:
01545 case NE_EXPR:
01546 return fold_convert (type, integer_zero_node);
01547
01548 case MULT_EXPR:
01549 case TRUTH_AND_EXPR:
01550 case TRUTH_ANDIF_EXPR:
01551 case EQ_EXPR:
01552 return fold_convert (type, integer_one_node);
01553
01554 case BIT_AND_EXPR:
01555 return fold_convert (type, integer_minus_one_node);
01556
01557 case MAX_EXPR:
01558 if (SCALAR_FLOAT_TYPE_P (type))
01559 {
01560 REAL_VALUE_TYPE max, min;
01561 if (HONOR_INFINITIES (TYPE_MODE (type)))
01562 {
01563 real_inf (&max);
01564 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
01565 }
01566 else
01567 real_maxval (&min, 1, TYPE_MODE (type));
01568 return build_real (type, min);
01569 }
01570 else
01571 {
01572 gcc_assert (INTEGRAL_TYPE_P (type));
01573 return TYPE_MIN_VALUE (type);
01574 }
01575
01576 case MIN_EXPR:
01577 if (SCALAR_FLOAT_TYPE_P (type))
01578 {
01579 REAL_VALUE_TYPE max;
01580 if (HONOR_INFINITIES (TYPE_MODE (type)))
01581 real_inf (&max);
01582 else
01583 real_maxval (&max, 0, TYPE_MODE (type));
01584 return build_real (type, max);
01585 }
01586 else
01587 {
01588 gcc_assert (INTEGRAL_TYPE_P (type));
01589 return TYPE_MAX_VALUE (type);
01590 }
01591
01592 default:
01593 gcc_unreachable ();
01594 }
01595 }
01596
01597
01598
01599
01600
01601
01602 static void
01603 lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
01604 omp_context *ctx)
01605 {
01606 tree_stmt_iterator diter;
01607 tree c, dtor, copyin_seq, x, args, ptr;
01608 bool copyin_by_ref = false;
01609 bool lastprivate_firstprivate = false;
01610 int pass;
01611
01612 *dlist = alloc_stmt_list ();
01613 diter = tsi_start (*dlist);
01614 copyin_seq = NULL;
01615
01616
01617
01618
01619
01620 for (pass = 0; pass < 2; ++pass)
01621 {
01622 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
01623 {
01624 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
01625 tree var, new_var;
01626 bool by_ref;
01627
01628 switch (c_kind)
01629 {
01630 case OMP_CLAUSE_PRIVATE:
01631 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
01632 continue;
01633 break;
01634 case OMP_CLAUSE_SHARED:
01635 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
01636 {
01637 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
01638 continue;
01639 }
01640 case OMP_CLAUSE_FIRSTPRIVATE:
01641 case OMP_CLAUSE_COPYIN:
01642 case OMP_CLAUSE_REDUCTION:
01643 break;
01644 case OMP_CLAUSE_LASTPRIVATE:
01645 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
01646 {
01647 lastprivate_firstprivate = true;
01648 if (pass != 0)
01649 continue;
01650 }
01651 break;
01652 default:
01653 continue;
01654 }
01655
01656 new_var = var = OMP_CLAUSE_DECL (c);
01657 if (c_kind != OMP_CLAUSE_COPYIN)
01658 new_var = lookup_decl (var, ctx);
01659
01660 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
01661 {
01662 if (pass != 0)
01663 continue;
01664 }
01665 else if (is_variable_sized (var))
01666 {
01667
01668
01669
01670 if (pass == 0)
01671 continue;
01672
01673 ptr = DECL_VALUE_EXPR (new_var);
01674 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
01675 ptr = TREE_OPERAND (ptr, 0);
01676 gcc_assert (DECL_P (ptr));
01677
01678 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
01679 args = tree_cons (NULL, x, NULL);
01680 x = built_in_decls[BUILT_IN_ALLOCA];
01681 x = build_function_call_expr (x, args);
01682 x = fold_convert (TREE_TYPE (ptr), x);
01683 x = build2 (MODIFY_EXPR, void_type_node, ptr, x);
01684 gimplify_and_add (x, ilist);
01685 }
01686 else if (is_reference (var))
01687 {
01688
01689
01690
01691
01692
01693
01694
01695
01696 if (pass == 0)
01697 continue;
01698
01699 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
01700 if (TREE_CONSTANT (x))
01701 {
01702 const char *name = NULL;
01703 if (DECL_NAME (var))
01704 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
01705
01706 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
01707 name);
01708 gimple_add_tmp_var (x);
01709 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
01710 }
01711 else
01712 {
01713 args = tree_cons (NULL, x, NULL);
01714 x = built_in_decls[BUILT_IN_ALLOCA];
01715 x = build_function_call_expr (x, args);
01716 x = fold_convert (TREE_TYPE (new_var), x);
01717 }
01718
01719 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
01720 gimplify_and_add (x, ilist);
01721
01722 new_var = build_fold_indirect_ref (new_var);
01723 }
01724 else if (c_kind == OMP_CLAUSE_REDUCTION
01725 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01726 {
01727 if (pass == 0)
01728 continue;
01729 }
01730 else if (pass != 0)
01731 continue;
01732
01733 switch (OMP_CLAUSE_CODE (c))
01734 {
01735 case OMP_CLAUSE_SHARED:
01736
01737 if (is_global_var (new_var))
01738 break;
01739
01740
01741
01742 by_ref = use_pointer_for_field (var, true);
01743 x = build_receiver_ref (var, by_ref, ctx);
01744 SET_DECL_VALUE_EXPR (new_var, x);
01745 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
01746
01747
01748
01749
01750
01751
01752 if (!by_ref)
01753 TREE_NO_WARNING (var) = 1;
01754 break;
01755
01756 case OMP_CLAUSE_LASTPRIVATE:
01757 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
01758 break;
01759
01760
01761 case OMP_CLAUSE_PRIVATE:
01762 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
01763 if (x)
01764 gimplify_and_add (x, ilist);
01765
01766
01767 do_dtor:
01768 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
01769 if (x)
01770 {
01771 dtor = x;
01772 gimplify_stmt (&dtor);
01773 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
01774 }
01775 break;
01776
01777 case OMP_CLAUSE_FIRSTPRIVATE:
01778 x = build_outer_var_ref (var, ctx);
01779 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
01780 gimplify_and_add (x, ilist);
01781 goto do_dtor;
01782 break;
01783
01784 case OMP_CLAUSE_COPYIN:
01785 by_ref = use_pointer_for_field (var, false);
01786 x = build_receiver_ref (var, by_ref, ctx);
01787 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
01788 append_to_statement_list (x, ©in_seq);
01789 copyin_by_ref |= by_ref;
01790 break;
01791
01792 case OMP_CLAUSE_REDUCTION:
01793 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01794 {
01795 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
01796 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
01797 }
01798 else
01799 {
01800 x = omp_reduction_init (c, TREE_TYPE (new_var));
01801 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
01802 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
01803 gimplify_and_add (x, ilist);
01804 }
01805 break;
01806
01807 default:
01808 gcc_unreachable ();
01809 }
01810 }
01811 }
01812
01813
01814
01815
01816 if (copyin_seq)
01817 {
01818 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
01819 x = build_function_call_expr (x, NULL);
01820 x = build2 (NE_EXPR, boolean_type_node, x,
01821 build_int_cst (TREE_TYPE (x), 0));
01822 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
01823 gimplify_and_add (x, ilist);
01824 }
01825
01826
01827
01828
01829
01830
01831 if (copyin_by_ref || lastprivate_firstprivate)
01832 build_omp_barrier (ilist);
01833 }
01834
01835
01836
01837
01838
01839
01840 static void
01841 lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
01842 omp_context *ctx)
01843 {
01844 tree sub_list, x, c;
01845
01846
01847 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
01848 if (clauses == NULL)
01849 {
01850
01851
01852
01853 if (is_parallel_ctx (ctx))
01854 return;
01855
01856 ctx = ctx->outer;
01857 if (ctx == NULL || !is_parallel_ctx (ctx))
01858 return;
01859
01860 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
01861 OMP_CLAUSE_LASTPRIVATE);
01862 if (clauses == NULL)
01863 return;
01864 }
01865
01866 sub_list = alloc_stmt_list ();
01867
01868 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
01869 {
01870 tree var, new_var;
01871
01872 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
01873 continue;
01874
01875 var = OMP_CLAUSE_DECL (c);
01876 new_var = lookup_decl (var, ctx);
01877
01878 x = build_outer_var_ref (var, ctx);
01879 if (is_reference (var))
01880 new_var = build_fold_indirect_ref (new_var);
01881 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
01882 append_to_statement_list (x, &sub_list);
01883 }
01884
01885 if (predicate)
01886 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
01887 else
01888 x = sub_list;
01889
01890 gimplify_and_add (x, stmt_list);
01891 }
01892
01893
01894
01895
01896 static void
01897 lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
01898 {
01899 tree sub_list = NULL, x, c;
01900 int count = 0;
01901
01902
01903
01904 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
01905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
01906 {
01907 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01908 {
01909
01910 count = -1;
01911 break;
01912 }
01913 count++;
01914 }
01915
01916 if (count == 0)
01917 return;
01918
01919 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
01920 {
01921 tree var, ref, new_var;
01922 enum tree_code code;
01923
01924 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
01925 continue;
01926
01927 var = OMP_CLAUSE_DECL (c);
01928 new_var = lookup_decl (var, ctx);
01929 if (is_reference (var))
01930 new_var = build_fold_indirect_ref (new_var);
01931 ref = build_outer_var_ref (var, ctx);
01932 code = OMP_CLAUSE_REDUCTION_CODE (c);
01933
01934
01935
01936 if (code == MINUS_EXPR)
01937 code = PLUS_EXPR;
01938
01939 if (count == 1)
01940 {
01941 tree addr = build_fold_addr_expr (ref);
01942
01943 addr = save_expr (addr);
01944 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
01945 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
01946 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
01947 gimplify_and_add (x, stmt_list);
01948 return;
01949 }
01950
01951 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
01952 {
01953 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
01954
01955 if (is_reference (var))
01956 ref = build_fold_addr_expr (ref);
01957 SET_DECL_VALUE_EXPR (placeholder, ref);
01958 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
01959 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
01960 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
01961 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
01962 }
01963 else
01964 {
01965 x = build2 (code, TREE_TYPE (ref), ref, new_var);
01966 ref = build_outer_var_ref (var, ctx);
01967 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
01968 append_to_statement_list (x, &sub_list);
01969 }
01970 }
01971
01972 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
01973 x = build_function_call_expr (x, NULL);
01974 gimplify_and_add (x, stmt_list);
01975
01976 gimplify_and_add (sub_list, stmt_list);
01977
01978 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
01979 x = build_function_call_expr (x, NULL);
01980 gimplify_and_add (x, stmt_list);
01981 }
01982
01983
01984
01985
01986 static void
01987 lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
01988 omp_context *ctx)
01989 {
01990 tree c;
01991
01992 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
01993 {
01994 tree var, ref, x;
01995 bool by_ref;
01996
01997 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
01998 continue;
01999
02000 var = OMP_CLAUSE_DECL (c);
02001 by_ref = use_pointer_for_field (var, false);
02002
02003 ref = build_sender_ref (var, ctx);
02004 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
02005 x = by_ref ? build_fold_addr_expr (x) : x;
02006 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
02007 gimplify_and_add (x, slist);
02008
02009 ref = build_receiver_ref (var, by_ref, ctx);
02010 if (is_reference (var))
02011 {
02012 ref = build_fold_indirect_ref (ref);
02013 var = build_fold_indirect_ref (var);
02014 }
02015 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
02016 gimplify_and_add (x, rlist);
02017 }
02018 }
02019
02020
02021
02022
02023
02024 static void
02025 lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
02026 {
02027 tree c;
02028
02029 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
02030 {
02031 tree val, ref, x, var;
02032 bool by_ref, do_in = false, do_out = false;
02033
02034 switch (OMP_CLAUSE_CODE (c))
02035 {
02036 case OMP_CLAUSE_FIRSTPRIVATE:
02037 case OMP_CLAUSE_COPYIN:
02038 case OMP_CLAUSE_LASTPRIVATE:
02039 case OMP_CLAUSE_REDUCTION:
02040 break;
02041 default:
02042 continue;
02043 }
02044
02045 var = val = OMP_CLAUSE_DECL (c);
02046 if (ctx->is_nested)
02047 var = lookup_decl_in_outer_ctx (val, ctx);
02048
02049 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
02050 && is_global_var (var))
02051 continue;
02052 if (is_variable_sized (val))
02053 continue;
02054 by_ref = use_pointer_for_field (val, false);
02055
02056 switch (OMP_CLAUSE_CODE (c))
02057 {
02058 case OMP_CLAUSE_FIRSTPRIVATE:
02059 case OMP_CLAUSE_COPYIN:
02060 do_in = true;
02061 break;
02062
02063 case OMP_CLAUSE_LASTPRIVATE:
02064 if (by_ref || is_reference (val))
02065 {
02066 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
02067 continue;
02068 do_in = true;
02069 }
02070 else
02071 do_out = true;
02072 break;
02073
02074 case OMP_CLAUSE_REDUCTION:
02075 do_in = true;
02076 do_out = !(by_ref || is_reference (val));
02077 break;
02078
02079 default:
02080 gcc_unreachable ();
02081 }
02082
02083 if (do_in)
02084 {
02085 ref = build_sender_ref (val, ctx);
02086 x = by_ref ? build_fold_addr_expr (var) : var;
02087 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
02088 gimplify_and_add (x, ilist);
02089 }
02090
02091 if (do_out)
02092 {
02093 ref = build_sender_ref (val, ctx);
02094 x = build2 (MODIFY_EXPR, void_type_node, var, ref);
02095 gimplify_and_add (x, olist);
02096 }
02097 }
02098 }
02099
02100
02101
02102
02103
02104 static void
02105 lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
02106 {
02107 tree var, ovar, nvar, f, x;
02108
02109 if (ctx->record_type == NULL)
02110 return;
02111
02112 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
02113 {
02114 ovar = DECL_ABSTRACT_ORIGIN (f);
02115 nvar = maybe_lookup_decl (ovar, ctx);
02116 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
02117 continue;
02118
02119 var = ovar;
02120
02121
02122
02123
02124 if (ctx->is_nested)
02125 var = lookup_decl_in_outer_ctx (ovar, ctx);
02126
02127 if (use_pointer_for_field (ovar, true))
02128 {
02129 x = build_sender_ref (ovar, ctx);
02130 var = build_fold_addr_expr (var);
02131 x = build2 (MODIFY_EXPR, void_type_node, x, var);
02132 gimplify_and_add (x, ilist);
02133 }
02134 else
02135 {
02136 x = build_sender_ref (ovar, ctx);
02137 x = build2 (MODIFY_EXPR, void_type_node, x, var);
02138 gimplify_and_add (x, ilist);
02139
02140 x = build_sender_ref (ovar, ctx);
02141 x = build2 (MODIFY_EXPR, void_type_node, var, x);
02142 gimplify_and_add (x, olist);
02143 }
02144 }
02145 }
02146
02147
02148
02149
02150
02151
02152
02153
02154 static void
02155 expand_parallel_call (struct omp_region *region, basic_block bb,
02156 tree entry_stmt, tree ws_args)
02157 {
02158 tree t, args, val, cond, c, list, clauses;
02159 block_stmt_iterator si;
02160 int start_ix;
02161
02162 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
02163 push_gimplify_context ();
02164
02165
02166
02167 start_ix = BUILT_IN_GOMP_PARALLEL_START;
02168 if (is_combined_parallel (region))
02169 {
02170 switch (region->inner->type)
02171 {
02172 case OMP_FOR:
02173 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
02174 + region->inner->sched_kind;
02175 break;
02176 case OMP_SECTIONS:
02177 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
02178 break;
02179 default:
02180 gcc_unreachable ();
02181 }
02182 }
02183
02184
02185
02186 cond = NULL_TREE;
02187 val = build_int_cst (unsigned_type_node, 0);
02188
02189 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
02190 if (c)
02191 cond = OMP_CLAUSE_IF_EXPR (c);
02192
02193 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
02194 if (c)
02195 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
02196
02197
02198 val = fold_convert (unsigned_type_node, val);
02199
02200
02201
02202 if (cond)
02203 {
02204 block_stmt_iterator si;
02205
02206 cond = gimple_boolify (cond);
02207
02208 if (integer_zerop (val))
02209 val = build2 (EQ_EXPR, unsigned_type_node, cond,
02210 build_int_cst (TREE_TYPE (cond), 0));
02211 else
02212 {
02213 basic_block cond_bb, then_bb, else_bb;
02214 edge e;
02215 tree t, then_lab, else_lab, tmp;
02216
02217 tmp = create_tmp_var (TREE_TYPE (val), NULL);
02218 e = split_block (bb, NULL);
02219 cond_bb = e->src;
02220 bb = e->dest;
02221 remove_edge (e);
02222
02223 then_bb = create_empty_bb (cond_bb);
02224 else_bb = create_empty_bb (then_bb);
02225 then_lab = create_artificial_label ();
02226 else_lab = create_artificial_label ();
02227
02228 t = build3 (COND_EXPR, void_type_node,
02229 cond,
02230 build_and_jump (&then_lab),
02231 build_and_jump (&else_lab));
02232
02233 si = bsi_start (cond_bb);
02234 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
02235
02236 si = bsi_start (then_bb);
02237 t = build1 (LABEL_EXPR, void_type_node, then_lab);
02238 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
02239 t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
02240 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
02241
02242 si = bsi_start (else_bb);
02243 t = build1 (LABEL_EXPR, void_type_node, else_lab);
02244 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
02245 t = build2 (MODIFY_EXPR, void_type_node, tmp,
02246 build_int_cst (unsigned_type_node, 1));
02247 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
02248
02249 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
02250 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
02251 make_edge (then_bb, bb, EDGE_FALLTHRU);
02252 make_edge (else_bb, bb, EDGE_FALLTHRU);
02253
02254 val = tmp;
02255 }
02256
02257 list = NULL_TREE;
02258 val = get_formal_tmp_var (val, &list);
02259 si = bsi_start (bb);
02260 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
02261 }
02262
02263 list = NULL_TREE;
02264 args = tree_cons (NULL, val, NULL);
02265 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
02266 if (t == NULL)
02267 t = null_pointer_node;
02268 else
02269 t = build_fold_addr_expr (t);
02270 args = tree_cons (NULL, t, args);
02271 t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
02272 args = tree_cons (NULL, t, args);
02273
02274 if (ws_args)
02275 args = chainon (args, ws_args);
02276
02277 t = built_in_decls[start_ix];
02278 t = build_function_call_expr (t, args);
02279 gimplify_and_add (t, &list);
02280
02281 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
02282 if (t == NULL)
02283 t = null_pointer_node;
02284 else
02285 t = build_fold_addr_expr (t);
02286 args = tree_cons (NULL, t, NULL);
02287 t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
02288 gimplify_and_add (t, &list);
02289
02290 t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
02291 t = build_function_call_expr (t, NULL);
02292 gimplify_and_add (t, &list);
02293
02294 si = bsi_last (bb);
02295 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
02296
02297 pop_gimplify_context (NULL_TREE);
02298 }
02299
02300
02301
02302
02303
02304
02305 static void
02306 maybe_catch_exception (tree *stmt_p)
02307 {
02308 tree f, t;
02309
02310 if (!flag_exceptions)
02311 return;
02312
02313 if (lang_protect_cleanup_actions)
02314 t = lang_protect_cleanup_actions ();
02315 else
02316 {
02317 t = built_in_decls[BUILT_IN_TRAP];
02318 t = build_function_call_expr (t, NULL);
02319 }
02320 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
02321 EH_FILTER_MUST_NOT_THROW (f) = 1;
02322 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
02323
02324 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
02325 append_to_statement_list (f, &TREE_OPERAND (t, 1));
02326
02327 *stmt_p = NULL;
02328 append_to_statement_list (t, stmt_p);
02329 }
02330
02331
02332
02333 static tree
02334 list2chain (tree list)
02335 {
02336 tree t;
02337
02338 for (t = list; t; t = TREE_CHAIN (t))
02339 {
02340 tree var = TREE_VALUE (t);
02341 if (TREE_CHAIN (t))
02342 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
02343 else
02344 TREE_CHAIN (var) = NULL_TREE;
02345 }
02346
02347 return list ? TREE_VALUE (list) : NULL_TREE;
02348 }
02349
02350
02351
02352
02353
02354
02355
02356
02357 static void
02358 remove_exit_barrier (struct omp_region *region)
02359 {
02360 block_stmt_iterator si;
02361 basic_block exit_bb;
02362 edge_iterator ei;
02363 edge e;
02364 tree t;
02365
02366 exit_bb = region->exit;
02367
02368
02369
02370 if (! exit_bb)
02371 return;
02372
02373
02374
02375
02376
02377
02378 si = bsi_last (exit_bb);
02379 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
02380 bsi_prev (&si);
02381 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
02382 return;
02383
02384 FOR_EACH_EDGE (e, ei, exit_bb->preds)
02385 {
02386 si = bsi_last (e->src);
02387 if (bsi_end_p (si))
02388 continue;
02389 t = bsi_stmt (si);
02390 if (TREE_CODE (t) == OMP_RETURN)
02391 OMP_RETURN_NOWAIT (t) = 1;
02392 }
02393 }
02394
02395 static void
02396 remove_exit_barriers (struct omp_region *region)
02397 {
02398 if (region->type == OMP_PARALLEL)
02399 remove_exit_barrier (region);
02400
02401 if (region->inner)
02402 {
02403 region = region->inner;
02404 remove_exit_barriers (region);
02405 while (region->next)
02406 {
02407 region = region->next;
02408 remove_exit_barriers (region);
02409 }
02410 }
02411 }
02412
02413
02414
02415 static void
02416 expand_omp_parallel (struct omp_region *region)
02417 {
02418 basic_block entry_bb, exit_bb, new_bb;
02419 struct function *child_cfun, *saved_cfun;
02420 tree child_fn, block, t, ws_args;
02421 block_stmt_iterator si;
02422 tree entry_stmt;
02423 edge e;
02424 bool do_cleanup_cfg = false;
02425
02426 entry_stmt = last_stmt (region->entry);
02427 child_fn = OMP_PARALLEL_FN (entry_stmt);
02428 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
02429 saved_cfun = cfun;
02430
02431 entry_bb = region->entry;
02432 exit_bb = region->exit;
02433
02434 if (is_combined_parallel (region))
02435 ws_args = region->ws_args;
02436 else
02437 ws_args = NULL_TREE;
02438
02439 if (child_cfun->cfg)
02440 {
02441
02442
02443
02444 edge entry_succ_e, exit_succ_e;
02445 block_stmt_iterator si;
02446
02447 entry_succ_e = single_succ_edge (entry_bb);
02448
02449 si = bsi_last (entry_bb);
02450 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
02451 bsi_remove (&si, true);
02452
02453 new_bb = entry_bb;
02454 remove_edge (entry_succ_e);
02455 if (exit_bb)
02456 {
02457 exit_succ_e = single_succ_edge (exit_bb);
02458 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
02459 }
02460 do_cleanup_cfg = true;
02461 }
02462 else
02463 {
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
02478 {
02479 basic_block entry_succ_bb = single_succ (entry_bb);
02480 block_stmt_iterator si;
02481
02482 for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
02483 {
02484 tree stmt, arg;
02485
02486 gcc_assert (!bsi_end_p (si));
02487 stmt = bsi_stmt (si);
02488 if (TREE_CODE (stmt) != MODIFY_EXPR)
02489 continue;
02490
02491 arg = TREE_OPERAND (stmt, 1);
02492 STRIP_NOPS (arg);
02493 if (TREE_CODE (arg) == ADDR_EXPR
02494 && TREE_OPERAND (arg, 0)
02495 == OMP_PARALLEL_DATA_ARG (entry_stmt))
02496 {
02497 if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
02498 bsi_remove (&si, true);
02499 else
02500 TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
02501 break;
02502 }
02503 }
02504 }
02505
02506
02507 block = DECL_INITIAL (child_fn);
02508 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
02509 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
02510
02511
02512 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
02513 DECL_CONTEXT (t) = child_fn;
02514
02515 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
02516 DECL_CONTEXT (t) = child_fn;
02517
02518
02519
02520 si = bsi_last (entry_bb);
02521 t = bsi_stmt (si);
02522 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
02523 bsi_remove (&si, true);
02524 e = split_block (entry_bb, t);
02525 entry_bb = e->dest;
02526 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
02527
02528
02529
02530
02531 free_dominance_info (CDI_DOMINATORS);
02532 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
02533 if (exit_bb)
02534 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
02535 cgraph_add_new_function (child_fn);
02536
02537
02538 if (exit_bb)
02539 {
02540 si = bsi_last (exit_bb);
02541 gcc_assert (!bsi_end_p (si)
02542 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
02543 t = build1 (RETURN_EXPR, void_type_node, NULL);
02544 bsi_insert_after (&si, t, BSI_SAME_STMT);
02545 bsi_remove (&si, true);
02546 }
02547 }
02548
02549
02550 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
02551
02552 if (do_cleanup_cfg)
02553 {
02554
02555 free_dominance_info (CDI_DOMINATORS);
02556 free_dominance_info (CDI_POST_DOMINATORS);
02557 cleanup_tree_cfg ();
02558 }
02559 }
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585 static void
02586 expand_omp_for_generic (struct omp_region *region,
02587 struct omp_for_data *fd,
02588 enum built_in_function start_fn,
02589 enum built_in_function next_fn)
02590 {
02591 tree l0, l1, l2 = NULL, l3 = NULL;
02592 tree type, istart0, iend0, iend;
02593 tree t, args, list;
02594 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb;
02595 basic_block l2_bb = NULL, l3_bb = NULL;
02596 block_stmt_iterator si;
02597 bool in_combined_parallel = is_combined_parallel (region);
02598
02599 type = TREE_TYPE (fd->v);
02600
02601 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
02602 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
02603 iend = create_tmp_var (type, NULL);
02604 TREE_ADDRESSABLE (istart0) = 1;
02605 TREE_ADDRESSABLE (iend0) = 1;
02606
02607 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
02608
02609 entry_bb = region->entry;
02610 l0_bb = create_empty_bb (entry_bb);
02611 l1_bb = single_succ (entry_bb);
02612
02613 l0 = tree_block_label (l0_bb);
02614 l1 = tree_block_label (l1_bb);
02615
02616 cont_bb = region->cont;
02617 exit_bb = region->exit;
02618 if (cont_bb)
02619 {
02620 l2_bb = create_empty_bb (cont_bb);
02621 l3_bb = single_succ (cont_bb);
02622
02623 l2 = tree_block_label (l2_bb);
02624 l3 = tree_block_label (l3_bb);
02625 }
02626
02627 si = bsi_last (entry_bb);
02628 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
02629 if (!in_combined_parallel)
02630 {
02631
02632
02633 list = alloc_stmt_list ();
02634 t = build_fold_addr_expr (iend0);
02635 args = tree_cons (NULL, t, NULL);
02636 t = build_fold_addr_expr (istart0);
02637 args = tree_cons (NULL, t, args);
02638 if (fd->chunk_size)
02639 {
02640 t = fold_convert (long_integer_type_node, fd->chunk_size);
02641 args = tree_cons (NULL, t, args);
02642 }
02643 t = fold_convert (long_integer_type_node, fd->step);
02644 args = tree_cons (NULL, t, args);
02645 t = fold_convert (long_integer_type_node, fd->n2);
02646 args = tree_cons (NULL, t, args);
02647 t = fold_convert (long_integer_type_node, fd->n1);
02648 args = tree_cons (NULL, t, args);
02649 t = build_function_call_expr (built_in_decls[start_fn], args);
02650 t = get_formal_tmp_var (t, &list);
02651 if (cont_bb)
02652 {
02653 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
02654 build_and_jump (&l3));
02655 append_to_statement_list (t, &list);
02656 }
02657 bsi_insert_after (&si, list, BSI_SAME_STMT);
02658 }
02659 bsi_remove (&si, true);
02660
02661
02662 list = alloc_stmt_list ();
02663 t = fold_convert (type, istart0);
02664 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
02665 gimplify_and_add (t, &list);
02666
02667 t = fold_convert (type, iend0);
02668 t = build2 (MODIFY_EXPR, void_type_node, iend, t);
02669 gimplify_and_add (t, &list);
02670
02671 si = bsi_start (l0_bb);
02672 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
02673
02674
02675 if (cont_bb == NULL)
02676 {
02677 remove_edge (single_succ_edge (entry_bb));
02678 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
02679 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
02680 return;
02681 }
02682
02683
02684
02685
02686
02687 list = alloc_stmt_list ();
02688
02689 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
02690 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
02691 gimplify_and_add (t, &list);
02692
02693 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
02694 t = get_formal_tmp_var (t, &list);
02695 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
02696 build_and_jump (&l2));
02697 append_to_statement_list (t, &list);
02698
02699 si = bsi_last (cont_bb);
02700 bsi_insert_after (&si, list, BSI_SAME_STMT);
02701 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
02702 bsi_remove (&si, true);
02703
02704
02705 list = alloc_stmt_list ();
02706
02707 t = build_fold_addr_expr (iend0);
02708 args = tree_cons (NULL, t, NULL);
02709 t = build_fold_addr_expr (istart0);
02710 args = tree_cons (NULL, t, args);
02711 t = build_function_call_expr (built_in_decls[next_fn], args);
02712 t = get_formal_tmp_var (t, &list);
02713 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
02714 build_and_jump (&l3));
02715 append_to_statement_list (t, &list);
02716
02717 si = bsi_start (l2_bb);
02718 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
02719
02720
02721 si = bsi_last (exit_bb);
02722 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
02723 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
02724 else
02725 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
02726 t = build_function_call_expr (t, NULL);
02727 bsi_insert_after (&si, t, BSI_SAME_STMT);
02728 bsi_remove (&si, true);
02729
02730
02731 remove_edge (single_succ_edge (entry_bb));
02732 if (in_combined_parallel)
02733 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
02734 else
02735 {
02736 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
02737 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
02738 }
02739
02740 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
02741
02742 remove_edge (single_succ_edge (cont_bb));
02743 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
02744 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
02745
02746 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
02747 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
02748 }
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779 static void
02780 expand_omp_for_static_nochunk (struct omp_region *region,
02781 struct omp_for_data *fd)
02782 {
02783 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
02784 tree type, list;
02785 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
02786 basic_block fin_bb;
02787 block_stmt_iterator si;
02788
02789 type = TREE_TYPE (fd->v);
02790
02791 entry_bb = region->entry;
02792 seq_start_bb = create_empty_bb (entry_bb);
02793 body_bb = single_succ (entry_bb);
02794 cont_bb = region->cont;
02795 fin_bb = single_succ (cont_bb);
02796 exit_bb = region->exit;
02797
02798 l0 = tree_block_label (seq_start_bb);
02799 l1 = tree_block_label (body_bb);
02800 l2 = tree_block_label (fin_bb);
02801
02802
02803 list = alloc_stmt_list ();
02804
02805 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
02806 t = build_function_call_expr (t, NULL);
02807 t = fold_convert (type, t);
02808 nthreads = get_formal_tmp_var (t, &list);
02809
02810 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
02811 t = build_function_call_expr (t, NULL);
02812 t = fold_convert (type, t);
02813 threadid = get_formal_tmp_var (t, &list);
02814
02815 fd->n1 = fold_convert (type, fd->n1);
02816 if (!is_gimple_val (fd->n1))
02817 fd->n1 = get_formal_tmp_var (fd->n1, &list);
02818
02819 fd->n2 = fold_convert (type, fd->n2);
02820 if (!is_gimple_val (fd->n2))
02821 fd->n2 = get_formal_tmp_var (fd->n2, &list);
02822
02823 fd->step = fold_convert (type, fd->step);
02824 if (!is_gimple_val (fd->step))
02825 fd->step = get_formal_tmp_var (fd->step, &list);
02826
02827 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
02828 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
02829 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
02830 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
02831 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
02832 t = fold_convert (type, t);
02833 if (is_gimple_val (t))
02834 n = t;
02835 else
02836 n = get_formal_tmp_var (t, &list);
02837
02838 t = build2 (TRUNC_DIV_EXPR, type, n, nthreads);
02839 q = get_formal_tmp_var (t, &list);
02840
02841 t = build2 (MULT_EXPR, type, q, nthreads);
02842 t = build2 (NE_EXPR, type, t, n);
02843 t = build2 (PLUS_EXPR, type, q, t);
02844 q = get_formal_tmp_var (t, &list);
02845
02846 t = build2 (MULT_EXPR, type, q, threadid);
02847 s0 = get_formal_tmp_var (t, &list);
02848
02849 t = build2 (PLUS_EXPR, type, s0, q);
02850 t = build2 (MIN_EXPR, type, t, n);
02851 e0 = get_formal_tmp_var (t, &list);
02852
02853 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
02854 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
02855 build_and_jump (&l0));
02856 append_to_statement_list (t, &list);
02857
02858 si = bsi_last (entry_bb);
02859 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
02860 bsi_insert_after (&si, list, BSI_SAME_STMT);
02861 bsi_remove (&si, true);
02862
02863
02864 list = alloc_stmt_list ();
02865
02866 t = fold_convert (type, s0);
02867 t = build2 (MULT_EXPR, type, t, fd->step);
02868 t = build2 (PLUS_EXPR, type, t, fd->n1);
02869 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
02870 gimplify_and_add (t, &list);
02871
02872 t = fold_convert (type, e0);
02873 t = build2 (MULT_EXPR, type, t, fd->step);
02874 t = build2 (PLUS_EXPR, type, t, fd->n1);
02875 e = get_formal_tmp_var (t, &list);
02876
02877 si = bsi_start (seq_start_bb);
02878 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
02879
02880
02881 list = alloc_stmt_list ();
02882
02883 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
02884 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
02885 gimplify_and_add (t, &list);
02886
02887 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
02888 t = get_formal_tmp_var (t, &list);
02889 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
02890 build_and_jump (&l2));
02891 append_to_statement_list (t, &list);
02892
02893 si = bsi_last (cont_bb);
02894 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
02895 bsi_insert_after (&si, list, BSI_SAME_STMT);
02896 bsi_remove (&si, true);
02897
02898
02899 si = bsi_last (exit_bb);
02900 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
02901 {
02902 list = alloc_stmt_list ();
02903 build_omp_barrier (&list);
02904 bsi_insert_after (&si, list, BSI_SAME_STMT);
02905 }
02906 bsi_remove (&si, true);
02907
02908
02909 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
02910
02911 remove_edge (single_succ_edge (entry_bb));
02912 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
02913 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
02914
02915 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
02916 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
02917 }
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951 static void
02952 expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
02953 {
02954 tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
02955 tree trip, nthreads, threadid;
02956 tree type;
02957 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
02958 basic_block trip_update_bb, cont_bb, fin_bb;
02959 tree list;
02960 block_stmt_iterator si;
02961
02962 type = TREE_TYPE (fd->v);
02963
02964 entry_bb = region->entry;
02965 iter_part_bb = create_empty_bb (entry_bb);
02966 seq_start_bb = create_empty_bb (iter_part_bb);
02967 body_bb = single_succ (entry_bb);
02968 cont_bb = region->cont;
02969 trip_update_bb = create_empty_bb (cont_bb);
02970 fin_bb = single_succ (cont_bb);
02971 exit_bb = region->exit;
02972
02973 l0 = tree_block_label (iter_part_bb);
02974 l1 = tree_block_label (seq_start_bb);
02975 l2 = tree_block_label (body_bb);
02976 l3 = tree_block_label (trip_update_bb);
02977 l4 = tree_block_label (fin_bb);
02978
02979
02980 list = alloc_stmt_list ();
02981
02982 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
02983 t = build_function_call_expr (t, NULL);
02984 t = fold_convert (type, t);
02985 nthreads = get_formal_tmp_var (t, &list);
02986
02987 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
02988 t = build_function_call_expr (t, NULL);
02989 t = fold_convert (type, t);
02990 threadid = get_formal_tmp_var (t, &list);
02991
02992 fd->n1 = fold_convert (type, fd->n1);
02993 if (!is_gimple_val (fd->n1))
02994 fd->n1 = get_formal_tmp_var (fd->n1, &list);
02995
02996 fd->n2 = fold_convert (type, fd->n2);
02997 if (!is_gimple_val (fd->n2))
02998 fd->n2 = get_formal_tmp_var (fd->n2, &list);
02999
03000 fd->step = fold_convert (type, fd->step);
03001 if (!is_gimple_val (fd->step))
03002 fd->step = get_formal_tmp_var (fd->step, &list);
03003
03004 fd->chunk_size = fold_convert (type, fd->chunk_size);
03005 if (!is_gimple_val (fd->chunk_size))
03006 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
03007
03008 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
03009 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
03010 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
03011 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
03012 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
03013 t = fold_convert (type, t);
03014 if (is_gimple_val (t))
03015 n = t;
03016 else
03017 n = get_formal_tmp_var (t, &list);
03018
03019 t = build_int_cst (type, 0);
03020 trip = get_initialized_tmp_var (t, &list, NULL);
03021
03022 si = bsi_last (entry_bb);
03023 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
03024 bsi_insert_after (&si, list, BSI_SAME_STMT);
03025 bsi_remove (&si, true);
03026
03027
03028 list = alloc_stmt_list ();
03029
03030 t = build2 (MULT_EXPR, type, trip, nthreads);
03031 t = build2 (PLUS_EXPR, type, t, threadid);
03032 t = build2 (MULT_EXPR, type, t, fd->chunk_size);
03033 s0 = get_formal_tmp_var (t, &list);
03034
03035 t = build2 (PLUS_EXPR, type, s0, fd->chunk_size);
03036 t = build2 (MIN_EXPR, type, t, n);
03037 e0 = get_formal_tmp_var (t, &list);
03038
03039 t = build2 (LT_EXPR, boolean_type_node, s0, n);
03040 t = build3 (COND_EXPR, void_type_node, t,
03041 build_and_jump (&l1), build_and_jump (&l4));
03042 append_to_statement_list (t, &list);
03043
03044 si = bsi_start (iter_part_bb);
03045 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
03046
03047
03048 list = alloc_stmt_list ();
03049
03050 t = fold_convert (type, s0);
03051 t = build2 (MULT_EXPR, type, t, fd->step);
03052 t = build2 (PLUS_EXPR, type, t, fd->n1);
03053 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
03054 gimplify_and_add (t, &list);
03055
03056 t = fold_convert (type, e0);
03057 t = build2 (MULT_EXPR, type, t, fd->step);
03058 t = build2 (PLUS_EXPR, type, t, fd->n1);
03059 e = get_formal_tmp_var (t, &list);
03060
03061 si = bsi_start (seq_start_bb);
03062 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
03063
03064
03065
03066 list = alloc_stmt_list ();
03067
03068 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
03069 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
03070 gimplify_and_add (t, &list);
03071
03072 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
03073 t = get_formal_tmp_var (t, &list);
03074 t = build3 (COND_EXPR, void_type_node, t,
03075 build_and_jump (&l2), build_and_jump (&l3));
03076 append_to_statement_list (t, &list);
03077
03078 si = bsi_last (cont_bb);
03079 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
03080 bsi_insert_after (&si, list, BSI_SAME_STMT);
03081 bsi_remove (&si, true);
03082
03083
03084 list = alloc_stmt_list ();
03085
03086 t = build_int_cst (type, 1);
03087 t = build2 (PLUS_EXPR, type, trip, t);
03088 t = build2 (MODIFY_EXPR, void_type_node, trip, t);
03089 gimplify_and_add (t, &list);
03090
03091 si = bsi_start (trip_update_bb);
03092 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
03093
03094
03095 si = bsi_last (exit_bb);
03096 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
03097 {
03098 list = alloc_stmt_list ();
03099 build_omp_barrier (&list);
03100 bsi_insert_after (&si, list, BSI_SAME_STMT);
03101 }
03102 bsi_remove (&si, true);
03103
03104
03105 remove_edge (single_succ_edge (entry_bb));
03106 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
03107
03108 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
03109 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
03110
03111 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
03112
03113 remove_edge (single_succ_edge (cont_bb));
03114 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
03115 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
03116
03117 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
03118 }
03119
03120
03121
03122
03123 static void
03124 expand_omp_for (struct omp_region *region)
03125 {
03126 struct omp_for_data fd;
03127
03128 push_gimplify_context ();
03129
03130 extract_omp_for_data (last_stmt (region->entry), &fd);
03131 region->sched_kind = fd.sched_kind;
03132
03133 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
03134 && !fd.have_ordered
03135 && region->cont
03136 && region->exit)
03137 {
03138 if (fd.chunk_size == NULL)
03139 expand_omp_for_static_nochunk (region, &fd);
03140 else
03141 expand_omp_for_static_chunk (region, &fd);
03142 }
03143 else
03144 {
03145 int fn_index = fd.sched_kind + fd.have_ordered * 4;
03146 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
03147 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
03148 expand_omp_for_generic (region, &fd, start_ix, next_ix);
03149 }
03150
03151 pop_gimplify_context (NULL);
03152 }
03153
03154
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182 static void
03183 expand_omp_sections (struct omp_region *region)
03184 {
03185 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
03186 unsigned i, len;
03187 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
03188 block_stmt_iterator si;
03189 struct omp_region *inner;
03190 edge e;
03191
03192 entry_bb = region->entry;
03193 l0_bb = create_empty_bb (entry_bb);
03194 l0 = tree_block_label (l0_bb);
03195
03196 gcc_assert ((region->cont != NULL) ^ (region->exit == NULL));
03197 l1_bb = region->cont;
03198 if (l1_bb)
03199 {
03200 l2_bb = single_succ (l1_bb);
03201 default_bb = create_empty_bb (l1_bb->prev_bb);
03202
03203 l1 = tree_block_label (l1_bb);
03204 }
03205 else
03206 {
03207 l2_bb = create_empty_bb (l0_bb);
03208 default_bb = l2_bb;
03209
03210 l1 = NULL;
03211 }
03212 l2 = tree_block_label (l2_bb);
03213
03214 exit_bb = region->exit;
03215
03216 v = create_tmp_var (unsigned_type_node, ".section");
03217
03218
03219
03220
03221 len = EDGE_COUNT (entry_bb->succs);
03222 label_vec = make_tree_vec (len + 2);
03223
03224
03225
03226 si = bsi_last (entry_bb);
03227 sections_stmt = bsi_stmt (si);
03228 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
03229 if (!is_combined_parallel (region))
03230 {
03231
03232
03233 t = build_int_cst (unsigned_type_node, len);
03234 t = tree_cons (NULL, t, NULL);
03235 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
03236 t = build_function_call_expr (u, t);
03237 t = build2 (MODIFY_EXPR, void_type_node, v, t);
03238 bsi_insert_after (&si, t, BSI_SAME_STMT);
03239 }
03240 bsi_remove (&si, true);
03241
03242
03243 si = bsi_start (l0_bb);
03244
03245 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
03246 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
03247
03248 t = build3 (CASE_LABEL_EXPR, void_type_node,
03249 build_int_cst (unsigned_type_node, 0), NULL, l2);
03250 TREE_VEC_ELT (label_vec, 0) = t;
03251 make_edge (l0_bb, l2_bb, 0);
03252
03253
03254 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
03255 {
03256 basic_block s_entry_bb, s_exit_bb;
03257
03258 s_entry_bb = inner->entry;
03259 s_exit_bb = inner->exit;
03260
03261 t = tree_block_label (s_entry_bb);
03262 u = build_int_cst (unsigned_type_node, i);
03263 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
03264 TREE_VEC_ELT (label_vec, i) = u;
03265
03266 si = bsi_last (s_entry_bb);
03267 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
03268 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
03269 bsi_remove (&si, true);
03270
03271 e = single_pred_edge (s_entry_bb);
03272 e->flags = 0;
03273 redirect_edge_pred (e, l0_bb);
03274
03275 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03276
03277 if (s_exit_bb == NULL)
03278 continue;
03279
03280 si = bsi_last (s_exit_bb);
03281 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
03282 bsi_remove (&si, true);
03283
03284 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
03285 }
03286
03287
03288 t = tree_block_label (default_bb);
03289 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
03290 TREE_VEC_ELT (label_vec, len + 1) = u;
03291 make_edge (l0_bb, default_bb, 0);
03292
03293 si = bsi_start (default_bb);
03294 t = built_in_decls[BUILT_IN_TRAP];
03295 t = build_function_call_expr (t, NULL);
03296 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
03297
03298
03299 if (l1_bb)
03300 {
03301 si = bsi_last (l1_bb);
03302 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
03303
03304 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
03305 t = build_function_call_expr (t, NULL);
03306 t = build2 (MODIFY_EXPR, void_type_node, v, t);
03307 bsi_insert_after (&si, t, BSI_SAME_STMT);
03308 bsi_remove (&si, true);
03309 }
03310
03311
03312 if (exit_bb)
03313 {
03314 si = bsi_last (exit_bb);
03315 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
03316 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
03317 else
03318 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
03319 t = build_function_call_expr (t, NULL);
03320 bsi_insert_after (&si, t, BSI_SAME_STMT);
03321 bsi_remove (&si, true);
03322 }
03323
03324
03325 if (is_combined_parallel (region))
03326 {
03327
03328
03329
03330 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
03331 }
03332 else
03333 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
03334
03335 if (l1_bb)
03336 {
03337 e = single_succ_edge (l1_bb);
03338 redirect_edge_succ (e, l0_bb);
03339 e->flags = EDGE_FALLTHRU;
03340 }
03341 }
03342
03343
03344
03345
03346
03347 static void
03348 expand_omp_single (struct omp_region *region)
03349 {
03350 basic_block entry_bb, exit_bb;
03351 block_stmt_iterator si;
03352 bool need_barrier = false;
03353
03354 entry_bb = region->entry;
03355 exit_bb = region->exit;
03356
03357 si = bsi_last (entry_bb);
03358
03359
03360
03361 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
03362 OMP_CLAUSE_COPYPRIVATE))
03363 need_barrier = true;
03364 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
03365 bsi_remove (&si, true);
03366 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
03367
03368 si = bsi_last (exit_bb);
03369 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
03370 {
03371 tree t = alloc_stmt_list ();
03372 build_omp_barrier (&t);
03373 bsi_insert_after (&si, t, BSI_SAME_STMT);
03374 }
03375 bsi_remove (&si, true);
03376 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
03377 }
03378
03379
03380
03381
03382
03383
03384 static void
03385 expand_omp_synch (struct omp_region *region)
03386 {
03387 basic_block entry_bb, exit_bb;
03388 block_stmt_iterator si;
03389
03390 entry_bb = region->entry;
03391 exit_bb = region->exit;
03392
03393 si = bsi_last (entry_bb);
03394 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
03395 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
03396 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
03397 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
03398 bsi_remove (&si, true);
03399 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
03400
03401 if (exit_bb)
03402 {
03403 si = bsi_last (exit_bb);
03404 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
03405 bsi_remove (&si, true);
03406 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
03407 }
03408 }
03409
03410
03411
03412
03413
03414
03415
03416
03417 static void
03418 expand_omp (struct omp_region *region)
03419 {
03420 while (region)
03421 {
03422 if (region->inner)
03423 expand_omp (region->inner);
03424
03425 switch (region->type)
03426 {
03427 case OMP_PARALLEL:
03428 expand_omp_parallel (region);
03429 break;
03430
03431 case OMP_FOR:
03432 expand_omp_for (region);
03433 break;
03434
03435 case OMP_SECTIONS:
03436 expand_omp_sections (region);
03437 break;
03438
03439 case OMP_SECTION:
03440
03441
03442 break;
03443
03444 case OMP_SINGLE:
03445 expand_omp_single (region);
03446 break;
03447
03448 case OMP_MASTER:
03449 case OMP_ORDERED:
03450 case OMP_CRITICAL:
03451 expand_omp_synch (region);
03452 break;
03453
03454 default:
03455 gcc_unreachable ();
03456 }
03457
03458 region = region->next;
03459 }
03460 }
03461
03462
03463
03464
03465
03466 static void
03467 build_omp_regions_1 (basic_block bb, struct omp_region *parent)
03468 {
03469 block_stmt_iterator si;
03470 tree stmt;
03471 basic_block son;
03472
03473 si = bsi_last (bb);
03474 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
03475 {
03476 struct omp_region *region;
03477 enum tree_code code;
03478
03479 stmt = bsi_stmt (si);
03480 code = TREE_CODE (stmt);
03481
03482 if (code == OMP_RETURN)
03483 {
03484
03485
03486
03487 gcc_assert (parent);
03488 region = parent;
03489 region->exit = bb;
03490 parent = parent->outer;
03491
03492
03493
03494 if (region->type == OMP_PARALLEL)
03495 determine_parallel_type (region);
03496 }
03497 else if (code == OMP_CONTINUE)
03498 {
03499 gcc_assert (parent);
03500 parent->cont = bb;
03501 }
03502 else
03503 {
03504
03505
03506 region = new_omp_region (bb, code, parent);
03507 parent = region;
03508 }
03509 }
03510
03511 for (son = first_dom_son (CDI_DOMINATORS, bb);
03512 son;
03513 son = next_dom_son (CDI_DOMINATORS, son))
03514 build_omp_regions_1 (son, parent);
03515 }
03516
03517
03518
03519
03520
03521 static void
03522 build_omp_regions (void)
03523 {
03524 gcc_assert (root_omp_region == NULL);
03525 calculate_dominance_info (CDI_DOMINATORS);
03526 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
03527 }
03528
03529
03530
03531
03532 static unsigned int
03533 execute_expand_omp (void)
03534 {
03535 build_omp_regions ();
03536
03537 if (!root_omp_region)
03538 return 0;
03539
03540 if (dump_file)
03541 {
03542 fprintf (dump_file, "\nOMP region tree\n\n");
03543 dump_omp_region (dump_file, root_omp_region, 0);
03544 fprintf (dump_file, "\n");
03545 }
03546
03547 remove_exit_barriers (root_omp_region);
03548
03549 expand_omp (root_omp_region);
03550
03551 free_dominance_info (CDI_DOMINATORS);
03552 free_dominance_info (CDI_POST_DOMINATORS);
03553 cleanup_tree_cfg ();
03554
03555 free_omp_regions ();
03556
03557 return 0;
03558 }
03559
03560 static bool
03561 gate_expand_omp (void)
03562 {
03563 return flag_openmp != 0 && errorcount == 0;
03564 }
03565
03566 struct tree_opt_pass pass_expand_omp =
03567 {
03568 "ompexp",
03569 gate_expand_omp,
03570 execute_expand_omp,
03571 NULL,
03572 NULL,
03573 0,
03574 0,
03575 PROP_gimple_any,
03576 PROP_gimple_lomp,
03577 0,
03578 0,
03579 TODO_dump_func,
03580 0
03581 };
03582
03583
03584
03585
03586
03587 static void
03588 lower_omp_sections (tree *stmt_p, omp_context *ctx)
03589 {
03590 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
03591 tree t, dlist;
03592 tree_stmt_iterator tsi;
03593 unsigned i, len;
03594
03595 stmt = *stmt_p;
03596
03597 push_gimplify_context ();
03598
03599 dlist = NULL;
03600 ilist = NULL;
03601 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
03602
03603 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
03604 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
03605 continue;
03606
03607 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
03608 body = alloc_stmt_list ();
03609 for (i = 0; i < len; i++, tsi_next (&tsi))
03610 {
03611 omp_context *sctx;
03612 tree sec_start, sec_end;
03613
03614 sec_start = tsi_stmt (tsi);
03615 sctx = maybe_lookup_ctx (sec_start);
03616 gcc_assert (sctx);
03617
03618 append_to_statement_list (sec_start, &body);
03619
03620 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
03621 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
03622 OMP_SECTION_BODY (sec_start) = NULL;
03623
03624 if (i == len - 1)
03625 {
03626 tree l = alloc_stmt_list ();
03627 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
03628 &l, ctx);
03629 append_to_statement_list (l, &body);
03630 OMP_SECTION_LAST (sec_start) = 1;
03631 }
03632
03633 sec_end = make_node (OMP_RETURN);
03634 append_to_statement_list (sec_end, &body);
03635 }
03636
03637 block = make_node (BLOCK);
03638 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
03639
03640 olist = NULL_TREE;
03641 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
03642
03643 pop_gimplify_context (NULL_TREE);
03644 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
03645
03646 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
03647 TREE_SIDE_EFFECTS (new_stmt) = 1;
03648
03649 new_body = alloc_stmt_list ();
03650 append_to_statement_list (ilist, &new_body);
03651 append_to_statement_list (stmt, &new_body);
03652 append_to_statement_list (bind, &new_body);
03653
03654 t = make_node (OMP_CONTINUE);
03655 append_to_statement_list (t, &new_body);
03656
03657 append_to_statement_list (olist, &new_body);
03658 append_to_statement_list (dlist, &new_body);
03659
03660 maybe_catch_exception (&new_body);
03661
03662 t = make_node (OMP_RETURN);
03663 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
03664 OMP_CLAUSE_NOWAIT);
03665 append_to_statement_list (t, &new_body);
03666
03667 BIND_EXPR_BODY (new_stmt) = new_body;
03668 OMP_SECTIONS_BODY (stmt) = NULL;
03669
03670 *stmt_p = new_stmt;
03671 }
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685 static void
03686 lower_omp_single_simple (tree single_stmt, tree *pre_p)
03687 {
03688 tree t;
03689
03690 t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
03691 t = build_function_call_expr (t, NULL);
03692 t = build3 (COND_EXPR, void_type_node, t,
03693 OMP_SINGLE_BODY (single_stmt), NULL);
03694 gimplify_and_add (t, pre_p);
03695 }
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727 static void
03728 lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
03729 {
03730 tree ptr_type, t, args, l0, l1, l2, copyin_seq;
03731
03732 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
03733
03734 ptr_type = build_pointer_type (ctx->record_type);
03735 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
03736
03737 l0 = create_artificial_label ();
03738 l1 = create_artificial_label ();
03739 l2 = create_artificial_label ();
03740
03741 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
03742 t = build_function_call_expr (t, NULL);
03743 t = fold_convert (ptr_type, t);
03744 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
03745 gimplify_and_add (t, pre_p);
03746
03747 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
03748 build_int_cst (ptr_type, 0));
03749 t = build3 (COND_EXPR, void_type_node, t,
03750 build_and_jump (&l0), build_and_jump (&l1));
03751 gimplify_and_add (t, pre_p);
03752
03753 t = build1 (LABEL_EXPR, void_type_node, l0);
03754 gimplify_and_add (t, pre_p);
03755
03756 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
03757
03758 copyin_seq = NULL;
03759 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
03760 ©in_seq, ctx);
03761
03762 t = build_fold_addr_expr (ctx->sender_decl);
03763 args = tree_cons (NULL, t, NULL);
03764 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
03765 t = build_function_call_expr (t, args);
03766 gimplify_and_add (t, pre_p);
03767
03768 t = build_and_jump (&l2);
03769 gimplify_and_add (t, pre_p);
03770
03771 t = build1 (LABEL_EXPR, void_type_node, l1);
03772 gimplify_and_add (t, pre_p);
03773
03774 append_to_statement_list (copyin_seq, pre_p);
03775
03776 t = build1 (LABEL_EXPR, void_type_node, l2);
03777 gimplify_and_add (t, pre_p);
03778 }
03779
03780
03781
03782
03783 static void
03784 lower_omp_single (tree *stmt_p, omp_context *ctx)
03785 {
03786 tree t, bind, block, single_stmt = *stmt_p, dlist;
03787
03788 push_gimplify_context ();
03789
03790 block = make_node (BLOCK);
03791 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
03792 TREE_SIDE_EFFECTS (bind) = 1;
03793
03794 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
03795 &BIND_EXPR_BODY (bind), &dlist, ctx);
03796 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
03797
03798 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
03799
03800 if (ctx->record_type)
03801 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
03802 else
03803 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
03804
03805 OMP_SINGLE_BODY (single_stmt) = NULL;
03806
03807 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
03808
03809 maybe_catch_exception (&BIND_EXPR_BODY (bind));
03810
03811 t = make_node (OMP_RETURN);
03812 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
03813 OMP_CLAUSE_NOWAIT);
03814 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
03815
03816 pop_gimplify_context (bind);
03817
03818 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
03819 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
03820 }
03821
03822
03823
03824
03825 static void
03826 lower_omp_master (tree *stmt_p, omp_context *ctx)
03827 {
03828 tree bind, block, stmt = *stmt_p, lab = NULL, x;
03829
03830 push_gimplify_context ();
03831
03832 block = make_node (BLOCK);
03833 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
03834 TREE_SIDE_EFFECTS (bind) = 1;
03835
03836 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
03837
03838 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
03839 x = build_function_call_expr (x, NULL);
03840 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
03841 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
03842 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
03843
03844 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
03845 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
03846 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
03847 OMP_MASTER_BODY (stmt) = NULL;
03848
03849 x = build1 (LABEL_EXPR, void_type_node, lab);
03850 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
03851
03852 x = make_node (OMP_RETURN);
03853 OMP_RETURN_NOWAIT (x) = 1;
03854 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
03855
03856 pop_gimplify_context (bind);
03857
03858 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
03859 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
03860 }
03861
03862
03863
03864
03865 static void
03866 lower_omp_ordered (tree *stmt_p, omp_context *ctx)
03867 {
03868 tree bind, block, stmt = *stmt_p, x;
03869
03870 push_gimplify_context ();
03871
03872 block = make_node (BLOCK);
03873 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
03874 TREE_SIDE_EFFECTS (bind) = 1;
03875
03876 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
03877
03878 x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
03879 x = build_function_call_expr (x, NULL);
03880 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
03881
03882 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
03883 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
03884 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
03885 OMP_ORDERED_BODY (stmt) = NULL;
03886
03887 x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
03888 x = build_function_call_expr (x, NULL);
03889 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
03890
03891 x = make_node (OMP_RETURN);
03892 OMP_RETURN_NOWAIT (x) = 1;
03893 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
03894
03895 pop_gimplify_context (bind);
03896
03897 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
03898 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
03899 }
03900
03901
03902
03903
03904
03905
03906
03907 static GTY((param1_is (tree), param2_is (tree)))
03908 splay_tree critical_name_mutexes;
03909
03910 static void
03911 lower_omp_critical (tree *stmt_p, omp_context *ctx)
03912 {
03913 tree bind, block, stmt = *stmt_p;
03914 tree t, lock, unlock, name;
03915
03916 name = OMP_CRITICAL_NAME (stmt);
03917 if (name)
03918 {
03919 tree decl, args;
03920 splay_tree_node n;
03921
03922 if (!critical_name_mutexes)
03923 critical_name_mutexes
03924 = splay_tree_new_ggc (splay_tree_compare_pointers);
03925
03926 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
03927 if (n == NULL)
03928 {
03929 char *new_str;
03930
03931 decl = create_tmp_var_raw (ptr_type_node, NULL);
03932
03933 new_str = ACONCAT ((".gomp_critical_user_",
03934 IDENTIFIER_POINTER (name), NULL));
03935 DECL_NAME (decl) = get_identifier (new_str);
03936 TREE_PUBLIC (decl) = 1;
03937 TREE_STATIC (decl) = 1;
03938 DECL_COMMON (decl) = 1;
03939 DECL_ARTIFICIAL (decl) = 1;
03940 DECL_IGNORED_P (decl) = 1;
03941 cgraph_varpool_finalize_decl (decl);
03942
03943 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
03944 (splay_tree_value) decl);
03945 }
03946 else
03947 decl = (tree) n->value;
03948
03949 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
03950 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
03951 lock = build_function_call_expr (lock, args);
03952
03953 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
03954 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
03955 unlock = build_function_call_expr (unlock, args);
03956 }
03957 else
03958 {
03959 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
03960 lock = build_function_call_expr (lock, NULL);
03961
03962 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
03963 unlock = build_function_call_expr (unlock, NULL);
03964 }
03965
03966 push_gimplify_context ();
03967
03968 block = make_node (BLOCK);
03969 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
03970 TREE_SIDE_EFFECTS (bind) = 1;
03971
03972 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
03973
03974 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
03975
03976 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
03977 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
03978 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
03979 OMP_CRITICAL_BODY (stmt) = NULL;
03980
03981 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
03982
03983 t = make_node (OMP_RETURN);
03984 OMP_RETURN_NOWAIT (t) = 1;
03985 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
03986
03987 pop_gimplify_context (bind);
03988 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
03989 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
03990 }
03991
03992
03993
03994
03995
03996
03997
03998
03999 static void
04000 lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
04001 tree *dlist, struct omp_context *ctx)
04002 {
04003 tree clauses, cond, stmts, vinit, t;
04004 enum tree_code cond_code;
04005
04006 cond_code = fd->cond_code;
04007 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
04008
04009
04010
04011 if (host_integerp (fd->step, 0))
04012 {
04013 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
04014 if (step == 1 || step == -1)
04015 cond_code = EQ_EXPR;
04016 }
04017
04018 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
04019
04020 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
04021 stmts = NULL;
04022 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
04023 if (stmts != NULL)
04024 {
04025 append_to_statement_list (stmts, dlist);
04026
04027
04028 vinit = fd->n1;
04029 if (cond_code == EQ_EXPR
04030 && host_integerp (fd->n2, 0)
04031 && ! integer_zerop (fd->n2))
04032 vinit = build_int_cst (TREE_TYPE (fd->v), 0);
04033
04034
04035
04036 t = build2 (MODIFY_EXPR, void_type_node, fd->v, vinit);
04037 gimplify_and_add (t, body_p);
04038 }
04039 }
04040
04041
04042
04043
04044 static void
04045 lower_omp_for (tree *stmt_p, omp_context *ctx)
04046 {
04047 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
04048 struct omp_for_data fd;
04049
04050 stmt = *stmt_p;
04051
04052 push_gimplify_context ();
04053
04054 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
04055 lower_omp (&OMP_FOR_BODY (stmt), ctx);
04056
04057
04058
04059 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
04060 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
04061
04062 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
04063 TREE_SIDE_EFFECTS (new_stmt) = 1;
04064 body_p = &BIND_EXPR_BODY (new_stmt);
04065
04066
04067 ilist = NULL;
04068 dlist = NULL;
04069 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
04070 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
04071
04072
04073
04074
04075
04076
04077
04078
04079 rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1);
04080 if (!is_gimple_min_invariant (*rhs_p))
04081 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
04082
04083 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
04084 if (!is_gimple_min_invariant (*rhs_p))
04085 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
04086
04087 rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
04088 if (!is_gimple_min_invariant (*rhs_p))
04089 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
04090
04091
04092 extract_omp_for_data (stmt, &fd);
04093
04094 lower_omp_for_lastprivate (&fd, body_p, &dlist, ctx);
04095
04096 append_to_statement_list (stmt, body_p);
04097
04098 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
04099
04100 t = make_node (OMP_CONTINUE);
04101 append_to_statement_list (t, body_p);
04102
04103
04104 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
04105 append_to_statement_list (dlist, body_p);
04106
04107 maybe_catch_exception (body_p);
04108
04109
04110 t = make_node (OMP_RETURN);
04111 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
04112 append_to_statement_list (t, body_p);
04113
04114 pop_gimplify_context (NULL_TREE);
04115 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
04116
04117 OMP_FOR_BODY (stmt) = NULL_TREE;
04118 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
04119 *stmt_p = new_stmt;
04120 }
04121
04122
04123
04124
04125
04126 static void
04127 lower_omp_parallel (tree *stmt_p, omp_context *ctx)
04128 {
04129 tree clauses, par_bind, par_body, new_body, bind;
04130 tree olist, ilist, par_olist, par_ilist;
04131 tree stmt, child_fn, t;
04132
04133 stmt = *stmt_p;
04134
04135 clauses = OMP_PARALLEL_CLAUSES (stmt);
04136 par_bind = OMP_PARALLEL_BODY (stmt);
04137 par_body = BIND_EXPR_BODY (par_bind);
04138 child_fn = ctx->cb.dst_fn;
04139
04140 push_gimplify_context ();
04141
04142 par_olist = NULL_TREE;
04143 par_ilist = NULL_TREE;
04144 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
04145 lower_omp (&par_body, ctx);
04146 lower_reduction_clauses (clauses, &par_olist, ctx);
04147
04148
04149
04150 record_vars_into (ctx->block_vars, child_fn);
04151 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
04152
04153 if (ctx->record_type)
04154 {
04155 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
04156 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
04157 }
04158
04159 olist = NULL_TREE;
04160 ilist = NULL_TREE;
04161 lower_send_clauses (clauses, &ilist, &olist, ctx);
04162 lower_send_shared_vars (&ilist, &olist, ctx);
04163
04164
04165
04166 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
04167 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
04168
04169 new_body = alloc_stmt_list ();
04170
04171 if (ctx->record_type)
04172 {
04173 t = build_fold_addr_expr (ctx->sender_decl);
04174
04175 t = fold_convert (TREE_TYPE (ctx->receiver_decl), t);
04176 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
04177 append_to_statement_list (t, &new_body);
04178 }
04179
04180 append_to_statement_list (par_ilist, &new_body);
04181 append_to_statement_list (par_body, &new_body);
04182 append_to_statement_list (par_olist, &new_body);
04183 maybe_catch_exception (&new_body);
04184 t = make_node (OMP_RETURN);
04185 append_to_statement_list (t, &new_body);
04186 OMP_PARALLEL_BODY (stmt) = new_body;
04187
04188 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
04189 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
04190
04191 *stmt_p = bind;
04192
04193 pop_gimplify_context (NULL_TREE);
04194 }
04195
04196
04197
04198
04199
04200
04201 static void
04202 lower_regimplify (tree *tp, struct walk_stmt_info *wi)
04203 {
04204 enum gimplify_status gs;
04205 tree pre = NULL;
04206
04207 if (wi->is_lhs)
04208 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
04209 else if (wi->val_only)
04210 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
04211 else
04212 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
04213 gcc_assert (gs == GS_ALL_DONE);
04214
04215 if (pre)
04216 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
04217 }
04218
04219
04220
04221 static tree
04222 init_tmp_var (tree exp, tree_stmt_iterator *tsi)
04223 {
04224 tree t, stmt;
04225
04226 t = create_tmp_var (TREE_TYPE (exp), NULL);
04227 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
04228 DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
04229 stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), t, exp);
04230 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
04231 tsi_link_before (tsi, stmt, TSI_SAME_STMT);
04232
04233 return t;
04234 }
04235
04236
04237
04238
04239 static tree
04240 save_tmp_var (tree exp, tree_stmt_iterator *tsi)
04241 {
04242 tree t, stmt;
04243
04244 t = create_tmp_var (TREE_TYPE (exp), NULL);
04245 if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
04246 DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
04247 stmt = build2 (MODIFY_EXPR, TREE_TYPE (t), exp, t);
04248 SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
04249 tsi_link_after (tsi, stmt, TSI_SAME_STMT);
04250
04251 return t;
04252 }
04253
04254
04255
04256 static tree
04257 lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
04258 {
04259 struct walk_stmt_info *wi = data;
04260 omp_context *ctx = wi->info;
04261 tree t = *tp;
04262
04263
04264
04265
04266 if (errorcount && OMP_DIRECTIVE_P (*tp))
04267 {
04268 *tp = build_empty_stmt ();
04269 return NULL_TREE;
04270 }
04271
04272 *walk_subtrees = 0;
04273 switch (TREE_CODE (*tp))
04274 {
04275 case OMP_PARALLEL:
04276 ctx = maybe_lookup_ctx (t);
04277 lower_omp_parallel (tp, ctx);
04278 break;
04279
04280 case OMP_FOR:
04281 ctx = maybe_lookup_ctx (t);
04282 gcc_assert (ctx);
04283 lower_omp_for (tp, ctx);
04284 break;
04285
04286 case OMP_SECTIONS:
04287 ctx = maybe_lookup_ctx (t);
04288 gcc_assert (ctx);
04289 lower_omp_sections (tp, ctx);
04290 break;
04291
04292 case OMP_SINGLE:
04293 ctx = maybe_lookup_ctx (t);
04294 gcc_assert (ctx);
04295 lower_omp_single (tp, ctx);
04296 break;
04297
04298 case OMP_MASTER:
04299 ctx = maybe_lookup_ctx (t);
04300 gcc_assert (ctx);
04301 lower_omp_master (tp, ctx);
04302 break;
04303
04304 case OMP_ORDERED:
04305 ctx = maybe_lookup_ctx (t);
04306 gcc_assert (ctx);
04307 lower_omp_ordered (tp, ctx);
04308 break;
04309
04310 case OMP_CRITICAL:
04311 ctx = maybe_lookup_ctx (t);
04312 gcc_assert (ctx);
04313 lower_omp_critical (tp, ctx);
04314 break;
04315
04316 case VAR_DECL:
04317 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
04318 {
04319 lower_regimplify (&t, wi);
04320 if (wi->val_only)
04321 {
04322 if (wi->is_lhs)
04323 t = save_tmp_var (t, &wi->tsi);
04324 else
04325 t = init_tmp_var (t, &wi->tsi);
04326 }
04327 *tp = t;
04328 }
04329 break;
04330
04331 case ADDR_EXPR:
04332 if (ctx)
04333 lower_regimplify (tp, wi);
04334 break;
04335
04336 case ARRAY_REF:
04337 case ARRAY_RANGE_REF:
04338 case REALPART_EXPR:
04339 case IMAGPART_EXPR:
04340 case COMPONENT_REF:
04341 case VIEW_CONVERT_EXPR:
04342 if (ctx)
04343 lower_regimplify (tp, wi);
04344 break;
04345
04346 case INDIRECT_REF:
04347 if (ctx)
04348 {
04349 wi->is_lhs = false;
04350 wi->val_only = true;
04351 lower_regimplify (&TREE_OPERAND (t, 0), wi);
04352 }
04353 break;
04354
04355 default:
04356 if (!TYPE_P (t) && !DECL_P (t))
04357 *walk_subtrees = 1;
04358 break;
04359 }
04360
04361 return NULL_TREE;
04362 }
04363
04364 static void
04365 lower_omp (tree *stmt_p, omp_context *ctx)
04366 {
04367 struct walk_stmt_info wi;
04368
04369 memset (&wi, 0, sizeof (wi));
04370 wi.callback = lower_omp_1;
04371 wi.info = ctx;
04372 wi.val_only = true;
04373 wi.want_locations = true;
04374
04375 walk_stmts (&wi, stmt_p);
04376 }
04377
04378
04379
04380 static unsigned int
04381 execute_lower_omp (void)
04382 {
04383 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
04384 delete_omp_context);
04385
04386 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
04387 gcc_assert (parallel_nesting_level == 0);
04388
04389 if (all_contexts->root)
04390 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
04391
04392 if (all_contexts)
04393 {
04394 splay_tree_delete (all_contexts);
04395 all_contexts = NULL;
04396 }
04397 return 0;
04398 }
04399
04400 static bool
04401 gate_lower_omp (void)
04402 {
04403 return flag_openmp != 0;
04404 }
04405
04406 struct tree_opt_pass pass_lower_omp =
04407 {
04408 "omplower",
04409 gate_lower_omp,
04410 execute_lower_omp,
04411 NULL,
04412 NULL,
04413 0,
04414 0,
04415 PROP_gimple_any,
04416 PROP_gimple_lomp,
04417 0,
04418 0,
04419 TODO_dump_func,
04420 0
04421 };
04422
04423
04424
04425
04426
04427 static splay_tree all_labels;
04428
04429
04430
04431
04432 static bool
04433 diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
04434 {
04435 bool exit_p = true;
04436
04437 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
04438 return false;
04439
04440
04441
04442
04443 if (branch_ctx == NULL)
04444 exit_p = false;
04445 else
04446 {
04447 while (label_ctx)
04448 {
04449 if (TREE_VALUE (label_ctx) == branch_ctx)
04450 {
04451 exit_p = false;
04452 break;
04453 }
04454 label_ctx = TREE_CHAIN (label_ctx);
04455 }
04456 }
04457
04458 if (exit_p)
04459 error ("invalid exit from OpenMP structured block");
04460 else
04461 error ("invalid entry to OpenMP structured block");
04462
04463 *stmt_p = build_empty_stmt ();
04464 return true;
04465 }
04466
04467
04468
04469
04470 static tree
04471 diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
04472 {
04473 struct walk_stmt_info *wi = data;
04474 tree context = (tree) wi->info;
04475 tree inner_context;
04476 tree t = *tp;
04477
04478 *walk_subtrees = 0;
04479 switch (TREE_CODE (t))
04480 {
04481 case OMP_PARALLEL:
04482 case OMP_SECTIONS:
04483 case OMP_SINGLE:
04484 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
04485
04486 case OMP_SECTION:
04487 case OMP_MASTER:
04488 case OMP_ORDERED:
04489 case OMP_CRITICAL:
04490
04491 inner_context = tree_cons (NULL, t, context);
04492 wi->info = inner_context;
04493 walk_stmts (wi, &OMP_BODY (t));
04494 wi->info = context;
04495 break;
04496
04497 case OMP_FOR:
04498 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
04499 inner_context = tree_cons (NULL, t, context);
04500 wi->info = inner_context;
04501 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
04502 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
04503 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
04504 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
04505 walk_stmts (wi, &OMP_FOR_BODY (t));
04506 wi->info = context;
04507 break;
04508
04509 case LABEL_EXPR:
04510 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
04511 (splay_tree_value) context);
04512 break;
04513
04514 default:
04515 break;
04516 }
04517
04518 return NULL_TREE;
04519 }
04520
04521
04522
04523
04524 static tree
04525 diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
04526 {
04527 struct walk_stmt_info *wi = data;
04528 tree context = (tree) wi->info;
04529 splay_tree_node n;
04530 tree t = *tp;
04531
04532 *walk_subtrees = 0;
04533 switch (TREE_CODE (t))
04534 {
04535 case OMP_PARALLEL:
04536 case OMP_SECTIONS:
04537 case OMP_SINGLE:
04538 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
04539
04540 case OMP_SECTION:
04541 case OMP_MASTER:
04542 case OMP_ORDERED:
04543 case OMP_CRITICAL:
04544 wi->info = t;
04545 walk_stmts (wi, &OMP_BODY (t));
04546 wi->info = context;
04547 break;
04548
04549 case OMP_FOR:
04550 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
04551 wi->info = t;
04552 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
04553 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
04554 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
04555 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
04556 walk_stmts (wi, &OMP_FOR_BODY (t));
04557 wi->info = context;
04558 break;
04559
04560 case GOTO_EXPR:
04561 {
04562 tree lab = GOTO_DESTINATION (t);
04563 if (TREE_CODE (lab) != LABEL_DECL)
04564 break;
04565
04566 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
04567 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
04568 }
04569 break;
04570
04571 case SWITCH_EXPR:
04572 {
04573 tree vec = SWITCH_LABELS (t);
04574 int i, len = TREE_VEC_LENGTH (vec);
04575 for (i = 0; i < len; ++i)
04576 {
04577 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
04578 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
04579 if (diagnose_sb_0 (tp, context, (tree) n->value))
04580 break;
04581 }
04582 }
04583 break;
04584
04585 case RETURN_EXPR:
04586 diagnose_sb_0 (tp, context, NULL_TREE);
04587 break;
04588
04589 default:
04590 break;
04591 }
04592
04593 return NULL_TREE;
04594 }
04595
04596 void
04597 diagnose_omp_structured_block_errors (tree fndecl)
04598 {
04599 tree save_current = current_function_decl;
04600 struct walk_stmt_info wi;
04601
04602 current_function_decl = fndecl;
04603
04604 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
04605
04606 memset (&wi, 0, sizeof (wi));
04607 wi.callback = diagnose_sb_1;
04608 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
04609
04610 memset (&wi, 0, sizeof (wi));
04611 wi.callback = diagnose_sb_2;
04612 wi.want_locations = true;
04613 wi.want_return_expr = true;
04614 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
04615
04616 splay_tree_delete (all_labels);
04617 all_labels = NULL;
04618
04619 current_function_decl = save_current;
04620 }
04621
04622 #include "gt-omp-low.h"