public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][V2] RISC-V: Nan-box the result of movhf on soft-fp16
@ 2023-11-29  3:06 KuanLin Chen
  0 siblings, 0 replies; only message in thread
From: KuanLin Chen @ 2023-11-29  3:06 UTC (permalink / raw)
  To: gcc-patches, Kito Cheng; +Cc: Monk Chiang


[-- Attachment #1.1: Type: text/plain, Size: 513 bytes --]

According to spec, fmv.h checks if the input operands are correctly
 NaN-boxed. If not, the input value is treated as an n-bit canonical NaN.
 This patch fixs the issue that operands returned by soft-fp16 libgcc
 (i.e., __truncdfhf2) was not correctly NaN-boxed.

*gcc/ChangeLog:*

* config/riscv/riscv.cc (riscv_legitimize_move): Expand movfh

with Nan-boxing value.

* config/riscv/riscv.md (*movhf_softfloat_unspec): New pattern.


*gcc/testsuite/ChangeLog:*


gcc.target/riscv/_Float16-nanboxing.c: New test.

[-- Attachment #2: 0001-RISC-V-Nan-box-the-result-of-movhf-on-soft-fp16.patch --]
[-- Type: application/octet-stream, Size: 5680 bytes --]

From bf6afdb07dc540deb51bb36c6a3b85b5c512ec5f Mon Sep 17 00:00:00 2001
From: Kai Kai-Yi Weng <kaiweng@andestech.com>
Date: Wed, 18 Jan 2023 18:04:22 +0800
Subject: [PATCH] RISC-V: Nan-box the result of movhf on soft-fp16

According to spec, fmv.h checks if the input operands are correctly
NaN-boxed. If not, the input value is treated as an n-bit canonical NaN.
This patch fixs the issue that operands returned by soft-fp16 libgcc
(i.e., __truncdfhf2) was not correctly NaN-boxed.

co-author: Patrick (patrick@andestech.com), Rufus (rufus@andestech.com),
Monk (monk.chiang@sifive.com).
---
 gcc/config/riscv/riscv.cc                     | 72 +++++++++++++++++++
 gcc/config/riscv/riscv.md                     | 13 ++++
 .../gcc.target/riscv/_Float16-nanboxing.c     | 35 +++++++++
 3 files changed, 120 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index d0efb939bf2..2c233af6474 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2704,6 +2704,78 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
       return true;
     }
 
+  /* In order to fit NaN boxing, expand
+       (set (reg:HF dest) (mem:HF src)
+     to
+       (set (reg:HI temp) (mem:HI src)
+       (set (reg:HF dest) (subreg:HF (reg:HI temp) 0))  */
+
+  if (TARGET_HARD_FLOAT
+      && !TARGET_ZFHMIN && mode == HFmode
+      && REG_P (dest) && MEM_P (src)
+      && can_create_pseudo_p ())
+    {
+      rtx temp = gen_reg_rtx (HImode);
+      riscv_emit_set (temp, gen_rtx_MEM (HImode, XEXP(src, 0)));
+      riscv_emit_move (dest, gen_lowpart (mode, temp));
+      return true;
+    }
+
+  /* In order to fit NaN boxing, expand
+       (set (reg:HF dest) (subreg:HF (reg:HI src) 0))
+     to
+       (set (reg:SI/DI mask) (const_int -65536)
+       (set (reg:SI/DI temp) (zero_extend:SI/DI (reg:HI src)))
+       (set (reg:SI/DI temp) (ior:SI/DI (reg:SI/DI mask) (reg:SI/DI temp)))
+       (set (reg:HF dest) (unspec:HF [ (reg:SI/DI temp) ] UNSPEC_FMV_SFP16_X))
+  */
+
+  if (TARGET_HARD_FLOAT
+      && !TARGET_ZFHMIN && mode == HFmode
+      && REG_P (dest)
+      && (SUBREG_P (src)) && (GET_MODE (XEXP (src, 0)) == HImode)
+      && can_create_pseudo_p ())
+    {
+      rtx mask = force_reg (word_mode, gen_int_mode (-65536, word_mode));
+      rtx temp = gen_reg_rtx (word_mode);
+      emit_insn (gen_extend_insn (temp, XEXP (src, 0), word_mode, HImode, 1));
+      if (word_mode == SImode)
+	emit_insn (gen_iorsi3 (temp, mask, temp));
+      else
+	emit_insn (gen_iordi3 (temp, mask, temp));
+      riscv_emit_move (dest, gen_rtx_UNSPEC (HFmode, gen_rtvec (1, temp),
+					     UNSPEC_FMV_SFP16_X));
+      return true;
+    }
+
+  /* In order to fit NaN boxing, expand
+     (set (reg:HF dest) (reg:HF src))
+     to
+     (set (reg:SI/DI mask) (const_int -65536)
+     (set (reg:SI/DI temp) (zero_extend:SI/DI (subreg:HI (reg:HF src))))
+     (set (reg:SI/DI temp) (ior:SI/DI (reg:SI/DI mask) (reg:SI/DI temp)))
+     (set (reg:HF dest) (unspec:HF [ (reg:SI/DI temp) ] UNSPEC_FMV_SFP16_X))  */
+
+  if (TARGET_HARD_FLOAT
+      && !TARGET_ZFHMIN && mode == HFmode
+      && REG_P (dest) && FP_REG_P (REGNO (dest))
+      && REG_P (src)
+      && can_create_pseudo_p ())
+    {
+      rtx mask = force_reg (word_mode, gen_int_mode (-65536, word_mode));
+      rtx temp = gen_reg_rtx (word_mode);
+
+      emit_insn (gen_extend_insn (temp, gen_lowpart (HImode, src),
+				  word_mode, HImode, 1));
+      if (word_mode == SImode)
+	emit_insn (gen_iorsi3 (temp, mask, temp));
+      else
+	emit_insn (gen_iordi3 (temp, mask, temp));
+      riscv_emit_move (dest, gen_rtx_UNSPEC (HFmode, gen_rtvec (1, temp),
+					     UNSPEC_FMV_SFP16_X));
+      return true;
+    }
+
   /* We need to deal with constants that would be legitimate
      immediate_operands but aren't legitimate move_operands.  */
   if (CONSTANT_P (src) && !move_operand (src, mode))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 935eeb7fd8e..0999957779f 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -85,6 +85,9 @@
 
   ;; String unspecs
   UNSPEC_STRLEN
+
+  ;; Workaround for HFmode without hardware extension
+  UNSPEC_FMV_SFP16_X
 ])
 
 (define_c_enum "unspecv" [
@@ -1824,6 +1827,16 @@
     DONE;
 })
 
