aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKuan-Lin Chen <rufus@andestech.com>2023-12-20 15:18:59 +0800
committerKito Cheng <kito.cheng@sifive.com>2024-01-04 21:41:30 +0800
commit057dc349021660c40699fb5c98fd9cac8e168653 (patch)
tree5e108e6ad0217d4abbbf9214b5b5613a884c5e86
parent3ac58063114cf491891072be6205d32a42c6707d (diff)
downloadgcc-057dc349021660c40699fb5c98fd9cac8e168653.zip
gcc-057dc349021660c40699fb5c98fd9cac8e168653.tar.gz
gcc-057dc349021660c40699fb5c98fd9cac8e168653.tar.bz2
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. 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>
-rw-r--r--gcc/config/riscv/riscv.cc31
-rw-r--r--gcc/config/riscv/riscv.md11
-rw-r--r--gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c36
3 files changed, 78 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7b63c67..6bd2236 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -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))
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0e89138..8421243 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -86,6 +86,9 @@
;; String unspecs
UNSPEC_STRLEN
+
+ ;; Workaround for HFmode without hardware extension
+ UNSPEC_FMV_SFP16_X
])
(define_c_enum "unspecv" [
@@ -1924,6 +1927,14 @@
(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
index 0000000..c99c069
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c
@@ -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 } } */
+