From patchwork Thu Sep 5 20:34:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Wilson X-Patchwork-Id: 1158669 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-508428-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="RC4zfB78"; dkim=pass (2048-bit key; unprotected) header.d=sifive.com header.i=@sifive.com header.b="LeaSBvLO"; 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 46PXVB4KjXz9sDB for ; Fri, 6 Sep 2019 06:34:24 +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:from :to:cc:subject:date:message-id; q=dns; s=default; b=ge3azg6QYVhG FXadMMOVLd3rjUJwgnUsdY8+UWi0PHDjBIy1C0GchxQvdpcCOPch/MqsiSiLdQA3 GzkdlBQUAyjyJVcHPRuBNe3Zm92nW4YQYec03gCB8ghy5Odjs2ezSpEb4l/CG8Dv SwETr0i+bCccvZr7VZkD2cgo2fhgY/k= 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:cc:subject:date:message-id; s=default; bh=t2x6yL+SgiQzICVl/n CKdgwba68=; b=RC4zfB78V0oLZMQ9G68jTVoMLJ+jh2Di66GPrcQZUfHf8aaWMt L1Erhxw7Z25ORMMgvizhrTJTkCh4VdWT2mjIG7ci+58nOVL1Sxp1OXiyKisH/4oa 2zQ1M+fN2DB2oqn9rqPjV8NUbduhgiKNdA8EqpNRg4Z5p8Q3yR0m3mwBQ= Received: (qmail 40448 invoked by alias); 5 Sep 2019 20:34:16 -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 40438 invoked by uid 89); 5 Sep 2019 20:34:16 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=HX-Received:a65, HX-Spam-Relays-External:209.85.210.193, H*RU:209.85.210.193 X-HELO: mail-pf1-f193.google.com Received: from mail-pf1-f193.google.com (HELO mail-pf1-f193.google.com) (209.85.210.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 05 Sep 2019 20:34:14 +0000 Received: by mail-pf1-f193.google.com with SMTP id y9so2661896pfl.4 for ; Thu, 05 Sep 2019 13:34:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id; bh=qbnF4qs93qi9YfC8ugRb4qX65WHRtifRk/KRhLLA/7s=; b=LeaSBvLOuFeHzgL/2wmnupmpQtlEFiOOFdd6VYVfW9IyiPwTAGq6+eHc2yT25FUi8T HLyy3N/J5xrRypLc4Oqcgw2PCoUv9UVMJ4MCtRuWVjoX4pdSHn/44TToAGtAPsCld6Zq UY079SZJ7nLGKWXYn0SmaoWBOoYS9peaDwfxDvL1jCCN+SntLhdSXovLmbKyE247ZTaf alI/kzkv/qWWisse4eiJGb2pDVImLt691rRhb94MEl785/PFj6brSLsAeyfcNdxQQXix RL4nNkGTiRUVY4pugBOCzDRw8TorE/l3EciJynqvDMVNSn8dNEtC52Xyg275D7545lgK 9CpQ== Received: from rohan.sifive.com ([12.206.222.5]) by smtp.gmail.com with ESMTPSA id c127sm4478964pfb.5.2019.09.05.13.34.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Sep 2019 13:34:11 -0700 (PDT) From: Jim Wilson To: gcc-patches@gcc.gnu.org Cc: Jim Wilson Subject: [PATCH] RISC-V: Fix bad insn splits with paradoxical subregs. Date: Thu, 5 Sep 2019 13:34:09 -0700 Message-Id: <20190905203409.759-1-jimw@sifive.com> X-IsSubscribed: yes Shifting by more than the size of a SUBREG_REG doesn't work, so we either need to disable splits if an input is paradoxical, or else we need to generate a clean temporary for intermediate results. This was tested with rv32i/newlib and rv64gc/linux cross builds and checks. There were no regressions. The new pr91635.c testcase works with the patch and fails without it. Also, code size for libc and libstdc++ was checked and is smaller or equal sized with the patch, ignoring alignment padding. The shift-shift-4.c testcase gives better code size with this patch. The shift-shift-5.c testcase gave worse code size with a draft version of this patch and is OK with the final version of this patch. Jakub wrote the first version of this patch, so gets primary credit for it. Committed. Jim gcc/ PR target/91635 * config/riscv/riscv.md (zero_extendsidi2, zero_extendhi2, extend2): Don't split if paradoxical_subreg_p (operands[0]). (*lshrsi3_zero_extend_3+1, *lshrsi3_zero_extend_3+2): Add clobber and use as intermediate value. gcc/testsuite/ PR target/91635 * gcc.c-torture/execute/pr91635.c: New test. * gcc.target/riscv/shift-shift-4.c: New test. * gcc.target/riscv/shift-shift-5.c: New test. --- gcc/config/riscv/riscv.md | 30 +++++++--- gcc/testsuite/gcc.c-torture/execute/pr91635.c | 57 +++++++++++++++++++ .../gcc.target/riscv/shift-shift-4.c | 13 +++++ .../gcc.target/riscv/shift-shift-5.c | 16 ++++++ 4 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr91635.c create mode 100644 gcc/testsuite/gcc.target/riscv/shift-shift-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/shift-shift-5.c diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 78260fcf6fd..744a027a1b7 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1051,7 +1051,9 @@ "@ # lwu\t%0,%1" - "&& reload_completed && REG_P (operands[1])" + "&& reload_completed + && REG_P (operands[1]) + && !paradoxical_subreg_p (operands[0])" [(set (match_dup 0) (ashift:DI (match_dup 1) (const_int 32))) (set (match_dup 0) @@ -1068,7 +1070,9 @@ "@ # lhu\t%0,%1" - "&& reload_completed && REG_P (operands[1])" + "&& reload_completed + && REG_P (operands[1]) + && !paradoxical_subreg_p (operands[0])" [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -1117,7 +1121,9 @@ "@ # l\t%0,%1" - "&& reload_completed && REG_P (operands[1])" + "&& reload_completed + && REG_P (operands[1]) + && !paradoxical_subreg_p (operands[0])" [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))] { @@ -1766,15 +1772,20 @@ ;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into ;; two logical shifts. Otherwise it requires 3 instructions: lui, ;; xor/addi/srli, and. + +;; Generating a temporary for the shift output gives better combiner results; +;; and also fixes a problem where op0 could be a paradoxical reg and shifting +;; by amounts larger than the size of the SUBREG_REG doesn't work. (define_split [(set (match_operand:GPR 0 "register_operand") (and:GPR (match_operand:GPR 1 "register_operand") - (match_operand:GPR 2 "p2m1_shift_operand")))] + (match_operand:GPR 2 "p2m1_shift_operand"))) + (clobber (match_operand:GPR 3 "register_operand"))] "" - [(set (match_dup 0) + [(set (match_dup 3) (ashift:GPR (match_dup 1) (match_dup 2))) (set (match_dup 0) - (lshiftrt:GPR (match_dup 0) (match_dup 2)))] + (lshiftrt:GPR (match_dup 3) (match_dup 2)))] { /* Op2 is a VOIDmode constant, so get the mode size from op1. */ operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])) @@ -1786,12 +1797,13 @@ (define_split [(set (match_operand:DI 0 "register_operand") (and:DI (match_operand:DI 1 "register_operand") - (match_operand:DI 2 "high_mask_shift_operand")))] + (match_operand:DI 2 "high_mask_shift_operand"))) + (clobber (match_operand:DI 3 "register_operand"))] "TARGET_64BIT" - [(set (match_dup 0) + [(set (match_dup 3) (lshiftrt:DI (match_dup 1) (match_dup 2))) (set (match_dup 0) - (ashift:DI (match_dup 0) (match_dup 2)))] + (ashift:DI (match_dup 3) (match_dup 2)))] { operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2]))); }) diff --git a/gcc/testsuite/gcc.c-torture/execute/pr91635.c b/gcc/testsuite/gcc.c-torture/execute/pr91635.c new file mode 100644 index 00000000000..878a491fc36 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr91635.c @@ -0,0 +1,57 @@ +/* PR target/91635 */ + +#if __CHAR_BIT__ == 8 && __SIZEOF_SHORT__ == 2 \ + && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 +unsigned short b, c; +int u, v, w, x; + +__attribute__ ((noipa)) int +foo (unsigned short c) +{ + c <<= __builtin_add_overflow (-c, -1, &b); + c >>= 1; + return c; +} + +__attribute__ ((noipa)) int +bar (unsigned short b) +{ + b <<= -14 & 15; + b = b >> -~1; + return b; +} + +__attribute__ ((noipa)) int +baz (unsigned short e) +{ + e <<= 1; + e >>= __builtin_add_overflow (8719476735, u, &v); + return e; +} + +__attribute__ ((noipa)) int +qux (unsigned int e) +{ + c = ~1; + c *= e; + c = c >> (-15 & 5); + return c + w + x; +} +#endif + +int +main () +{ +#if __CHAR_BIT__ == 8 && __SIZEOF_SHORT__ == 2 \ + && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 + if (foo (0xffff) != 0x7fff) + __builtin_abort (); + if (bar (5) != 5) + __builtin_abort (); + if (baz (~0) != 0x7fff) + __builtin_abort (); + if (qux (2) != 0x7ffe) + __builtin_abort (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-4.c b/gcc/testsuite/gcc.target/riscv/shift-shift-4.c new file mode 100644 index 00000000000..72a45ee87ae --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32i -mabi=ilp32 -O2" } */ + +/* One zero-extend shift can be eliminated by modifying the constant in the + greater than test. Started working after modifying the splitter + lshrsi3_zero_extend_3+1 to use a temporary reg for the first split dest. */ +int +sub (int i) +{ + i &= 0x7fffffff; + return i > 0x7f800000; +} +/* { dg-final { scan-assembler-not "srli" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-5.c b/gcc/testsuite/gcc.target/riscv/shift-shift-5.c new file mode 100644 index 00000000000..5b2ae89a471 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */ + +/* Fails if lshrsi3_zero_extend_3+1 uses a temp reg which has no REG_DEST + note. */ +unsigned long +sub (long l) +{ + union u { + struct s { int a : 19; unsigned int b : 13; int x; } s; + long l; + } u; + u.l = l; + return u.s.b; +} +/* { dg-final { scan-assembler "srliw" } } */