aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/riscv/riscv-string.cc
diff options
context:
space:
mode:
authorChristoph Müllner <christoph.muellner@vrull.eu>2024-05-14 09:21:17 -0600
committerJeff Law <jlaw@ventanamicro.com>2024-05-14 09:21:17 -0600
commit54ba8d44bbd703bca6984700b4d6f978890097e2 (patch)
treef9be2e4fd02d147296241c3c5cec48899127ba43 /gcc/config/riscv/riscv-string.cc
parent21855f960141c1811d6a5f6ad3b2065f20d4b353 (diff)
downloadgcc-54ba8d44bbd703bca6984700b4d6f978890097e2.zip
gcc-54ba8d44bbd703bca6984700b4d6f978890097e2.tar.gz
gcc-54ba8d44bbd703bca6984700b4d6f978890097e2.tar.bz2
[PATCH 3/3] RISC-V: Add memset-zero expansion to cbo.zero
The Zicboz extension offers the cbo.zero instruction, which can be used to clean a memory region corresponding to a cache block. The Zic64b extension defines the cache block size to 64 byte. If both extensions are available, it is possible to use cbo.zero to clear memory, if the alignment and size constraints are met. This patch implements this. gcc/ChangeLog: * config/riscv/riscv-protos.h (riscv_expand_block_clear): New prototype. * config/riscv/riscv-string.cc (riscv_expand_block_clear_zicboz_zic64b): New function to expand a block-clear with cbo.zero. (riscv_expand_block_clear): New RISC-V block-clear expansion function. * config/riscv/riscv.md (setmem<mode>): New setmem expansion.
Diffstat (limited to 'gcc/config/riscv/riscv-string.cc')
-rw-r--r--gcc/config/riscv/riscv-string.cc59
1 files changed, 59 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv-string.cc b/gcc/config/riscv/riscv-string.cc
index 41cb061..87f5fde 100644
--- a/gcc/config/riscv/riscv-string.cc
+++ b/gcc/config/riscv/riscv-string.cc
@@ -794,6 +794,65 @@ riscv_expand_block_move (rtx dest, rtx src, rtx length)
return false;
}
+/* Expand a block-clear instruction via cbo.zero instructions. */
+
+static bool
+riscv_expand_block_clear_zicboz_zic64b (rtx dest, rtx length)
+{
+ unsigned HOST_WIDE_INT hwi_length;
+ unsigned HOST_WIDE_INT align;
+ const unsigned HOST_WIDE_INT cbo_bytes = 64;
+
+ gcc_assert (TARGET_ZICBOZ && TARGET_ZIC64B);
+
+ if (!CONST_INT_P (length))
+ return false;
+
+ hwi_length = UINTVAL (length);
+ if (hwi_length < cbo_bytes)
+ return false;
+
+ align = MEM_ALIGN (dest) / BITS_PER_UNIT;
+ if (align < cbo_bytes)
+ return false;
+
+ /* We don't emit loops. Instead apply move-bytes limitation. */
+ unsigned HOST_WIDE_INT max_bytes = RISCV_MAX_MOVE_BYTES_STRAIGHT /
+ UNITS_PER_WORD * cbo_bytes;
+ if (hwi_length > max_bytes)
+ return false;
+
+ unsigned HOST_WIDE_INT offset = 0;
+ while (offset + cbo_bytes <= hwi_length)
+ {
+ rtx mem = adjust_address (dest, BLKmode, offset);
+ rtx addr = force_reg (Pmode, XEXP (mem, 0));
+ emit_insn (gen_riscv_zero_di (addr));
+ offset += cbo_bytes;
+ }
+
+ if (offset < hwi_length)
+ {
+ rtx mem = adjust_address (dest, BLKmode, offset);
+ clear_by_pieces (mem, hwi_length - offset, align);
+ }
+
+ return true;
+}
+
+bool
+riscv_expand_block_clear (rtx dest, rtx length)
+{
+ /* Only use setmem-zero expansion for Zicboz + Zic64b. */
+ if (!TARGET_ZICBOZ || !TARGET_ZIC64B)
+ return false;
+
+ if (optimize_function_for_size_p (cfun))
+ return false;
+
+ return riscv_expand_block_clear_zicboz_zic64b (dest, length);
+}
+
/* --- Vector expanders --- */
namespace riscv_vector {