X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgimplify.c;h=2b402720b1ad512f393c87505cb7003860211f19;hb=28918f8e0acd0e75c39839724f8fc13c56ca580a;hp=8f7ff89d44cc70cf85ab275f0a000187de79cffd;hpb=eda3733553b5ca1932c5bf3313b3492cf34cecaf;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8f7ff89d44c..2b402720b1a 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -74,9 +74,10 @@ enum gimplify_omp_var_data enum omp_region_type { ORT_WORKSHARE = 0, - ORT_TASK = 1, ORT_PARALLEL = 2, - ORT_COMBINED_PARALLEL = 3 + ORT_COMBINED_PARALLEL = 3, + ORT_TASK = 4, + ORT_UNTIED_TASK = 5 }; struct gimplify_omp_ctx @@ -157,7 +158,7 @@ gimple_tree_eq (const void *p1, const void *p2) During gimplification, we need to manipulate statement sequences before the def/use vectors have been constructed. */ -static void +void gimplify_seq_add_stmt (gimple_seq *seq_p, gimple gs) { gimple_stmt_iterator si; @@ -318,7 +319,7 @@ new_omp_context (enum omp_region_type region_type) c->privatized_types = pointer_set_create (); c->location = input_location; c->region_type = region_type; - if (region_type != ORT_TASK) + if ((region_type & ORT_TASK) == 0) c->default_kind = OMP_CLAUSE_DEFAULT_SHARED; else c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; @@ -339,47 +340,6 @@ delete_omp_context (struct gimplify_omp_ctx *c) static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int); static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool); -/* A subroutine of append_to_statement_list{,_force}. T is not NULL. */ - -static void -append_to_statement_list_1 (tree t, tree *list_p) -{ - tree list = *list_p; - tree_stmt_iterator i; - - if (!list) - { - if (t && TREE_CODE (t) == STATEMENT_LIST) - { - *list_p = t; - return; - } - *list_p = list = alloc_stmt_list (); - } - - i = tsi_last (list); - tsi_link_after (&i, t, TSI_CONTINUE_LINKING); -} - -/* Add T to the end of the list container pointed to by LIST_P. - If T is an expression with no effects, it is ignored. */ - -void -append_to_statement_list (tree t, tree *list_p) -{ - if (t && TREE_SIDE_EFFECTS (t)) - append_to_statement_list_1 (t, list_p); -} - -/* Similar, but the statement is always added, regardless of side effects. */ - -void -append_to_statement_list_force (tree t, tree *list_p) -{ - if (t != NULL_TREE) - append_to_statement_list_1 (t, list_p); -} - /* Both gimplify the statement T and append it to *SEQ_P. This function behaves exactly as gimplify_stmt, but you don't have to pass T as a reference. */ @@ -1228,9 +1188,22 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) hard_function_value generates a PARALLEL, we'll die during normal expansion of structure assignments; there's special code in expand_return to handle this case that does not exist in expand_expr. */ - if (!result_decl - || aggregate_value_p (result_decl, TREE_TYPE (current_function_decl))) - result = result_decl; + if (!result_decl) + result = NULL_TREE; + else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl))) + { + if (TREE_CODE (DECL_SIZE (result_decl)) != INTEGER_CST) + { + if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl))) + gimplify_type_sizes (TREE_TYPE (result_decl), pre_p); + /* Note that we don't use gimplify_vla_decl because the RESULT_DECL + should be effectively allocated by the caller, i.e. all calls to + this function must be subject to the Return Slot Optimization. */ + gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p); + gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p); + } + result = result_decl; + } else if (gimplify_ctxp->return_temp) result = gimplify_ctxp->return_temp; else @@ -1901,9 +1874,10 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { tree *p; VEC(tree,heap) *stack; - enum gimplify_status ret = GS_OK, tret; + enum gimplify_status ret = GS_ALL_DONE, tret; int i; location_t loc = EXPR_LOCATION (*expr_p); + tree expr = *expr_p; /* Create a stack of the subexpressions so later we can walk them in order from inner to outer. */ @@ -2057,11 +2031,12 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF) { canonicalize_component_ref (expr_p); - ret = MIN (ret, GS_OK); } VEC_free (tree, heap, stack); + gcc_assert (*expr_p == expr || ret != GS_ALL_DONE); + return ret; } @@ -4278,7 +4253,10 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR) { *from_p = TREE_OPERAND (*from_p, 0); - ret = GS_OK; + /* We don't change ret in this case because the + WITH_SIZE_EXPR might have been added in + gimplify_modify_expr, so returning GS_OK would lead to an + infinite loop. */ changed = true; } break; @@ -5452,6 +5430,31 @@ omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags) splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags); } +/* Notice a threadprivate variable DECL used in OpenMP context CTX. + This just prints out diagnostics about threadprivate variable uses + in untied tasks. If DECL2 is non-NULL, prevent this warning + on that variable. */ + +static bool +omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl, + tree decl2) +{ + splay_tree_node n; + + if (ctx->region_type != ORT_UNTIED_TASK) + return false; + n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); + if (n == NULL) + { + error ("threadprivate variable %qE used in untied task", DECL_NAME (decl)); + error_at (ctx->location, "enclosing task"); + splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0); + } + if (decl2) + splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0); + return false; +} + /* Record the fact that DECL was used within the OpenMP context CTX. IN_CODE is true when real code uses DECL, and false when we should merely emit default(none) errors. Return true if DECL is going to @@ -5472,14 +5475,14 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) if (is_global_var (decl)) { if (DECL_THREAD_LOCAL_P (decl)) - return false; + return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE); if (DECL_HAS_VALUE_EXPR_P (decl)) { tree value = get_base_address (DECL_VALUE_EXPR (decl)); if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value)) - return false; + return omp_notice_threadprivate_variable (ctx, decl, value); } } @@ -5505,7 +5508,10 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) case OMP_CLAUSE_DEFAULT_NONE: error ("%qE not specified in enclosing parallel", DECL_NAME (decl)); - error_at (ctx->location, "enclosing parallel"); + if ((ctx->region_type & ORT_TASK) != 0) + error_at (ctx->location, "enclosing task"); + else + error_at (ctx->location, "enclosing parallel"); /* FALLTHRU */ case OMP_CLAUSE_DEFAULT_SHARED: flags |= GOVD_SHARED; @@ -5518,7 +5524,7 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) break; case OMP_CLAUSE_DEFAULT_UNSPECIFIED: /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */ - gcc_assert (ctx->region_type == ORT_TASK); + gcc_assert ((ctx->region_type & ORT_TASK) != 0); if (ctx->outer_context) omp_notice_variable (ctx->outer_context, decl, in_code); for (octx = ctx->outer_context; octx; octx = octx->outer_context) @@ -6021,7 +6027,10 @@ gimplify_omp_task (tree *expr_p, gimple_seq *pre_p) gimple_seq body = NULL; struct gimplify_ctx gctx; - gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, ORT_TASK); + gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p, + find_omp_clause (OMP_TASK_CLAUSES (expr), + OMP_CLAUSE_UNTIED) + ? ORT_UNTIED_TASK : ORT_TASK); push_gimplify_context (&gctx); @@ -6551,7 +6560,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, else if (ret != GS_UNHANDLED) break; - ret = GS_OK; + /* Make sure that all the cases set 'ret' appropriately. */ + ret = GS_UNHANDLED; switch (TREE_CODE (*expr_p)) { /* First deal with the special cases. */ @@ -6585,6 +6595,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); mark_addressable (*expr_p); + ret = GS_OK; } break; @@ -6599,6 +6610,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); mark_addressable (*expr_p); + ret = GS_OK; } break; @@ -6615,16 +6627,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case MODIFY_EXPR: case INIT_EXPR: - { - tree from = TREE_OPERAND (*expr_p, 1); - ret = gimplify_modify_expr (expr_p, pre_p, post_p, - fallback != fb_none); - /* Don't let the end of loop logic change GS_OK into GS_ALL_DONE - if the RHS has changed. */ - if (ret == GS_OK && *expr_p == save_expr - && TREE_OPERAND (*expr_p, 1) != from) - continue; - } + ret = gimplify_modify_expr (expr_p, pre_p, post_p, + fallback != fb_none); break; case TRUTH_ANDIF_EXPR: @@ -6668,6 +6672,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Just strip a conversion to void (or in void context) and try again. */ *expr_p = TREE_OPERAND (*expr_p, 0); + ret = GS_OK; break; } @@ -6688,7 +6693,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case INDIRECT_REF: *expr_p = fold_indirect_ref_loc (input_location, *expr_p); if (*expr_p != save_expr) - break; + { + ret = GS_OK; + break; + } /* else fall through. */ case ALIGN_INDIRECT_REF: case MISALIGNED_INDIRECT_REF: @@ -6715,7 +6723,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, if (fallback & fb_lvalue) ret = GS_ALL_DONE; else - *expr_p = DECL_INITIAL (*expr_p); + { + *expr_p = DECL_INITIAL (*expr_p); + ret = GS_OK; + } break; case DECL_EXPR: @@ -6750,6 +6761,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } gimplify_seq_add_stmt (pre_p, gimple_build_goto (GOTO_DESTINATION (*expr_p))); + ret = GS_ALL_DONE; break; case PREDICT_EXPR: @@ -6792,7 +6804,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, append_to_statement_list (ce->value, &temp); *expr_p = temp; - ret = GS_OK; + ret = temp ? GS_OK : GS_ALL_DONE; } /* C99 code may assign to an array in a constructed structure or union, and this has undefined behavior only @@ -6802,6 +6814,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, { *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p); mark_addressable (*expr_p); + ret = GS_OK; } else ret = GS_ALL_DONE; @@ -6949,6 +6962,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gimple_test_f, fallback); gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, is_gimple_val, fb_rvalue); + ret = GS_ALL_DONE; } break; @@ -7036,6 +7050,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, TREE_TYPE (*expr_p)))) { *expr_p = tmp; + ret = GS_OK; break; } /* Convert (void *)&a + 4 into (void *)&a[1]. */ @@ -7051,6 +7066,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, 0))))) { *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp); + ret = GS_OK; break; } /* FALLTHRU */ @@ -7120,9 +7136,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, break; } - /* If we replaced *expr_p, gimplify again. */ - if (ret == GS_OK && (*expr_p == NULL || *expr_p == save_expr)) - ret = GS_ALL_DONE; + gcc_assert (*expr_p || ret != GS_OK); } while (ret == GS_OK);