From: Pan Li <pan2...@intel.com> This patch would like to fix one bug to align below items of spec.
RVV floating-point instructions always (implicitly) use the dynamic rounding mode. This implies that rounding is performed according to the rounding mode set in the FRM register. The FRM register itself only holds proper rounding modes and never the dynamic rounding mode. Signed-off-by: Pan Li <pan2...@intel.com> Co-Authored-By: Robin Dapp <rd...@ventanamicro.com> gcc/ChangeLog: * config/riscv/riscv.cc (riscv_emit_mode_set): Avoid emit insn when FRM_MODE_DYN. (riscv_mode_entry): Take FRM_MODE_DYN as entry mode. (riscv_mode_exit): Likewise for exit mode. (riscv_mode_needed): Likewise for needed mode. (riscv_mode_after): Likewise for after mode. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/float-point-frm-insert-6.c: New test. --- gcc/config/riscv/riscv.cc | 27 +++++++++++++--- .../riscv/rvv/base/float-point-frm-insert-6.c | 31 +++++++++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index e4dc8115e69..38d8eb2fcf5 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -7670,8 +7670,19 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode, emit_insn (gen_vxrmsi (gen_int_mode (mode, SImode))); break; case RISCV_FRM: - if (mode != FRM_MODE_NONE && mode != prev_mode) + /* Switching to the dynamic rounding mode is not necessary. When an + instruction requests it, it effectively uses the rounding mode already + set in the FRM register. All other rounding modes require us to + switch the rounding mode via the FRM register. */ + if (mode != FRM_MODE_DYN && mode != prev_mode) { + /* TODO: By design, FRM_MODE_xxx used by mode switch which is + different from the FRM value like FRM_RTZ defined in + riscv-protos.h. When mode switching we actually need a conversion + function to convert the mode of mode switching to the actual + FRM value like FRM_RTZ. For now, the value between the mode of + mode swith and the FRM value in riscv-protos.h take the same value, + and then we leverage this assumption when emit. */ rtx scaler = gen_reg_rtx (SImode); rtx imm = gen_int_mode (mode, SImode); @@ -7697,7 +7708,10 @@ riscv_mode_needed (int entity, rtx_insn *insn) case RISCV_VXRM: return code >= 0 ? get_attr_vxrm_mode (insn) : VXRM_MODE_NONE; case RISCV_FRM: - return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_NONE; + /* TODO: Here we may return FRM_MODE_NONE from get_attr_frm_mode, as well + as FRM_MODE_DYN as default. It is kind of inconsistent and we will + take care of it after dynamic rounding mode. */ + return code >= 0 ? get_attr_frm_mode (insn) : FRM_MODE_DYN; default: gcc_unreachable (); } @@ -7757,7 +7771,7 @@ riscv_mode_after (int entity, int mode, rtx_insn *insn) case RISCV_FRM: return riscv_entity_mode_after (FRM_REGNUM, insn, mode, (int (*)(rtx_insn *)) get_attr_frm_mode, - FRM_MODE_NONE); + FRM_MODE_DYN); default: gcc_unreachable (); } @@ -7774,7 +7788,10 @@ riscv_mode_entry (int entity) case RISCV_VXRM: return VXRM_MODE_NONE; case RISCV_FRM: - return FRM_MODE_NONE; + /* According to RVV 1.0 spec, all vector floating-point operations use + the dynamic rounding mode in the frm register. Likewise in other + similar places. */ + return FRM_MODE_DYN; default: gcc_unreachable (); } @@ -7791,7 +7808,7 @@ riscv_mode_exit (int entity) case RISCV_VXRM: return VXRM_MODE_NONE; case RISCV_FRM: - return FRM_MODE_NONE; + return FRM_MODE_DYN; default: gcc_unreachable (); } diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c new file mode 100644 index 00000000000..6d896e0953e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/float-point-frm-insert-6.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */ + +#include "riscv_vector.h" + +typedef float float32_t; + +vfloat32m1_t +test_riscv_vfadd_vv_f32m1_rm (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) { + return __riscv_vfadd_vv_f32m1_rm (op1, op2, 7, vl); +} + +vfloat32m1_t +test_vfadd_vv_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, vfloat32m1_t op2, + size_t vl) { + return __riscv_vfadd_vv_f32m1_m_rm(mask, op1, op2, 7, vl); +} + +vfloat32m1_t +test_vfadd_vf_f32m1_rm(vfloat32m1_t op1, float32_t op2, size_t vl) { + return __riscv_vfadd_vf_f32m1_rm(op1, op2, 7, vl); +} + +vfloat32m1_t +test_vfadd_vf_f32m1_m_rm(vbool32_t mask, vfloat32m1_t op1, float32_t op2, + size_t vl) { + return __riscv_vfadd_vf_f32m1_m_rm(mask, op1, op2, 7, vl); +} + +/* { dg-final { scan-assembler-times {vfadd\.v[vf]\s+v[0-9]+,\s*v[0-9]+,\s*[fav]+[0-9]+} 4 } } */ +/* { dg-final { scan-assembler-not {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} } } */ -- 2.34.1