From patchwork Fri Dec 9 13:31:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 704531 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 3tZtS74d63z9vDV for ; Sat, 10 Dec 2016 00:31:51 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="l0/j0y+s"; 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:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=AahIJJnWArPVzh4c0PU0uCU/cpmBx 41XhcS54rM9X3q/lXmd0SIz+Jwnb6OINTLgoQXph4Mz9mjApaPdVCtP9195lyKNR XUxPwyrokkXtkOGV9N66dRsQouKz8d4l1hwALP1pQNFkXmUMayTFDzu/hnM4zE/M vEymVr8byXmkWU= 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:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=1aQ+fysdAgXj1QfFjRTzDma6SA0=; b=l0/ j0y+sw8mvQMG3fVVsnRu2rH0AhNvEShNfe7O/RhJsYoqLWHVdiNFLyVbYUEZ34K2 gYoGwj6wWeJCDxM7gc/lwnUIiLZ6fdhkEWiNmg9/V2gagMZNyQWVFtkd6b6s6bUM 8i6QyiTM55JEGt5L38Yotudbt3Dngy5LPSXDoSx0= Received: (qmail 50694 invoked by alias); 9 Dec 2016 13:31:41 -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 50677 invoked by uid 89); 9 Dec 2016 13:31:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Dec 2016 13:31:37 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id EAA00707; Fri, 9 Dec 2016 05:31:35 -0800 (PST) Received: from localhost (e105548-lin.manchester.arm.com [10.45.32.67]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 76E413F477 for ; Fri, 9 Dec 2016 05:31:35 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [54/67] Add explicit int checks for alternative optab implementations References: <87h96dp8u6.fsf@e105548-lin.cambridge.arm.com> Date: Fri, 09 Dec 2016 13:31:33 +0000 In-Reply-To: <87h96dp8u6.fsf@e105548-lin.cambridge.arm.com> (Richard Sandiford's message of "Fri, 09 Dec 2016 12:48:01 +0000") Message-ID: <87zik5fcui.fsf@e105548-lin.cambridge.arm.com> User-Agent: Gnus/5.130012 (Ma Gnus v0.12) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 expand_unop can expand narrow clz, clrsb, ctz, bswap, parity and ffs operations using optabs for wider modes. These expansions apply only to scalar integer modes (and not for example to vectors), so the patch adds explicit checks for that. gcc/ 2016-11-24 Richard Sandiford Alan Hayward David Sherwood * optabs.c (widen_leading): Change the type of the mode argument to scalar_int_mode. Use opt_scalar_int_mode for the mode iterator. (widen_bswap): Likewise. (expand_parity): Likewise. (expand_ctz): Change the type of the mode argument to scalar_int_mode. (expand_ffs): Likewise. (epand_unop): Check for scalar integer modes before calling the above routines. diff --git a/gcc/optabs.c b/gcc/optabs.c index 509f0d3..cc03c9b 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -2127,39 +2127,36 @@ expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0, A similar operation can be used for clrsb. UNOPTAB says which operation we are trying to expand. */ static rtx -widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab) +widen_leading (scalar_int_mode mode, rtx op0, rtx target, optab unoptab) { - enum mode_class mclass = GET_MODE_CLASS (mode); - if (CLASS_HAS_WIDER_MODES_P (mclass)) + opt_scalar_int_mode wider_mode_iter; + FOR_EACH_WIDER_MODE (wider_mode_iter, mode) { - machine_mode wider_mode; - FOR_EACH_WIDER_MODE (wider_mode, mode) + scalar_int_mode wider_mode = *wider_mode_iter; + if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) { - if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) - { - rtx xop0, temp; - rtx_insn *last; + rtx xop0, temp; + rtx_insn *last; - last = get_last_insn (); + last = get_last_insn (); - if (target == 0) - target = gen_reg_rtx (mode); - xop0 = widen_operand (op0, wider_mode, mode, - unoptab != clrsb_optab, false); - temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, - unoptab != clrsb_optab); - if (temp != 0) - temp = expand_binop - (wider_mode, sub_optab, temp, - gen_int_mode (GET_MODE_PRECISION (wider_mode) - - GET_MODE_PRECISION (mode), - wider_mode), - target, true, OPTAB_DIRECT); - if (temp == 0) - delete_insns_since (last); + if (target == 0) + target = gen_reg_rtx (mode); + xop0 = widen_operand (op0, wider_mode, mode, + unoptab != clrsb_optab, false); + temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX, + unoptab != clrsb_optab); + if (temp != 0) + temp = expand_binop + (wider_mode, sub_optab, temp, + gen_int_mode (GET_MODE_PRECISION (wider_mode) + - GET_MODE_PRECISION (mode), + wider_mode), + target, true, OPTAB_DIRECT); + if (temp == 0) + delete_insns_since (last); - return temp; - } + return temp; } } return 0; @@ -2293,22 +2290,20 @@ expand_doubleword_parity (machine_mode mode, rtx op0, rtx target) as (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */ static rtx -widen_bswap (machine_mode mode, rtx op0, rtx target) +widen_bswap (scalar_int_mode mode, rtx op0, rtx target) { - enum mode_class mclass = GET_MODE_CLASS (mode); - machine_mode wider_mode; rtx x; rtx_insn *last; + opt_scalar_int_mode wider_mode_iter; - if (!CLASS_HAS_WIDER_MODES_P (mclass)) - return NULL_RTX; + FOR_EACH_WIDER_MODE (wider_mode_iter, mode) + if (optab_handler (bswap_optab, *wider_mode_iter) != CODE_FOR_nothing) + break; - FOR_EACH_WIDER_MODE (wider_mode, mode) - if (optab_handler (bswap_optab, wider_mode) != CODE_FOR_nothing) - goto found; - return NULL_RTX; + if (!wider_mode_iter.exists ()) + return NULL_RTX; - found: + scalar_int_mode wider_mode = *wider_mode_iter; last = get_last_insn (); x = widen_operand (op0, wider_mode, mode, true, true); @@ -2359,42 +2354,40 @@ expand_doubleword_bswap (machine_mode mode, rtx op, rtx target) /* Try calculating (parity x) as (and (popcount x) 1), where popcount can also be done in a wider mode. */ static rtx -expand_parity (machine_mode mode, rtx op0, rtx target) +expand_parity (scalar_int_mode mode, rtx op0, rtx target) { enum mode_class mclass = GET_MODE_CLASS (mode); - if (CLASS_HAS_WIDER_MODES_P (mclass)) + opt_scalar_int_mode wider_mode_iter; + FOR_EACH_MODE_FROM (wider_mode_iter, mode) { - machine_mode wider_mode; - FOR_EACH_MODE_FROM (wider_mode, mode) + scalar_int_mode wider_mode = *wider_mode_iter; + if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing) { - if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing) - { - rtx xop0, temp; - rtx_insn *last; + rtx xop0, temp; + rtx_insn *last; - last = get_last_insn (); + last = get_last_insn (); - if (target == 0 || GET_MODE (target) != wider_mode) - target = gen_reg_rtx (wider_mode); + if (target == 0 || GET_MODE (target) != wider_mode) + target = gen_reg_rtx (wider_mode); - xop0 = widen_operand (op0, wider_mode, mode, true, false); - temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX, - true); - if (temp != 0) - temp = expand_binop (wider_mode, and_optab, temp, const1_rtx, - target, true, OPTAB_DIRECT); + xop0 = widen_operand (op0, wider_mode, mode, true, false); + temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX, + true); + if (temp != 0) + temp = expand_binop (wider_mode, and_optab, temp, const1_rtx, + target, true, OPTAB_DIRECT); - if (temp) - { - if (mclass != MODE_INT - || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode)) - return convert_to_mode (mode, temp, 0); - else - return gen_lowpart (mode, temp); - } + if (temp) + { + if (mclass != MODE_INT + || !TRULY_NOOP_TRUNCATION_MODES_P (mode, wider_mode)) + return convert_to_mode (mode, temp, 0); else - delete_insns_since (last); + return gen_lowpart (mode, temp); } + else + delete_insns_since (last); } } return 0; @@ -2413,7 +2406,7 @@ expand_parity (machine_mode mode, rtx op0, rtx target) less convenient for expand_ffs anyway. */ static rtx -expand_ctz (machine_mode mode, rtx op0, rtx target) +expand_ctz (scalar_int_mode mode, rtx op0, rtx target) { rtx_insn *seq; rtx temp; @@ -2456,7 +2449,7 @@ expand_ctz (machine_mode mode, rtx op0, rtx target) may have an undefined value in that case. If they do not give us a convenient value, we have to generate a test and branch. */ static rtx -expand_ffs (machine_mode mode, rtx op0, rtx target) +expand_ffs (scalar_int_mode mode, rtx op0, rtx target) { HOST_WIDE_INT val = 0; bool defined_at_zero = false; @@ -2713,16 +2706,19 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, /* Widening (or narrowing) clz needs special treatment. */ if (unoptab == clz_optab) { - temp = widen_leading (mode, op0, target, unoptab); - if (temp) - return temp; - - if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD - && optab_handler (unoptab, word_mode) != CODE_FOR_nothing) + if (is_a (mode, &int_mode)) { - temp = expand_doubleword_clz (mode, op0, target); + temp = widen_leading (int_mode, op0, target, unoptab); if (temp) return temp; + + if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD + && optab_handler (unoptab, word_mode) != CODE_FOR_nothing) + { + temp = expand_doubleword_clz (int_mode, op0, target); + if (temp) + return temp; + } } goto try_libcall; @@ -2730,9 +2726,12 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, if (unoptab == clrsb_optab) { - temp = widen_leading (mode, op0, target, unoptab); - if (temp) - return temp; + if (is_a (mode, &int_mode)) + { + temp = widen_leading (int_mode, op0, target, unoptab); + if (temp) + return temp; + } goto try_libcall; } @@ -2804,16 +2803,19 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, delete_insns_since (last); } - temp = widen_bswap (mode, op0, target); - if (temp) - return temp; - - if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD - && optab_handler (unoptab, word_mode) != CODE_FOR_nothing) + if (is_a (mode, &int_mode)) { - temp = expand_doubleword_bswap (mode, op0, target); + temp = widen_bswap (int_mode, op0, target); if (temp) return temp; + + if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD + && optab_handler (unoptab, word_mode) != CODE_FOR_nothing) + { + temp = expand_doubleword_bswap (mode, op0, target); + if (temp) + return temp; + } } goto try_libcall; @@ -2914,25 +2916,25 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, } /* Try calculating parity (x) as popcount (x) % 2. */ - if (unoptab == parity_optab) + if (unoptab == parity_optab && is_a (mode, &int_mode)) { - temp = expand_parity (mode, op0, target); + temp = expand_parity (int_mode, op0, target); if (temp) return temp; } /* Try implementing ffs (x) in terms of clz (x). */ - if (unoptab == ffs_optab) + if (unoptab == ffs_optab && is_a (mode, &int_mode)) { - temp = expand_ffs (mode, op0, target); + temp = expand_ffs (int_mode, op0, target); if (temp) return temp; } /* Try implementing ctz (x) in terms of clz (x). */ - if (unoptab == ctz_optab) + if (unoptab == ctz_optab && is_a (mode, &int_mode)) { - temp = expand_ctz (mode, op0, target); + temp = expand_ctz (int_mode, op0, target); if (temp) return temp; }