From: juzhe.zhong@rivai.ai
To: gcc-patches@gcc.gnu.org
Cc: kito.cheng@gmail.com, palmer@dabbelt.com, juzhe.zhong@rivai.ai
Subject: [PATCH 08/21] Add poly manipulation
Date: Tue, 31 May 2022 16:49:59 +0800 [thread overview]
Message-ID: <20220531085012.269719-9-juzhe.zhong@rivai.ai> (raw)
In-Reply-To: <20220531085012.269719-1-juzhe.zhong@rivai.ai>
From: zhongjuzhe <juzhe.zhong@rivai.ai>
gcc/ChangeLog:
* config/riscv/riscv-protos.h (riscv_add_offset): Change riscv_add_offset as global function.
* config/riscv/riscv-vector.cc (rvv_report_required): New function.
(expand_quotient): New function.
(rvv_expand_poly_move): New function.
* config/riscv/riscv-vector.h (rvv_report_required): New function.
(rvv_expand_poly_move): New function.
* config/riscv/riscv.cc (riscv_const_insns): Fix no return value bug.
(riscv_split_symbol): Add symbol_ref with poly_int support.
(riscv_legitimize_const_move): Add const poly_int move support.
(riscv_legitimize_move): Add const poly_int move support.
(riscv_hard_regno_mode_ok): Add VL_REGNUM and VTYPE_REGNUM register allocation.
(riscv_conditional_register_usage): Fix RVV registers.
---
gcc/config/riscv/riscv-protos.h | 1 +
gcc/config/riscv/riscv-vector.cc | 254 +++++++++++++++++++++++++++++++
gcc/config/riscv/riscv-vector.h | 2 +
gcc/config/riscv/riscv.cc | 46 +++++-
4 files changed, 299 insertions(+), 4 deletions(-)
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 618eb746eaa..2d63fe76930 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -74,6 +74,7 @@ extern bool riscv_expand_block_move (rtx, rtx, rtx);
extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *);
extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *);
extern bool riscv_gpr_save_operation_p (rtx);
+extern rtx riscv_add_offset (rtx, rtx, HOST_WIDE_INT);
/* Routines implemented in riscv-c.cc. */
void riscv_cpu_cpp_builtins (cpp_reader *);
diff --git a/gcc/config/riscv/riscv-vector.cc b/gcc/config/riscv/riscv-vector.cc
index 4b2fe2a8d11..d09fc1b8e49 100644
--- a/gcc/config/riscv/riscv-vector.cc
+++ b/gcc/config/riscv/riscv-vector.cc
@@ -592,6 +592,260 @@ rvv_const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
IN_RANGE (INTVAL (elt), minval, maxval));
}
+/* Report when we try to do something that requires vector when vector is disabled.
+ This is an error of last resort and isn't very high-quality. It usually
+ involves attempts to measure the vector length in some way. */
+void
+rvv_report_required (void)
+{
+ static bool reported_p = false;
+
+ /* Avoid reporting a slew of messages for a single oversight. */
+ if (reported_p)
+ return;
+
+ error ("this operation requires the RVV ISA extension");
+ inform (input_location, "you can enable RVV using the command-line"
+ " option %<-march%>, or by using the %<target%>"
+ " attribute or pragma");
+ reported_p = true;
+}
+
+/* Note: clobber register holds the vlenb or 1/2 vlenb or 1/4 vlenb or 1/8 vlenb value. */
+/* Expand move for quotient. */
+static void
+expand_quotient (int quotient, machine_mode mode, rtx clobber_vlenb, rtx dest)
+{
+ if (quotient == 0)
+ {
+ riscv_emit_move(dest, GEN_INT(0));
+ return;
+ }
+
+ bool is_neg = quotient < 0;
+ quotient = abs(quotient);
+ int log2 = exact_log2 (quotient);
+ int vlenb = BYTES_PER_RISCV_VECTOR.coeffs[1];
+
+ if (GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ emit_insn (gen_rtx_SET (clobber_vlenb, gen_int_mode (poly_int64 (vlenb, vlenb), mode)));
+ else
+ {
+ riscv_emit_move (gen_highpart (Pmode, clobber_vlenb), GEN_INT (0));
+ emit_insn (gen_rtx_SET (gen_lowpart (Pmode, clobber_vlenb), gen_int_mode (poly_int64 (vlenb, vlenb), Pmode)));
+ }
+
+ if (log2 == 0)
+ {
+ if (is_neg)
+ {
+ if (GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ emit_insn (gen_rtx_SET (dest, gen_rtx_NEG (mode, clobber_vlenb)));
+ else
+ {
+ /* We should use SImode to simulate DImode negation. */
+ /* prologue and epilogue can not go through this condition. */
+ gcc_assert (can_create_pseudo_p ());
+ rtx reg = gen_reg_rtx (Pmode);
+ riscv_emit_move(dest, clobber_vlenb);
+ emit_insn (gen_rtx_SET (reg,
+ gen_rtx_NE (Pmode, gen_lowpart (Pmode, dest), const0_rtx)));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_NEG (Pmode, gen_highpart (Pmode, dest))));
+ emit_insn (gen_rtx_SET (gen_lowpart (Pmode, dest),
+ gen_rtx_NEG (Pmode, gen_lowpart (Pmode, dest))));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_MINUS (Pmode, gen_highpart (Pmode, dest), reg)));
+ }
+ }
+ else
+ riscv_emit_move(dest, clobber_vlenb);
+ }
+ else if (log2 != -1
+ && GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ {
+ gcc_assert (IN_RANGE (log2, 0, 31));
+
+ if (is_neg)
+ {
+ emit_insn (gen_rtx_SET (dest, gen_rtx_NEG (mode, clobber_vlenb)));
+ emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, dest, GEN_INT (log2))));
+ }
+ else
+ emit_insn (gen_rtx_SET (dest, gen_rtx_ASHIFT (mode, clobber_vlenb, GEN_INT (log2))));
+ }
+ else if (exact_log2 (quotient + 1) != -1
+ && GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ {
+ gcc_assert (IN_RANGE (exact_log2 (quotient + 1), 0, 31));
+ emit_insn (gen_rtx_SET (
+ dest,
+ gen_rtx_ASHIFT (mode, clobber_vlenb, GEN_INT (exact_log2 (quotient + 1)))));
+
+ if (is_neg)
+ emit_insn (gen_rtx_SET (dest, gen_rtx_MINUS (mode, clobber_vlenb, dest)));
+ else
+ emit_insn (gen_rtx_SET (dest, gen_rtx_MINUS (mode, dest, clobber_vlenb)));
+ }
+ else if (exact_log2 (quotient - 1) != -1
+ && GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ {
+ gcc_assert (IN_RANGE (exact_log2 (quotient - 1), 0, 31));
+ emit_insn (gen_rtx_SET (
+ dest, gen_rtx_ASHIFT (mode, clobber_vlenb,
+ GEN_INT (exact_log2 (quotient - 1)))));
+
+ if (is_neg)
+ {
+ emit_insn (gen_rtx_SET (dest, gen_rtx_NEG (mode, dest)));
+ emit_insn (gen_rtx_SET (dest, gen_rtx_MINUS (mode, dest, clobber_vlenb)));
+ }
+ else
+ emit_insn (gen_rtx_SET (dest, gen_rtx_PLUS (mode, dest, clobber_vlenb)));
+ }
+ else
+ {
+ gcc_assert (TARGET_MUL
+ && "M-extension must be enabled to calculate the poly_int "
+ "size/offset.");
+
+ if (is_neg)
+ riscv_emit_move (dest, GEN_INT (-quotient));
+ else
+ riscv_emit_move (dest, GEN_INT (quotient));
+
+ if (GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ emit_insn (gen_rtx_SET (dest, gen_rtx_MULT (mode, dest, clobber_vlenb)));
+ else
+ {
+ /* We should use SImode to simulate DImode multiplication. */
+ /* prologue and epilogue can not go through this condition. */
+ gcc_assert (can_create_pseudo_p ());
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_umulsi3_highpart (reg, gen_lowpart (Pmode, dest),
+ gen_lowpart (Pmode, clobber_vlenb)));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, clobber_vlenb),
+ gen_rtx_MULT (Pmode, gen_highpart (Pmode, clobber_vlenb),
+ gen_lowpart (Pmode, dest))));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_MULT (Pmode, gen_highpart (Pmode, dest),
+ gen_lowpart (Pmode, clobber_vlenb))));
+ emit_insn (gen_rtx_SET (gen_lowpart (Pmode, dest),
+ gen_rtx_MULT (Pmode, gen_lowpart (Pmode, dest),
+ gen_lowpart (Pmode, clobber_vlenb))));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_PLUS (Pmode, gen_highpart (Pmode, dest),
+ gen_highpart (Pmode, clobber_vlenb))));
+ emit_insn (gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_PLUS (Pmode, gen_highpart (Pmode, dest), reg)));
+ }
+ }
+}
+
+/* Analyze src and emit const_poly_int mov sequence. */
+
+void
+rvv_expand_poly_move (machine_mode mode, rtx dest, rtx clobber, rtx src)
+{
+ poly_int64 value = rtx_to_poly_int64 (src);
+ int offset = value.coeffs[0];
+ int factor = value.coeffs[1];
+ int vlenb = BYTES_PER_RISCV_VECTOR.coeffs[1];
+ int div_factor = 0;
+
+ if (BYTES_PER_RISCV_VECTOR.is_constant ())
+ {
+ gcc_assert (value.is_constant ());
+ riscv_emit_move (dest, GEN_INT (value.to_constant ()));
+ return;
+ }
+ else if ((factor % vlenb) == 0)
+ expand_quotient (factor / vlenb, mode, clobber, dest);
+ else if ((factor % (vlenb / 2)) == 0)
+ {
+ expand_quotient (factor / (vlenb / 2), mode, clobber, dest);
+ div_factor = 2;
+ }
+ else if ((factor % (vlenb / 4)) == 0)
+ {
+ expand_quotient (factor / (vlenb / 4), mode, clobber, dest);
+ div_factor = 4;
+ }
+ else if ((factor % (vlenb / 8)) == 0)
+ {
+ expand_quotient (factor / (vlenb / 8), mode, clobber, dest);
+ div_factor = 8;
+ }
+ else if ((factor % (vlenb / 16)) == 0)
+ {
+ expand_quotient (factor / (vlenb / 16), mode, clobber, dest);
+ div_factor = 16;
+ }
+ else
+ gcc_unreachable ();
+
+ if (div_factor != 0)
+ {
+ if (GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ emit_insn (gen_rtx_SET (
+ dest,
+ gen_rtx_ASHIFTRT (mode, dest, GEN_INT (exact_log2 (div_factor)))));
+ else
+ {
+ /* We should use SImode to simulate DImode shift. */
+ /* prologue and epilogue can not go through this condition. */
+ gcc_assert (can_create_pseudo_p ());
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (
+ reg, gen_rtx_ASHIFT (Pmode, gen_highpart (Pmode, dest),
+ GEN_INT (GET_MODE_BITSIZE (Pmode) -
+ exact_log2 (div_factor)))));
+ emit_insn (gen_rtx_SET (
+ gen_lowpart (Pmode, dest),
+ gen_rtx_LSHIFTRT (Pmode, gen_lowpart (Pmode, dest),
+ GEN_INT (exact_log2 (div_factor)))));
+ emit_insn (gen_rtx_SET (
+ gen_lowpart (Pmode, dest),
+ gen_rtx_IOR (Pmode, reg, gen_lowpart (Pmode, dest))));
+ emit_insn (gen_rtx_SET (
+ gen_highpart (Pmode, dest),
+ gen_rtx_ASHIFTRT (Pmode, gen_highpart (Pmode, dest),
+ GEN_INT (exact_log2 (div_factor)))));
+ }
+ }
+
+ HOST_WIDE_INT constant = offset - factor;
+
+ if (constant == 0)
+ return;
+ else if (SMALL_OPERAND (constant))
+ {
+ if (GET_MODE_SIZE (mode).to_constant () <= GET_MODE_SIZE (Pmode))
+ emit_insn (
+ gen_rtx_SET (dest, gen_rtx_PLUS (mode, dest, GEN_INT (constant))));
+ else
+ {
+ /* We should use SImode to simulate DImode addition. */
+ /* prologue and epilogue can not go through this condition. */
+ gcc_assert (can_create_pseudo_p ());
+ rtx reg = gen_reg_rtx (Pmode);
+ emit_insn (
+ gen_rtx_SET (reg, gen_rtx_PLUS (Pmode, gen_lowpart (Pmode, dest),
+ GEN_INT (constant))));
+ emit_insn (gen_rtx_SET (
+ gen_lowpart (Pmode, dest),
+ gen_rtx_LTU (Pmode, reg, gen_lowpart (Pmode, dest))));
+ emit_insn (
+ gen_rtx_SET (gen_highpart (Pmode, dest),
+ gen_rtx_PLUS (Pmode, gen_lowpart (Pmode, dest),
+ gen_highpart (Pmode, dest))));
+ riscv_emit_move (gen_lowpart (Pmode, dest), reg);
+ }
+ }
+ else
+ emit_insn (gen_rtx_SET (dest, riscv_add_offset (clobber, dest, constant)));
+}
+
/* Helper functions for handling sew=64 on RV32 system. */
bool
imm32_p (rtx a)
diff --git a/gcc/config/riscv/riscv-vector.h b/gcc/config/riscv/riscv-vector.h
index e93852e3e56..b70cf676e26 100644
--- a/gcc/config/riscv/riscv-vector.h
+++ b/gcc/config/riscv/riscv-vector.h
@@ -20,4 +20,6 @@
#ifndef GCC_RISCV_VECTOR_H
#define GCC_RISCV_VECTOR_H
+void rvv_report_required (void);
+void rvv_expand_poly_move (machine_mode, rtx, rtx, rtx);
#endif // GCC_RISCV_VECTOR_H
\ No newline at end of file
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index fc27dc957dc..7a1f19b32ee 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1164,6 +1164,7 @@ riscv_const_insns (rtx x)
factor = 1 + riscv_integer_cost (INTVAL (elt));
}
}
+ return factor;
}
case CONST:
@@ -1467,7 +1468,7 @@ riscv_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out,
riscv_force_temporary; it is only needed when OFFSET is not a
SMALL_OPERAND. */
-static rtx
+rtx
riscv_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
{
if (!SMALL_OPERAND (offset))
@@ -1723,7 +1724,20 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
riscv_emit_move (dest, riscv_add_offset (NULL, base, INTVAL (offset)));
return;
}
-
+
+ /* Handle (const:SI (plus:SI (symbol_ref:SI)
+ (const_poly_int:SI [16, 16]))) */
+ if (GET_CODE (src) == CONST && GET_CODE (XEXP (src, 0)) == PLUS
+ && CONST_POLY_INT_P (XEXP (XEXP (src, 0), 1)))
+ {
+ rtx reg = gen_reg_rtx (mode);
+ rtx clobber = gen_reg_rtx (mode);
+ riscv_emit_move (dest, XEXP (XEXP (src, 0), 0));
+ rvv_expand_poly_move (mode, reg, clobber, XEXP (XEXP (src, 0), 1));
+ emit_insn (gen_rtx_SET (dest, gen_rtx_PLUS (mode, dest, reg)));
+ return;
+ }
+
src = force_const_mem (mode, src);
/* When using explicit relocs, constant pool references are sometimes
@@ -1738,6 +1752,28 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
bool
riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
{
+ scalar_int_mode int_mode;
+ if (CONST_POLY_INT_P (src)
+ && is_a <scalar_int_mode> (mode, &int_mode))
+ {
+ poly_int64 value = rtx_to_poly_int64 (src);
+ if (!value.is_constant () && !TARGET_VECTOR)
+ {
+ rvv_report_required ();
+ return true;
+ }
+ if (GET_MODE_SIZE (mode).to_constant () < GET_MODE_SIZE (Pmode))
+ {
+ rtx clobber = gen_reg_rtx (Pmode);
+ rvv_expand_poly_move (Pmode, gen_lowpart (Pmode, dest), clobber, src);
+ }
+ else
+ {
+ rtx clobber = gen_reg_rtx (mode);
+ rvv_expand_poly_move (mode, dest, clobber, src);
+ }
+ return true;
+ }
/* Expand
(set (reg:QI target) (mem:QI (address)))
to
@@ -4998,7 +5034,9 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (regsize != 1)
return ((regno % regsize) == 0);
- }
+ }
+ else if (regno == VTYPE_REGNUM || regno == VL_REGNUM)
+ return (nregs == 1 && mode == SImode);
else
return false;
@@ -5388,7 +5426,7 @@ riscv_conditional_register_usage (void)
if (!TARGET_VECTOR)
{
for (int regno = V_REG_FIRST; regno <= V_REG_LAST; regno++)
- call_used_regs[regno] = 1;
+ fixed_regs[regno] = call_used_regs[regno] = 1;
fixed_regs[VTYPE_REGNUM] = call_used_regs[VTYPE_REGNUM] = 1;
fixed_regs[VL_REGNUM] = call_used_regs[VL_REGNUM] = 1;
--
2.36.1
next prev parent reply other threads:[~2022-05-31 8:50 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-31 8:49 [PATCH 00/21] *** Add RVV (RISC-V 'V' Extension) support *** juzhe.zhong
2022-05-31 8:49 ` [PATCH 01/21] Add RVV modes and support scalable vector juzhe.zhong
2022-05-31 8:49 ` [PATCH 02/21] Add RVV intrinsic framework juzhe.zhong
2022-05-31 8:49 ` [PATCH 03/21] Add RVV datatypes juzhe.zhong
2022-05-31 8:49 ` [PATCH 04/21] Add RVV intrinsic enable #pragma riscv intrinsic "vector" and introduce RVV header "riscv_vector.h" juzhe.zhong
2022-05-31 8:49 ` [PATCH 05/21] Add RVV configuration intrinsic juzhe.zhong
2022-05-31 8:49 ` [PATCH 06/21] Add insert-vsetvl pass juzhe.zhong
2022-05-31 8:49 ` [PATCH 07/21] Add register spilling support juzhe.zhong
2022-05-31 8:49 ` juzhe.zhong [this message]
2022-05-31 8:50 ` [PATCH 09/21] Add misc function intrinsic support juzhe.zhong
2022-05-31 8:50 ` [PATCH 11/21] Add calling function support juzhe.zhong
2022-05-31 8:50 ` [PATCH 12/21] Add set get intrinsic support juzhe.zhong
2022-05-31 8:50 ` [PATCH 13/21] Adjust scalable frame and full testcases juzhe.zhong
2022-05-31 8:50 ` [PATCH 15/21] Add integer intrinsics juzhe.zhong
2022-05-31 8:50 ` [PATCH 18/21] Add rest intrinsic support juzhe.zhong
2022-05-31 16:51 ` [PATCH 00/21] *** Add RVV (RISC-V 'V' Extension) support *** Palmer Dabbelt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220531085012.269719-9-juzhe.zhong@rivai.ai \
--to=juzhe.zhong@rivai.ai \
--cc=gcc-patches@gcc.gnu.org \
--cc=kito.cheng@gmail.com \
--cc=palmer@dabbelt.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).