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 ();
}
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 ();
}
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
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 ();
}
{
case RISCV_VXRM:
return VXRM_MODE_NONE;
+ case RISCV_FRM:
+ return FRM_MODE_NONE;
default:
gcc_unreachable ();
}
{
case RISCV_VXRM:
return VXRM_MODE_NONE;
+ case RISCV_FRM:
+ return FRM_MODE_NONE;
default:
gcc_unreachable ();
}
"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", \
/* 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 */
;; 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
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,
UNSPEC_VCOMPRESS
UNSPEC_VLEFF
UNSPEC_MODIFY_VL
+
+ UNSPEC_FSRM
])
(define_mode_iterator V [
(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
;; -----------------------------------------------------------------
[(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
;; -----------------------------------------------------------------
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { 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 } } */
--- /dev/null
+/* { 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 } } */