From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id 2D0593858D32; Thu, 6 Apr 2023 03:14:08 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D0593858D32 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1680750848; bh=4zPzjT7bME92RMaGaElzp9jcwN5jg9Vw6moq7w7uPaA=; h=From:To:Subject:Date:From; b=fJiYKkrzXaRPC9q7z7B03dt+HIl1YreKpMabvmbuEtsqcIVOkat6ef3j7Bk/w3Jqm HB5AlhHS3tTogyep7l7g1/wsnioICTIDTRju1PTKQ2oLkL+s3zDMShbioyhAL8UOwd ioVyru4ZdxhaG1+KWkRHjA2ep8gGsfnzMbt6ZLU0= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Michael Meissner To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/meissner/heads/work117)] Do not generate fmaddfp and fnmsubfp X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/work117 X-Git-Oldrev: a92e6b0c7ff0ce7e04770792204fe4af54b7c45a X-Git-Newrev: 705e878b8261bf703a24a9067d0d44d842f39846 Message-Id: <20230406031408.2D0593858D32@sourceware.org> Date: Thu, 6 Apr 2023 03:14:08 +0000 (GMT) List-Id: https://gcc.gnu.org/g:705e878b8261bf703a24a9067d0d44d842f39846 commit 705e878b8261bf703a24a9067d0d44d842f39846 Author: Michael Meissner Date: Wed Apr 5 23:13:52 2023 -0400 Do not generate fmaddfp and fnmsubfp The Altivec instructions fmaddfp and fnmsubfp have different rounding behaviors than the VSX xvmaddsp and xvnmsubsp instructions. In particular, generating these instructions seems to break Eigen. 2023-04-05 Michael Meissner gcc/ PR target/70243 * config/rs6000/altivec.md (altivec_fmav4sf4): Add a test to prevent fmaddfp and fnmsubfp from being generated on VSX systems. (altivec_vnmsubfp): Likewise. * config/rs6000/rs6000.md (vsx_fmav4sf4): Do not generate fmaddfp or fnmsubfp. (vsx_nfmsv4sf4): Likewise. gcc/testsuite/ PR target/70243 * gcc.target/powerpc/pr70243.c: New test. Diff: --- gcc/config/rs6000/altivec.md | 9 +++++-- gcc/config/rs6000/vsx.md | 29 ++++++++++----------- gcc/testsuite/gcc.target/powerpc/pr70243.c | 41 ++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 49b0c964f4d..63eab228d0d 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -750,12 +750,15 @@ ;; Fused multiply add. +;; If we are using VSX instructions, do not generate the vmaddfp instruction +;; since is has different rounding behavior than the xvmaddsp instruction. + (define_insn "*altivec_fmav4sf4" [(set (match_operand:V4SF 0 "register_operand" "=v") (fma:V4SF (match_operand:V4SF 1 "register_operand" "v") (match_operand:V4SF 2 "register_operand" "v") (match_operand:V4SF 3 "register_operand" "v")))] - "VECTOR_UNIT_ALTIVEC_P (V4SFmode)" + "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && !TARGET_VSX" "vmaddfp %0,%1,%2,%3" [(set_attr "type" "vecfloat")]) @@ -984,6 +987,8 @@ [(set_attr "type" "vecsimple")]) ;; Fused multiply subtract +;; If we are using VSX instructions, do not generate the vnmsubfp instruction +;; since is has different rounding behavior than the xvnmsubsp instruction. (define_insn "*altivec_vnmsubfp" [(set (match_operand:V4SF 0 "register_operand" "=v") (neg:V4SF @@ -991,7 +996,7 @@ (match_operand:V4SF 2 "register_operand" "v") (neg:V4SF (match_operand:V4SF 3 "register_operand" "v")))))] - "VECTOR_UNIT_ALTIVEC_P (V4SFmode)" + "VECTOR_UNIT_ALTIVEC_P (V4SFmode) && !TARGET_VSX" "vnmsubfp %0,%1,%2,%3" [(set_attr "type" "vecfloat")]) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 0865608f94a..03c1d787b6c 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -2009,22 +2009,20 @@ "xtsqrtp %0,%x1" [(set_attr "type" "")]) -;; Fused vector multiply/add instructions. Support the classical Altivec -;; versions of fma, which allows the target to be a separate register from the -;; 3 inputs. Under VSX, the target must be either the addend or the first -;; multiply. +;; Fused vector multiply/add instructions. Do not use the classical Altivec +;; versions of fma. Those instructions allows the target to be a separate +;; register from the 3 inputs, but they have different rounding behaviors. (define_insn "*vsx_fmav4sf4" - [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,v") + [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa") (fma:V4SF - (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa,v") - (match_operand:V4SF 2 "vsx_register_operand" "wa,0,v") - (match_operand:V4SF 3 "vsx_register_operand" "0,wa,v")))] + (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa") + (match_operand:V4SF 2 "vsx_register_operand" "wa,0") + (match_operand:V4SF 3 "vsx_register_operand" "0,wa")))] "VECTOR_UNIT_VSX_P (V4SFmode)" "@ xvmaddasp %x0,%x1,%x2 - xvmaddmsp %x0,%x1,%x3 - vmaddfp %0,%1,%2,%3" + xvmaddmsp %x0,%x1,%x3" [(set_attr "type" "vecfloat")]) (define_insn "*vsx_fmav2df4" @@ -2066,18 +2064,17 @@ [(set_attr "type" "")]) (define_insn "*vsx_nfmsv4sf4" - [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,v") + [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa") (neg:V4SF (fma:V4SF - (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa,v") - (match_operand:V4SF 2 "vsx_register_operand" "wa,0,v") + (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa") + (match_operand:V4SF 2 "vsx_register_operand" "wa,0") (neg:V4SF - (match_operand:V4SF 3 "vsx_register_operand" "0,wa,v")))))] + (match_operand:V4SF 3 "vsx_register_operand" "0,wa")))))] "VECTOR_UNIT_VSX_P (V4SFmode)" "@ xvnmsubasp %x0,%x1,%x2 - xvnmsubmsp %x0,%x1,%x3 - vnmsubfp %0,%1,%2,%3" + xvnmsubmsp %x0,%x1,%x3" [(set_attr "type" "vecfloat")]) (define_insn "*vsx_nfmsv2df4" diff --git a/gcc/testsuite/gcc.target/powerpc/pr70243.c b/gcc/testsuite/gcc.target/powerpc/pr70243.c new file mode 100644 index 00000000000..4ec54734f3e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr70243.c @@ -0,0 +1,41 @@ +/* { dg-do compile */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O2 -mvsx" } */ + +/* PR 70423, Make sure we don't generate fmaddfp or fnmsubfp. These + instructions have different rounding modes than the VSX instructions + xvmaddsp and xvnmsubsp. These tests are written where the 3 inputs and + target are all separate registers. Because fmaddfp and fnmsubfp are no + longer generated the compiler will have to generate an xsmadd[am]sp or + xsnmsub[am]sp instruction along with a move operation. */ + +#include + +vector float +do_add1 (vector float dummy, vector float a, vector float b, vector float c) +{ + return (a * b) + c; +} + +vector float +do_nsub1 (vector float dummy, vector float a, vector float b, vector float c) +{ + return -((a * b) - c); +} + +vector float +do_add2 (vector float dummy, vector float a, vector float b, vector float c) +{ + return vec_madd (a, b, c); +} + +vector float +do_nsub2 (vector float dummy, vector float a, vector float b, vector float c) +{ + return vec_nmsub (a, b, c); +} + +/* { dg-final { scan-assembler {\mxvmadd[am]sp\M} } } */ +/* { dg-final { scan-assembler {\mxvnmsub[am]sp\M} } } */ +/* { dg-final { scan-assembler-not {\mfmaddfp\M} } } */ +/* { dg-final { scan-assembler-not {\mfnmsubfp\M} } } */