+(define_insn "*movhf_softfloat_unspec"
+  [(set (match_operand:HF 0 "register_operand" "=f,m")
+	(unspec:HF [(match_operand:X 1 "nonimmediate_operand" "r,r")] UNSPEC_FMV_SFP16_X))]
+  "TARGET_HARD_FLOAT && !TARGET_ZFH"
+  "@
+   fmv.w.x\t%0,%1
+   sh\t%1,%0"
+  [(set_attr "type" "fmove, store")
+   (set_attr "mode" "SF, HI")])
+
 (define_insn "*movhf_hardfloat"
   [(set (match_operand:HF 0 "nonimmediate_operand" "=f,   f,f,f,m,m,*f,*r,  *r,*r,*m")
 	(match_operand:HF 1 "move_operand"         " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))]
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c b/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c
new file mode 100644
index 00000000000..4ee37343fd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64ifd -mabi=lp64d -O" } */
+
+_Float16 gvar = 9.87654;
+
+union U {
+  unsigned short i16;
+  _Float16 f16;
+};
+
+_Float16 test1(unsigned short input)
+{
+  union U tmp;
+  tmp.i16 = input;
+
+  return tmp.f16;
+}
+
+_Float16 test2()
+{
+  return 1.234f;
+}
+
+_Float16 test3()
+{
+  return gvar;
+}
+
+_Float16 test()
+{
+  return 0.0f;
+}
+
+/* { dg-final { scan-assembler-times {\mli\M} 4 } } */
+/* { dg-final { scan-assembler-times {\mfmv\.w\.x\M} 4 } } */
-- 
2.30.1


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-29  3:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-29  3:06 [PATCH][V2] RISC-V: Nan-box the result of movhf on soft-fp16 KuanLin Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).