aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/riscv')
-rw-r--r--gcc/config/riscv/bitmanip.md56
-rw-r--r--gcc/config/riscv/gnu.h59
-rw-r--r--gcc/config/riscv/riscv-cores.def48
-rw-r--r--gcc/config/riscv/riscv-target-attr.cc6
-rw-r--r--gcc/config/riscv/riscv-vsetvl.cc19
-rw-r--r--gcc/config/riscv/riscv.cc5
-rw-r--r--gcc/config/riscv/riscv.h2
-rw-r--r--gcc/config/riscv/riscv.md28
-rw-r--r--gcc/config/riscv/vector.md22
9 files changed, 224 insertions, 21 deletions
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 5ed5e18..d0919ec 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -908,6 +908,24 @@
"bext\t%0,%1,%2"
[(set_attr "type" "bitmanip")])
+;; We do not define SHIFT_COUNT_TRUNCATED, so we have to have variants
+;; that mask/extend the count if we want to eliminate those ops
+;;
+;; We could (in theory) use GPR for the various modes, but I haven't
+;; seen those cases appear in practice. Without a testcase I've
+;; elected to keep the modes X which is easy to reason about.
+(define_insn "*bext<mode>_mask_pos"
+ [(set (match_operand:X 0 "register_operand" "=r")
+ (zero_extract:X (match_operand:X 1 "register_operand" "r")
+ (const_int 1)
+ (and:X
+ (match_operand:X 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand"))))]
+ "(TARGET_ZBS
+ && INTVAL (operands[3]) + 1 == GET_MODE_BITSIZE (<MODE>mode))"
+ "bext\t%0,%1,%2"
+ [(set_attr "type" "bitmanip")])
+
;; This is a bext followed by a seqz. Normally this would be a 3->2 split
;; But the and-not pattern with a constant operand is a define_insn_and_split,
;; so this looks like a 2->2 split, which combine rejects. So implement it
@@ -1245,3 +1263,41 @@
expand_crc_using_clmul (<SUBX:MODE>mode, <SUBX1:MODE>mode, operands);
DONE;
})
+
+;; If we have an XOR/IOR with a constant operand (C) and the we can
+;; synthesize ~C more efficiently than C, then synthesize ~C and use
+;; xnor/orn instead.
+;;
+;; The same can be done for AND, but mvconst_internal's issues get in
+;; the way. That's future work.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (any_or:X (match_operand:X 1 "register_operand")
+ (match_operand:X 2 "const_int_operand")))
+ (clobber (match_operand:X 3 "register_operand"))]
+ "TARGET_ZBB
+ && (riscv_const_insns (operands[2], true)
+ > riscv_const_insns (GEN_INT (~INTVAL (operands[2])), true))"
+ [(const_int 0)]
+{
+ /* Get the inverted constant into the temporary register. */
+ riscv_emit_move (operands[3], GEN_INT (~INTVAL (operands[2])));
+
+ /* For xnor, the NOT operation is in a different position. So
+ we have to customize the split code we generate a bit.
+
+ It is expected that AND will be handled like IOR in the future. */
+ if (<CODE> == XOR)
+ {
+ rtx x = gen_rtx_XOR (<X:MODE>mode, operands[1], operands[3]);
+ x = gen_rtx_NOT (<X:MODE>mode, x);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+ else
+ {
+ rtx x = gen_rtx_NOT (<X:MODE>mode, operands[3]);
+ x = gen_rtx_IOR (<X:MODE>mode, x, operands[1]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+ DONE;
+})
diff --git a/gcc/config/riscv/gnu.h b/gcc/config/riscv/gnu.h
new file mode 100644
index 0000000..047399b
--- /dev/null
+++ b/gcc/config/riscv/gnu.h
@@ -0,0 +1,59 @@
+/* Definitions for RISC-V GNU/Hurd systems with ELF format.
+ Copyright (C) 1998-2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \
+ } while (0)
+
+#define GNU_USER_DYNAMIC_LINKER "/lib/ld-riscv" XLEN_SPEC "-" ABI_SPEC ".so.1"
+
+#define ICACHE_FLUSH_FUNC "__riscv_flush_icache"
+
+#define CPP_SPEC "%{pthread:-D_REENTRANT}"
+
+#define LD_EMUL_SUFFIX \
+ "%{mabi=lp64d:}" \
+ "%{mabi=lp64f:_lp64f}" \
+ "%{mabi=lp64:_lp64}" \
+ "%{mabi=ilp32d:}" \
+ "%{mabi=ilp32f:_ilp32f}" \
+ "%{mabi=ilp32:_ilp32}"
+
+#define LINK_SPEC "\
+-melf" XLEN_SPEC DEFAULT_ENDIAN_SPEC "riscv" LD_EMUL_SUFFIX " \
+%{mno-relax:--no-relax} \
+-X \
+%{mbig-endian:-EB} \
+%{mlittle-endian:-EL} \
+%{shared} \
+ %{!shared: \
+ %{!static: \
+ %{!static-pie: \
+ %{rdynamic:-export-dynamic} \
+ -dynamic-linker " GNU_USER_DYNAMIC_LINKER "}} \
+ %{static:-static} %{static-pie:-static -pie --no-dynamic-linker -z text}}"
+
+#define STARTFILE_PREFIX_SPEC \
+ "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/lib/ " \
+ "/usr/lib/ "
+
+#define RISCV_USE_CUSTOMISED_MULTI_LIB select_by_abi
diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index 2918496..e31afc3 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -41,6 +41,12 @@ RISCV_TUNE("sifive-p400-series", sifive_p400, sifive_p400_tune_info)
RISCV_TUNE("sifive-p600-series", sifive_p600, sifive_p600_tune_info)
RISCV_TUNE("tt-ascalon-d8", generic_ooo, tt_ascalon_d8_tune_info)
RISCV_TUNE("thead-c906", generic, thead_c906_tune_info)
+RISCV_TUNE("xt-c908", generic, generic_ooo_tune_info)
+RISCV_TUNE("xt-c908v", generic, generic_ooo_tune_info)
+RISCV_TUNE("xt-c910", generic, generic_ooo_tune_info)
+RISCV_TUNE("xt-c910v2", generic, generic_ooo_tune_info)
+RISCV_TUNE("xt-c920", generic, generic_ooo_tune_info)
+RISCV_TUNE("xt-c920v2", generic, generic_ooo_tune_info)
RISCV_TUNE("xiangshan-nanhu", xiangshan, xiangshan_nanhu_tune_info)
RISCV_TUNE("generic-ooo", generic_ooo, generic_ooo_tune_info)
RISCV_TUNE("size", generic, optimize_size_tune_info)
@@ -93,6 +99,48 @@ RISCV_CORE("thead-c906", "rv64imafdc_xtheadba_xtheadbb_xtheadbs_xtheadcmo_"
"xtheadmemidx_xtheadmempair_xtheadsync",
"thead-c906")
+RISCV_CORE("xt-c908", "rv64imafdc_zicbom_zicbop_zicboz_zicntr_zicsr_"
+ "zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_"
+ "sstc_svinval_svnapot_svpbmt_xtheadba_xtheadbb_"
+ "xtheadbs_xtheadcmo_xtheadcondmov_xtheadfmemidx_"
+ "xtheadmac_xtheadmemidx_xtheadmempair_xtheadsync",
+ "xt-c908")
+RISCV_CORE("xt-c908v", "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicsr_"
+ "zifencei_zihintpause_zihpm_zfh_zba_zbb_zbc_zbs_"
+ "zvfh_sstc_svinval_svnapot_svpbmt__xtheadba_"
+ "xtheadbb_xtheadbs_xtheadcmo_xtheadcondmov_"
+ "xtheadfmemidx_xtheadmac_xtheadmemidx_"
+ "xtheadmempair_xtheadsync_xtheadvdot",
+ "xt-c908")
+RISCV_CORE("xt-c910", "rv64imafdc_zicntr_zicsr_zifencei_zihpm_zfh_"
+ "xtheadba_xtheadbb_xtheadbs_xtheadcmo_"
+ "xtheadcondmov_xtheadfmemidx_xtheadmac_"
+ "xtheadmemidx_xtheadmempair_xtheadsync",
+ "xt-c910")
+RISCV_CORE("xt-c910v2", "rv64imafdc_zicbom_zicbop_zicboz_zicntr_zicond_"
+ "zicsr_zifencei _zihintntl_zihintpause_zihpm_"
+ "zawrs_zfa_zfbfmin_zfh_zca_zcb_zcd_zba_zbb_zbc_"
+ "zbs_sscofpmf_sstc_svinval_svnapot_svpbmt_"
+ "xtheadba_xtheadbb_xtheadbs_xtheadcmo_"
+ "xtheadcondmov_xtheadfmemidx_xtheadmac_"
+ "xtheadmemidx_xtheadmempair_xtheadsync",
+ "xt-c910v2")
+RISCV_CORE("xt-c920", "rv64imafdc_zicntr_zicsr_zifencei_zihpm_zfh_"
+ "xtheadba_xtheadbb_xtheadbs_xtheadcmo_"
+ "xtheadcondmov_xtheadfmemidx_xtheadmac_"
+ "xtheadmemidx_xtheadmempair_xtheadsync_"
+ "xtheadvector",
+ "xt-c910")
+RISCV_CORE("xt-c920v2", "rv64imafdcv_zicbom_zicbop_zicboz_zicntr_zicond_"
+ "zicsr_zifencei _zihintntl_zihintpause_zihpm_"
+ "zawrs_zfa_zfbfmin_zfh_zca_zcb_zcd_zba_zbb_zbc_"
+ "zbs_zvfbfmin_zvfbfwma_zvfh_sscofpmf_sstc_"
+ "svinval_svnapot_svpbmt_xtheadba_xtheadbb_"
+ "xtheadbs_xtheadcmo_xtheadcondmov_xtheadfmemidx_"
+ "xtheadmac_xtheadmemidx_xtheadmempair_"
+ "xtheadsync_xtheadvdot",
+ "xt-c920v2")
+
RISCV_CORE("tt-ascalon-d8", "rv64imafdcv_zic64b_zicbom_zicbop_zicboz_"
"ziccamoa_ziccif_zicclsm_ziccrse_zicond_zicsr_"
"zifencei_zihintntl_zihintpause_zimop_za64rs_"
diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc
index 1d96865..8ad3025 100644
--- a/gcc/config/riscv/riscv-target-attr.cc
+++ b/gcc/config/riscv/riscv-target-attr.cc
@@ -257,11 +257,7 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const
{
std::string local_arch = m_subset_list->to_string (true);
const char* local_arch_str = local_arch.c_str ();
- struct cl_target_option *default_opts
- = TREE_TARGET_OPTION (target_option_default_node);
- if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string)
- free (CONST_CAST (void *, (const void *) opts->x_riscv_arch_string));
- opts->x_riscv_arch_string = xstrdup (local_arch_str);
+ opts->x_riscv_arch_string = ggc_strdup (local_arch_str);
riscv_set_arch_by_subset_list (m_subset_list, opts);
}
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index 0ac2538..a8c9256 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -685,7 +685,7 @@ invalid_opt_bb_p (basic_block cfg_bb)
/* We only do LCM optimizations on blocks that are post dominated by
EXIT block, that is, we don't do LCM optimizations on infinite loop. */
FOR_EACH_EDGE (e, ei, cfg_bb->succs)
- if (e->flags & EDGE_FAKE)
+ if ((e->flags & EDGE_FAKE) || (e->flags & EDGE_ABNORMAL))
return true;
return false;
@@ -2698,6 +2698,7 @@ pre_vsetvl::compute_lcm_local_properties ()
m_avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), num_exprs);
bitmap_vector_clear (m_avloc, last_basic_block_for_fn (cfun));
+ bitmap_vector_clear (m_kill, last_basic_block_for_fn (cfun));
bitmap_vector_clear (m_antloc, last_basic_block_for_fn (cfun));
bitmap_vector_ones (m_transp, last_basic_block_for_fn (cfun));
@@ -2749,6 +2750,10 @@ pre_vsetvl::compute_lcm_local_properties ()
if (invalid_opt_bb_p (bb->cfg_bb ()))
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "\n --- skipping bb %u due to weird edge",
+ bb->index ());
+
bitmap_clear (m_antloc[bb_index]);
bitmap_clear (m_transp[bb_index]);
}
@@ -3022,6 +3027,18 @@ pre_vsetvl::earliest_fuse_vsetvl_info (int iter)
continue;
}
+ /* We cannot lift a vsetvl into the source block if the block is
+ not transparent WRT to it.
+ This is too restrictive for blocks where a register's use only
+ feeds into vsetvls and no regular insns. One example is the
+ test rvv/vsetvl/avl_single-68.c which is currently XFAILed for
+ that reason.
+ In order to support this case we'd need to check the vsetvl's
+ AVL operand's uses in the source block and make sure they are
+ only used in other vsetvls. */
+ if (!bitmap_bit_p (m_transp[eg->src->index], expr_index))
+ continue;
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file,
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 38f3ae7..bad59e2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -10382,7 +10382,7 @@ riscv_file_end ()
fprintf (asm_out_file, "1:\n");
/* pr_type. */
- fprintf (asm_out_file, "\t.p2align\t3\n");
+ fprintf (asm_out_file, "\t.p2align\t%u\n", p2align);
fprintf (asm_out_file, "2:\n");
fprintf (asm_out_file, "\t.long\t0xc0000000\n");
/* pr_datasz. */
@@ -13136,9 +13136,6 @@ parse_features_for_version (tree decl,
DECL_SOURCE_LOCATION (decl));
gcc_assert (parse_res);
- if (arch_string != default_opts->x_riscv_arch_string)
- free (CONST_CAST (void *, (const void *) arch_string));
-
cl_target_option_restore (&global_options, &global_options_set,
&cur_target);
}
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 2bcabd0..2759a4c 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -888,7 +888,7 @@ extern enum riscv_cc get_riscv_cc (const rtx use);
#define ASM_OUTPUT_OPCODE(STREAM, PTR) \
(PTR) = riscv_asm_output_opcode(STREAM, PTR)
-#define JUMP_TABLES_IN_TEXT_SECTION 0
+#define JUMP_TABLES_IN_TEXT_SECTION (riscv_cmodel == CM_LARGE)
#define CASE_VECTOR_MODE SImode
#define CASE_VECTOR_PC_RELATIVE (riscv_cmodel != CM_MEDLOW)
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 26a247c..eec9687 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -789,7 +789,7 @@
rtx t5 = gen_reg_rtx (DImode);
rtx t6 = gen_reg_rtx (DImode);
- riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
+ emit_insn (gen_addsi3_extended (t6, operands[1], operands[2]));
if (GET_CODE (operands[1]) != CONST_INT)
emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
else
@@ -799,7 +799,10 @@
else
t5 = operands[2];
emit_insn (gen_adddi3 (t3, t4, t5));
- emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
+ rtx t7 = gen_lowpart (SImode, t6);
+ SUBREG_PROMOTED_VAR_P (t7) = 1;
+ SUBREG_PROMOTED_SET (t7, SRP_SIGNED);
+ emit_move_insn (operands[0], t7);
riscv_expand_conditional_branch (operands[3], NE, t6, t3);
}
@@ -835,8 +838,11 @@
emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
else
t3 = operands[1];
- riscv_emit_binary (PLUS, operands[0], operands[1], operands[2]);
- emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
+ emit_insn (gen_addsi3_extended (t4, operands[1], operands[2]));
+ rtx t5 = gen_lowpart (SImode, t4);
+ SUBREG_PROMOTED_VAR_P (t5) = 1;
+ SUBREG_PROMOTED_SET (t5, SRP_SIGNED);
+ emit_move_insn (operands[0], t5);
riscv_expand_conditional_branch (operands[3], LTU, t4, t3);
}
@@ -966,7 +972,7 @@
rtx t5 = gen_reg_rtx (DImode);
rtx t6 = gen_reg_rtx (DImode);
- riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
+ emit_insn (gen_subsi3_extended (t6, operands[1], operands[2]));
if (GET_CODE (operands[1]) != CONST_INT)
emit_insn (gen_extend_insn (t4, operands[1], DImode, SImode, 0));
else
@@ -976,7 +982,10 @@
else
t5 = operands[2];
emit_insn (gen_subdi3 (t3, t4, t5));
- emit_insn (gen_extend_insn (t6, operands[0], DImode, SImode, 0));
+ rtx t7 = gen_lowpart (SImode, t6);
+ SUBREG_PROMOTED_VAR_P (t7) = 1;
+ SUBREG_PROMOTED_SET (t7, SRP_SIGNED);
+ emit_move_insn (operands[0], t7);
riscv_expand_conditional_branch (operands[3], NE, t6, t3);
}
@@ -1015,8 +1024,11 @@
emit_insn (gen_extend_insn (t3, operands[1], DImode, SImode, 0));
else
t3 = operands[1];
- riscv_emit_binary (MINUS, operands[0], operands[1], operands[2]);
- emit_insn (gen_extend_insn (t4, operands[0], DImode, SImode, 0));
+ emit_insn (gen_subsi3_extended (t4, operands[1], operands[2]));
+ rtx t5 = gen_lowpart (SImode, t4);
+ SUBREG_PROMOTED_VAR_P (t5) = 1;
+ SUBREG_PROMOTED_SET (t5, SRP_SIGNED);
+ emit_move_insn (operands[0], t5);
riscv_expand_conditional_branch (operands[3], LTU, t3, t4);
}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 51eb64f..3ab4d76 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -2136,18 +2136,34 @@
(match_operand 7 "const_int_operand")
(reg:SI VL_REGNUM)
(reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
- (vec_duplicate:V_VLS
- (match_operand:<VEL> 3 "direct_broadcast_operand"))
+ ;; (vec_duplicate:V_VLS ;; wrapper activated by wrap_vec_dup below.
+ (match_operand:<VEL> 3 "direct_broadcast_operand") ;; )
(match_operand:V_VLS 2 "vector_merge_operand")))]
"TARGET_VECTOR"
{
/* Transform vmv.v.x/vfmv.v.f (avl = 1) into vmv.s.x since vmv.s.x/vfmv.s.f
has better chances to do vsetvl fusion in vsetvl pass. */
+ bool wrap_vec_dup = true;
+ rtx vec_cst = NULL_RTX;
if (riscv_vector::splat_to_scalar_move_p (operands))
{
operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
operands[3] = force_reg (<VEL>mode, operands[3]);
}
+ else if (immediate_operand (operands[3], <VEL>mode)
+ && (vec_cst = gen_const_vec_duplicate (<MODE>mode, operands[3]))
+ && (/* -> pred_broadcast<mode>_zero */
+ (vector_least_significant_set_mask_operand (operands[1],
+ <VM>mode)
+ && vector_const_0_operand (vec_cst, <MODE>mode))
+ || (/* pred_broadcast<mode>_imm */
+ vector_all_trues_mask_operand (operands[1], <VM>mode)
+ && vector_const_int_or_double_0_operand (vec_cst,
+ <MODE>mode))))
+ {
+ operands[3] = vec_cst;
+ wrap_vec_dup = false;
+ }
/* Handle vmv.s.x instruction (Wb1 mask) which has memory scalar. */
else if (satisfies_constraint_Wdm (operands[3]))
{
@@ -2191,6 +2207,8 @@
;
else
operands[3] = force_reg (<VEL>mode, operands[3]);
+ if (wrap_vec_dup)
+ operands[3] = gen_rtx_VEC_DUPLICATE (<MODE>mode, operands[3]);
})
(define_insn_and_split "*pred_broadcast<mode>"