From patchwork Mon Aug 28 08:21:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 111100 Delivered-To: patch@linaro.org Received: by 10.37.128.210 with SMTP id c18csp4517156ybm; Mon, 28 Aug 2017 01:22:18 -0700 (PDT) X-Received: by 10.84.215.208 with SMTP id g16mr7618462plj.191.1503908538632; Mon, 28 Aug 2017 01:22:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1503908538; cv=none; d=google.com; s=arc-20160816; b=iCl4Ontt68HinrNzA+EcN1NIYaYbTNDJcneUVgCZEEi3GmfQVPVx1qNXjD+RLFrUdc c4S7uPGL/iWXeeZNZvFtlBq/jIQa3WCoWU1rA21DP2zVp0NuYik5WIvrXqI/Ii28yhuK CJNz5dwMxHEszvj1zsI8f6dda9gOYt5JTlBFbLwzgxY6D1IkrwravwCTSZCuV0DU67Sh J5eQU+atHXUpEB4/Q07xcVlWJCyf/+Nkw0U/hr8gNT8MzKGKj4l9JToypQ5CpnQCtusT 6pjd2ZZd2e0bTV5P3coRno9iNu/N5vgV3ufsCIfLBwq5uRJybFT0bTPOciUE3MWIzBR/ X3gA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:date:subject:mail-followup-to:to :from:delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature:arc-authentication-results; bh=ig1DXQX2IVVPeRAK05dIi7+TLdsoqdF5+WaD5LNU64s=; b=jOMOrFRQvjOaII35NBBYwhrQ/VbylXTw2W1PwPbEBFQA8INM6J0hoj0O8YHDYNMG1M wGePJ3N2Ve+kwrHNeCyyl565/uL6dELEF9STHvoQSfEXR8T5YGlI9bRwbcj7JHJUtnjD fhXtL3N2CfkuuaVYSp4VaG2QqDNDmI2U+akJeOaj0XdwqQw4DeciOoqxu/lewvXM0vni 9jemgz0Oe2NXaIIvtEmb4oZUotLOc5/pvWNd02bD9hEEvVZxNfhTNDwz2ALugXZuMUu8 1edZ/CuLL/UjBHJlmXXWM0HtjMnqGQExKOKDd9X8tpiTVCE8aJIBAYV5V2AGSqXM4EeI c+cQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=g40Lxs6T; spf=pass (google.com: domain of gcc-patches-return-460997-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-460997-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id y188si9063448pfy.505.2017.08.28.01.22.18 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Aug 2017 01:22:18 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-460997-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=g40Lxs6T; spf=pass (google.com: domain of gcc-patches-return-460997-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-460997-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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:date:message-id:mime-version:content-type; q=dns; s= default; b=qC73EX/7LOGWuvGjOHMCcypfn45chkAhIoe8l2mqUrbm3f1naZC7Z LLVHKTyA5NwObXFOFdcYlOAJ4lRoq3OiEMtXP9nIJh3OkYNWsSL5MekF+1ryQktr JtJKL+HE96vSevbDE7wW0CDMpydaEcgnSyxkRHwr9bjF6Ezl3f9Q/E= 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:date:message-id:mime-version:content-type; s= default; bh=D8iNad2JVsrjZxx05LrWwsxNia8=; b=g40Lxs6TysuEJ2agR7QF C3OoOzAGpIVQG9dHm8e2pFJ3/URb6etNJe5tUdrwLJAS8AAaiWbADqVDqp6geGJX MQpSRp7L4LzF1ZxJyVlEeNYYEMB6GT+tmoTnZsswjK4CPIErMWT/gMQrWn9F4Woy 2OH8wbxEAs2Ex68OWko6Ov8= Received: (qmail 100029 invoked by alias); 28 Aug 2017 08:22:03 -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 99973 invoked by uid 89); 28 Aug 2017 08:21:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=irritating X-HELO: mail-wr0-f175.google.com Received: from mail-wr0-f175.google.com (HELO mail-wr0-f175.google.com) (209.85.128.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 28 Aug 2017 08:21:53 +0000 Received: by mail-wr0-f175.google.com with SMTP id y14so8166170wrd.5 for ; Mon, 28 Aug 2017 01:21:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:mail-followup-to:subject:date:message-id :user-agent:mime-version; bh=ig1DXQX2IVVPeRAK05dIi7+TLdsoqdF5+WaD5LNU64s=; b=WnpIQbgpq3yWAtIG0/Ppi8wKuy5GtGDjtZ9JCfp66mZgWHKgH/uRXvuj2al9DIY7bz fSzYvWf2qk9vawiRYH4WTSU4LFSzM46K8WDzcNZEkPb4pj05sptTcgEeLDz++Kca3Fo9 6cg3tclfa0/r8UbxbZxP2Xh79gyov1AlMEimUU95xTmV8gxZs+D/belCfkuLVeFt75vV UHd3TBX0Sc7iLKfjCjCg0V8+zZEWR3zrnqeWfmE6yJ/Httx3DJ2RPluGg/3lCrQViGUt Q1FeG8pwOQIbQj7SyS1kOBhRUMqgKLDmUsCFf4KaQ7vm4TA1fVjCPfK9sBqkvkDiXFix K/Iw== X-Gm-Message-State: AHYfb5gT1/IchWGJpOMPpHliFDWPLdxFZerfzBwQ1aVNx314iud2seVB 89ABX21fw4IO62DBF/oyNw== X-Received: by 10.223.130.45 with SMTP id 42mr3866924wrb.327.1503908511238; Mon, 28 Aug 2017 01:21:51 -0700 (PDT) Received: from localhost ([95.145.139.63]) by smtp.gmail.com with ESMTPSA id u127sm8271740wmd.15.2017.08.28.01.21.49 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 28 Aug 2017 01:21:50 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: Add subreg_memory_offset helper functions Date: Mon, 28 Aug 2017 09:21:57 +0100 Message-ID: <87shgct84a.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 This patch adds routines for converting a SUBREG_BYTE offset into a memory address offset. The two only differ for paradoxical subregs, where SUBREG_BYTE is always 0 but the memory address offset can be negative. Tested on aarch64-linux-gnu and x86_64-linux-gnu, and by checking there was no change in the testsuite assembly output for at least one target per CPU. OK to install? Richard 2017-08-28 Richard Sandiford Alan Hayward David Sherwood gcc/ * rtl.h (subreg_memory_offset): Declare. * emit-rtl.c (subreg_memory_offset): New function. * expmed.c (store_bit_field_1): Use it. * expr.c (undefined_operand_subword_p): Likewise. * simplify-rtx.c (simplify_subreg): Likewise. Index: gcc/rtl.h =================================================================== --- gcc/rtl.h 2017-08-27 23:19:56.284397205 +0100 +++ gcc/rtl.h 2017-08-28 09:19:13.737714836 +0100 @@ -2827,6 +2827,8 @@ subreg_highpart_offset (machine_mode out } extern int byte_lowpart_offset (machine_mode, machine_mode); +extern int subreg_memory_offset (machine_mode, machine_mode, unsigned int); +extern int subreg_memory_offset (const_rtx); extern rtx make_safe_from (rtx, rtx); extern rtx convert_memory_address_addr_space_1 (machine_mode, rtx, addr_space_t, bool, bool); Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c 2017-08-22 17:14:30.335896832 +0100 +++ gcc/emit-rtl.c 2017-08-28 09:19:13.736814836 +0100 @@ -1013,6 +1013,33 @@ byte_lowpart_offset (machine_mode outer_ else return subreg_lowpart_offset (outer_mode, inner_mode); } + +/* Return the offset of (subreg:OUTER_MODE (mem:INNER_MODE X) OFFSET) + from address X. For paradoxical big-endian subregs this is a + negative value, otherwise it's the same as OFFSET. */ + +int +subreg_memory_offset (machine_mode outer_mode, machine_mode inner_mode, + unsigned int offset) +{ + if (paradoxical_subreg_p (outer_mode, inner_mode)) + { + gcc_assert (offset == 0); + return -subreg_lowpart_offset (inner_mode, outer_mode); + } + return offset; +} + +/* As above, but return the offset that existing subreg X would have + if SUBREG_REG (X) were stored in memory. The only significant thing + about the current SUBREG_REG is its mode. */ + +int +subreg_memory_offset (const_rtx x) +{ + return subreg_memory_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x)); +} /* Generate a REG rtx for a new pseudo register of mode MODE. This pseudo is assigned the next sequential register number. */ Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-08-27 23:19:56.284397205 +0100 +++ gcc/expmed.c 2017-08-28 09:19:13.736814836 +0100 @@ -726,29 +726,7 @@ store_bit_field_1 (rtx str_rtx, unsigned while (GET_CODE (op0) == SUBREG) { - /* The following line once was done only if WORDS_BIG_ENDIAN, - but I think that is a mistake. WORDS_BIG_ENDIAN is - meaningful at a much higher level; when structures are copied - between memory and regs, the higher-numbered regs - always get higher addresses. */ - int inner_mode_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))); - int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0)); - int byte_offset = 0; - - /* Paradoxical subregs need special handling on big-endian machines. */ - if (paradoxical_subreg_p (op0)) - { - int difference = inner_mode_size - outer_mode_size; - - if (WORDS_BIG_ENDIAN) - byte_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - byte_offset += difference % UNITS_PER_WORD; - } - else - byte_offset = SUBREG_BYTE (op0); - - bitnum += byte_offset * BITS_PER_UNIT; + bitnum += subreg_memory_offset (op0) * BITS_PER_UNIT; op0 = SUBREG_REG (op0); } Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-08-27 23:19:56.149397206 +0100 +++ gcc/expr.c 2017-08-28 09:19:13.737714836 +0100 @@ -3524,30 +3524,12 @@ emit_move_ccmode (machine_mode mode, rtx static bool undefined_operand_subword_p (const_rtx op, int i) { - machine_mode innermode, innermostmode; - int offset; if (GET_CODE (op) != SUBREG) return false; - innermode = GET_MODE (op); - innermostmode = GET_MODE (SUBREG_REG (op)); - offset = i * UNITS_PER_WORD + SUBREG_BYTE (op); - /* The SUBREG_BYTE represents offset, as if the value were stored in - memory, except for a paradoxical subreg where we define - SUBREG_BYTE to be 0; undo this exception as in - simplify_subreg. */ - if (SUBREG_BYTE (op) == 0 - && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) - { - int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); - if (WORDS_BIG_ENDIAN) - offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - offset += difference % UNITS_PER_WORD; - } - if (offset >= GET_MODE_SIZE (innermostmode) - || offset <= -GET_MODE_SIZE (word_mode)) - return true; - return false; + machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); + HOST_WIDE_INT offset = i * UNITS_PER_WORD + subreg_memory_offset (op); + return (offset >= GET_MODE_SIZE (innermostmode) + || offset <= -UNITS_PER_WORD); } /* A subroutine of emit_move_insn_1. Generate a move from Y into X. Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c 2017-08-27 23:19:56.284397205 +0100 +++ gcc/simplify-rtx.c 2017-08-28 09:19:13.739514836 +0100 @@ -6050,34 +6050,18 @@ simplify_subreg (machine_mode outermode, if (GET_CODE (op) == SUBREG) { machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); - int final_offset = byte + SUBREG_BYTE (op); rtx newx; if (outermode == innermostmode && byte == 0 && SUBREG_BYTE (op) == 0) return SUBREG_REG (op); - /* The SUBREG_BYTE represents offset, as if the value were stored - in memory. Irritating exception is paradoxical subreg, where - we define SUBREG_BYTE to be 0. On big endian machines, this - value should be negative. For a moment, undo this exception. */ - if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) - { - int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } - if (SUBREG_BYTE (op) == 0 - && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) - { - int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } + /* Work out the memory offset of the final OUTERMODE value relative + to the inner value of OP. */ + HOST_WIDE_INT mem_offset = subreg_memory_offset (outermode, + innermode, byte); + HOST_WIDE_INT op_mem_offset = subreg_memory_offset (op); + HOST_WIDE_INT final_offset = mem_offset + op_mem_offset; /* See whether resulting subreg will be paradoxical. */ if (!paradoxical_subreg_p (outermode, innermostmode)) @@ -6092,19 +6076,12 @@ simplify_subreg (machine_mode outermode, } else { - int offset = 0; - int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode)); - - /* In paradoxical subreg, see if we are still looking on lower part. - If so, our SUBREG_BYTE will be 0. */ - if (WORDS_BIG_ENDIAN) - offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - offset += difference % UNITS_PER_WORD; - if (offset == final_offset) - final_offset = 0; - else + HOST_WIDE_INT required_offset + = subreg_memory_offset (outermode, innermostmode, 0); + if (final_offset != required_offset) return NULL_RTX; + /* Paradoxical subregs always have byte offset 0. */ + final_offset = 0; } /* Recurse for further possible simplifications. */ @@ -6145,22 +6122,9 @@ simplify_subreg (machine_mode outermode, final_regno = simplify_subreg_regno (regno, innermode, byte, outermode); if (HARD_REGISTER_NUM_P (final_regno)) { - rtx x; - int final_offset = byte; - - /* Adjust offset for paradoxical subregs. */ - if (byte == 0 - && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) - { - int difference = (GET_MODE_SIZE (innermode) - - GET_MODE_SIZE (outermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } - - x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); + rtx x = gen_rtx_REG_offset (op, outermode, final_regno, + subreg_memory_offset (outermode, + innermode, byte)); /* Propagate original regno. We don't have any way to specify the offset inside original regno, so do so only for lowpart.