diff options
author | Juzhe-Zhong <juzhe.zhong@rivai.ai> | 2023-05-17 17:58:18 +0800 |
---|---|---|
committer | Pan Li <pan2.li@intel.com> | 2023-05-17 23:16:37 +0800 |
commit | e682d300261c0f2c8a5cc51151adabfe98e1006c (patch) | |
tree | 5fbb75c67fd45ca1cffe220beabf5c8b8759e34d /gcc/config/riscv/riscv.cc | |
parent | 24bd7168112f96e363cacaf593b3ac0c38c238f9 (diff) | |
download | gcc-e682d300261c0f2c8a5cc51151adabfe98e1006c.tar.gz |
RISC-V: Add mode switching target hook to insert rounding mode config for fixed-point instructions
Hi, this patch support the new coming fixed-point intrinsics:
https://github.com/riscv-non-isa/rvv-intrinsic-doc/pull/222
Insert fixed-point rounding mode configuration by mode switching target hook.
Mode switching target hook is implemented applying LCM (Lazy code Motion).
So the performance && correctness can be well trusted.
Here is the example:
void f (void * in, void *out, int32_t x, int n, int m)
{
for (int i = 0; i < n; i++) {
vint32m1_t v = __riscv_vle32_v_i32m1 (in + i, 4);
vint32m1_t v2 = __riscv_vle32_v_i32m1_tu (v, in + 100 + i, 4);
vint32m1_t v3 = __riscv_vaadd_vx_i32m1 (v2, 0, VXRM_RDN, 4);
v3 = __riscv_vaadd_vx_i32m1 (v3, 3, VXRM_RDN, 4);
__riscv_vse32_v_i32m1 (out + 100 + i, v3, 4);
}
for (int i = 0; i < n; i++) {
vint32m1_t v = __riscv_vle32_v_i32m1 (in + i + 1000, 4);
vint32m1_t v2 = __riscv_vle32_v_i32m1_tu (v, in + 100 + i + 1000, 4);
vint32m1_t v3 = __riscv_vaadd_vx_i32m1 (v2, 0, VXRM_RDN, 4);
v3 = __riscv_vaadd_vx_i32m1 (v3, 3, VXRM_RDN, 4);
__riscv_vse32_v_i32m1 (out + 100 + i + 1000, v3, 4);
}
}
ASM:
...
csrwi vxrm,2
vsetivli zero,4,e32,m1,tu,ma
...
Loop 1
...
Loop 2
mode switching can global recognize both Loop 1 and Loop 2 are using RDN
rounding mode and hoist such single "csrwi vxrm,2" to dominate both Loop 1
and Loop 2.
Besides, I have add correctness check sanity tests in this patch too.
Ok for trunk ?
gcc/ChangeLog:
* config/riscv/riscv-opts.h (enum riscv_entity): New enum.
* config/riscv/riscv.cc (riscv_emit_mode_set): New function.
(riscv_mode_needed): Ditto.
(riscv_mode_after): Ditto.
(riscv_mode_entry): Ditto.
(riscv_mode_exit): Ditto.
(riscv_mode_priority): Ditto.
(TARGET_MODE_EMIT): New target hook.
(TARGET_MODE_NEEDED): Ditto.
(TARGET_MODE_AFTER): Ditto.
(TARGET_MODE_ENTRY): Ditto.
(TARGET_MODE_EXIT): Ditto.
(TARGET_MODE_PRIORITY): Ditto.
* config/riscv/riscv.h (OPTIMIZE_MODE_SWITCHING): Ditto.
(NUM_MODES_FOR_MODE_SWITCHING): Ditto.
* config/riscv/riscv.md: Add csrwvxrm.
* config/riscv/vector.md (rnu,rne,rdn,rod,none): New attribute.
(vxrmsi): New pattern.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/base/vxrm-10.c: New test.
* gcc.target/riscv/rvv/base/vxrm-6.c: New test.
* gcc.target/riscv/rvv/base/vxrm-7.c: New test.
* gcc.target/riscv/rvv/base/vxrm-8.c: New test.
* gcc.target/riscv/rvv/base/vxrm-9.c: New test.
Diffstat (limited to 'gcc/config/riscv/riscv.cc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index de5b87b1a87..0d1b83f4315 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -7513,6 +7513,95 @@ riscv_vectorize_preferred_vector_alignment (const_tree type) return TYPE_ALIGN (type); } +/* Implement Mode switching. */ + +static void +riscv_emit_mode_set (int entity, int mode, int prev_mode, + HARD_REG_SET regs_live ATTRIBUTE_UNUSED) +{ + switch (entity) + { + case RISCV_VXRM: + if (mode != VXRM_MODE_NONE && mode != prev_mode) + emit_insn (gen_vxrmsi (gen_int_mode (mode, SImode))); + break; + default: + gcc_unreachable (); + } +} + +/* Return mode that entity must be switched into + prior to the execution of insn. */ + +static int +riscv_mode_needed (int entity, rtx_insn *insn) +{ + switch (entity) + { + case RISCV_VXRM: + return recog_memoized (insn) >= 0 ? get_attr_vxrm_mode (insn) + : VXRM_MODE_NONE; + default: + gcc_unreachable (); + } +} + +/* Return the mode that an insn results in. */ + +static int +riscv_mode_after (int entity, int mode, rtx_insn *insn) +{ + switch (entity) + { + case RISCV_VXRM: + 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; + default: + gcc_unreachable (); + } +} + +/* Return a mode that ENTITY is assumed to be + switched to at function entry. */ + +static int +riscv_mode_entry (int entity) +{ + switch (entity) + { + case RISCV_VXRM: + return VXRM_MODE_NONE; + default: + gcc_unreachable (); + } +} + +/* Return a mode that ENTITY is assumed to be + switched to at function exit. */ + +static int +riscv_mode_exit (int entity) +{ + switch (entity) + { + case RISCV_VXRM: + return VXRM_MODE_NONE; + default: + gcc_unreachable (); + } +} + +static int +riscv_mode_priority (int, int n) +{ + return n; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -7789,6 +7878,21 @@ riscv_vectorize_preferred_vector_alignment (const_tree type) #define TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT \ riscv_vectorize_preferred_vector_alignment +/* Mode switching hooks. */ + +#undef TARGET_MODE_EMIT +#define TARGET_MODE_EMIT riscv_emit_mode_set +#undef TARGET_MODE_NEEDED +#define TARGET_MODE_NEEDED riscv_mode_needed +#undef TARGET_MODE_AFTER +#define TARGET_MODE_AFTER riscv_mode_after +#undef TARGET_MODE_ENTRY +#define TARGET_MODE_ENTRY riscv_mode_entry +#undef TARGET_MODE_EXIT +#define TARGET_MODE_EXIT riscv_mode_exit +#undef TARGET_MODE_PRIORITY +#define TARGET_MODE_PRIORITY riscv_mode_priority + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" |