From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id 5B6473858D32; Thu, 6 Apr 2023 02:48:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5B6473858D32 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1680749286; bh=HhHl19S3TtTVWXXfin+GgTz19Xx9IAhxGxXfsUHchRs=; h=From:To:Subject:Date:From; b=f10cVfgbTMqd8jFImmju0gT2lMWsNPsMOE1WLV+BK9MVSSYuhKWeGDc2pJs04aQcU uP5GCnYaqZrJHEZpUucOpv1afUVozTPvAc0rT7lxggpvQx4hKCX0YhQbLHMkuLyPCt 0TAqc8CJWtHhcH7exG01ZUmyU6bgerHPrbfLkmCw= 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: 927a6371823e2be3b383415a0f072ab8a04467f5 X-Git-Newrev: e20b21164990960fb8c2afaa4811d2c9ad645794 Message-Id: <20230406024806.5B6473858D32@sourceware.org> Date: Thu, 6 Apr 2023 02:48:06 +0000 (GMT) List-Id: https://gcc.gnu.org/g:e20b21164990960fb8c2afaa4811d2c9ad645794 commit e20b21164990960fb8c2afaa4811d2c9ad645794 Author: Michael Meissner Date: Wed Apr 5 22:47:04 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..1dfc13a8864 --- /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 xsmaddsp or xsnmsubsp + instruction followed by 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 "xvmaddsp" } } */ +/* { dg-final { scan-assembler "xvnmsubsp" } } */ +/* { dg-final { scan-assembler-not "fmaddfp" } } */ +/* { dg-final { scan-assembler-not "fnmsubfp" } } */