From patchwork Thu May 7 15:36:32 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 469718 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 544A21402A0 for ; Fri, 8 May 2015 01:36:55 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Gn4IIEuw; dkim-atps=neutral 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:subject:message-id:reply-to:mime-version:content-type; q=dns; s=default; b=R5dVrDB+QOdbxDpEgjVzXQJ4jyzlRu/II/Z98wL8AQO zD9VW48Fk8Ulkidi6gfzogXBsQMXcrZfJVFGakNK6R+MtFQTeCeO84xDVUszD00y IikR8GtiTKb0u1QER+eKGL2j6vRCf5mz14NQ3IGZV4IvgE+ZrH7fADVSruXmYNh0 = 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:subject:message-id:reply-to:mime-version:content-type; s=default; bh=Q+LEaJQ5NilAXOEv8gKoG5hqA9A=; b=Gn4IIEuw/nSqq9zdy wNldLd1uIVzl8W47T1tEWdcVKV0DX5zznE65Zsc7ecQP2xmiBHX+5KnnC90Bq3oS 54LY5WOPBwBsW20gPGZHggECDhVXnVN/FafPHpNbykmtHT5kfpOy50h82MBt1/bl laWLBSrVRH/koO5adTvs6zYhKQ= Received: (qmail 50145 invoked by alias); 7 May 2015 15:36:45 -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 50130 invoked by uid 89); 7 May 2015 15:36:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.6 required=5.0 tests=AWL, BAYES_50, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 07 May 2015 15:36:39 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t47FabYD000776 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 7 May 2015 11:36:38 -0400 Received: from tucnak.zalov.cz (ovpn-116-89.ams2.redhat.com [10.36.116.89]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t47FaZ2x029092 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 7 May 2015 11:36:36 -0400 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.14.9/8.14.9) with ESMTP id t47FaYId028896 for ; Thu, 7 May 2015 17:36:34 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.14.9/8.14.9/Submit) id t47FaW2H028895 for gcc-patches@gcc.gnu.org; Thu, 7 May 2015 17:36:32 +0200 Date: Thu, 7 May 2015 17:36:32 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [gomp4.1] Taskloop construct lowering and expansion Message-ID: <20150507153632.GP1751@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes Hi! This patch gimplifies OMP_TASKLOOP as 3 different gimple statements - two GIMPLE_OMP_FOR with GIMPLE_OMP_TASK sandwiched in between them, so that we can represent properly the effect of what happens in the GOMP_taskloop caller (needs to compute number of iterations, prepare counts of collapsed loops), the data sharing of the created explicit tasks and finally the needed loop expansion inside of the explicit task region. Regtested on x86_64-linux, committed to gomp-4_1-branch. 2015-05-07 Jakub Jelinek * gimple.h (enum gf_mask): Add GF_OMP_TASK_TASKLOOP. Add GF_OMP_FOR_KIND_TASKLOOP and renumber GF_OMP_FOR_*. (gimple_omp_task_taskloop_p, gimple_omp_task_set_taskloop_p): New functions. * gimplify.c (is_gimple_stmt): Return true for OMP_TARGET, OMP_TARGET_DATA, OMP_TARGET_UPDATE, OMP_TARGET_ENTER_DATA, OMP_TARGET_EXIT_DATA, OMP_TASKLOOP and OMP_TEAMS. (gimplify_omp_for): Handle OMP_TASKLOOP. (gimplify_expr): Likewise. * gimple-pretty-print.c (dump_gimple_omp_for): Handle taskloop. (dump_gimple_omp_task): Likewise. * omp-low.c (is_taskloop_ctx): New function. (is_taskreg_ctx): Use is_parallel_ctx and is_task_ctx helpers. (extract_omp_for_data): Use OMP_CLAUSE_SCHEDULE_RUNTIME for taskloop. (scan_sharing_clauses): Allow _LOOPTEMP_ clause on GOMP_TASK. (find_combined_for): Allow searching for different GIMPLE_OMP_FOR kinds. (add_taskreg_looptemp_clauses): New function. (scan_omp_parallel): Use it. (scan_omp_task): Likewise. (finish_taskreg_scan): For taskloop, move fields for the first two _LOOPTEMP_ clauses first. (check_omp_nesting_restrictions): Allow the sandwiched taskloop constructs. (lower_rec_input_clauses): Allow _LOOPTEMP_ clause on GOMP_TASK. (lower_send_clauses): Ignore first two _LOOPTEMP_ clauses in taskloop GOMP_TASK. (expand_task_call): Handle taskloop construct expansion. Add REGION argument. (expand_omp_taskreg): Adjust caller. (expand_omp_for_init_vars): Handle GOMP_TASK inner_stmt. (expand_omp_taskloop_for_outer, expand_omp_taskloop_for_inner): New functions. (expand_omp_for): Call them. (lower_omp_for): Handle taskloop constructs. * omp-builtins.def (BUILT_IN_GOMP_TASKLOOP, BUILT_IN_GOMP_TASKLOOP_ULL): New builtins. * builtin-types.def (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_LONG_LONG_LONG, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_ULL_ULL_ULL): New. c/ * c-parser.c (OMP_TASKLOOP_CLAUSE_MASK): Add untied clause. c-family/ * c-pragma.c (omp_pragmas_simd): Add taskloop. * c-common.c (DEF_FUNCTION_TYPE_10): Define. lto/ * lto-lang.c (DEF_FUNCTION_TYPE_10): Define. fortran/ * types.def (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_LONG_LONG_LONG, BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_ULL_ULL_ULL): New. * f95-lang.c (DEF_FUNCTION_TYPE_10): Define. jit/ * jit-builtins.c (DEF_FUNCTION_TYPE_10): Define. * jit-builtins.h (DEF_FUNCTION_TYPE_10): Define. Jakub --- gcc/gimple.h.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/gimple.h 2015-05-05 12:59:58.728488815 +0200 @@ -89,17 +89,19 @@ enum gf_mask { GF_CALL_CTRL_ALTERING = 1 << 7, GF_CALL_WITH_BOUNDS = 1 << 8, GF_OMP_PARALLEL_COMBINED = 1 << 0, - GF_OMP_FOR_KIND_MASK = (1 << 3) - 1, + GF_OMP_TASK_TASKLOOP = 1 << 0, + GF_OMP_FOR_KIND_MASK = (1 << 4) - 1, GF_OMP_FOR_KIND_FOR = 0, GF_OMP_FOR_KIND_DISTRIBUTE = 1, - GF_OMP_FOR_KIND_CILKFOR = 2, - GF_OMP_FOR_KIND_OACC_LOOP = 3, + GF_OMP_FOR_KIND_TASKLOOP = 2, + GF_OMP_FOR_KIND_CILKFOR = 3, + GF_OMP_FOR_KIND_OACC_LOOP = 4, /* Flag for SIMD variants of OMP_FOR kinds. */ - GF_OMP_FOR_SIMD = 1 << 2, + GF_OMP_FOR_SIMD = 1 << 3, GF_OMP_FOR_KIND_SIMD = GF_OMP_FOR_SIMD | 0, GF_OMP_FOR_KIND_CILKSIMD = GF_OMP_FOR_SIMD | 1, - GF_OMP_FOR_COMBINED = 1 << 3, - GF_OMP_FOR_COMBINED_INTO = 1 << 4, + GF_OMP_FOR_COMBINED = 1 << 4, + GF_OMP_FOR_COMBINED_INTO = 1 << 5, GF_OMP_TARGET_KIND_MASK = (1 << 4) - 1, GF_OMP_TARGET_KIND_REGION = 0, GF_OMP_TARGET_KIND_DATA = 1, @@ -4833,6 +4835,31 @@ gimple_omp_task_set_clauses (gimple gs, } +/* Return true if OMP task statement G has the + GF_OMP_TASK_TASKLOOP flag set. */ + +static inline bool +gimple_omp_task_taskloop_p (const_gimple g) +{ + GIMPLE_CHECK (g, GIMPLE_OMP_TASK); + return (gimple_omp_subcode (g) & GF_OMP_TASK_TASKLOOP) != 0; +} + + +/* Set the GF_OMP_TASK_TASKLOOP field in G depending on the boolean + value of TASKLOOP_P. */ + +static inline void +gimple_omp_task_set_taskloop_p (gimple g, bool taskloop_p) +{ + GIMPLE_CHECK (g, GIMPLE_OMP_TASK); + if (taskloop_p) + g->subcode |= GF_OMP_TASK_TASKLOOP; + else + g->subcode &= ~GF_OMP_TASK_TASKLOOP; +} + + /* Return the child function used to hold the body of OMP_TASK GS. */ static inline tree --- gcc/gimplify.c.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/gimplify.c 2015-05-06 17:04:52.554393875 +0200 @@ -4486,6 +4486,13 @@ is_gimple_stmt (tree t) case OMP_ORDERED: case OMP_CRITICAL: case OMP_TASK: + case OMP_TARGET: + case OMP_TARGET_DATA: + case OMP_TARGET_UPDATE: + case OMP_TARGET_ENTER_DATA: + case OMP_TARGET_EXIT_DATA: + case OMP_TASKLOOP: + case OMP_TEAMS: /* These are always void. */ return true; @@ -6914,8 +6921,8 @@ gimplify_omp_for (tree *expr_p, gimple_s gomp_for *gfor; gimple_seq for_body, for_pre_body; int i; - bool simd; bitmap has_decl_expr = NULL; + enum omp_region_type ort = ORT_WORKSHARE; orig_for_stmt = for_stmt = *expr_p; @@ -6925,24 +6932,28 @@ gimplify_omp_for (tree *expr_p, gimple_s case CILK_FOR: case OMP_DISTRIBUTE: case OACC_LOOP: - simd = false; + break; + case OMP_TASKLOOP: + if (find_omp_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED)) + ort = ORT_UNTIED_TASK; + else + ort = ORT_TASK; break; case OMP_SIMD: case CILK_SIMD: - simd = true; + ort = ORT_SIMD; break; default: gcc_unreachable (); } - gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, - simd ? ORT_SIMD : ORT_WORKSHARE); + gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort); if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE) gimplify_omp_ctxp->distribute = true; /* Handle OMP_FOR_INIT. */ for_pre_body = NULL; - if (simd && OMP_FOR_PRE_BODY (for_stmt)) + if (ort == ORT_SIMD && OMP_FOR_PRE_BODY (for_stmt)) { has_decl_expr = BITMAP_ALLOC (NULL); if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR @@ -6996,10 +7007,10 @@ gimplify_omp_for (tree *expr_p, gimple_s tree c2 = NULL_TREE; if (orig_for_stmt != for_stmt) /* Do this only on innermost construct for combined ones. */; - else if (simd) + else if (ort == ORT_SIMD) { splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables, - (splay_tree_key)decl); + (splay_tree_key) decl); omp_is_private (gimplify_omp_ctxp, decl, 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) != 1)); @@ -7073,14 +7084,16 @@ gimplify_omp_for (tree *expr_p, gimple_s if (orig_for_stmt != for_stmt) var = decl; else if (!is_gimple_reg (decl) - || (simd && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)) + || (ort == ORT_SIMD + && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)) { var = create_tmp_var (TREE_TYPE (decl), get_name (decl)); TREE_OPERAND (t, 0) = var; gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var)); - if (simd && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) + if (ort == ORT_SIMD + && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1) { c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR); OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1; @@ -7272,6 +7285,7 @@ gimplify_omp_for (tree *expr_p, gimple_s case CILK_SIMD: kind = GF_OMP_FOR_KIND_CILKSIMD; break; case CILK_FOR: kind = GF_OMP_FOR_KIND_CILKFOR; break; case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break; + case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break; case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break; default: gcc_unreachable (); @@ -7306,7 +7320,95 @@ gimplify_omp_for (tree *expr_p, gimple_s gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1)); } - gimplify_seq_add_stmt (pre_p, gfor); + /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop + constructs with GIMPLE_OMP_TASK sandwiched in between them. + The outer taskloop stands for computing the number of iterations, + counts for collapsed loops and holding taskloop specific clauses. + The task construct stands for the effect of data sharing on the + explicit task it creates and the inner taskloop stands for expansion + of the static loop inside of the explicit task construct. */ + if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP) + { + tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor); + tree task_clauses = NULL_TREE; + tree c = *gfor_clauses_ptr; + tree *gtask_clauses_ptr = &task_clauses; + tree outer_for_clauses = NULL_TREE; + tree *gforo_clauses_ptr = &outer_for_clauses; + for (; c; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + /* These clauses are allowed on task, move them there. */ + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_DEFAULT: + case OMP_CLAUSE_IF: + case OMP_CLAUSE_UNTIED: + case OMP_CLAUSE_FINAL: + case OMP_CLAUSE_MERGEABLE: + case OMP_CLAUSE_PRIORITY: + *gtask_clauses_ptr = c; + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + break; + /* These clauses go into outer taskloop clauses. */ + case OMP_CLAUSE_GRAINSIZE: + case OMP_CLAUSE_NUM_TASKS: + case OMP_CLAUSE_NOGROUP: + *gforo_clauses_ptr = c; + gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + break; + /* Taskloop clause we duplicate on both taskloops. */ + case OMP_CLAUSE_COLLAPSE: + *gfor_clauses_ptr = c; + gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + *gforo_clauses_ptr = copy_node (c); + gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr); + break; + /* For lastprivate, keep the clause on inner taskloop, and add + a shared clause on task. */ + case OMP_CLAUSE_LASTPRIVATE: + *gfor_clauses_ptr = c; + gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c); + *gtask_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_SHARED); + OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c); + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); + break; + default: + gcc_unreachable (); + } + *gfor_clauses_ptr = NULL_TREE; + *gtask_clauses_ptr = NULL_TREE; + *gforo_clauses_ptr = NULL_TREE; + gimple g + = gimple_build_bind (NULL_TREE, gfor, NULL_TREE); + g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE, + NULL_TREE, NULL_TREE, NULL_TREE); + gimple_omp_task_set_taskloop_p (g, true); + g = gimple_build_bind (NULL_TREE, g, NULL_TREE); + gomp_for *gforo + = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses, + gimple_omp_for_collapse (gfor), NULL); + gimple_omp_for_set_combined_p (gforo, true); + gimple_omp_for_set_combined_into_p (gfor, true); + for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++) + { + t = unshare_expr (gimple_omp_for_index (gfor, i)); + gimple_omp_for_set_index (gforo, i, t); + t = unshare_expr (gimple_omp_for_initial (gfor, i)); + gimple_omp_for_set_initial (gforo, i, t); + gimple_omp_for_set_cond (gforo, i, + gimple_omp_for_cond (gfor, i)); + t = unshare_expr (gimple_omp_for_final (gfor, i)); + gimple_omp_for_set_final (gforo, i, t); + t = unshare_expr (gimple_omp_for_incr (gfor, i)); + gimple_omp_for_set_incr (gforo, i, t); + } + gimplify_seq_add_stmt (pre_p, gforo); + } + else + gimplify_seq_add_stmt (pre_p, gfor); if (ret != GS_ALL_DONE) return GS_ERROR; *expr_p = NULL_TREE; @@ -8403,6 +8505,7 @@ gimplify_expr (tree *expr_p, gimple_seq case CILK_SIMD: case CILK_FOR: case OMP_DISTRIBUTE: + case OMP_TASKLOOP: case OACC_LOOP: ret = gimplify_omp_for (expr_p, pre_p); break; --- gcc/gimple-pretty-print.c.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/gimple-pretty-print.c 2015-05-05 13:05:07.285653256 +0200 @@ -1154,6 +1154,9 @@ dump_gimple_omp_for (pretty_printer *buf case GF_OMP_FOR_KIND_DISTRIBUTE: kind = " distribute"; break; + case GF_OMP_FOR_KIND_TASKLOOP: + kind = " taskloop"; + break; case GF_OMP_FOR_KIND_CILKFOR: kind = " _Cilk_for"; break; @@ -1194,6 +1197,9 @@ dump_gimple_omp_for (pretty_printer *buf case GF_OMP_FOR_KIND_DISTRIBUTE: pp_string (buffer, "#pragma omp distribute"); break; + case GF_OMP_FOR_KIND_TASKLOOP: + pp_string (buffer, "#pragma omp taskloop"); + break; case GF_OMP_FOR_KIND_CILKFOR: break; case GF_OMP_FOR_KIND_OACC_LOOP: @@ -1995,7 +2001,10 @@ dump_gimple_omp_task (pretty_printer *bu else { gimple_seq body; - pp_string (buffer, "#pragma omp task"); + if (gimple_omp_task_taskloop_p (gs)) + pp_string (buffer, "#pragma omp taskloop"); + else + pp_string (buffer, "#pragma omp task"); dump_omp_clauses (buffer, gimple_omp_task_clauses (gs), spc, flags); if (gimple_omp_task_child_fn (gs)) { --- gcc/c/c-parser.c.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/c/c-parser.c 2015-05-06 17:04:52.565393703 +0200 @@ -15194,6 +15194,7 @@ c_parser_omp_declare (c_parser *parser, | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \ --- gcc/jit/jit-builtins.c.jj 2015-04-24 12:31:31.000000000 +0200 +++ gcc/jit/jit-builtins.c 2015-05-06 18:07:02.725716765 +0200 @@ -305,6 +305,11 @@ builtins_manager::make_type (enum jit_bu ARG6, ARG7, ARG8) \ case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \ ARG4, ARG5, ARG6, ARG7, ARG8); +#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) \ + case ENUM: return make_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, \ + ARG4, ARG5, ARG6, ARG7, ARG8, ARG9, \ + ARG10); #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ case ENUM: return make_fn_type (ENUM, RETURN, 1, 0); #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ @@ -343,6 +348,7 @@ builtins_manager::make_type (enum jit_bu #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 --- gcc/jit/jit-builtins.h.jj 2015-04-24 12:31:31.000000000 +0200 +++ gcc/jit/jit-builtins.h 2015-05-06 18:07:39.095152627 +0200 @@ -43,6 +43,8 @@ enum jit_builtin_type ARG6, ARG7) NAME, #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ ARG6, ARG7, ARG8) NAME, +#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) NAME, #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME, #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, @@ -66,6 +68,7 @@ enum jit_builtin_type #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 --- gcc/c-family/c-pragma.c.jj 2015-04-24 12:31:30.000000000 +0200 +++ gcc/c-family/c-pragma.c 2015-04-29 16:03:55.086027400 +0200 @@ -1230,6 +1230,7 @@ static const struct omp_pragma_def omp_p { "parallel", PRAGMA_OMP_PARALLEL }, { "simd", PRAGMA_OMP_SIMD }, { "target", PRAGMA_OMP_TARGET }, + { "taskloop", PRAGMA_OMP_TASKLOOP }, { "teams", PRAGMA_OMP_TEAMS }, }; --- gcc/c-family/c-common.c.jj 2015-04-29 10:59:19.000000000 +0200 +++ gcc/c-family/c-common.c 2015-05-06 18:03:59.402560350 +0200 @@ -5262,6 +5262,8 @@ enum c_builtin_type ARG6, ARG7) NAME, #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ ARG6, ARG7, ARG8) NAME, +#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) NAME, #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME, #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, @@ -5285,6 +5287,7 @@ enum c_builtin_type #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 @@ -5373,6 +5376,10 @@ c_define_builtins (tree va_list_ref_type ARG6, ARG7, ARG8) \ def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ ARG7, ARG8); +#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) \ + def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ + ARG7, ARG8, ARG9, ARG10); #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ def_fn_type (ENUM, RETURN, 1, 0); #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ @@ -5407,6 +5414,7 @@ c_define_builtins (tree va_list_ref_type #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 --- gcc/omp-low.c.jj 2015-04-29 11:03:04.000000000 +0200 +++ gcc/omp-low.c 2015-05-07 17:26:19.719608184 +0200 @@ -388,13 +388,22 @@ is_task_ctx (omp_context *ctx) } +/* Return true if CTX is for an omp taskloop. */ + +static inline bool +is_taskloop_ctx (omp_context *ctx) +{ + return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP; +} + + /* Return true if CTX is for an omp parallel or omp task. */ static inline bool is_taskreg_ctx (omp_context *ctx) { - return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL - || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK; + return is_parallel_ctx (ctx) || is_task_ctx (ctx); } @@ -423,6 +432,8 @@ extract_omp_for_data (gomp_for *for_stmt bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD; bool distribute = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE; + bool taskloop = gimple_omp_for_kind (for_stmt) + == GF_OMP_FOR_KIND_TASKLOOP; fd->for_stmt = for_stmt; fd->pre = NULL; @@ -451,7 +462,7 @@ extract_omp_for_data (gomp_for *for_stmt fd->have_ordered = true; break; case OMP_CLAUSE_SCHEDULE: - gcc_assert (!distribute); + gcc_assert (!distribute && !taskloop); fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t); fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t); break; @@ -480,6 +491,8 @@ extract_omp_for_data (gomp_for *for_stmt gcc_assert (fd->chunk_size == NULL); } gcc_assert (fd->collapse == 1 || collapse_iter != NULL); + if (taskloop) + fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME; if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME) gcc_assert (fd->chunk_size == NULL); else if (fd->chunk_size == NULL) @@ -1783,7 +1796,7 @@ scan_sharing_clauses (tree clauses, omp_ break; case OMP_CLAUSE__LOOPTEMP_: - gcc_assert (is_parallel_ctx (ctx)); + gcc_assert (is_taskreg_ctx (ctx)); decl = OMP_CLAUSE_DECL (c); install_var_field (decl, false, 3, ctx); install_var_local (decl, ctx); @@ -2286,7 +2299,8 @@ find_combined_for (gimple_stmt_iterator case GIMPLE_OMP_FOR: if (gimple_omp_for_combined_into_p (stmt) - && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR) + && gimple_omp_for_kind (stmt) + == *(const enum gf_mask *) (wi->info)) { wi->info = stmt; return integer_zero_node; @@ -2298,6 +2312,43 @@ find_combined_for (gimple_stmt_iterator return NULL; } +/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */ + +static void +add_taskreg_looptemp_clauses (enum gf_mask msk, gimple stmt, + omp_context *outer_ctx) +{ + struct walk_stmt_info wi; + + memset (&wi, 0, sizeof (wi)); + wi.val_only = true; + wi.info = (void *) &msk; + walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi); + if (wi.info != (void *) &msk) + { + gomp_for *for_stmt = as_a ((gimple) wi.info); + struct omp_for_data fd; + extract_omp_for_data (for_stmt, &fd, NULL); + /* We need two temporaries with fd.loop.v type (istart/iend) + and then (fd.collapse - 1) temporaries with the same + type for count2 ... countN-1 vars if not constant. */ + size_t count = 2, i; + tree type = fd.iter_type; + if (fd.collapse > 1 + && TREE_CODE (fd.loop.n2) != INTEGER_CST) + count += fd.collapse - 1; + for (i = 0; i < count; i++) + { + tree temp = create_tmp_var (type); + tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_); + insert_decl_map (&outer_ctx->cb, temp, temp); + OMP_CLAUSE_DECL (c) = temp; + OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt); + gimple_omp_taskreg_set_clauses (stmt, c); + } + } +} + /* Scan an OpenMP parallel directive. */ static void @@ -2319,38 +2370,7 @@ scan_omp_parallel (gimple_stmt_iterator } if (gimple_omp_parallel_combined_p (stmt)) - { - struct walk_stmt_info wi; - - memset (&wi, 0, sizeof (wi)); - wi.val_only = true; - walk_gimple_seq (gimple_omp_body (stmt), - find_combined_for, NULL, &wi); - if (wi.info) - { - gomp_for *for_stmt = as_a ((gimple) wi.info); - struct omp_for_data fd; - extract_omp_for_data (for_stmt, &fd, NULL); - /* We need two temporaries with fd.loop.v type (istart/iend) - and then (fd.collapse - 1) temporaries with the same - type for count2 ... countN-1 vars if not constant. */ - size_t count = 2, i; - tree type = fd.iter_type; - if (fd.collapse > 1 - && TREE_CODE (fd.loop.n2) != INTEGER_CST) - count += fd.collapse - 1; - for (i = 0; i < count; i++) - { - tree temp = create_tmp_var (type); - tree c = build_omp_clause (UNKNOWN_LOCATION, - OMP_CLAUSE__LOOPTEMP_); - insert_decl_map (&outer_ctx->cb, temp, temp); - OMP_CLAUSE_DECL (c) = temp; - OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt); - gimple_omp_parallel_set_clauses (stmt, c); - } - } - } + add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx); ctx = new_omp_context (stmt, outer_ctx); taskreg_contexts.safe_push (ctx); @@ -2393,6 +2413,9 @@ scan_omp_task (gimple_stmt_iterator *gsi return; } + if (gimple_omp_task_taskloop_p (stmt)) + add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx); + ctx = new_omp_context (stmt, outer_ctx); taskreg_contexts.safe_push (ctx); if (taskreg_nesting_level > 1) @@ -2514,6 +2537,41 @@ finish_taskreg_scan (omp_context *ctx) else p = &DECL_CHAIN (*p); *p = vla_fields; + if (gimple_omp_task_taskloop_p (ctx->stmt)) + { + /* Move fields corresponding to first and second _looptemp_ + clause first. There are filled by GOMP_taskloop + and thus need to be in specific positions. */ + tree c1 = gimple_omp_task_clauses (ctx->stmt); + c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_); + tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1), + OMP_CLAUSE__LOOPTEMP_); + tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx); + tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx); + p = &TYPE_FIELDS (ctx->record_type); + while (*p) + if (*p == f1 || *p == f2) + *p = DECL_CHAIN (*p); + else + p = &DECL_CHAIN (*p); + DECL_CHAIN (f1) = f2; + DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type); + TYPE_FIELDS (ctx->record_type) = f1; + if (ctx->srecord_type) + { + f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx); + f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx); + p = &TYPE_FIELDS (ctx->srecord_type); + while (*p) + if (*p == f1 || *p == f2) + *p = DECL_CHAIN (*p); + else + p = &DECL_CHAIN (*p); + DECL_CHAIN (f1) = f2; + DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type); + TYPE_FIELDS (ctx->srecord_type) = f1; + } + } layout_type (ctx->record_type); fixup_child_record_type (ctx); if (ctx->srecord_type) @@ -2803,6 +2861,9 @@ check_omp_nesting_restrictions (gimple s } return true; } + /* We split taskloop into task and nested taskloop in it. */ + if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP) + return true; /* FALLTHRU */ case GIMPLE_CALL: if (is_gimple_call (stmt) @@ -3706,7 +3767,7 @@ lower_rec_input_clauses (tree clauses, g reduction_omp_orig_ref = true; break; case OMP_CLAUSE__LOOPTEMP_: - /* Handle _looptemp_ clauses only on parallel. */ + /* Handle _looptemp_ clauses only on parallel/task. */ if (fd) continue; break; @@ -4070,7 +4131,7 @@ lower_rec_input_clauses (tree clauses, g goto do_dtor; case OMP_CLAUSE__LOOPTEMP_: - gcc_assert (is_parallel_ctx (ctx)); + gcc_assert (is_taskreg_ctx (ctx)); x = build_outer_var_ref (var, ctx); x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x); gimplify_and_add (x, ilist); @@ -4707,6 +4768,12 @@ lower_send_clauses (tree clauses, gimple omp_context *ctx) { tree c; + int ignored_looptemp = 0; + + /* For taskloop, ignore first two _looptemp_ clauses, those are initialized + by GOMP_taskloop. */ + if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt)) + ignored_looptemp = 2; for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) { @@ -4724,7 +4791,13 @@ lower_send_clauses (tree clauses, gimple case OMP_CLAUSE_COPYIN: case OMP_CLAUSE_LASTPRIVATE: case OMP_CLAUSE_REDUCTION: + break; case OMP_CLAUSE__LOOPTEMP_: + if (ignored_looptemp) + { + ignored_looptemp--; + continue; + } break; default: continue; @@ -5069,34 +5142,91 @@ expand_cilk_for_call (basic_block bb, go generate the task operation. BB is the block where to insert the code. */ static void -expand_task_call (basic_block bb, gomp_task *entry_stmt) +expand_task_call (struct omp_region *region, basic_block bb, + gomp_task *entry_stmt) { - tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend; + tree t1, t2, t3; gimple_stmt_iterator gsi; location_t loc = gimple_location (entry_stmt); - clauses = gimple_omp_task_clauses (entry_stmt); + tree clauses = gimple_omp_task_clauses (entry_stmt); - c = find_omp_clause (clauses, OMP_CLAUSE_IF); - if (c) - cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c)); - else - cond = boolean_true_node; + tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF); + tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED); + tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE); + tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND); + tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL); + + unsigned int iflags + = (untied ? 1 : 0) | (mergeable ? 4 : 0) | (depend ? 8 : 0); + + bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt); + tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE; + tree num_tasks = NULL_TREE; + bool ull = false; + if (taskloop_p) + { + gimple g = last_stmt (region->outer->entry); + gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR + && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP); + struct omp_for_data fd; + extract_omp_for_data (as_a (g), &fd, NULL); + startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_); + endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar), + OMP_CLAUSE__LOOPTEMP_); + startvar = OMP_CLAUSE_DECL (startvar); + endvar = OMP_CLAUSE_DECL (endvar); + step = fold_convert_loc (loc, fd.iter_type, fd.loop.step); + if (fd.loop.cond_code == LT_EXPR) + iflags |= 256; + tree tclauses = gimple_omp_for_clauses (g); + num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS); + if (num_tasks) + num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks); + else + { + num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE); + if (num_tasks) + { + iflags |= 512; + num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks); + } + else + num_tasks = integer_zero_node; + } + num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks); + if (ifc == NULL_TREE) + iflags |= 1024; + if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP)) + iflags |= 2048; + ull = fd.iter_type == long_long_unsigned_type_node; + } - c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED); - c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE); - depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND); - flags = build_int_cst (unsigned_type_node, - (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0)); + tree flags = build_int_cst (unsigned_type_node, iflags); - c = find_omp_clause (clauses, OMP_CLAUSE_FINAL); - if (c) + tree cond = boolean_true_node; + if (ifc) { - c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c)); - c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c, + if (taskloop_p) + { + tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc)); + t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t, + build_int_cst (unsigned_type_node, 1024), + build_int_cst (unsigned_type_node, 0)); + flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, + flags, t); + } + else + cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc)); + } + + if (finalc) + { + tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc)); + t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t, build_int_cst (unsigned_type_node, 2), build_int_cst (unsigned_type_node, 0)); - flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c); + flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t); } if (depend) depend = OMP_CLAUSE_DECL (depend); @@ -5104,7 +5234,7 @@ expand_task_call (basic_block bb, gomp_t depend = build_int_cst (ptr_type_node, 0); gsi = gsi_last_bb (bb); - t = gimple_omp_task_data_arg (entry_stmt); + tree t = gimple_omp_task_data_arg (entry_stmt); if (t == NULL) t2 = null_pointer_node; else @@ -5116,11 +5246,20 @@ expand_task_call (basic_block bb, gomp_t else t3 = build_fold_addr_expr_loc (loc, t); - t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK), - 8, t1, t2, t3, - gimple_omp_task_arg_size (entry_stmt), - gimple_omp_task_arg_align (entry_stmt), cond, flags, - depend); + if (taskloop_p) + t = build_call_expr (ull + ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL) + : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP), + 10, t1, t2, t3, + gimple_omp_task_arg_size (entry_stmt), + gimple_omp_task_arg_align (entry_stmt), flags, + num_tasks, startvar, endvar, step); + else + t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK), + 8, t1, t2, t3, + gimple_omp_task_arg_size (entry_stmt), + gimple_omp_task_arg_align (entry_stmt), cond, flags, + depend); force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false, GSI_CONTINUE_LINKING); @@ -5631,7 +5770,7 @@ expand_omp_taskreg (struct omp_region *r expand_parallel_call (region, new_bb, as_a (entry_stmt), ws_args); else - expand_task_call (new_bb, as_a (entry_stmt)); + expand_task_call (region, new_bb, as_a (entry_stmt)); if (gimple_in_ssa_p (cfun)) update_ssa (TODO_update_ssa_only_virtuals); } @@ -5846,8 +5985,8 @@ expand_omp_for_init_vars (struct omp_for if (TREE_CODE (fd->loop.n2) == INTEGER_CST) return; - tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL - ? gimple_omp_parallel_clauses (inner_stmt) + tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR + ? gimple_omp_taskreg_clauses (inner_stmt) : gimple_omp_for_clauses (inner_stmt); /* First two _looptemp_ clauses are for istart/iend, counts[0] isn't supposed to be handled, as the inner loop doesn't @@ -7843,6 +7982,343 @@ expand_omp_simd (struct omp_region *regi } } +/* Taskloop construct is represented after gimplification with + two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched + in between them. This routine expands the outer GIMPLE_OMP_FOR, + which should just compute all the needed loop temporaries + for GIMPLE_OMP_TASK. */ + +static void +expand_omp_taskloop_for_outer (struct omp_region *region, + struct omp_for_data *fd, + gimple inner_stmt) +{ + tree type, bias = NULL_TREE; + basic_block entry_bb, cont_bb, exit_bb; + gimple_stmt_iterator gsi; + gassign *assign_stmt; + tree *counts = NULL; + int i; + + gcc_assert (inner_stmt); + gcc_assert (region->cont); + gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK + && gimple_omp_task_taskloop_p (inner_stmt)); + type = TREE_TYPE (fd->loop.v); + + /* See if we need to bias by LLONG_MIN. */ + if (fd->iter_type == long_long_unsigned_type_node + && TREE_CODE (type) == INTEGER_TYPE + && !TYPE_UNSIGNED (type)) + { + tree n1, n2; + + if (fd->loop.cond_code == LT_EXPR) + { + n1 = fd->loop.n1; + n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step); + } + else + { + n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step); + n2 = fd->loop.n1; + } + if (TREE_CODE (n1) != INTEGER_CST + || TREE_CODE (n2) != INTEGER_CST + || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0))) + bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type)); + } + + entry_bb = region->entry; + cont_bb = region->cont; + gcc_assert (EDGE_COUNT (entry_bb->succs) == 2); + gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest); + exit_bb = region->exit; + + gsi = gsi_last_bb (entry_bb); + gimple for_stmt = gsi_stmt (gsi); + gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR); + if (fd->collapse > 1) + { + int first_zero_iter = -1; + basic_block zero_iter_bb = NULL, l2_dom_bb = NULL; + + counts = XALLOCAVEC (tree, fd->collapse); + expand_omp_for_init_counts (fd, &gsi, entry_bb, counts, + zero_iter_bb, first_zero_iter, + l2_dom_bb); + + if (zero_iter_bb) + { + /* Some counts[i] vars might be uninitialized if + some loop has zero iterations. But the body shouldn't + be executed in that case, so just avoid uninit warnings. */ + for (i = first_zero_iter; i < fd->collapse; i++) + if (SSA_VAR_P (counts[i])) + TREE_NO_WARNING (counts[i]) = 1; + gsi_prev (&gsi); + edge e = split_block (entry_bb, gsi_stmt (gsi)); + entry_bb = e->dest; + make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU); + gsi = gsi_last_bb (entry_bb); + set_immediate_dominator (CDI_DOMINATORS, entry_bb, + get_immediate_dominator (CDI_DOMINATORS, + zero_iter_bb)); + } + } + + tree t0, t1; + t1 = fd->loop.n2; + t0 = fd->loop.n1; + if (POINTER_TYPE_P (TREE_TYPE (t0)) + && TYPE_PRECISION (TREE_TYPE (t0)) + != TYPE_PRECISION (fd->iter_type)) + { + /* Avoid casting pointers to integer of a different size. */ + tree itype = signed_type_for (type); + t1 = fold_convert (fd->iter_type, fold_convert (itype, t1)); + t0 = fold_convert (fd->iter_type, fold_convert (itype, t0)); + } + else + { + t1 = fold_convert (fd->iter_type, t1); + t0 = fold_convert (fd->iter_type, t0); + } + if (bias) + { + t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias); + t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias); + } + + tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt), + OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + tree startvar = OMP_CLAUSE_DECL (innerc); + innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + tree endvar = OMP_CLAUSE_DECL (innerc); + + t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false, + GSI_CONTINUE_LINKING); + assign_stmt = gimple_build_assign (startvar, t0); + gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); + + t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false, + GSI_CONTINUE_LINKING); + assign_stmt = gimple_build_assign (endvar, t1); + gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); + if (fd->collapse > 1) + expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar); + + /* Remove the GIMPLE_OMP_FOR statement. */ + gsi = gsi_for_stmt (for_stmt); + gsi_remove (&gsi, true); + + gsi = gsi_last_bb (cont_bb); + gsi_remove (&gsi, true); + + gsi = gsi_last_bb (exit_bb); + gsi_remove (&gsi, true); + + FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE; + remove_edge (BRANCH_EDGE (entry_bb)); + FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE; + remove_edge (BRANCH_EDGE (cont_bb)); + set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb); + set_immediate_dominator (CDI_DOMINATORS, region->entry, + recompute_dominator (CDI_DOMINATORS, region->entry)); +} + +/* Taskloop construct is represented after gimplification with + two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched + in between them. This routine expands the inner GIMPLE_OMP_FOR. + GOMP_taskloop{,_ull} function arranges for each task to be given just + a single range of iterations. */ + +static void +expand_omp_taskloop_for_inner (struct omp_region *region, + struct omp_for_data *fd, + gimple inner_stmt) +{ + tree e, t, type, itype, vmain, vback; + basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL; + basic_block fin_bb; + gimple_stmt_iterator gsi; + edge ep; + bool broken_loop = region->cont == NULL; + tree *counts = NULL; + tree n1, n2, step; + + itype = type = TREE_TYPE (fd->loop.v); + if (POINTER_TYPE_P (type)) + itype = signed_type_for (type); + + entry_bb = region->entry; + cont_bb = region->cont; + gcc_assert (EDGE_COUNT (entry_bb->succs) == 2); + fin_bb = BRANCH_EDGE (entry_bb)->dest; + gcc_assert (broken_loop + || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest)); + body_bb = FALLTHRU_EDGE (entry_bb)->dest; + if (!broken_loop) + { + gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb); + gcc_assert (EDGE_COUNT (cont_bb->succs) == 2); + } + exit_bb = region->exit; + + /* Iteration space partitioning goes in ENTRY_BB. */ + gsi = gsi_last_bb (entry_bb); + gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR); + + if (fd->collapse > 1) + { + int first_zero_iter = -1; + basic_block l2_dom_bb = NULL; + + counts = XALLOCAVEC (tree, fd->collapse); + expand_omp_for_init_counts (fd, &gsi, entry_bb, counts, + fin_bb, first_zero_iter, + l2_dom_bb); + t = NULL_TREE; + } + else + t = integer_one_node; + + step = fd->loop.step; + tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt), + OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + n1 = OMP_CLAUSE_DECL (innerc); + innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + n2 = OMP_CLAUSE_DECL (innerc); + n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1), + true, NULL_TREE, true, GSI_SAME_STMT); + n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2), + true, NULL_TREE, true, GSI_SAME_STMT); + step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step), + true, NULL_TREE, true, GSI_SAME_STMT); + + tree startvar = fd->loop.v; + tree endvar = NULL_TREE; + + if (gimple_omp_for_combined_p (fd->for_stmt)) + { + tree clauses = gimple_omp_for_clauses (inner_stmt); + tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + startvar = OMP_CLAUSE_DECL (innerc); + innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), + OMP_CLAUSE__LOOPTEMP_); + gcc_assert (innerc); + endvar = OMP_CLAUSE_DECL (innerc); + } + t = fold_convert (TREE_TYPE (startvar), n1); + t = force_gimple_operand_gsi (&gsi, t, + DECL_P (startvar) + && TREE_ADDRESSABLE (startvar), + NULL_TREE, false, GSI_CONTINUE_LINKING); + gimple assign_stmt = gimple_build_assign (startvar, t); + gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); + + t = fold_convert (TREE_TYPE (startvar), n2); + e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, + false, GSI_CONTINUE_LINKING); + if (endvar) + { + assign_stmt = gimple_build_assign (endvar, e); + gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); + if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e))) + assign_stmt = gimple_build_assign (fd->loop.v, e); + else + assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e); + gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); + } + if (fd->collapse > 1) + expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar); + + if (!broken_loop) + { + /* The code controlling the sequential loop replaces the + GIMPLE_OMP_CONTINUE. */ + gsi = gsi_last_bb (cont_bb); + gomp_continue *cont_stmt = as_a (gsi_stmt (gsi)); + gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE); + vmain = gimple_omp_continue_control_use (cont_stmt); + vback = gimple_omp_continue_control_def (cont_stmt); + + if (!gimple_omp_for_combined_p (fd->for_stmt)) + { + if (POINTER_TYPE_P (type)) + t = fold_build_pointer_plus (vmain, step); + else + t = fold_build2 (PLUS_EXPR, type, vmain, step); + t = force_gimple_operand_gsi (&gsi, t, + DECL_P (vback) + && TREE_ADDRESSABLE (vback), + NULL_TREE, true, GSI_SAME_STMT); + assign_stmt = gimple_build_assign (vback, t); + gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT); + + t = build2 (fd->loop.cond_code, boolean_type_node, + DECL_P (vback) && TREE_ADDRESSABLE (vback) + ? t : vback, e); + gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT); + } + + /* Remove the GIMPLE_OMP_CONTINUE statement. */ + gsi_remove (&gsi, true); + + if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt)) + collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb); + } + + /* Remove the GIMPLE_OMP_FOR statement. */ + gsi = gsi_for_stmt (fd->for_stmt); + gsi_remove (&gsi, true); + + /* Remove the GIMPLE_OMP_RETURN statement. */ + gsi = gsi_last_bb (exit_bb); + gsi_remove (&gsi, true); + + FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE; + remove_edge (BRANCH_EDGE (entry_bb)); + + /* Connect all the blocks. */ + if (!broken_loop) + { + ep = find_edge (cont_bb, body_bb); + if (gimple_omp_for_combined_p (fd->for_stmt)) + { + remove_edge (ep); + ep = NULL; + } + else if (fd->collapse > 1) + { + remove_edge (ep); + ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE); + } + else + ep->flags = EDGE_TRUE_VALUE; + find_edge (cont_bb, fin_bb)->flags + = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU; + } + + set_immediate_dominator (CDI_DOMINATORS, body_bb, + recompute_dominator (CDI_DOMINATORS, body_bb)); + set_immediate_dominator (CDI_DOMINATORS, fin_bb, + recompute_dominator (CDI_DOMINATORS, fin_bb)); + + if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt)) + { + struct loop *loop = alloc_loop (); + loop->header = body_bb; + if (collapse_bb == NULL) + loop->latch = cont_bb; + add_loop (loop, body_bb->loop_father); + } +} /* Expand the OMP loop defined by REGION. */ @@ -7879,6 +8355,13 @@ expand_omp_for (struct omp_region *regio expand_omp_simd (region, &fd); else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR) expand_cilk_for (region, &fd); + else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP) + { + if (gimple_omp_for_combined_into_p (fd.for_stmt)) + expand_omp_taskloop_for_inner (region, &fd, inner_stmt); + else + expand_omp_taskloop_for_outer (region, &fd, inner_stmt); + } else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered) { @@ -10620,17 +11103,19 @@ lower_omp_for (gimple_stmt_iterator *gsi if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST) count += fd.collapse - 1; - bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR; + bool taskreg_for + = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR + || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP); tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt); tree clauses = *pc; - if (parallel_for) + if (taskreg_for) outerc - = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt), + = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt), OMP_CLAUSE__LOOPTEMP_); for (i = 0; i < count; i++) { tree temp; - if (parallel_for) + if (taskreg_for) { gcc_assert (outerc); temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer); --- gcc/fortran/types.def.jj 2015-04-24 12:32:08.000000000 +0200 +++ gcc/fortran/types.def 2015-05-06 18:12:22.395758259 +0200 @@ -211,6 +211,16 @@ DEF_FUNCTION_TYPE_8 (BT_FN_VOID_OMPFN_PT BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, BT_BOOL, BT_UINT, BT_PTR) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_LONG_LONG_LONG, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_UINT, BT_LONG, BT_LONG, BT_LONG, BT_LONG) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_ULL_ULL_ULL, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_UINT, BT_LONG, + BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG) + DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID) DEF_FUNCTION_TYPE_VAR_2 (BT_FN_VOID_INT_INT_VAR, BT_VOID, BT_INT, BT_INT) --- gcc/fortran/f95-lang.c.jj 2015-04-24 12:32:08.000000000 +0200 +++ gcc/fortran/f95-lang.c 2015-05-06 18:13:32.897664681 +0200 @@ -671,6 +671,8 @@ gfc_init_builtin_functions (void) ARG6, ARG7) NAME, #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ ARG6, ARG7, ARG8) NAME, +#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) NAME, #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, #define DEF_FUNCTION_TYPE_VAR_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ @@ -689,6 +691,7 @@ gfc_init_builtin_functions (void) #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_2 #undef DEF_FUNCTION_TYPE_VAR_7 @@ -1123,6 +1126,21 @@ gfc_init_builtin_functions (void) builtin_types[(int) ARG7], \ builtin_types[(int) ARG8], \ NULL_TREE); +#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, \ + ARG5, ARG6, ARG7, ARG8, ARG9, ARG10) \ + builtin_types[(int) ENUM] \ + = build_function_type_list (builtin_types[(int) RETURN], \ + builtin_types[(int) ARG1], \ + builtin_types[(int) ARG2], \ + builtin_types[(int) ARG3], \ + builtin_types[(int) ARG4], \ + builtin_types[(int) ARG5], \ + builtin_types[(int) ARG6], \ + builtin_types[(int) ARG7], \ + builtin_types[(int) ARG8], \ + builtin_types[(int) ARG9], \ + builtin_types[(int) ARG10], \ + NULL_TREE); #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ builtin_types[(int) ENUM] \ = build_varargs_function_type_list (builtin_types[(int) RETURN], \ @@ -1175,6 +1193,7 @@ gfc_init_builtin_functions (void) #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_2 #undef DEF_FUNCTION_TYPE_VAR_7 --- gcc/omp-builtins.def.jj 2015-04-24 12:32:12.000000000 +0200 +++ gcc/omp-builtins.def 2015-05-06 17:12:46.641239391 +0200 @@ -235,6 +235,12 @@ DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK, "GOMP_task", BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR, ATTR_NOTHROW_LIST) +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKLOOP, "GOMP_taskloop", + BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_LONG_LONG_LONG, + ATTR_NOTHROW_LIST) +DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKLOOP_ULL, "GOMP_taskloop_ull", + BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_ULL_ULL_ULL, + ATTR_NOTHROW_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_START, "GOMP_sections_start", BT_FN_UINT_UINT, ATTR_NOTHROW_LEAF_LIST) DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_NEXT, "GOMP_sections_next", --- gcc/builtin-types.def.jj 2015-04-24 12:32:03.000000000 +0200 +++ gcc/builtin-types.def 2015-05-06 18:03:20.396165391 +0200 @@ -546,6 +546,16 @@ DEF_FUNCTION_TYPE_8 (BT_FN_VOID_OMPFN_PT BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, BT_BOOL, BT_UINT, BT_PTR) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_LONG_LONG_LONG, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_UINT, BT_LONG, BT_LONG, BT_LONG, BT_LONG) +DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_ULL_ULL_ULL, + BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, + BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG, + BT_UINT, BT_LONG, + BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG) + DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID) DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT) DEF_FUNCTION_TYPE_VAR_0 (BT_FN_PTR_VAR, BT_PTR) --- gcc/lto/lto-lang.c.jj 2015-04-24 12:32:10.000000000 +0200 +++ gcc/lto/lto-lang.c 2015-05-06 18:08:47.340094057 +0200 @@ -170,6 +170,8 @@ enum lto_builtin_type ARG6, ARG7) NAME, #define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ ARG6, ARG7, ARG8) NAME, +#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) NAME, #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME, #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME, #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME, @@ -193,6 +195,7 @@ enum lto_builtin_type #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2 @@ -673,6 +676,10 @@ lto_define_builtins (tree va_list_ref_ty ARG6, ARG7, ARG8) \ def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ ARG7, ARG8); +#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \ + ARG6, ARG7, ARG8, ARG9, ARG10) \ + def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \ + ARG7, ARG8, ARG9, ARG10); #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \ def_fn_type (ENUM, RETURN, 1, 0); #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \ @@ -707,6 +714,7 @@ lto_define_builtins (tree va_list_ref_ty #undef DEF_FUNCTION_TYPE_6 #undef DEF_FUNCTION_TYPE_7 #undef DEF_FUNCTION_TYPE_8 +#undef DEF_FUNCTION_TYPE_10 #undef DEF_FUNCTION_TYPE_VAR_0 #undef DEF_FUNCTION_TYPE_VAR_1 #undef DEF_FUNCTION_TYPE_VAR_2