From patchwork Wed Sep 16 07:40:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Greenhalgh X-Patchwork-Id: 518281 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 B69921401AF for ; Wed, 16 Sep 2015 17:41:07 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=cz0VfcbW; 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:cc:subject:date:message-id:mime-version:content-type; q=dns; s=default; b=wiIHmrwwHTDep8zDvzm4XPoauFTy5wSOWgw678eq+DBviyPcCH HBo4p/gbPyGUEbbiKy7t6oAAH1U6h7BNYBBfLSwXW/33LvChubjbuRGbBdHT6Yfw 4GL9wmHvCJU8aE+4rqODmMDmHWn8PBiAGVsLPAcZ6XIg+OyqG6se5Tc3M= 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:mime-version:content-type; s= default; bh=XLZR/ldL6Lys1wxc5nB9Er3XPAQ=; b=cz0VfcbWWDkotGTWlnI9 bQyIgKzS8FBNUPuMLSSCDrnm8974QsrAN2jsmZot0vYbyS7w2h93cs2Nl9xZxw7b 4L9ondjADzqBBiS5sqHz2/Xbx7Zokp8JnrNaHsJPjRaUr3IQnJvXUmU4r2bcLI7n 7QMvSDcGZVjzp0ghIbO7W3g= Received: (qmail 2440 invoked by alias); 16 Sep 2015 07:41:01 -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 2427 invoked by uid 89); 16 Sep 2015 07:41:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, SPF_PASS autolearn=no version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 16 Sep 2015 07:40:58 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-29-BNSNthJ0TqCMa6YUVh1X0g-1; Wed, 16 Sep 2015 08:40:53 +0100 Received: from e107456-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 16 Sep 2015 08:40:52 +0100 From: James Greenhalgh To: gcc-patches@gcc.gnu.org Cc: marcus.shawcroft@arm.com, richard.earnshaw@arm.com Subject: [AArch64] Implement copysign[ds]f3 Date: Wed, 16 Sep 2015 08:40:48 +0100 Message-Id: <1442389248-34153-1-git-send-email-james.greenhalgh@arm.com> MIME-Version: 1.0 X-MC-Unique: BNSNthJ0TqCMa6YUVh1X0g-1 X-IsSubscribed: yes Hi, This patch adds expanders for copysigndf3 and copysignsf3 to the AArch64 backend. These use the BSL/BIT/BIF insn to save us from the default expansion pattern. Bootstrapped on aarch64-none-linux-gnu with no issues, and checked the performance to show a slight improvement to FP routines using copysign or SIGN from fortran. OK? Thanks, James --- gcc/ 2015-09-16 James Greenhalgh * config/aarch64/aarch64.md (copysigndf3): New. (copysignsf3): Likewise. gcc/testsuite/ 2015-09-16 James Greenhalgh * gcc.target/aarch64/copysign_1.c: New. * gcc.target/aarch64/copysign_2.c: New. diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 88ba72e..925c6b1 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4412,6 +4412,52 @@ [(set_attr "type" "f_minmax")] ) +;; For copysign (x, y), we want to generate: +;; +;; LDR d2, #(1 << 63) +;; BSL v2.8b, [y], [x] +;; +;; or another, equivalent, sequence using one of BSL/BIT/BIF. +;; aarch64_simd_bsldf will select the best suited of these instructions +;; to generate based on register allocation, and knows how to partially +;; constant fold based on the values of X and Y, so expand through that. + +(define_expand "copysigndf3" + [(match_operand:DF 0 "register_operand") + (match_operand:DF 1 "register_operand") + (match_operand:DF 2 "register_operand")] + "TARGET_FLOAT && TARGET_SIMD" +{ + rtx mask = gen_reg_rtx (DImode); + emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 63)); + emit_insn (gen_aarch64_simd_bsldf (operands[0], mask, + operands[2], operands[1])); + DONE; +} +) + +;; As above, but we must first get to a 64-bit value if we wish to use +;; aarch64_simd_bslv2sf. + +(define_expand "copysignsf3" + [(match_operand:SF 0 "register_operand") + (match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")] + "TARGET_FLOAT && TARGET_SIMD" +{ + rtx mask = gen_reg_rtx (DImode); + + /* Juggle modes to get us in to a vector mode for BSL. */ + rtx op1 = lowpart_subreg (V2SFmode, operands[1], SFmode); + rtx op2 = lowpart_subreg (V2SFmode, operands[2], SFmode); + rtx tmp = gen_reg_rtx (V2SFmode); + emit_move_insn (mask, GEN_INT (HOST_WIDE_INT_1U << 31)); + emit_insn (gen_aarch64_simd_bslv2sf (tmp, mask, op2, op1)); + emit_move_insn (operands[0], lowpart_subreg (SFmode, tmp, V2SFmode)); + DONE; +} +) + ;; ------------------------------------------------------------------- ;; Reload support ;; ------------------------------------------------------------------- diff --git a/gcc/testsuite/gcc.target/aarch64/copysign_1.c b/gcc/testsuite/gcc.target/aarch64/copysign_1.c new file mode 100644 index 0000000..27fb9ca --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/copysign_1.c @@ -0,0 +1,81 @@ +/* { dg-do run } */ +/* { dg-options "-O2 --save-temps" } */ + +double fabs (double); + +double +check (double x, double y) +{ + return __builtin_copysign (x, y); +} + +double +check1 (double x) +{ + return __builtin_copysign (x, 1.0); +} + +double +check2 (double x) +{ + return __builtin_copysign (1.0, x); +} + +double +check3 (double x) +{ + return -__builtin_copysign (x, 1.0); +} + +double +check4 (double x, double y) +{ + return x * __builtin_copysign (x, y); +} + +double +check5 (double x, double y) +{ + return __builtin_copysign (-x, -y); +} + +int +main (int argc, char** argv) +{ + double x = 2.0; + double y = -5.0; + double epsilon = 0.00001; + + double expected = -2.0; + + if (fabs (check (x, y) - expected) >= epsilon) + __builtin_abort (); + + expected = 2.0; + + if (fabs (check1 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = 1.0; + + if (fabs (check2 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = -2.0; + + if (fabs (check3 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = -4.0; + + if (fabs (check4 (x, y) - expected) >= epsilon) + __builtin_abort (); + + expected = 2.0; + + if (fabs (check5 (x, y) - expected) >= epsilon) + __builtin_abort (); +} + +/* { dg-final { scan-assembler-not "copysign\tw" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/copysign_2.c b/gcc/testsuite/gcc.target/aarch64/copysign_2.c new file mode 100644 index 0000000..6eaa704 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/copysign_2.c @@ -0,0 +1,81 @@ +/* { dg-do run } */ +/* { dg-options "-O2 --save-temps" } */ + +float fabsf (float); + +float +check (float x, float y) +{ + return __builtin_copysignf (x, y); +} + +float +check1 (float x) +{ + return __builtin_copysignf (x, 1.0); +} + +float +check2 (float x) +{ + return __builtin_copysignf (1.0, x); +} + +float +check3 (float x) +{ + return -__builtin_copysignf (x, 1.0); +} + +float +check4 (float x, float y) +{ + return x * __builtin_copysignf (x, y); +} + +float +check5 (float x, float y) +{ + return __builtin_copysignf (-x, -y); +} + +int +main (int argc, char** argv) +{ + float x = 2.0f; + float y = -5.0f; + float epsilon = 0.00001f; + + float expected = -2.0f; + + if (fabsf (check (x, y) - expected) >= epsilon) + __builtin_abort (); + + expected = 2.0f; + + if (fabsf (check1 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = 1.0f; + + if (fabsf (check2 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = -2.0f; + + if (fabsf (check3 (x) - expected) >= epsilon) + __builtin_abort (); + + expected = -4.0f; + + if (fabsf (check4 (x, y) - expected) >= epsilon) + __builtin_abort (); + + expected = 2.0f; + + if (fabsf (check5 (x, y) - expected) >= epsilon) + __builtin_abort (); +} + +/* { dg-final { scan-assembler-not "copysign\tw" } } */ +