diff options
Diffstat (limited to 'gcc/gimplify.cc')
-rw-r--r-- | gcc/gimplify.cc | 108 |
1 files changed, 86 insertions, 22 deletions
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index a0e8cc2..9f4722f 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "tree-pretty-print.h" #include "diagnostic-core.h" +#include "diagnostic.h" /* For errorcount. */ #include "alias.h" #include "fold-const.h" #include "calls.h" @@ -1372,6 +1373,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t))) != NULL_TREE) { + gcc_assert (!DECL_HAS_VALUE_EXPR_P (t)); tree alloc = TREE_PURPOSE (TREE_VALUE (attr)); tree align = TREE_VALUE (TREE_VALUE (attr)); /* Allocate directives that appear in a target region must specify @@ -1396,12 +1398,56 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) error_at (DECL_SOURCE_LOCATION (t), "%<allocate%> directive for %qD inside a target " "region must specify an %<allocator%> clause", t); - else if (align != NULL_TREE - || alloc == NULL_TREE - || !integer_onep (alloc)) - sorry_at (DECL_SOURCE_LOCATION (t), - "OpenMP %<allocate%> directive, used for %qD, not " - "yet supported", t); + /* Skip for omp_default_mem_alloc (= 1), + unless align is present. */ + else if (!errorcount + && (align != NULL_TREE + || alloc == NULL_TREE + || !integer_onep (alloc))) + { + tree tmp = build_pointer_type (TREE_TYPE (t)); + tree v = create_tmp_var (tmp, get_name (t)); + DECL_IGNORED_P (v) = 0; + tmp = remove_attribute ("omp allocate", DECL_ATTRIBUTES (t)); + DECL_ATTRIBUTES (v) + = tree_cons (get_identifier ("omp allocate var"), + build_tree_list (NULL_TREE, t), tmp); + tmp = build_fold_indirect_ref (v); + TREE_THIS_NOTRAP (tmp) = 1; + SET_DECL_VALUE_EXPR (t, tmp); + DECL_HAS_VALUE_EXPR_P (t) = 1; + tree sz = TYPE_SIZE_UNIT (TREE_TYPE (t)); + if (alloc == NULL_TREE) + alloc = build_zero_cst (ptr_type_node); + if (align == NULL_TREE) + align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t)); + else + align = build_int_cst (size_type_node, + MAX (tree_to_uhwi (align), + DECL_ALIGN_UNIT (t))); + tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC); + tmp = build_call_expr_loc (DECL_SOURCE_LOCATION (t), tmp, + 3, align, sz, alloc); + tmp = fold_build2_loc (DECL_SOURCE_LOCATION (t), MODIFY_EXPR, + TREE_TYPE (v), v, + fold_convert (TREE_TYPE (v), tmp)); + gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE + && (TREE_CODE (BIND_EXPR_BODY (bind_expr)) + == STATEMENT_LIST)); + tree_stmt_iterator e = tsi_start (BIND_EXPR_BODY (bind_expr)); + while (!tsi_end_p (e)) + { + if ((TREE_CODE (*e) == DECL_EXPR + && TREE_OPERAND (*e, 0) == t) + || (TREE_CODE (*e) == CLEANUP_POINT_EXPR + && TREE_CODE (TREE_OPERAND (*e, 0)) == DECL_EXPR + && TREE_OPERAND (TREE_OPERAND (*e, 0), 0) == t)) + break; + ++e; + } + gcc_assert (!tsi_end_p (e)); + tsi_link_before (&e, tmp, TSI_SAME_STMT); + } } /* Mark variable as local. */ @@ -1486,22 +1532,6 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) cleanup = NULL; stack_save = NULL; - /* If the code both contains VLAs and calls alloca, then we cannot reclaim - the stack space allocated to the VLAs. */ - if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack) - { - gcall *stack_restore; - - /* Save stack on entry and restore it on exit. Add a try_finally - block to achieve this. */ - build_stack_save_restore (&stack_save, &stack_restore); - - gimple_set_location (stack_save, start_locus); - gimple_set_location (stack_restore, end_locus); - - gimplify_seq_add_stmt (&cleanup, stack_restore); - } - /* Add clobbers for all variables that go out of scope. */ for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t)) { @@ -1509,6 +1539,17 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) && !is_global_var (t) && DECL_CONTEXT (t) == current_function_decl) { + if (flag_openmp + && DECL_HAS_VALUE_EXPR_P (t) + && TREE_USED (t) + && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t))) + { + tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE); + tmp = build_call_expr_loc (end_locus, tmp, 2, + TREE_OPERAND (DECL_VALUE_EXPR (t), 0), + build_zero_cst (ptr_type_node)); + gimplify_and_add (tmp, &cleanup); + } if (!DECL_HARD_REGISTER (t) && !TREE_THIS_VOLATILE (t) && !DECL_HAS_VALUE_EXPR_P (t) @@ -1565,6 +1606,22 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) gimplify_ctxp->live_switch_vars->remove (t); } + /* If the code both contains VLAs and calls alloca, then we cannot reclaim + the stack space allocated to the VLAs. */ + if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack) + { + gcall *stack_restore; + + /* Save stack on entry and restore it on exit. Add a try_finally + block to achieve this. */ + build_stack_save_restore (&stack_save, &stack_restore); + + gimple_set_location (stack_save, start_locus); + gimple_set_location (stack_restore, end_locus); + + gimplify_seq_add_stmt (&cleanup, stack_restore); + } + if (ret_clauses) { gomp_target *stmt; @@ -7894,6 +7951,13 @@ omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code) if (error_operand_p (decl)) return false; + if (DECL_ARTIFICIAL (decl)) + { + tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl)); + if (attr) + decl = TREE_VALUE (TREE_VALUE (attr)); + } + if (ctx->region_type == ORT_NONE) return lang_hooks.decls.omp_disregard_value_expr (decl, false); |