diff options
author | Kuan-Lin Chen <rufus@andestech.com> | 2023-12-20 15:18:59 +0800 |
---|---|---|
committer | Kito Cheng <kito.cheng@sifive.com> | 2024-01-04 21:41:30 +0800 |
commit | 057dc349021660c40699fb5c98fd9cac8e168653 (patch) | |
tree | 5e108e6ad0217d4abbbf9214b5b5613a884c5e86 | |
parent | 3ac58063114cf491891072be6205d32a42c6707d (diff) | |
download | gcc-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.cc | 31 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.md | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/_Float16-nanboxing.c | 36 |
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 } } */ + |