summaryrefslogtreecommitdiff
path: root/gcc/config/riscv/riscv.cc
diff options
context:
space:
mode:
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>2023-05-17 17:58:18 +0800
committerPan Li <pan2.li@intel.com>2023-05-17 23:16:37 +0800
commite682d300261c0f2c8a5cc51151adabfe98e1006c (patch)
tree5fbb75c67fd45ca1cffe220beabf5c8b8759e34d /gcc/config/riscv/riscv.cc
parent24bd7168112f96e363cacaf593b3ac0c38c238f9 (diff)
downloadgcc-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.cc104
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"