From patchwork Tue May 28 12:39:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 246859 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 35C722C0085 for ; Tue, 28 May 2013 22:39:30 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=fEB4yqlroa/Y/qNcUT5D1KZPaoYBc RoT67+bV7kjU60N7yxmoXc4VEKrCTVpxLNHLexfPyyTewJLlZ3BzaUH4D1/5iADF PULyarHVG6MsQ46vz8xVqOfSg+Zaa/4a8/H8z+sdiV8pPv333+0C0ltMBNzMgSk1 qBt/btheBLGTvo= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=/JYY0V0F+bwHqT0jVjQjmcvsWCg=; b=ivs uuZhxb1DLazSzTo2RlzgyGdd3g3uihpNvDaPGK9WpoCe/qhZV59FoFIPAFzuHs3r VEyZtGoVW94WhodRxKceB/iQfkvuw+IhEmGzcFAzmrDPg9ojibGlJykk3fMaCIDq QnYLVzShyMyC9Fv3K7vpt7gEP70zWNpIBCBCKgKg= Received: (qmail 27794 invoked by alias); 28 May 2013 12:39:17 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 27754 invoked by uid 89); 28 May 2013 12:39:17 -0000 X-Spam-SWARE-Status: No, score=-6.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Tue, 28 May 2013 12:39:14 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r4SCdDYL007947 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 28 May 2013 08:39:13 -0400 Received: from zalov.cz (vpn-49-71.rdu2.redhat.com [10.10.49.71]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r4SCdBQo015607 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 28 May 2013 08:39:12 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.cz (8.14.5/8.14.5) with ESMTP id r4SCdAWX014746; Tue, 28 May 2013 14:39:10 +0200 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r4SCd8Nh014745; Tue, 28 May 2013 14:39:08 +0200 Date: Tue, 28 May 2013 14:39:07 +0200 From: Jakub Jelinek To: Jason Merrill , Richard Henderson Cc: gcc-patches@gcc.gnu.org Subject: [gomp4] #pragma omp declare target and some nesting checking Message-ID: <20130528123907.GN1377@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi! This patch handles #pragma omp declare target ... #pragma omp end declare target and adds some accelerator related nesting restrictions. I haven't done much checking that both the opening and closing directive appear in the same scope, perhaps that can be done later on. Plus I guess further checking should be done during intantiation (something cplus_declare_attributes doesn't verify if processing_template_decl), and we'll need extra diagnostics that all vars/functions used in target regions actually have "omp declare target" attribute, but that will be probably best done during omplow when we clone the bodies. All the VAR_DECLs/FUNCTION_DECLs seen in the declare target directive get "omp declare target" attribute on them. Does this look reasonable? 2013-05-28 Jakub Jelinek * omp-low.c (check_omp_nesting_restrictions): Add some accelerator related nesting restrictions. (scan_omp_1_stmt): Call check_omp_nesting_restrictions even for GOMP_taskgroup_{start,end}. * gimplify.c (omp_notice_threadprivate_variable): Fix a typo. (gimplify_body): For functions with "omp declare target" attribute add ORT_TARGET region around the body. cp/ * parser.c (cp_parser_omp_declare_target, cp_parser_omp_end_declare_target): New functions. (cp_parser_omp_declare): For target keyword call cp_parser_omp_declare_target. (cp_parser_pragma): Handle PRAGMA_OMP_END_DECLARE_TARGET. * cp-tree.h (current_omp_declare_target_attribute): Declare. * decl2.c (current_omp_declare_target_attribute): New variable. (cp_omp_mappable_type): New function. (cplus_decl_attributes): Handle addition of "omp declare target" attribute for decls in #pragma omp declare target region. Complain for invalid uses. c-family/ * c-common.c (c_common_attribute_table): Add "omp declare target" attribute. (handle_omp_declare_target_attribute): New function. Jakub --- gcc/omp-low.c.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/omp-low.c 2013-05-27 19:14:16.156240922 +0200 @@ -1864,20 +1864,54 @@ scan_omp_single (gimple stmt, omp_contex static bool check_omp_nesting_restrictions (gimple stmt, omp_context *ctx) { - if (ctx != NULL - && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR - && (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD - || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR_SIMD)) + if (ctx != NULL) { - error_at (gimple_location (stmt), - "OpenMP constructs may not be nested inside simd region"); - return false; + if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + && (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD + || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR_SIMD)) + { + error_at (gimple_location (stmt), + "OpenMP constructs may not be nested inside simd region"); + return false; + } + else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS) + { + if ((gimple_code (stmt) != GIMPLE_OMP_FOR + || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_DISTRIBUTE) + && gimple_code (stmt) != GIMPLE_OMP_PARALLEL) + { + error_at (gimple_location (stmt), + "only distribute or parallel constructs are allowed to " + "be closely nested inside teams construct"); + return false; + } + } + else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_DISTRIBUTE + && gimple_code (stmt) != GIMPLE_OMP_PARALLEL) + { + error_at (gimple_location (stmt), + "only parallel constructs are allowed to " + "be closely nested inside distribute construct"); + return false; + } } switch (gimple_code (stmt)) { case GIMPLE_OMP_FOR: if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD) return true; + if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE) + { + if (ctx == NULL || gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS) + { + error_at (gimple_location (stmt), + "distribute construct must be closely nested inside " + "teams construct"); + return false; + } + return true; + } /* FALLTHRU */ case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: @@ -1973,6 +2007,17 @@ check_omp_nesting_restrictions (gimple s return false; } break; + case GIMPLE_OMP_TEAMS: + if (ctx == NULL + || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET + || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION) + { + error_at (gimple_location (stmt), + "teams construct not closely nested inside of target " + "region"); + return false; + } + break; default: break; } @@ -2062,6 +2107,8 @@ scan_omp_1_stmt (gimple_stmt_iterator *g case BUILT_IN_GOMP_CANCELLATION_POINT: case BUILT_IN_GOMP_TASKYIELD: case BUILT_IN_GOMP_TASKWAIT: + case BUILT_IN_GOMP_TASKGROUP_START: + case BUILT_IN_GOMP_TASKGROUP_END: remove = !check_omp_nesting_restrictions (stmt, ctx); break; default: --- gcc/cp/parser.c.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/cp/parser.c 2013-05-27 17:07:36.697516807 +0200 @@ -29240,6 +29240,30 @@ cp_parser_omp_declare_simd (cp_parser *p } } +/* OpenMP 4.0: + # pragma omp declare target new-line + declarations and definitions + # pragma omp end declare target new-line */ + +static void +cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + current_omp_declare_target_attribute++; +} + +static void +cp_parser_omp_end_declare_target (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + if (!current_omp_declare_target_attribute) + error_at (pragma_tok->location, + "%<#pragma omp end declare target%> without corresponding " + "%<#pragma omp declare target%>"); + else + current_omp_declare_target_attribute--; +} + /* OpenMP 4.0 #pragma omp declare simd declare-simd-clauses[optseq] new-line #pragma omp declare reduction (reduction-id : typename-list : expression) \ @@ -29269,6 +29293,12 @@ cp_parser_omp_declare (cp_parser *parser context); return; } */ + if (strcmp (p, "target") == 0) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_omp_declare_target (parser, pragma_tok); + return; + } } cp_parser_error (parser, "expected % or %"); cp_parser_require_pragma_eol (parser, pragma_tok); @@ -29811,6 +29841,10 @@ cp_parser_pragma (cp_parser *parser, enu case PRAGMA_OMP_TARGET: return cp_parser_omp_target (parser, pragma_tok, context); + case PRAGMA_OMP_END_DECLARE_TARGET: + cp_parser_omp_end_declare_target (parser, pragma_tok); + return false; + case PRAGMA_OMP_SECTION: error_at (pragma_tok->location, "%<#pragma omp section%> may only be used in " --- gcc/cp/cp-tree.h.jj 2013-05-13 16:46:13.000000000 +0200 +++ gcc/cp/cp-tree.h 2013-05-28 10:49:49.848595138 +0200 @@ -4428,6 +4428,10 @@ extern GTY(()) vec *local_c extern int at_eof; +/* If non-zero, implicit "omp declare target" attribute is added into the + attribute lists. */ +extern GTY(()) int current_omp_declare_target_attribute; + /* A list of namespace-scope objects which have constructors or destructors which reside in the global scope. The decl is stored in the TREE_VALUE slot and the initializer is stored in the --- gcc/cp/decl2.c.jj 2013-05-13 16:46:02.000000000 +0200 +++ gcc/cp/decl2.c 2013-05-28 12:50:31.749223097 +0200 @@ -102,6 +102,9 @@ static GTY(()) vec *no_link int at_eof; +/* If non-zero, implicit "omp declare target" attribute is added into the + attribute lists. */ +int current_omp_declare_target_attribute; /* Return a member function type (a METHOD_TYPE), given FNTYPE (a @@ -1330,6 +1333,27 @@ cp_check_const_attributes (tree attribut } } +/* Return true if TYPE is an OpenMP mappable type. */ +static bool +cp_omp_mappable_type (tree type) +{ + /* Mappable type has to be complete. */ + if (type == error_mark_node || !COMPLETE_TYPE_P (type)) + return false; + /* A mappable type cannot contain virtual members. */ + if (CLASS_TYPE_P (type) && CLASSTYPE_VTABLES (type)) + return false; + /* All data members must be non-static. */ + if (CLASS_TYPE_P (type)) + { + tree field; + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == VAR_DECL) + return false; + } + return true; +} + /* Like decl_attributes, but handle C++ complexity. */ void @@ -1339,6 +1363,30 @@ cplus_decl_attributes (tree *decl, tree || *decl == error_mark_node) return; + /* Add implicit "omp declare target" attribute if requested. */ + if (current_omp_declare_target_attribute + && (TREE_CODE (*decl) == VAR_DECL + || TREE_CODE (*decl) == FUNCTION_DECL)) + { + if (TREE_CODE (*decl) == VAR_DECL + && RECORD_OR_UNION_CODE_P (TREE_CODE (CP_DECL_CONTEXT (*decl)))) + error ("%q+D static data member inside of declare target directive", + *decl); + else if (TREE_CODE (*decl) == VAR_DECL + && (TREE_CODE (CP_DECL_CONTEXT (*decl)) == FUNCTION_DECL + || (current_function_decl && !DECL_EXTERNAL (*decl)))) + error ("%q+D in block scope inside of declare target directive", + *decl); + else if (!processing_template_decl + && TREE_CODE (*decl) == VAR_DECL + && !cp_omp_mappable_type (TREE_TYPE (*decl))) + error ("%q+D in declare target directive does not have mappable type", + *decl); + else + attributes = tree_cons (get_identifier ("omp declare target"), + NULL_TREE, attributes); + } + if (processing_template_decl) { if (check_for_bare_parameter_packs (attributes)) --- gcc/gimplify.c.jj 2013-05-27 09:22:21.000000000 +0200 +++ gcc/gimplify.c 2013-05-27 18:11:15.113539762 +0200 @@ -5911,7 +5911,7 @@ omp_notice_threadprivate_variable (struc for (octx = ctx; octx; octx = octx->outer_context) if (octx->region_type == ORT_TARGET) { - n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl); + n = splay_tree_lookup (octx->variables, (splay_tree_key)decl); if (n == NULL) { error ("threadprivate variable %qE used in target region", @@ -8587,6 +8587,13 @@ gimplify_body (tree fndecl, bool do_parm gcc_assert (gimplify_ctxp == NULL); push_gimplify_context (&gctx); + if (flag_openmp) + { + gcc_assert (gimplify_omp_ctxp == NULL); + if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl))) + gimplify_omp_ctxp = new_omp_context (ORT_TARGET); + } + /* Unshare most shared trees in the body and in that of any nested functions. It would seem we don't have to do this for nested functions because they are supposed to be output and then the outer function gimplified @@ -8649,6 +8656,12 @@ gimplify_body (tree fndecl, bool do_parm nonlocal_vlas = NULL; } + if (flag_openmp && gimplify_omp_ctxp) + { + delete_omp_context (gimplify_omp_ctxp); + gimplify_omp_ctxp = NULL; + } + pop_gimplify_context (outer_bind); gcc_assert (gimplify_ctxp == NULL); --- gcc/c-family/c-common.c.jj 2013-05-20 13:18:25.000000000 +0200 +++ gcc/c-family/c-common.c 2013-05-27 16:58:37.870668360 +0200 @@ -370,6 +370,8 @@ static tree handle_no_split_stack_attrib static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); +static tree handle_omp_declare_target_attribute (tree *, tree, tree, int, + bool *); static void check_function_nonnull (tree, int, tree *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -742,6 +744,8 @@ const struct attribute_spec c_common_att handle_fnspec_attribute, false }, { "omp declare simd", 0, -1, true, false, false, handle_omp_declare_simd_attribute, false }, + { "omp declare target", 0, 0, true, false, false, + handle_omp_declare_target_attribute, false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -7966,6 +7970,15 @@ handle_omp_declare_simd_attribute (tree { return NULL_TREE; } + +/* Handle an "omp declare target" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *) +{ + return NULL_TREE; +} /* Handle a "returns_twice" attribute; arguments as in struct attribute_spec.handler. */