From patchwork Tue May 31 08:49:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?6ZKf5bGF5ZOy?= X-Patchwork-Id: 54550 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5B4C63955605 for ; Tue, 31 May 2022 08:56:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtpbg151.qq.com (smtpbg151.qq.com [18.169.211.239]) by sourceware.org (Postfix) with ESMTPS id E085D3836655 for ; Tue, 31 May 2022 08:50:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E085D3836655 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai X-QQ-mid: bizesmtp84t1653987039t8ppay7z Received: from server1.localdomain ( [42.247.22.65]) by bizesmtp.qq.com (ESMTP) with id ; Tue, 31 May 2022 16:50:39 +0800 (CST) X-QQ-SSF: 01400000002000B0F000000A0000000 X-QQ-FEAT: NFbnPP6/4uLanzkTxpVUzEhnpZZNtxTDNHcLGlUsCvgTu6QVZhF86QqY19OhF crDl+w0JFe6E2WSE0vRuBOurOZ0JMqFoBENcxBvoKN3utUWylRkKHlMLtZLCKkzDoF1REnT +T+dG5FGKuDaAq5LidneZjY99e3s7yiKBAdvFwdpPth+51GvjVIX/LIhE8Hg5kpYGehRSmB zMSiwbNxD24nhexYhIR1tbzm5jVzSc1eixba177I2paykAxPDH9w2C+yTFXF+O8N/LRgbAK Glf3F0msRXlAhXEH/xR/1uBIMyt3Qu6IhYPOJMEljYY2ictZEKCXDIMba+wljv5YBj2CS7w aoYOc8OxBu50vCdMeLY2zzuwodh3f9vQd5qrAgPgY4QwaQcLd4= X-QQ-GoodBg: 2 From: juzhe.zhong@rivai.ai To: gcc-patches@gcc.gnu.org Subject: [PATCH 08/21] Add poly manipulation Date: Tue, 31 May 2022 16:49:59 +0800 Message-Id: <20220531085012.269719-9-juzhe.zhong@rivai.ai> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220531085012.269719-1-juzhe.zhong@rivai.ai> References: <20220531085012.269719-1-juzhe.zhong@rivai.ai> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybgforeign:qybgforeign4 X-QQ-Bgrelay: 1 X-Spam-Status: No, score=-10.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kito.cheng@gmail.com, juzhe.zhong@rivai.ai Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: zhongjuzhe 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 %" + " 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 (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;