From patchwork Tue Oct 16 12:56:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chung-Lin Tang X-Patchwork-Id: 984747 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-487643-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mentor.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="oj0G5T3l"; dkim-atps=neutral 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 42ZFgg36vwz9s5c for ; Tue, 16 Oct 2018 23:56:47 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :reply-to:from:subject:to:message-id:date:mime-version :content-type; q=dns; s=default; b=e5Zb5wHTigIkkdez/4FqtrxeeLoqt N09tKZxvrt2rGS1nS3tOViFhVF5IzZ3kXhg7C2aJDAbQWFNc2jA+0EJoD8nxEm8d XazLsR//ezDIwHHF79fEs5jVfEgk4sX6SI1CXJY5Tvmkvtkagw9bzbxHtvdOgBlA P6YmsysihsYLqY= 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 :reply-to:from:subject:to:message-id:date:mime-version :content-type; s=default; bh=mu+YZiRfHw9BOqSbAgsIdH/T8O4=; b=oj0 G5T3l3RmJPm9GWMOKEft/dG58w9KDq91SlehQOaQSh2lJLgdkBrucQ/e87vRZS20 QARiVRnqNy3fVyBMSOk76BJWrSyRNl0HNjN5Y4KKbGNS2xtRsmZ+a7l86YmjMOv7 iO9I2ScM17rrovhpbMvcr2eFPNtZS87JIOow8mz0= Received: (qmail 76690 invoked by alias); 16 Oct 2018 12:56:39 -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 76676 invoked by uid 89); 16 Oct 2018 12:56:39 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 16 Oct 2018 12:56:37 +0000 Received: from svr-orw-mbx-02.mgc.mentorg.com ([147.34.90.202]) by relay1.mentorg.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-SHA384:256) id 1gCOto-0007IF-03 from ChungLin_Tang@mentor.com ; Tue, 16 Oct 2018 05:56:36 -0700 Received: from [0.0.0.0] (147.34.91.1) by svr-orw-mbx-02.mgc.mentorg.com (147.34.90.202) with Microsoft SMTP Server (TLS) id 15.0.1320.4; Tue, 16 Oct 2018 05:56:32 -0700 Reply-To: From: Chung-Lin Tang Subject: [PATCH, OpenACC, 5/8] Multi-dimensional dynamic array support for OpenACC data clauses, omp-low: bias scanning/adjustment during omp-lowering To: , Jakub Jelinek , Thomas Schwinge Message-ID: Date: Tue, 16 Oct 2018 20:56:29 +0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 This part is also in omp-low.c. We scan and adjust the code during omp-lowering, to add the biases for each dimension when a dynamic array access is detected, which is required for generally supporting copying sections of each dimension. The code is a bit sophisticated, and I wonder if this is better implemented in gimplify.c (though probably a non-trivial task as well). Nevertheless, it is currently working. Thanks, Chung-Lin gcc/ * omp-low.c (dynamic_array_lookup): New function. (dynamic_array_reference_start): Likewise. (scan_for_op): Likewise. (scan_for_reference): Likewise. (da_create_bias): Likewise. (da_dimension_peel): Likewise. (lower_omp_1): Add case to look for start of dynamic array reference, and handle bias adjustments for the code sequence. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 6a1cb05..4c44800 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -8734,6 +8946,201 @@ lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx) gimple_build_omp_return (false)); } +/* Helper to lookup dynamic array through nested omp contexts. Returns + TREE_LIST of dimensions, and the CTX where it was found in *CTX_P. */ + +static tree +dynamic_array_lookup (tree t, omp_context **ctx_p) +{ + omp_context *c = *ctx_p; + while (c) + { + tree *dims = c->dynamic_arrays->get (t); + if (dims) + { + *ctx_p = c; + return *dims; + } + c = c->outer; + } + return NULL_TREE; +} + +/* Tests if this gimple STMT is the start of a dynamic array access sequence. + Returns true if found, and also returns the gimple operand ptr and + dimensions tree list through *OUT_REF and *OUT_DIMS respectively. */ + +static bool +dynamic_array_reference_start (gimple *stmt, omp_context **ctx_p, + tree **out_ref, tree *out_dims) +{ + if (gimple_code (stmt) == GIMPLE_ASSIGN) + for (unsigned i = 1; i < gimple_num_ops (stmt); i++) + { + tree *op = gimple_op_ptr (stmt, i), dims; + if (TREE_CODE (*op) == ARRAY_REF) + op = &TREE_OPERAND (*op, 0); + if (TREE_CODE (*op) == MEM_REF) + op = &TREE_OPERAND (*op, 0); + if ((dims = dynamic_array_lookup (*op, ctx_p)) != NULL_TREE) + { + *out_ref = op; + *out_dims = dims; + return true; + } + } + return false; +} + +static tree +scan_for_op (tree *tp, int *walk_subtrees, void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; + tree t = *tp; + tree op = (tree) wi->info; + *walk_subtrees = 1; + if (operand_equal_p (t, op, 0)) + { + wi->info = tp; + return t; + } + return NULL_TREE; +} + +static tree * +scan_for_reference (gimple *stmt, tree op) +{ + struct walk_stmt_info wi; + memset (&wi, 0, sizeof (wi)); + wi.info = op; + if (walk_gimple_op (stmt, scan_for_op, &wi)) + return (tree *) wi.info; + return NULL; +} + +static tree +da_create_bias (tree orig_bias, tree unit_type) +{ + return build2 (MULT_EXPR, sizetype, fold_convert (sizetype, orig_bias), + TYPE_SIZE_UNIT (unit_type)); +} + +/* Main worker for adjusting dynamic array accesses, handles the adjustment + of many cases of statement forms, and called multiple times to 'peel' away + each dimension. */ + +static gimple_stmt_iterator +da_dimension_peel (omp_context *da_ctx, + gimple_stmt_iterator da_gsi, tree orig_da, + tree *da_op_p, tree *da_type_p, tree *da_dims_p) +{ + gimple *stmt = gsi_stmt (da_gsi); + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + + if (gimple_num_ops (stmt) == 2 + && TREE_CODE (rhs) == MEM_REF + && operand_equal_p (*da_op_p, TREE_OPERAND (rhs, 0), 0) + && !operand_equal_p (orig_da, TREE_OPERAND (rhs, 0), 0) + && (TREE_OPERAND (rhs, 1) == NULL_TREE + || integer_zerop (TREE_OPERAND (rhs, 1)))) + { + gcc_assert (TREE_CODE (TREE_TYPE (*da_type_p)) == POINTER_TYPE); + *da_type_p = TREE_TYPE (*da_type_p); + } + else + { + gimple *g; + gimple_seq ilist = NULL; + tree bias, t; + tree op = *da_op_p; + tree orig_type = *da_type_p; + tree orig_bias = TREE_PURPOSE (*da_dims_p); + bool by_ref = false; + + if (TREE_CODE (orig_bias) != INTEGER_CST) + orig_bias = lookup_decl (orig_bias, da_ctx); + + if (gimple_num_ops (stmt) == 2) + { + if (TREE_CODE (rhs) == ADDR_EXPR) + { + rhs = TREE_OPERAND (rhs, 0); + *da_dims_p = NULL_TREE; + } + + if (TREE_CODE (rhs) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF + && operand_equal_p (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0), + *da_op_p, 0)) + { + bias = da_create_bias (orig_bias, + TREE_TYPE (TREE_TYPE (orig_type))); + *da_type_p = TREE_TYPE (TREE_TYPE (orig_type)); + } + else if (TREE_CODE (rhs) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (rhs, 0)) == VAR_DECL + && operand_equal_p (TREE_OPERAND (rhs, 0), *da_op_p, 0)) + { + tree ptr_type = build_pointer_type (orig_type); + op = create_tmp_var (ptr_type); + gimplify_assign (op, build_fold_addr_expr (TREE_OPERAND (rhs, 0)), + &ilist); + bias = da_create_bias (orig_bias, TREE_TYPE (orig_type)); + *da_type_p = TREE_TYPE (orig_type); + orig_type = ptr_type; + by_ref = true; + } + else if (TREE_CODE (rhs) == MEM_REF + && operand_equal_p (*da_op_p, TREE_OPERAND (rhs, 0), 0) + && TREE_OPERAND (rhs, 1) != NULL_TREE) + { + bias = da_create_bias (orig_bias, TREE_TYPE (orig_type)); + *da_type_p = TREE_TYPE (orig_type); + } + else if (TREE_CODE (lhs) == MEM_REF + && operand_equal_p (*da_op_p, TREE_OPERAND (lhs, 0), 0)) + { + if (*da_dims_p != NULL_TREE) + { + gcc_assert (TREE_CHAIN (*da_dims_p) == NULL_TREE); + bias = da_create_bias (orig_bias, TREE_TYPE (orig_type)); + *da_type_p = TREE_TYPE (orig_type); + } + else + /* This should be the end of the dynamic array access + sequence. */ + return da_gsi; + } + else + gcc_unreachable (); + } + else if (gimple_num_ops (stmt) == 3 + && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + && operand_equal_p (*da_op_p, rhs, 0)) + { + bias = da_create_bias (orig_bias, TREE_TYPE (orig_type)); + } + else + gcc_unreachable (); + + bias = fold_build1 (NEGATE_EXPR, sizetype, bias); + bias = fold_build2 (POINTER_PLUS_EXPR, orig_type, op, bias); + + t = create_tmp_var (by_ref ? build_pointer_type (orig_type) : orig_type); + + g = gimplify_assign (t, bias, &ilist); + gsi_insert_seq_before (&da_gsi, ilist, GSI_NEW_STMT); + *da_op_p = gimple_assign_lhs (g); + + if (by_ref) + *da_op_p = build2 (MEM_REF, TREE_TYPE (orig_type), *da_op_p, + build_int_cst (orig_type, 0)); + *da_dims_p = TREE_CHAIN (*da_dims_p); + } + + return da_gsi; +} /* Callback for lower_omp_1. Return non-NULL if *tp needs to be regimplified. If DATA is non-NULL, lower_omp_1 is outside @@ -9009,6 +9416,51 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) } /* FALLTHRU */ default: + + /* If we detect the start of a dynamic array reference sequence, scan + and do the needed adjustments. */ + tree da_dims, *da_op_p; + omp_context *da_ctx = ctx; + if (da_ctx && dynamic_array_reference_start (stmt, &da_ctx, + &da_op_p, &da_dims)) + { + bool started = false; + tree orig_da = *da_op_p; + tree da_type = TREE_TYPE (orig_da); + tree next_da_op; + + gimple_stmt_iterator da_gsi = *gsi_p, new_gsi; + while (da_op_p) + { + if (!is_gimple_assign (gsi_stmt (da_gsi)) + || ((gimple_assign_single_p (gsi_stmt (da_gsi)) + || gimple_assign_cast_p (gsi_stmt (da_gsi))) + && *da_op_p == gimple_assign_rhs1 (gsi_stmt (da_gsi)))) + break; + + new_gsi = da_dimension_peel (da_ctx, da_gsi, orig_da, + da_op_p, &da_type, &da_dims); + if (!started) + { + /* Point 'stmt' to the start of the newly added + sequence. */ + started = true; + *gsi_p = new_gsi; + stmt = gsi_stmt (*gsi_p); + } + if (!da_dims) + break; + + next_da_op = gimple_assign_lhs (gsi_stmt (da_gsi)); + + do { + gsi_next (&da_gsi); + da_op_p = scan_for_reference (gsi_stmt (da_gsi), next_da_op); + } + while (!da_op_p); + } + } + if ((ctx || task_shared_vars) && walk_gimple_op (stmt, lower_omp_regimplify_p, ctx ? NULL : &wi))