]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Nan-box the result of movhf on soft-fp16
authorKuan-Lin Chen <rufus@andestech.com>
Wed, 20 Dec 2023 07:18:59 +0000 (15:18 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Thu, 4 Jan 2024 13:41:30 +0000 (21:41 +0800)
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.

Co-authored-by: Patrick Lin <patrick@andestech.com>
Co-authored-by: Rufus Chen <rufus@andestech.com>
Co-authored-by: Monk Chiang <monk.chiang@sifive.com>
gcc/config/riscv/riscv.cc
gcc/config/riscv/riscv.md
gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c [new file with mode: 0644]

index 7b63c67d06e6cb374519d9dbade6e94853d07bd7..6bd22369a5e067f3e1b6bb5f14b03e3ba636fc50 100644 (file)
@@ -2807,6 +2807,37 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
       return true;
     }
 
+  /* In order to fit NaN boxing, expand
+     (set FP_REG (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) 0)))
+     (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) && !FP_REG_P (REGNO (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,
+                                simplify_gen_subreg (HImode, src, mode, 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;
+   }
+
   /* 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))
index 0e891382bccc14a0eee64ecdd3db3cd660682f54..84212430dc06731fc394b7d94eb914876a23a02f 100644 (file)
@@ -86,6 +86,9 @@
 
   ;; String unspecs
   UNSPEC_STRLEN
+
+  ;; Workaround for HFmode without hardware extension
+  UNSPEC_FMV_SFP16_X
 ])
 
 (define_c_enum "unspecv" [
    (set_attr "type" "fmove")
    (set_attr "mode" "HF")])
 
+(define_insn "*movhf_softfloat_boxing"
+  [(set (match_operand:HF 0 "register_operand"            "=f")
+        (unspec:HF [(match_operand:X 1 "register_operand" " r")] UNSPEC_FMV_SFP16_X))]
+  "!TARGET_ZFHMIN"
+  "fmv.w.x\t%0,%1"
+  [(set_attr "type" "fmove")
+   (set_attr "mode" "SF")])
+
 ;;
 ;;  ....................
 ;;
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c b/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c
new file mode 100644 (file)
index 0000000..c99c069
--- /dev/null
@@ -0,0 +1,36 @@
+/* { 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 "li\[ \t\]" 4 } } */
+/* { dg-final { scan-assembler-times "fmv\.w\.x\[ \t\]" 4 } } */
+