From patchwork Fri Oct 28 04:07:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 122338 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]) by ozlabs.org (Postfix) with SMTP id EC5BE1007DD for ; Fri, 28 Oct 2011 15:08:54 +1100 (EST) Received: (qmail 13926 invoked by alias); 28 Oct 2011 04:08:28 -0000 Received: (qmail 13676 invoked by uid 22791); 28 Oct 2011 04:08:25 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_TM, T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from mail-yw0-f47.google.com (HELO mail-yw0-f47.google.com) (209.85.213.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 28 Oct 2011 04:07:56 +0000 Received: by ywf9 with SMTP id 9so3781712ywf.20 for ; Thu, 27 Oct 2011 21:07:55 -0700 (PDT) Received: by 10.236.76.136 with SMTP id b8mr970346yhe.9.1319774875669; Thu, 27 Oct 2011 21:07:55 -0700 (PDT) Received: from localhost.localdomain (c-98-203-235-125.hsd1.wa.comcast.net. [98.203.235.125]) by mx.google.com with ESMTPS id j25sm10849016yhm.12.2011.10.27.21.07.54 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 27 Oct 2011 21:07:55 -0700 (PDT) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: amacleod@redhat.com, jakub@redhat.com Subject: [PATCH 7/9] Update omp for new atomic optabs. Date: Thu, 27 Oct 2011 21:07:36 -0700 Message-Id: <1319774858-9181-8-git-send-email-rth@redhat.com> In-Reply-To: <1319774858-9181-1-git-send-email-rth@redhat.com> References: <1319774858-9181-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes 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 Cc: jakub@redhat.com --- gcc/omp-low.c | 55 +++++++++++------------ gcc/optabs.c | 134 +++++++++++++++++++-------------------------------------- gcc/optabs.h | 13 ++++++ 3 files changed, 84 insertions(+), 118 deletions(-) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 5faa084..972cb6d 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -5009,13 +5009,16 @@ expand_omp_atomic_fetch_op (basic_block load_bb, { enum built_in_function oldbase, newbase, tmpbase; tree decl, itype, call; - direct_optab optab, oldoptab, newoptab; + const struct atomic_op_functions *optab; tree lhs, rhs; basic_block store_bb = single_succ (load_bb); gimple_stmt_iterator gsi; gimple stmt; location_t loc; bool need_old, need_new; + enum rtx_code r_code; + enum machine_mode imode; + bool have_old, have_new, have_noval; /* We expect to find the following sequences: @@ -5053,41 +5056,33 @@ expand_omp_atomic_fetch_op (basic_block load_bb, case POINTER_PLUS_EXPR: oldbase = BUILT_IN_SYNC_FETCH_AND_ADD_N; newbase = BUILT_IN_SYNC_ADD_AND_FETCH_N; - optab = sync_add_optab; - oldoptab = sync_old_add_optab; - newoptab = sync_new_add_optab; + r_code = PLUS; break; case MINUS_EXPR: oldbase = BUILT_IN_SYNC_FETCH_AND_SUB_N; newbase = BUILT_IN_SYNC_SUB_AND_FETCH_N; - optab = sync_add_optab; - oldoptab = sync_old_add_optab; - newoptab = sync_new_add_optab; + r_code = MINUS; break; case BIT_AND_EXPR: oldbase = BUILT_IN_SYNC_FETCH_AND_AND_N; newbase = BUILT_IN_SYNC_AND_AND_FETCH_N; - optab = sync_and_optab; - oldoptab = sync_old_and_optab; - newoptab = sync_new_and_optab; + r_code = AND; break; case BIT_IOR_EXPR: oldbase = BUILT_IN_SYNC_FETCH_AND_OR_N; newbase = BUILT_IN_SYNC_OR_AND_FETCH_N; - optab = sync_ior_optab; - oldoptab = sync_old_ior_optab; - newoptab = sync_new_ior_optab; + r_code = IOR; break; case BIT_XOR_EXPR: oldbase = BUILT_IN_SYNC_FETCH_AND_XOR_N; newbase = BUILT_IN_SYNC_XOR_AND_FETCH_N; - optab = sync_xor_optab; - oldoptab = sync_old_xor_optab; - newoptab = sync_new_xor_optab; + r_code = XOR; break; default: return false; } + optab = get_atomic_op_for_code (r_code); + /* Make sure the expression is of the proper form. */ if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0)) rhs = gimple_assign_rhs2 (stmt); @@ -5103,31 +5098,33 @@ expand_omp_atomic_fetch_op (basic_block load_bb, if (decl == NULL_TREE) return false; itype = TREE_TYPE (TREE_TYPE (decl)); + imode = TYPE_MODE (itype); + + have_new = + (direct_optab_handler (optab->mem_fetch_after, imode) == CODE_FOR_nothing + || direct_optab_handler (optab->fetch_after, imode) == CODE_FOR_nothing); + have_old = + (direct_optab_handler (optab->mem_fetch_before, imode) == CODE_FOR_nothing + || direct_optab_handler (optab->fetch_before, imode) == CODE_FOR_nothing); + have_noval = + (direct_optab_handler (optab->mem_no_result, imode) == CODE_FOR_nothing + || direct_optab_handler (optab->no_result, imode) == CODE_FOR_nothing); if (need_new) { /* expand_sync_fetch_operation can always compensate when interested in the new value. */ - if (direct_optab_handler (newoptab, TYPE_MODE (itype)) - == CODE_FOR_nothing - && direct_optab_handler (oldoptab, TYPE_MODE (itype)) - == CODE_FOR_nothing) + if (!have_new && !have_old) return false; } else if (need_old) { /* When interested in the old value, expand_sync_fetch_operation - can compensate only if the operation is reversible. AND and OR - are not reversible. */ - if (direct_optab_handler (oldoptab, TYPE_MODE (itype)) - == CODE_FOR_nothing - && (oldbase == BUILT_IN_SYNC_FETCH_AND_AND_N - || oldbase == BUILT_IN_SYNC_FETCH_AND_OR_N - || direct_optab_handler (newoptab, TYPE_MODE (itype)) - == CODE_FOR_nothing)) + can compensate only if the operation is reversible. */ + if (!have_old && !(have_new && optab->reverse_code != UNKNOWN)) return false; } - else if (direct_optab_handler (optab, TYPE_MODE (itype)) == CODE_FOR_nothing) + else if (!have_noval && !have_new && !have_old) return false; gsi = gsi_last_bb (load_bb); diff --git a/gcc/optabs.c b/gcc/optabs.c index b7c00be..f594226 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7172,70 +7172,48 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model) /* Structure containing the pointers and values required to process the various forms of the atomic_fetch_op and atomic_op_fetch builtins. */ -struct op_functions { - struct direct_optab_d *mem_fetch_before; - struct direct_optab_d *mem_fetch_after; - struct direct_optab_d *mem_no_result; - struct direct_optab_d *fetch_before; - struct direct_optab_d *fetch_after; - struct direct_optab_d *no_result; - enum rtx_code reverse_code; -}; -/* Initialize the fields for each supported opcode. */ -static const struct op_functions add_op = { atomic_fetch_add_optab, - atomic_add_fetch_optab, - atomic_add_optab, - sync_old_add_optab, - sync_new_add_optab, - sync_add_optab, - MINUS - }; - -static const struct op_functions sub_op = { atomic_fetch_sub_optab, - atomic_sub_fetch_optab, - atomic_sub_optab, - sync_old_sub_optab, - sync_new_sub_optab, - sync_sub_optab, - PLUS - }; - -static const struct op_functions xor_op = { atomic_fetch_xor_optab, - atomic_xor_fetch_optab, - atomic_xor_optab, - sync_old_xor_optab, - sync_new_xor_optab, - sync_xor_optab, - UNKNOWN - }; - -static const struct op_functions and_op = { atomic_fetch_and_optab, - atomic_and_fetch_optab, - atomic_and_optab, - sync_old_and_optab, - sync_new_and_optab, - sync_and_optab, - UNKNOWN - }; - -static const struct op_functions nand_op = { atomic_fetch_nand_optab, - atomic_nand_fetch_optab, - atomic_nand_optab, - sync_old_nand_optab, - sync_new_nand_optab, - sync_nand_optab, - UNKNOWN - }; - -static const struct op_functions or_op = { atomic_fetch_or_optab, - atomic_or_fetch_optab, - atomic_or_optab, - sync_old_ior_optab, - sync_new_ior_optab, - sync_ior_optab, - UNKNOWN - }; +const struct atomic_op_functions * +get_atomic_op_for_code (enum rtx_code code) +{ + static const struct atomic_op_functions add_op = { + atomic_fetch_add_optab, atomic_add_fetch_optab, atomic_add_optab, + sync_old_add_optab, sync_new_add_optab, sync_add_optab, MINUS + }, sub_op = { + atomic_fetch_sub_optab, atomic_sub_fetch_optab, atomic_sub_optab, + sync_old_sub_optab, sync_new_sub_optab, sync_sub_optab, PLUS + }, xor_op = { + atomic_fetch_xor_optab, atomic_xor_fetch_optab, atomic_xor_optab, + sync_old_xor_optab, sync_new_xor_optab, sync_xor_optab, XOR + }, and_op = { + atomic_fetch_and_optab, atomic_and_fetch_optab, atomic_and_optab, + sync_old_and_optab, sync_new_and_optab, sync_and_optab, UNKNOWN + }, nand_op = { + atomic_fetch_nand_optab, atomic_nand_fetch_optab, atomic_nand_optab, + sync_old_nand_optab, sync_new_nand_optab, sync_nand_optab, UNKNOWN + }, ior_op = { + atomic_fetch_or_optab, atomic_or_fetch_optab, atomic_or_optab, + sync_old_ior_optab, sync_new_ior_optab, sync_ior_optab, UNKNOWN + }; + + switch (code) + { + case PLUS: + return &add_op; + case MINUS: + return &sub_op; + case XOR: + return &xor_op; + case AND: + return &and_op; + case IOR: + return &ior_op; + case NOT: + return &nand_op; + default: + gcc_unreachable (); + } +} /* Try to emit an instruction for a specific operation varaition. OPTAB contains the OP functions. @@ -7247,8 +7225,8 @@ static const struct op_functions or_op = { atomic_fetch_or_optab, AFTER is true if the returned result is the value after the operation. */ static rtx -maybe_emit_op (const struct op_functions *optab, rtx target, rtx mem, rtx val, - bool use_memmodel, enum memmodel model, bool after) +maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem, + rtx val, bool use_memmodel, enum memmodel model, bool after) { enum machine_mode mode = GET_MODE (mem); struct direct_optab_d *this_optab; @@ -7317,33 +7295,11 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, enum memmodel model, bool after) { enum machine_mode mode = GET_MODE (mem); - const struct op_functions *optab; + const struct atomic_op_functions *optab; rtx result; bool unused_result = (target == const0_rtx); - switch (code) - { - case PLUS: - optab = &add_op; - break; - case MINUS: - optab = &sub_op; - break; - case AND: - optab = &and_op; - break; - case XOR: - optab = &xor_op; - break; - case IOR: - optab = &or_op; - break; - case NOT: - optab = &nand_op; - break; - default: - gcc_unreachable(); - } + optab = get_atomic_op_for_code (code); /* Check for the case where the result isn't used and try those patterns. */ if (unused_result) diff --git a/gcc/optabs.h b/gcc/optabs.h index 2ca0fcd..4487f52 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -955,6 +955,19 @@ enum insn_code can_float_p (enum machine_mode, enum machine_mode, int); /* Return true if there is an inline compare and swap pattern. */ extern bool can_compare_and_swap_p (enum machine_mode); +struct atomic_op_functions +{ + struct direct_optab_d *mem_fetch_before; + struct direct_optab_d *mem_fetch_after; + struct direct_optab_d *mem_no_result; + struct direct_optab_d *fetch_before; + struct direct_optab_d *fetch_after; + struct direct_optab_d *no_result; + enum rtx_code reverse_code; +}; + +extern const struct atomic_op_functions *get_atomic_op_for_code (enum rtx_code); + /* Generate code for a compare and swap. */ extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool, enum memmodel, enum memmodel);