From patchwork Fri Dec 9 13:10:04 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 704497 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 3tZszM1X4jz9vFT for ; Sat, 10 Dec 2016 00:10:22 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="RJRKNZi/"; 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=dWW0/ilpj4TMzInZSWbghs93oChtw iMhWC7AA3znnkqsrbaXhZx9tBOSdmWGp15xofSpLTDwRMCFyN5I/NSsEBBI6xo+/ AeKx2p0PmbacYBILXadwuh76IN+wWOA+Q0Z+JYH5kLxmxpl6XXDfyevnesAGVWyi K5joDlzJXt+8rA= 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=JzCkUPPjlmO9nEUjEOn9h2Y9l6A=; b=RJR KNZi/NJj1MPYlMs1mxnN5kqU7SLxJyhnR06rkpncX3j8x0JJB6wm8S2jdlgcDlCU 8ohx66zV0GabzK13CrcflfOXxp/8Q0ZvyKoTAM+Y+me543amgCPWqUV7xUgC+MT+ oyDvhAgkSbvYVk+3w3j9wS1kLlRmDrGoAdb1V5Uk= Received: (qmail 78620 invoked by alias); 9 Dec 2016 13:10:12 -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 78606 invoked by uid 89); 9 Dec 2016 13:10:11 -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=(unknown) 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:10:08 +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 7590E707; Fri, 9 Dec 2016 05:10:06 -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 F372A3F477 for ; Fri, 9 Dec 2016 05:10:05 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [26/67] Use is_a in subreg/extract simplifications References: <87h96dp8u6.fsf@e105548-lin.cambridge.arm.com> Date: Fri, 09 Dec 2016 13:10:04 +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: <87d1h1l043.fsf@e105548-lin.cambridge.arm.com> User-Agent: Gnus/5.130012 (Ma Gnus v0.12) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Add is_a checks to various places that were optimising subregs or extractions in ways that only made sense for scalar integers. Often the subreg transformations were looking for extends, truncates or shifts and trying to remove the subreg, which wouldn't be correct if the SUBREG_REG was a vector rather than a scalar. The simplify_binary_operation_1 part also removes a redundant: GET_MODE (opleft) == GET_MODE (XEXP (opright, 0)) since this must be true for: (ior A (lshifrt B ...)) A == opleft, B == XEXP (opright, 0) gcc/ 2016-11-24 Richard Sandiford Alan Hayward David Sherwood * combine.c (find_split_point): Add is_a checks. (make_compound_operation): Likewise. (change_zero_ext): Likewise. * expr.c (convert_move): Likewise. (convert_modes): Likewise. * fwprop.c (forward_propagate_subreg): Likewise. * loop-iv.c (get_biv_step_1): Likewise. * optabs.c (widen_operand): Likewise. * postreload.c (move2add_valid_value_p): Likewise. * recog.c (simplify_while_replacing): Likewise. * simplify-rtx.c (simplify_unary_operation_1): Likewise. (simplify_binary_operation_1): Likewise. Remove redundant mode equality check. diff --git a/gcc/combine.c b/gcc/combine.c index e1e8457..7f943be 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -4768,7 +4768,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) HOST_WIDE_INT pos = 0; int unsignedp = 0; rtx inner = NULL_RTX; - scalar_int_mode inner_mode; + scalar_int_mode mode, inner_mode; /* First special-case some codes. */ switch (code) @@ -5022,7 +5022,9 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) case SIGN_EXTRACT: case ZERO_EXTRACT: - if (CONST_INT_P (XEXP (SET_SRC (x), 1)) + if (is_a (GET_MODE (XEXP (SET_SRC (x), 0)), + &inner_mode) + && CONST_INT_P (XEXP (SET_SRC (x), 1)) && CONST_INT_P (XEXP (SET_SRC (x), 2))) { inner = XEXP (SET_SRC (x), 0); @@ -5030,7 +5032,7 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) pos = INTVAL (XEXP (SET_SRC (x), 2)); if (BITS_BIG_ENDIAN) - pos = GET_MODE_PRECISION (GET_MODE (inner)) - len - pos; + pos = GET_MODE_PRECISION (inner_mode) - len - pos; unsignedp = (code == ZERO_EXTRACT); } break; @@ -5040,10 +5042,9 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src) } if (len && pos >= 0 - && pos + len <= GET_MODE_PRECISION (GET_MODE (inner))) + && pos + len <= GET_MODE_PRECISION (GET_MODE (inner)) + && is_a (GET_MODE (SET_SRC (x)), &mode)) { - machine_mode mode = GET_MODE (SET_SRC (x)); - /* For unsigned, we have a choice of a shift followed by an AND or two shifts. Use two shifts for field sizes where the constant might be too large. We assume here that we can @@ -7836,6 +7837,7 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr, int i; rtx tem; bool equality_comparison = false; + scalar_int_mode inner_mode; if (in_code == EQ) { @@ -7943,11 +7945,12 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr, /* Same as previous, but for (subreg (lshiftrt ...)) in first op. */ else if (GET_CODE (XEXP (x, 0)) == SUBREG && subreg_lowpart_p (XEXP (x, 0)) + && is_a (GET_MODE (SUBREG_REG (XEXP (x, 0))), + &inner_mode) && GET_CODE (SUBREG_REG (XEXP (x, 0))) == LSHIFTRT && (i = exact_log2 (UINTVAL (XEXP (x, 1)) + 1)) >= 0) { rtx inner_x0 = SUBREG_REG (XEXP (x, 0)); - machine_mode inner_mode = GET_MODE (inner_x0); new_rtx = make_compound_operation (XEXP (inner_x0, 0), next_code); new_rtx = make_extraction (inner_mode, new_rtx, 0, XEXP (inner_x0, 1), @@ -8146,10 +8149,10 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr, /* If the SUBREG is masking of a logical right shift, make an extraction. */ if (GET_CODE (inner) == LSHIFTRT + && is_a (GET_MODE (inner), &inner_mode) + && GET_MODE_SIZE (mode) < GET_MODE_SIZE (inner_mode) && CONST_INT_P (XEXP (inner, 1)) - && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner)) - && (UINTVAL (XEXP (inner, 1)) - < GET_MODE_PRECISION (GET_MODE (inner))) + && UINTVAL (XEXP (inner, 1)) < GET_MODE_PRECISION (inner_mode) && subreg_lowpart_p (x)) { new_rtx = make_compound_operation (XEXP (inner, 0), next_code); @@ -11324,15 +11327,16 @@ change_zero_ext (rtx pat) maybe_swap_commutative_operands (**iter); rtx *dst = &SET_DEST (pat); + scalar_int_mode mode; if (GET_CODE (*dst) == ZERO_EXTRACT && REG_P (XEXP (*dst, 0)) + && is_a (GET_MODE (XEXP (*dst, 0)), &mode) && CONST_INT_P (XEXP (*dst, 1)) && CONST_INT_P (XEXP (*dst, 2))) { rtx reg = XEXP (*dst, 0); int width = INTVAL (XEXP (*dst, 1)); int offset = INTVAL (XEXP (*dst, 2)); - machine_mode mode = GET_MODE (reg); int reg_width = GET_MODE_PRECISION (mode); if (BITS_BIG_ENDIAN) offset = reg_width - width - offset; diff --git a/gcc/expr.c b/gcc/expr.c index 467c873..843c402 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -237,11 +237,14 @@ convert_move (rtx to, rtx from, int unsignedp) the required extension, strip it. We don't handle such SUBREGs as TO here. */ - if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from) + scalar_int_mode to_int_mode; + if (GET_CODE (from) == SUBREG + && SUBREG_PROMOTED_VAR_P (from) + && is_a (to_mode, &to_int_mode) && (GET_MODE_PRECISION (GET_MODE (SUBREG_REG (from))) - >= GET_MODE_PRECISION (to_mode)) + >= GET_MODE_PRECISION (to_int_mode)) && SUBREG_CHECK_PROMOTED_SIGN (from, unsignedp)) - from = gen_lowpart (to_mode, from), from_mode = to_mode; + from = gen_lowpart (to_int_mode, from), from_mode = to_int_mode; gcc_assert (GET_CODE (to) != SUBREG || !SUBREG_PROMOTED_VAR_P (to)); @@ -633,10 +636,12 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp) /* If FROM is a SUBREG that indicates that we have already done at least the required extension, strip it. */ - if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x) - && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode) + if (GET_CODE (x) == SUBREG + && SUBREG_PROMOTED_VAR_P (x) + && is_a (mode, &int_mode) + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (int_mode) && SUBREG_CHECK_PROMOTED_SIGN (x, unsignedp)) - x = gen_lowpart (mode, SUBREG_REG (x)); + x = gen_lowpart (int_mode, SUBREG_REG (x)); if (GET_MODE (x) != VOIDmode) oldmode = GET_MODE (x); diff --git a/gcc/fwprop.c b/gcc/fwprop.c index a3fbb34..2f22e4d 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -1089,6 +1089,7 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set) rtx use_reg = DF_REF_REG (use); rtx_insn *use_insn; rtx src; + scalar_int_mode int_use_mode, src_mode; /* Only consider subregs... */ machine_mode use_mode = GET_MODE (use_reg); @@ -1132,17 +1133,19 @@ forward_propagate_subreg (df_ref use, rtx_insn *def_insn, rtx def_set) definition of Y or, failing that, allow A to be deleted after reload through register tying. Introducing more uses of Y prevents both optimisations. */ - else if (subreg_lowpart_p (use_reg)) + else if (is_a (use_mode, &int_use_mode) + && subreg_lowpart_p (use_reg)) { use_insn = DF_REF_INSN (use); src = SET_SRC (def_set); if ((GET_CODE (src) == ZERO_EXTEND || GET_CODE (src) == SIGN_EXTEND) + && is_a (GET_MODE (src), &src_mode) && REG_P (XEXP (src, 0)) && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER && GET_MODE (XEXP (src, 0)) == use_mode && !free_load_extend (src, def_insn) - && (targetm.mode_rep_extended (use_mode, GET_MODE (src)) + && (targetm.mode_rep_extended (int_use_mode, src_mode) != (int) GET_CODE (src)) && all_uses_available_at (def_insn, use_insn)) return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0), diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index 9e13938..f684da2 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -739,9 +739,9 @@ get_biv_step_1 (df_ref def, rtx reg, if (GET_CODE (next) == SUBREG) { - machine_mode amode = GET_MODE (next); - - if (GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode)) + scalar_int_mode amode; + if (!is_a (GET_MODE (next), &amode) + || GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode)) return false; *inner_mode = amode; diff --git a/gcc/optabs.c b/gcc/optabs.c index b641cbe..acf89bd 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -195,6 +195,7 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode, int unsignedp, int no_extend) { rtx result; + scalar_int_mode int_mode; /* If we don't have to extend and this is a constant, return it. */ if (no_extend && GET_MODE (op) == VOIDmode) @@ -204,19 +205,20 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode, extend since it will be more efficient to do so unless the signedness of a promoted object differs from our extension. */ if (! no_extend + || !is_a (mode, &int_mode) || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op) && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp))) return convert_modes (mode, oldmode, op, unsignedp); /* If MODE is no wider than a single word, we return a lowpart or paradoxical SUBREG. */ - if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) - return gen_lowpart (mode, force_reg (GET_MODE (op), op)); + if (GET_MODE_SIZE (int_mode) <= UNITS_PER_WORD) + return gen_lowpart (int_mode, force_reg (GET_MODE (op), op)); /* Otherwise, get an object of MODE, clobber it, and set the low-order part to OP. */ - result = gen_reg_rtx (mode); + result = gen_reg_rtx (int_mode); emit_clobber (result); emit_move_insn (gen_lowpart (GET_MODE (op), result), op); return result; diff --git a/gcc/postreload.c b/gcc/postreload.c index ff77d4c..ff7e7c3 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -1694,14 +1694,16 @@ move2add_valid_value_p (int regno, machine_mode mode) if (mode != reg_mode[regno]) { - if (!MODES_OK_FOR_MOVE2ADD (mode, reg_mode[regno])) + scalar_int_mode old_mode; + if (!is_a (reg_mode[regno], &old_mode) + || !MODES_OK_FOR_MOVE2ADD (mode, old_mode)) return false; /* The value loaded into regno in reg_mode[regno] is also valid in mode after truncation only if (REG:mode regno) is the lowpart of (REG:reg_mode[regno] regno). Now, for big endian, the starting regno of the lowpart might be different. */ - int s_off = subreg_lowpart_offset (mode, reg_mode[regno]); - s_off = subreg_regno_offset (regno, reg_mode[regno], s_off, mode); + int s_off = subreg_lowpart_offset (mode, old_mode); + s_off = subreg_regno_offset (regno, old_mode, s_off, mode); if (s_off != 0) /* We could in principle adjust regno, check reg_mode[regno] to be BLKmode, and return s_off to the caller (vs. -1 for failure), diff --git a/gcc/recog.c b/gcc/recog.c index 22b5aaa..3a17de2 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -560,6 +560,7 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object, rtx x = *loc; enum rtx_code code = GET_CODE (x); rtx new_rtx = NULL_RTX; + scalar_int_mode is_mode; if (SWAPPABLE_OPERANDS_P (x) && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1))) @@ -655,6 +656,7 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object, happen, we might just fail in some cases). */ if (MEM_P (XEXP (x, 0)) + && is_a (GET_MODE (XEXP (x, 0)), &is_mode) && CONST_INT_P (XEXP (x, 1)) && CONST_INT_P (XEXP (x, 2)) && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0), @@ -662,7 +664,6 @@ simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object, && !MEM_VOLATILE_P (XEXP (x, 0))) { machine_mode wanted_mode = VOIDmode; - machine_mode is_mode = GET_MODE (XEXP (x, 0)); int pos = INTVAL (XEXP (x, 2)); if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ()) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 1e6dd22..854d026 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -916,7 +916,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) { enum rtx_code reversed; rtx temp; - scalar_int_mode inner, int_mode; + scalar_int_mode inner, int_mode, op0_mode; switch (code) { @@ -1626,21 +1626,19 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) (zero_extend:SI (subreg:QI (and:SI (reg:SI) (const_int 63)) 0)) is (and:SI (reg:SI) (const_int 63)). */ if (GET_CODE (op) == SUBREG - && GET_MODE_PRECISION (GET_MODE (op)) - < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) - && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) - <= HOST_BITS_PER_WIDE_INT - && GET_MODE_PRECISION (mode) - >= GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op))) + && is_a (mode, &int_mode) + && is_a (GET_MODE (SUBREG_REG (op)), &op0_mode) + && GET_MODE_PRECISION (GET_MODE (op)) < GET_MODE_PRECISION (op0_mode) + && GET_MODE_PRECISION (op0_mode) <= HOST_BITS_PER_WIDE_INT + && GET_MODE_PRECISION (int_mode) >= GET_MODE_PRECISION (op0_mode) && subreg_lowpart_p (op) - && (nonzero_bits (SUBREG_REG (op), GET_MODE (SUBREG_REG (op))) + && (nonzero_bits (SUBREG_REG (op), op0_mode) & ~GET_MODE_MASK (GET_MODE (op))) == 0) { - if (GET_MODE_PRECISION (mode) - == GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op)))) + if (GET_MODE_PRECISION (int_mode) == GET_MODE_PRECISION (op0_mode)) return SUBREG_REG (op); - return simplify_gen_unary (ZERO_EXTEND, mode, SUBREG_REG (op), - GET_MODE (SUBREG_REG (op))); + return simplify_gen_unary (ZERO_EXTEND, int_mode, SUBREG_REG (op), + op0_mode); } #if defined(POINTERS_EXTEND_UNSIGNED) @@ -2702,21 +2700,23 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, by simplify_shift_const. */ if (GET_CODE (opleft) == SUBREG + && is_a (mode, &int_mode) + && is_a (GET_MODE (SUBREG_REG (opleft)), + &inner_mode) && GET_CODE (SUBREG_REG (opleft)) == ASHIFT && GET_CODE (opright) == LSHIFTRT && GET_CODE (XEXP (opright, 0)) == SUBREG - && GET_MODE (opleft) == GET_MODE (XEXP (opright, 0)) && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0)) - && (GET_MODE_SIZE (GET_MODE (opleft)) - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (opleft)))) + && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode) && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0), SUBREG_REG (XEXP (opright, 0))) && CONST_INT_P (XEXP (SUBREG_REG (opleft), 1)) && CONST_INT_P (XEXP (opright, 1)) - && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + INTVAL (XEXP (opright, 1)) - == GET_MODE_PRECISION (mode))) - return gen_rtx_ROTATE (mode, XEXP (opright, 0), - XEXP (SUBREG_REG (opleft), 1)); + && (INTVAL (XEXP (SUBREG_REG (opleft), 1)) + + INTVAL (XEXP (opright, 1)) + == GET_MODE_PRECISION (int_mode))) + return gen_rtx_ROTATE (int_mode, XEXP (opright, 0), + XEXP (SUBREG_REG (opleft), 1)); /* If we have (ior (and (X C1) C2)), simplify this by making C1 as small as possible if C1 actually changes. */