From patchwork Fri Jun 29 13:32:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrill Tkachov X-Patchwork-Id: 936879 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-480753-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=foss.arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="UBeteqLz"; 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 41HHcy0rTfz9ry1 for ; Fri, 29 Jun 2018 23:32:17 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=Kym3LSpdMgHQ9ERIT8ZhWPZrKXzPvle5YUH3z5xWBfqpqW +JHlNWa5RF+6wk2BTm0wau/kiTz3i42lLkLe63n67lfVrTQ3pW2ge6WSK38FHtg2 vztctJhYtYB8cp7g5Zd8GngRARSpnbPDQCTZUEsfcMW+p3hb1Lzh02vXH/7F0= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=LA0dtxvniUAYy2GNWZ0HnLEdhD8=; b=UBeteqLzYkmLgwQzxqKV hXaUY+y7o13Z83v6dfkP0UYz9hnXPgQ235F4xwxBWr/igF2k+x1wB2SSBHXJxuSK 7uBr1wEtJmdL7Yg3vcMxh/+vTk8WL+VT5t+RDZTuId0Agef5Uy7z4zJkWNFyhEPb jh5fMLydCGYhB36yGm+P1lg= Received: (qmail 108350 invoked by alias); 29 Jun 2018 13:32:10 -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 107907 invoked by uid 89); 29 Jun 2018 13:32:10 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 spammy=fan, m0, our 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, 29 Jun 2018 13:32: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 68A4E80D for ; Fri, 29 Jun 2018 06:32:07 -0700 (PDT) Received: from [10.2.207.77] (e100706-lin.cambridge.arm.com [10.2.207.77]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 149433F318 for ; Fri, 29 Jun 2018 06:32:06 -0700 (PDT) Message-ID: <5B3634D5.6000808@foss.arm.com> Date: Fri, 29 Jun 2018 14:32:05 +0100 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org" Subject: [PATCH][arm] Avoid STRD with odd register for TARGET_ARM in output_move_double Hi all, In this testcase the user forces an odd register as the starting reg for a DFmode value. The output_move_double function tries to store that using an STRD instruction. But for TARGET_ARM the starting register of an STRD must be an even one. This is always the case with compiler-allocated registers for DFmode values, but the inline assembly forced our hand here. This patch restricts the STRD-emitting logic in output_move_double to not avoid odd-numbered source registers in STRD. I'm not a fan of the whole function, we should be exposing a lot of the logic in there to RTL rather than at the final output stage, but that would need to be fixed separately. This patch is much safer for backporting purposes. Bootstrapped and tested on arm-none-linux-gnueabihf. Committing to trunk. Thanks, Kyrill 2018-06-29 Kyrylo Tkachov * config/arm/arm.c (output_move_double): Don't allow STRD instructions if starting source register is not even. 2018-06-29 Kyrylo Tkachov * gcc.target/arm/arm-soft-strd-even.c: New test. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 0c6738cf4d669b17d063e9c5c7ab3b4f455fe8bb..8f1df45fca589c6af2f136bcba30cc1a04b0ceec 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -18455,12 +18455,18 @@ output_move_double (rtx *operands, bool emit, int *count) gcc_assert ((REGNO (operands[1]) != IP_REGNUM) || (TARGET_ARM && TARGET_LDRD)); + /* For TARGET_ARM the first source register of an STRD + must be even. This is usually the case for double-word + values but user assembly constraints can force an odd + starting register. */ + bool allow_strd = TARGET_LDRD + && !(TARGET_ARM && (REGNO (operands[1]) & 1) == 1); switch (GET_CODE (XEXP (operands[0], 0))) { case REG: if (emit) { - if (TARGET_LDRD) + if (allow_strd) output_asm_insn ("strd%?\t%1, [%m0]", operands); else output_asm_insn ("stm%?\t%m0, %M1", operands); @@ -18468,7 +18474,7 @@ output_move_double (rtx *operands, bool emit, int *count) break; case PRE_INC: - gcc_assert (TARGET_LDRD); + gcc_assert (allow_strd); if (emit) output_asm_insn ("strd%?\t%1, [%m0, #8]!", operands); break; @@ -18476,7 +18482,7 @@ output_move_double (rtx *operands, bool emit, int *count) case PRE_DEC: if (emit) { - if (TARGET_LDRD) + if (allow_strd) output_asm_insn ("strd%?\t%1, [%m0, #-8]!", operands); else output_asm_insn ("stmdb%?\t%m0!, %M1", operands); @@ -18486,7 +18492,7 @@ output_move_double (rtx *operands, bool emit, int *count) case POST_INC: if (emit) { - if (TARGET_LDRD) + if (allow_strd) output_asm_insn ("strd%?\t%1, [%m0], #8", operands); else output_asm_insn ("stm%?\t%m0!, %M1", operands); @@ -18494,7 +18500,7 @@ output_move_double (rtx *operands, bool emit, int *count) break; case POST_DEC: - gcc_assert (TARGET_LDRD); + gcc_assert (allow_strd); if (emit) output_asm_insn ("strd%?\t%1, [%m0], #-8", operands); break; @@ -18505,8 +18511,8 @@ output_move_double (rtx *operands, bool emit, int *count) otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0); otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1); - /* IWMMXT allows offsets larger than ldrd can handle, - fix these up with a pair of ldr. */ + /* IWMMXT allows offsets larger than strd can handle, + fix these up with a pair of str. */ if (!TARGET_THUMB2 && CONST_INT_P (otherops[2]) && (INTVAL(otherops[2]) <= -256 @@ -18571,7 +18577,7 @@ output_move_double (rtx *operands, bool emit, int *count) return ""; } } - if (TARGET_LDRD + if (allow_strd && (REG_P (otherops[2]) || TARGET_THUMB2 || (CONST_INT_P (otherops[2]) diff --git a/gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c b/gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c new file mode 100644 index 0000000000000000000000000000000000000000..fb7317c8718229f5a6a01a6ce2a734edb466c151 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/arm-soft-strd-even.c @@ -0,0 +1,18 @@ +/* { dg-do assemble } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-O2 -marm -mfloat-abi=soft" } */ + +/* Check that we don't try to emit STRD in ARM state with + odd starting register. */ + +struct S { + double M0; +} __attribute((aligned)) __attribute((packed)); + +void bar(void *); + +void foo(int x, struct S y) { + asm("" : : : "r1", "r8", "r7", "r4"); + y.M0 ?: bar(0); + bar(__builtin_alloca(8)); +}