RISC-V: Fix one bug for floating-point static frm

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.li@intel.com>
Co-Authored-By: Robin Dapp <rdapp@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.
This commit is contained in:
Pan Li 2023-07-04 22:05:36 +08:00
parent f58819c9aa
commit 55900189ab
2 changed files with 53 additions and 5 deletions

View File

@ -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 ();
}

View File

@ -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]+} } } */