RISC-V: Support vfadd static rounding mode by mode switching
This patch would like to support the vfadd static round mode similar to the fixed-point. Then the related fsrm instructions will be inserted correlatively. Please *NOTE* this PATCH doesn't cover anything about FRM dynamic mode, it will be implemented in the underlying PATCH(s). Signed-off-by: Pan Li <pan2.li@intel.com> gcc/ChangeLog: * config/riscv/riscv.cc (riscv_emit_mode_set): Add emit for FRM. (riscv_mode_needed): Likewise. (riscv_entity_mode_after): Likewise. (riscv_mode_after): Likewise. (riscv_mode_entry): Likewise. (riscv_mode_exit): Likewise. * config/riscv/riscv.h (NUM_MODES_FOR_MODE_SWITCHING): Add number for FRM. * config/riscv/riscv.md: Add FRM register. * config/riscv/vector-iterators.md: Add FRM type. * config/riscv/vector.md (frm_mode): Define new attr for FRM mode. (fsrm): Define new insn for fsrm instruction. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/float-point-frm-insert-1.c: New test. * gcc.target/riscv/rvv/base/float-point-frm-insert-2.c: New test. * gcc.target/riscv/rvv/base/float-point-frm-insert-3.c: New test. * gcc.target/riscv/rvv/base/float-point-frm-insert-4.c: New test. * gcc.target/riscv/rvv/base/float-point-frm-insert-5.c: New test.
This commit is contained in:
parent
4d1e97f583
commit
e714af12e3
10 changed files with 206 additions and 14 deletions
|
@ -7669,6 +7669,16 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
|
|||
if (mode != VXRM_MODE_NONE && mode != prev_mode)
|
||||
emit_insn (gen_vxrmsi (gen_int_mode (mode, SImode)));
|
||||
break;
|
||||
case RISCV_FRM:
|
||||
if (mode != FRM_MODE_NONE && mode != prev_mode)
|
||||
{
|
||||
rtx scaler = gen_reg_rtx (SImode);
|
||||
rtx imm = gen_int_mode (mode, SImode);
|
||||
|
||||
emit_insn (gen_movsi (scaler, imm));
|
||||
emit_insn (gen_fsrm (scaler, scaler));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -7680,11 +7690,14 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
|
|||
static int
|
||||
riscv_mode_needed (int entity, rtx_insn *insn)
|
||||
{
|
||||
int code = recog_memoized (insn);
|
||||
|
||||
switch (entity)
|
||||
{
|
||||
case RISCV_VXRM:
|
||||
return recog_memoized (insn) >= 0 ? get_attr_vxrm_mode (insn)
|
||||
: VXRM_MODE_NONE;
|
||||
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;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -7715,6 +7728,21 @@ global_state_unknown_p (rtx_insn *insn, unsigned int regno)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
riscv_entity_mode_after (int regnum, rtx_insn *insn, int mode,
|
||||
int (*get_attr_mode) (rtx_insn *), int default_mode)
|
||||
{
|
||||
if (global_state_unknown_p (insn, regnum))
|
||||
return default_mode;
|
||||
else if (recog_memoized (insn) < 0)
|
||||
return mode;
|
||||
|
||||
rtx reg = gen_rtx_REG (SImode, regnum);
|
||||
bool mentioned_p = reg_mentioned_p (reg, PATTERN (insn));
|
||||
|
||||
return mentioned_p ? get_attr_mode (insn): mode;
|
||||
}
|
||||
|
||||
/* Return the mode that an insn results in. */
|
||||
|
||||
static int
|
||||
|
@ -7723,15 +7751,13 @@ riscv_mode_after (int entity, int mode, rtx_insn *insn)
|
|||
switch (entity)
|
||||
{
|
||||
case RISCV_VXRM:
|
||||
if (global_state_unknown_p (insn, VXRM_REGNUM))
|
||||
return VXRM_MODE_NONE;
|
||||
else if (recog_memoized (insn) >= 0)
|
||||
return reg_mentioned_p (gen_rtx_REG (SImode, VXRM_REGNUM),
|
||||
PATTERN (insn))
|
||||
? get_attr_vxrm_mode (insn)
|
||||
: mode;
|
||||
else
|
||||
return mode;
|
||||
return riscv_entity_mode_after (VXRM_REGNUM, insn, mode,
|
||||
(int (*)(rtx_insn *)) get_attr_vxrm_mode,
|
||||
VXRM_MODE_NONE);
|
||||
case RISCV_FRM:
|
||||
return riscv_entity_mode_after (FRM_REGNUM, insn, mode,
|
||||
(int (*)(rtx_insn *)) get_attr_frm_mode,
|
||||
FRM_MODE_NONE);
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -7747,6 +7773,8 @@ riscv_mode_entry (int entity)
|
|||
{
|
||||
case RISCV_VXRM:
|
||||
return VXRM_MODE_NONE;
|
||||
case RISCV_FRM:
|
||||
return FRM_MODE_NONE;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -7762,6 +7790,8 @@ riscv_mode_exit (int entity)
|
|||
{
|
||||
case RISCV_VXRM:
|
||||
return VXRM_MODE_NONE;
|
||||
case RISCV_FRM:
|
||||
return FRM_MODE_NONE;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
|
|
@ -849,7 +849,7 @@ typedef struct {
|
|||
"fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", \
|
||||
"fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", \
|
||||
"fs8", "fs9", "fs10","fs11","ft8", "ft9", "ft10","ft11", \
|
||||
"arg", "frame", "vl", "vtype", "vxrm", "N/A", "N/A", "N/A", \
|
||||
"arg", "frame", "vl", "vtype", "vxrm", "frm", "N/A", "N/A", \
|
||||
"N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
|
||||
"N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
|
||||
"N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", "N/A", \
|
||||
|
@ -1113,6 +1113,6 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
|
|||
|
||||
/* Mode switching (Lazy code motion) for RVV rounding mode instructions. */
|
||||
#define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
|
||||
#define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE}
|
||||
#define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, FRM_MODE_NONE}
|
||||
|
||||
#endif /* ! GCC_RISCV_H */
|
||||
|
|
|
@ -282,6 +282,7 @@
|
|||
;; rdvlenb vector byte length vlenb csrr read
|
||||
;; rdvl vector length vl csrr read
|
||||
;; wrvxrm vector fixed-point rounding mode write
|
||||
;; wrfrm vector floating-point rounding mode write
|
||||
;; vsetvl vector configuration-setting instrucions
|
||||
;; 7. Vector Loads and Stores
|
||||
;; vlde vector unit-stride load instructions
|
||||
|
@ -385,7 +386,8 @@
|
|||
mtc,mfc,const,arith,logical,shift,slt,imul,idiv,move,fmove,fadd,fmul,
|
||||
fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate,
|
||||
clmul,min,max,minu,maxu,clz,ctz,cpop,
|
||||
atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,vsetvl,vlde,vste,vldm,vstm,vlds,vsts,
|
||||
atomic,condmove,crypto,rdvlenb,rdvl,wrvxrm,wrfrm,vsetvl,
|
||||
vlde,vste,vldm,vstm,vlds,vsts,
|
||||
vldux,vldox,vstux,vstox,vldff,vldr,vstr,
|
||||
vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
|
||||
vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
|
||||
|
|
|
@ -81,6 +81,8 @@
|
|||
UNSPEC_VCOMPRESS
|
||||
UNSPEC_VLEFF
|
||||
UNSPEC_MODIFY_VL
|
||||
|
||||
UNSPEC_FSRM
|
||||
])
|
||||
|
||||
(define_mode_iterator V [
|
||||
|
|
|
@ -462,6 +462,38 @@
|
|||
(const_string "rod")]
|
||||
(const_string "none")))
|
||||
|
||||
;; Defines rounding mode of an floating-point operation.
|
||||
(define_attr "frm_mode" "rne,rtz,rdn,rup,rmm,dyn,none"
|
||||
(cond
|
||||
[
|
||||
(eq_attr "type" "vfalu")
|
||||
(cond
|
||||
[
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RNE")
|
||||
(const_string "rne")
|
||||
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RTZ")
|
||||
(const_string "rtz")
|
||||
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RDN")
|
||||
(const_string "rdn")
|
||||
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RUP")
|
||||
(const_string "rup")
|
||||
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RMM")
|
||||
(const_string "rmm")
|
||||
|
||||
(match_test "INTVAL (operands[9]) == riscv_vector::FRM_RDN")
|
||||
(const_string "rdn")
|
||||
]
|
||||
(const_string "none")
|
||||
)
|
||||
]
|
||||
(const_string "none")
|
||||
)
|
||||
)
|
||||
|
||||
;; -----------------------------------------------------------------
|
||||
;; ---- Miscellaneous Operations
|
||||
;; -----------------------------------------------------------------
|
||||
|
@ -538,6 +570,27 @@
|
|||
[(set_attr "type" "wrvxrm")
|
||||
(set_attr "mode" "SI")])
|
||||
|
||||
;; Set FRM
|
||||
(define_insn "fsrm"
|
||||
[
|
||||
(set
|
||||
(reg:SI FRM_REGNUM)
|
||||
(unspec:SI
|
||||
[
|
||||
(match_operand:SI 0 "register_operand" "=&r")
|
||||
(match_operand:SI 1 "register_operand" "r")
|
||||
] UNSPEC_FSRM
|
||||
)
|
||||
)
|
||||
]
|
||||
"TARGET_VECTOR"
|
||||
"fsrm\t%0,%1"
|
||||
[
|
||||
(set_attr "type" "wrfrm")
|
||||
(set_attr "mode" "SI")
|
||||
]
|
||||
)
|
||||
|
||||
;; -----------------------------------------------------------------
|
||||
;; ---- Moves Operations
|
||||
;; -----------------------------------------------------------------
|
||||
|
|
|
@ -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, 0, 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, 1, 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, 2, 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, 3, 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-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 4 } } */
|
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
|
||||
|
||||
#include "riscv_vector.h"
|
||||
|
||||
vfloat32m1_t
|
||||
test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
|
||||
vfloat32m1_t v1 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 0, vl);
|
||||
vfloat32m1_t v2 = __riscv_vfmin_vv_f32m1 (op1, v1, vl);
|
||||
return __riscv_vfadd_vv_f32m1_rm (v1, v2, 0, vl);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
|
|
@ -0,0 +1,14 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
|
||||
|
||||
#include "riscv_vector.h"
|
||||
|
||||
vfloat32m1_t
|
||||
test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl) {
|
||||
vfloat32m1_t v1 = __riscv_vfadd_vv_f32m1_rm (op1, op2, 0, vl);
|
||||
vfloat32m1_t v2 = __riscv_vfmin_vv_f32m1 (op1, v1, vl);
|
||||
return __riscv_vfadd_vv_f32m1_rm (v1, v2, 1, vl);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 2 } } */
|
||||
/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 2 } } */
|
|
@ -0,0 +1,23 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
|
||||
|
||||
#include "riscv_vector.h"
|
||||
|
||||
vfloat32m1_t
|
||||
test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
|
||||
size_t count) {
|
||||
vfloat32m1_t tmp = op1, result;
|
||||
|
||||
result = __riscv_vfadd_vv_f32m1_rm (result, op1, 1, vl);
|
||||
result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
tmp = __riscv_vfadd_vv_f32m1_rm (op1, tmp, 1, vl + i);
|
||||
result = __riscv_vfrsqrt7_v_f32m1 (tmp, vl + i);
|
||||
}
|
||||
|
||||
return __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
|
||||
/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 1 } } */
|
|
@ -0,0 +1,23 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
|
||||
|
||||
#include "riscv_vector.h"
|
||||
|
||||
vfloat32m1_t
|
||||
test_float_point_frm_insert (vfloat32m1_t op1, vfloat32m1_t op2, size_t vl,
|
||||
size_t count) {
|
||||
vfloat32m1_t tmp = op1, result;
|
||||
|
||||
result = __riscv_vfadd_vv_f32m1_rm (result, op1, 1, vl);
|
||||
result = __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
tmp = __riscv_vfadd_vv_f32m1_rm (op1, tmp, 2, vl + i);
|
||||
result = __riscv_vfrsqrt7_v_f32m1 (tmp, vl + i);
|
||||
}
|
||||
|
||||
return __riscv_vfadd_vv_f32m1_rm (result, op2, 1, vl);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times {vfadd\.vv\s+v[0-9]+,\s*v[0-9]+,\s*v+[0-9]+} 4 } } */
|
||||
/* { dg-final { scan-assembler-times {fsrm\s+[ax][0-9]+,\s*[ax][0-9]+} 3 } } */
|
Loading…
Add table
Reference in a new issue