From patchwork Thu Nov 11 17:51:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Andre Vieira (lists)" X-Patchwork-Id: 47495 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7044B3857404 for ; Thu, 11 Nov 2021 17:51:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7044B3857404 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636653094; bh=mnR6FbK4CUKDMZS9Q0sUFPr3j+KIlbwdVbTFtUSHTXE=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=Myxv1i7QEI29LbuH8ekfP6ayDDQg0qD/g4mCFXm/niZd5oljE4whlR0SrdWnbJ8Zp Ner8yyQT6Vef58e++Vm4V8MbEXR+FbKzr1/PRztWOP8nRxw3I2ENWIxdq8BrVTpLfK dXKzVogrNxPe+qcz92lDqbhJ1/O0sxFaReRewmMY= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id EAA413858402 for ; Thu, 11 Nov 2021 17:51:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EAA413858402 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8A57D101E; Thu, 11 Nov 2021 09:51:01 -0800 (PST) Received: from [10.57.26.224] (unknown [10.57.26.224]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id F41483F718; Thu, 11 Nov 2021 09:51:00 -0800 (PST) Message-ID: <8225375c-eb9e-f9b3-6bcd-9fbccf2fc87b@arm.com> Date: Thu, 11 Nov 2021 17:51:08 +0000 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.2.1 Content-Language: en-US To: "gcc-patches@gcc.gnu.org" Subject: [AArch64] Enable generation of FRINTNZ instructions X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, BODY_8BITS, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_LOTSOFHASH, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Andre Vieira \(lists\) via Gcc-patches" From: "Andre Vieira (lists)" Reply-To: "Andre Vieira \(lists\)" Cc: Richard Sandiford , Richard Biener Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch introduces two IFN's FTRUNC32 and FTRUNC64, the corresponding optabs and mappings. It also creates a backend pattern to implement them for aarch64 and a match.pd pattern to idiom recognize these. These IFN's (and optabs) represent a truncation towards zero, as if performed by first casting it to a signed integer of 32 or 64 bits and then back to the same floating point type/mode. The match.pd pattern choses to use these, when supported, regardless of trapping math, since these new patterns mimic the original behavior of truncating through an integer. I didn't think any of the existing IFN's represented these. I know it's a bit late in stage 1, but I thought this might be OK given it's only used by a single target and should have very little impact on anything else. Bootstrapped on aarch64-none-linux. OK for trunk? gcc/ChangeLog:         * config/aarch64/aarch64.md (ftrunc2): New pattern.         * config/aarch64/iterators.md (FRINTZ): New iterator.         * doc/md.texi: New entry for ftrunc pattern name.         * internal-fn.def (FTRUNC32): New IFN.         (FTRUNC64): Likewise.         * match.pd: Add to the existing TRUNC pattern match.         * optabs.def (OPTAB_D): New entries for ftrunc. gcc/testsuite/ChangeLog:         * gcc.target/aarch64/merge_trunc1.c: Adapted to skip if frintNz instruction available.         * lib/target-supports.exp: Added arm_v8_5a_frintnzx_ok target.         * gcc.target/aarch64/frintnz.c: New test. diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 4035e061706793849c68ae09bcb2e4b9580ab7b6..ad4e04d7c874da095513442e7d7f247791d8921d 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7345,6 +7345,16 @@ (define_insn "despeculate_simpleti" (set_attr "speculation_barrier" "true")] ) +(define_insn "ftrunc2" + [(set (match_operand:VSFDF 0 "register_operand" "=w") + (unspec:VSFDF [(match_operand:VSFDF 1 "register_operand" "w")] + FRINTNZ))] + "TARGET_FRINT && TARGET_FLOAT + && !(VECTOR_MODE_P (mode) && !TARGET_SIMD)" + "\\t%0, %1" + [(set_attr "type" "f_rint")] +) + (define_insn "aarch64_" [(set (match_operand:VSFDF 0 "register_operand" "=w") (unspec:VSFDF [(match_operand:VSFDF 1 "register_operand" "w")] diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index bdc8ba3576cf2c9b4ae96b45a382234e4e25b13f..49510488a2a800689e95c399f2e6c967b566516d 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -3067,6 +3067,8 @@ (define_int_iterator FCMLA [UNSPEC_FCMLA (define_int_iterator FRINTNZX [UNSPEC_FRINT32Z UNSPEC_FRINT32X UNSPEC_FRINT64Z UNSPEC_FRINT64X]) +(define_int_iterator FRINTNZ [UNSPEC_FRINT32Z UNSPEC_FRINT64Z]) + (define_int_iterator SVE_BRK_UNARY [UNSPEC_BRKA UNSPEC_BRKB]) (define_int_iterator SVE_BRK_BINARY [UNSPEC_BRKN UNSPEC_BRKPA UNSPEC_BRKPB]) @@ -3482,6 +3484,8 @@ (define_int_attr f16mac1 [(UNSPEC_FMLAL "a") (UNSPEC_FMLSL "s") (define_int_attr frintnzs_op [(UNSPEC_FRINT32Z "frint32z") (UNSPEC_FRINT32X "frint32x") (UNSPEC_FRINT64Z "frint64z") (UNSPEC_FRINT64X "frint64x")]) +(define_int_attr frintnz_mode [(UNSPEC_FRINT32Z "si") (UNSPEC_FRINT64Z "di")]) + ;; The condition associated with an UNSPEC_COND_. (define_int_attr cmp_op [(UNSPEC_COND_CMPEQ_WIDE "eq") (UNSPEC_COND_CMPGE_WIDE "ge") diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 41f1850bf6e95005647ca97a495a97d7e184d137..7bd66818144e87e1dca2ef13bef1d6f21f239570 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -6175,6 +6175,13 @@ operands; otherwise, it may not. This pattern is not allowed to @code{FAIL}. +@cindex @code{ftrunc@var{m}@var{n}2} instruction pattern +@item @samp{ftrunc@var{m}@var{n}2} +Truncate operand 1 to a @var{n} mode signed integer, towards zero, and store +the result in operand 0. Both operands have mode @var{m}, which is a scalar or +vector floating-point mode. + + @cindex @code{round@var{m}2} instruction pattern @item @samp{round@var{m}2} Round operand 1 to the nearest integer, rounding away from zero in the diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index bb13c6cce1bf55633760bc14980402f1f0ac1689..64263cbb83548b140f613cb4bf5ce6565373f96d 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -269,6 +269,8 @@ DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary) DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary) DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary) DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary) +DEF_INTERNAL_OPTAB_FN (FTRUNC32, ECF_CONST, ftrunc32, unary) +DEF_INTERNAL_OPTAB_FN (FTRUNC64, ECF_CONST, ftrunc64, unary) /* Binary math functions. */ DEF_INTERNAL_FLT_FN (ATAN2, ECF_CONST, atan2, binary) diff --git a/gcc/match.pd b/gcc/match.pd index a319aefa8081ac177981ad425c461f8a771128f4..7937eeb7865ce05d32dd5fdc2a90699a0e15230e 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3713,12 +3713,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) trapping behaviour, so require !flag_trapping_math. */ #if GIMPLE (simplify - (float (fix_trunc @0)) - (if (!flag_trapping_math - && types_match (type, TREE_TYPE (@0)) - && direct_internal_fn_supported_p (IFN_TRUNC, type, - OPTIMIZE_FOR_BOTH)) - (IFN_TRUNC @0))) + (float (fix_trunc@1 @0)) + (if (types_match (type, TREE_TYPE (@0))) + (if (TYPE_SIGN (TREE_TYPE (@1)) == SIGNED + && TYPE_MODE (TREE_TYPE (@1)) == SImode + && direct_internal_fn_supported_p (IFN_FTRUNC32, type, + OPTIMIZE_FOR_BOTH)) + (IFN_FTRUNC32 @0) + (if (TYPE_SIGN (TREE_TYPE (@1)) == SIGNED + && TYPE_MODE (TREE_TYPE (@1)) == DImode + && direct_internal_fn_supported_p (IFN_FTRUNC64, type, + OPTIMIZE_FOR_BOTH)) + (IFN_FTRUNC64 @0) + (if (!flag_trapping_math + && direct_internal_fn_supported_p (IFN_TRUNC, type, + OPTIMIZE_FOR_BOTH)) + (IFN_TRUNC @0)))))) #endif /* If we have a narrowing conversion to an integral type that is fed by a diff --git a/gcc/optabs.def b/gcc/optabs.def index b889ad2e5a08613db51d16d072080ac6cb48404f..740af19fcf5c53e25663038ff6c2e88cf8d7334f 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -282,6 +282,8 @@ OPTAB_D (floor_optab, "floor$a2") OPTAB_D (ceil_optab, "ceil$a2") OPTAB_D (btrunc_optab, "btrunc$a2") OPTAB_D (nearbyint_optab, "nearbyint$a2") +OPTAB_D (ftrunc32_optab, "ftrunc$asi2") +OPTAB_D (ftrunc64_optab, "ftrunc$adi2") OPTAB_D (acos_optab, "acos$a2") OPTAB_D (acosh_optab, "acosh$a2") diff --git a/gcc/testsuite/gcc.target/aarch64/frintnz.c b/gcc/testsuite/gcc.target/aarch64/frintnz.c new file mode 100644 index 0000000000000000000000000000000000000000..2e1971f8aa11d8b95f454d03a03e050a3bf96747 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/frintnz.c @@ -0,0 +1,88 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv8.5-a" } */ +/* { dg-require-effective-target arm_v8_5a_frintnzx_ok } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** f1: +** ... +** frint32z s0, s0 +** ... +*/ +float +f1 (float x) +{ + int y = x; + return (float) y; +} + +/* +** f2: +** ... +** frint64z s0, s0 +** ... +*/ +float +f2 (float x) +{ + long long int y = x; + return (float) y; +} + +/* +** f3: +** ... +** frint32z d0, d0 +** ... +*/ +double +f3 (double x) +{ + int y = x; + return (double) y; +} + +/* +** f4: +** ... +** frint64z d0, d0 +** ... +*/ +double +f4 (double x) +{ + long long int y = x; + return (double) y; +} + +float +f1_dont (float x) +{ + unsigned int y = x; + return (float) y; +} + +float +f2_dont (float x) +{ + unsigned long long int y = x; + return (float) y; +} + +double +f3_dont (double x) +{ + unsigned int y = x; + return (double) y; +} + +double +f4_dont (double x) +{ + unsigned long long int y = x; + return (double) y; +} + +/* Make sure the 'dont's don't generate any frintNz. */ +/* { dg-final { scan-assembler-times {frint32z} 2 } } */ +/* { dg-final { scan-assembler-times {frint64z} 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c index 07217064e2ba54fcf4f5edc440e6ec19ddae66e1..3b34dc3ad79f1406a41ec4c00db10347ba1ca2c4 100644 --- a/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c +++ b/gcc/testsuite/gcc.target/aarch64/merge_trunc1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -ffast-math" } */ +/* { dg-skip-if "" { arm_v8_5a_frintnzx_ok } } */ float f1 (float x) diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 8cbda192fe0fae59ea208ee43696b4d22c43e61e..0d64acb987614710d84490fce20e49db2ebf2e48 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -11365,6 +11365,33 @@ proc check_effective_target_arm_v8_3a_bkey_directive { } { }] } +# Return 1 if the target supports Armv8.5-A scalar and Advanced SIMD +# FRINT32[ZX] and FRINT64[ZX] instructions, 0 otherwise. The test is valid +# for AArch64. + +proc check_effective_target_arm_v8_5a_frintnzx_ok_nocache { } { + + if { ![istarget aarch64*-*-*] } { + return 0; + } + + if { [check_no_compiler_messages_nocache \ + arm_v8_5a_frintnzx_ok assembly { + #if !defined (__ARM_FEATURE_FRINT) + #error "__ARM_FEATURE_FRINT not defined" + #endif + } [current_compiler_flags]] } { + return 1; + } + + return 0; +} + +proc check_effective_target_arm_v8_5a_frintnzx_ok { } { + return [check_cached_effective_target arm_v8_5a_frintnzx_ok \ + check_effective_target_arm_v8_5a_frintnzx_ok_nocache] +} + # Return 1 if the target supports executing the Armv8.1-M Mainline Low # Overhead Loop, 0 otherwise. The test is valid for ARM.