aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/riscv')
-rw-r--r--gcc/config/riscv/autovec-opt.md123
-rw-r--r--gcc/config/riscv/autovec.md99
-rw-r--r--gcc/config/riscv/bitmanip.md175
-rw-r--r--gcc/config/riscv/constraints.md8
-rw-r--r--gcc/config/riscv/gen-riscv-ext-opt.cc105
-rw-r--r--gcc/config/riscv/gen-riscv-ext-texi.cc88
-rw-r--r--gcc/config/riscv/iterators.md3
-rw-r--r--gcc/config/riscv/mips-p8700.md167
-rwxr-xr-xgcc/config/riscv/pipeline-checker191
-rw-r--r--gcc/config/riscv/predicates.md28
-rw-r--r--gcc/config/riscv/riscv-c.cc34
-rw-r--r--gcc/config/riscv/riscv-cores.def20
-rw-r--r--gcc/config/riscv/riscv-ext-corev.def87
-rw-r--r--gcc/config/riscv/riscv-ext-sifive.def87
-rw-r--r--gcc/config/riscv/riscv-ext-thead.def191
-rw-r--r--gcc/config/riscv/riscv-ext-ventana.def35
-rw-r--r--gcc/config/riscv/riscv-ext.def2084
-rw-r--r--gcc/config/riscv/riscv-ext.opt447
-rw-r--r--gcc/config/riscv/riscv-ext.opt.urls2
-rw-r--r--gcc/config/riscv/riscv-opts.h26
-rw-r--r--gcc/config/riscv/riscv-protos.h7
-rw-r--r--gcc/config/riscv/riscv-shorten-memrefs.cc3
-rw-r--r--gcc/config/riscv/riscv-subset.h65
-rw-r--r--gcc/config/riscv/riscv-v.cc108
-rw-r--r--gcc/config/riscv/riscv-vect-permconst.cc22
-rw-r--r--gcc/config/riscv/riscv-vector-builtins-shapes.cc4
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.cc26
-rw-r--r--gcc/config/riscv/riscv-vector-builtins.h40
-rw-r--r--gcc/config/riscv/riscv-vector-costs.cc29
-rw-r--r--gcc/config/riscv/riscv-vsetvl.cc47
-rw-r--r--gcc/config/riscv/riscv.cc1508
-rw-r--r--gcc/config/riscv/riscv.h2
-rw-r--r--gcc/config/riscv/riscv.md169
-rw-r--r--gcc/config/riscv/riscv.opt319
-rw-r--r--gcc/config/riscv/sifive-7.md169
-rw-r--r--gcc/config/riscv/sync.md13
-rw-r--r--gcc/config/riscv/t-riscv46
-rw-r--r--gcc/config/riscv/vector-iterators.md8
-rw-r--r--gcc/config/riscv/vector.md75
-rw-r--r--gcc/config/riscv/zicond.md36
40 files changed, 5739 insertions, 957 deletions
diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 0c3b0cc..8df7f64 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -1673,3 +1673,126 @@
DONE;
}
[(set_attr "type" "vandn")])
+
+
+;; =============================================================================
+;; Combine vec_duplicate + op.vv to op.vx
+;; Include
+;; - vadd.vx
+;; =============================================================================
+(define_insn_and_split "*<optab>_vx_<mode>"
+ [(set (match_operand:V_VLSI 0 "register_operand")
+ (any_int_binop_no_shift_vdup_v:V_VLSI
+ (vec_duplicate:V_VLSI
+ (match_operand:<VEL> 1 "register_operand"))
+ (match_operand:V_VLSI 2 "<binop_rhs2_predicate>")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ riscv_vector::expand_vx_binary_vec_dup_vec (operands[0], operands[2],
+ operands[1], <CODE>,
+ <MODE>mode);
+ }
+ [(set_attr "type" "vialu")])
+
+(define_insn_and_split "*<optab>_vx_<mode>"
+ [(set (match_operand:V_VLSI 0 "register_operand")
+ (any_int_binop_no_shift_v_vdup:V_VLSI
+ (match_operand:V_VLSI 1 "<binop_rhs2_predicate>")
+ (vec_duplicate:V_VLSI
+ (match_operand:<VEL> 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ riscv_vector::expand_vx_binary_vec_vec_dup (operands[0], operands[1],
+ operands[2], <CODE>,
+ <MODE>mode);
+ }
+ [(set_attr "type" "vialu")])
+
+;; =============================================================================
+;; Combine vec_duplicate + op.vv to op.vf
+;; Include
+;; - vfmadd.vf
+;; - vfmsub.vf
+;; - vfnmadd.vf
+;; - vfnmsub.vf
+;; - vfmacc.vf
+;; - vfmsac.vf
+;; - vfnmacc.vf
+;; - vfnmsac.vf
+;; =============================================================================
+
+;; vfmadd.vf, vfmsub.vf, vfmacc.vf, vfmsac.vf
+(define_insn_and_split "*<optab>_vf_<mode>"
+ [(set (match_operand:V_VLSF 0 "register_operand")
+ (plus_minus:V_VLSF
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 1 "register_operand"))
+ (match_operand:V_VLSF 2 "register_operand"))
+ (match_operand:V_VLSF 3 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
+ RVV_VUNDEF(<MODE>mode)};
+ riscv_vector::emit_vlmax_insn (code_for_pred_mul_scalar (<CODE>, <MODE>mode),
+ riscv_vector::TERNARY_OP_FRM_DYN, ops);
+ DONE;
+ }
+ [(set_attr "type" "vfmuladd")]
+)
+
+;; vfnmsub.vf, vfnmsac.vf
+(define_insn_and_split "*vfnmsub_<mode>"
+ [(set (match_operand:V_VLSF 0 "register_operand")
+ (minus:V_VLSF
+ (match_operand:V_VLSF 3 "register_operand")
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 1 "register_operand"))
+ (match_operand:V_VLSF 2 "register_operand"))))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
+ RVV_VUNDEF(<MODE>mode)};
+ riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg_scalar (PLUS, <MODE>mode),
+ riscv_vector::TERNARY_OP_FRM_DYN, ops);
+ DONE;
+ }
+ [(set_attr "type" "vfmuladd")]
+)
+
+;; vfnmadd.vf, vfnmacc.vf
+(define_insn_and_split "*vfnmadd_<mode>"
+ [(set (match_operand:V_VLSF 0 "register_operand")
+ (minus:V_VLSF
+ (mult:V_VLSF
+ (neg:V_VLSF
+ (match_operand:V_VLSF 2 "register_operand"))
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 1 "register_operand")))
+ (match_operand:V_VLSF 3 "register_operand")))]
+ "TARGET_VECTOR && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+ {
+ rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
+ RVV_VUNDEF(<MODE>mode)};
+ riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg_scalar (MINUS, <MODE>mode),
+ riscv_vector::TERNARY_OP_FRM_DYN, ops);
+ DONE;
+ }
+ [(set_attr "type" "vfmuladd")]
+)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 9e51e3c..94a61bd 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -1338,7 +1338,7 @@
(define_expand "select_vl<mode>"
[(match_operand:P 0 "register_operand")
(match_operand:P 1 "vector_length_operand")
- (match_operand:P 2 "")]
+ (match_operand:P 2 "immediate_operand")]
"TARGET_VECTOR"
{
riscv_vector::expand_select_vl (operands);
@@ -2491,19 +2491,13 @@
(sign_extend:VWEXTI
(match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))))]
"TARGET_VECTOR"
-{
- /* First emit a widening addition. */
- rtx tmp1 = gen_reg_rtx (<MODE>mode);
- rtx ops1[] = {tmp1, operands[1], operands[2]};
- insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
-
- /* Then a narrowing shift. */
- rtx ops2[] = {operands[0], tmp1, const1_rtx};
- icode = code_for_pred_narrow_scalar (ASHIFTRT, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
- DONE;
-})
+ {
+ insn_code icode = code_for_pred (UNSPEC_VAADD, <V_DOUBLE_TRUNC>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN,
+ operands);
+ DONE;
+ }
+)
(define_expand "avg<v_double_trunc>3_ceil"
[(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
@@ -2517,25 +2511,13 @@
(match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
(const_int 1)))))]
"TARGET_VECTOR"
-{
- /* First emit a widening addition. */
- rtx tmp1 = gen_reg_rtx (<MODE>mode);
- rtx ops1[] = {tmp1, operands[1], operands[2]};
- insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
-
- /* Then add 1. */
- rtx tmp2 = gen_reg_rtx (<MODE>mode);
- rtx ops2[] = {tmp2, tmp1, const1_rtx};
- icode = code_for_pred_scalar (PLUS, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
-
- /* Finally, a narrowing shift. */
- rtx ops3[] = {operands[0], tmp2, const1_rtx};
- icode = code_for_pred_narrow_scalar (ASHIFTRT, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);
- DONE;
-})
+ {
+ insn_code icode = code_for_pred (UNSPEC_VAADD, <V_DOUBLE_TRUNC>mode);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU,
+ operands);
+ DONE;
+ }
+)
;; csrwi vxrm, 2
;; vaaddu.vv vd, vs2, vs1
@@ -2546,7 +2528,8 @@
"TARGET_VECTOR"
{
insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN, operands);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN,
+ operands);
DONE;
})
@@ -2559,7 +2542,8 @@
"TARGET_VECTOR"
{
insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
- riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU, operands);
+ riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU,
+ operands);
DONE;
})
@@ -2584,7 +2568,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_ceil (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_ceil (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2594,7 +2579,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_floor (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_floor (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2604,7 +2590,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_nearbyint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_nearbyint (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2614,7 +2601,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_rint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_rint (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2624,7 +2612,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_round (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_round (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2634,7 +2623,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_trunc (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_trunc (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2644,7 +2634,8 @@
(match_operand:V_VLSF 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_roundeven (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
+ riscv_vector::expand_vec_roundeven (operands[0], operands[1], <MODE>mode,
+ <VCONVERT>mode);
DONE;
}
)
@@ -2701,7 +2692,8 @@
(match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
+ riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode,
+ <V_F2SI_CONVERT>mode);
DONE;
}
)
@@ -2711,7 +2703,8 @@
(match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
+ riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode,
+ <V_F2DI_CONVERT>mode);
DONE;
}
)
@@ -2721,7 +2714,8 @@
(match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
+ riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode,
+ <V_F2SI_CONVERT>mode);
DONE;
}
)
@@ -2731,7 +2725,8 @@
(match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
"TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
{
- riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
+ riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode,
+ <V_F2DI_CONVERT>mode);
DONE;
}
)
@@ -2763,7 +2758,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_usadd (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_usadd (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2774,7 +2770,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2785,7 +2782,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_ussub (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_ussub (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
@@ -2796,7 +2794,8 @@
(match_operand:V_VLSI 2 "register_operand")]
"TARGET_VECTOR"
{
- riscv_vector::expand_vec_sssub (operands[0], operands[1], operands[2], <MODE>mode);
+ riscv_vector::expand_vec_sssub (operands[0], operands[1], operands[2],
+ <MODE>mode);
DONE;
}
)
diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 20d03dc..21426f4 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -1,4 +1,4 @@
-;; Machine description for RISC-V Bit Manipulation operations.
+;); Machine description for RISC-V Bit Manipulation operations.
;; Copyright (C) 2021-2025 Free Software Foundation, Inc.
;; This file is part of GCC.
@@ -68,23 +68,25 @@
[(set (match_operand:DI 0 "register_operand")
(zero_extend:DI (plus:SI (ashift:SI (subreg:SI (match_operand:DI 1 "register_operand") 0)
(match_operand:QI 2 "imm123_operand"))
- (subreg:SI (match_operand:DI 3 "register_operand") 0))))]
+ (subreg:SI (match_operand:DI 3 "register_operand") 0))))
+ (clobber (match_operand:DI 4 "register_operand"))]
"TARGET_64BIT && TARGET_ZBA"
- [(set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
- (set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 0) 0)))])
+ [(set (match_dup 4) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
+ (set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 4) 0)))])
(define_split
[(set (match_operand:DI 0 "register_operand")
(zero_extend:DI (plus:SI (subreg:SI (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
(match_operand:QI 2 "imm123_operand"))
(match_operand:DI 3 "consecutive_bits_operand")) 0)
- (subreg:SI (match_operand:DI 4 "register_operand") 0))))]
+ (subreg:SI (match_operand:DI 4 "register_operand") 0))))
+ (clobber (match_operand:DI 5 "register_operand"))]
"TARGET_64BIT && TARGET_ZBA
&& riscv_shamt_matches_mask_p (INTVAL (operands[2]), INTVAL (operands[3]))
/* Ensure the mask includes all the bits in SImode. */
&& ((INTVAL (operands[3]) & (HOST_WIDE_INT_1U << 31)) != 0)"
- [(set (match_dup 0) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 4)))
- (set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 0) 0)))])
+ [(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) (match_dup 4)))
+ (set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 5) 0)))])
; Make sure that an andi followed by a sh[123]add remains a two instruction
; sequence--and is not torn apart into slli, slri, add.
@@ -195,13 +197,14 @@
(match_operand:QI 2 "imm123_operand"))
(match_operand 3 "consecutive_bits32_operand"))
(match_operand:DI 4 "register_operand"))
- (match_operand 5 "immediate_operand")))]
+ (match_operand 5 "immediate_operand")))
+ (clobber (match_operand:DI 6 "register_operand"))]
"TARGET_64BIT && TARGET_ZBA"
- [(set (match_dup 0)
+ [(set (match_dup 6)
(plus:DI (and:DI (ashift:DI (match_dup 1) (match_dup 2))
(match_dup 3))
(match_dup 4)))
- (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 5)))])
+ (set (match_dup 0) (plus:DI (match_dup 6) (match_dup 5)))])
;; ZBB extension.
@@ -843,44 +846,40 @@
[(set_attr "type" "bitmanip")])
;; In case we have "val & ~IMM" where ~IMM has 2 bits set.
-(define_insn_and_split "*bclri<mode>_nottwobits"
- [(set (match_operand:X 0 "register_operand" "=r")
- (and:X (match_operand:X 1 "register_operand" "r")
- (match_operand:X 2 "const_nottwobits_not_arith_operand" "i")))]
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (match_operand:X 1 "register_operand")
+ (match_operand:X 2 "const_nottwobits_not_arith_operand")))
+ (clobber (match_operand:X 3 "register_operand"))]
"TARGET_ZBS && !paradoxical_subreg_p (operands[1])"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (and:X (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (and:X (match_dup 0) (match_dup 4)))]
+ [(set (match_dup 3) (and:X (match_dup 1) (match_dup 4)))
+ (set (match_dup 0) (and:X (match_dup 3) (match_dup 5)))]
{
- unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]);
- unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits);
+ unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits);
- operands[3] = GEN_INT (~bits | topbit);
- operands[4] = GEN_INT (~topbit);
-}
-[(set_attr "type" "bitmanip")])
+ operands[4] = GEN_INT (~bits | topbit);
+ operands[5] = GEN_INT (~topbit);
+})
;; In case of a paradoxical subreg, the sign bit and the high bits are
;; not allowed to be changed
-(define_insn_and_split "*bclridisi_nottwobits"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (and:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const_nottwobits_not_arith_operand" "i")))]
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (and:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "const_nottwobits_not_arith_operand")))
+ (clobber (match_operand:DI 3 "register_operand"))]
"TARGET_64BIT && TARGET_ZBS
&& clz_hwi (~UINTVAL (operands[2])) > 33"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))]
+ [(set (match_dup 3) (and:DI (match_dup 1) (match_dup 4)))
+ (set (match_dup 0) (and:DI (match_dup 3) (match_dup 5)))]
{
- unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]);
- unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits);
+ unsigned HOST_WIDE_INT bits = ~UINTVAL (operands[2]);
+ unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits);
- operands[3] = GEN_INT (~bits | topbit);
- operands[4] = GEN_INT (~topbit);
-}
-[(set_attr "type" "bitmanip")])
+ operands[4] = GEN_INT (~bits | topbit);
+ operands[5] = GEN_INT (~topbit);
+})
;; An outer AND with a constant where bits 31..63 are 0 can be seen as
;; a virtual zero extension from 31 to 64 bits.
@@ -1011,12 +1010,13 @@
[(set (match_operand:X 0 "register_operand")
(and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand")
(match_operand:QI 2 "register_operand")))
- (const_int 1)))]
+ (const_int 1)))
+ (clobber (match_operand:X 3 "register_operand"))]
"TARGET_ZBS"
- [(set (match_dup 0) (zero_extract:X (match_dup 1)
+ [(set (match_dup 3) (zero_extract:X (match_dup 1)
(const_int 1)
(match_dup 2)))
- (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))]
+ (set (match_dup 0) (xor:X (match_dup 3) (const_int 1)))]
"operands[2] = gen_lowpart (<MODE>mode, operands[2]);")
;; We can create a polarity-reversed mask (i.e. bit N -> { set = 0, clear = -1 })
@@ -1027,49 +1027,49 @@
(neg:GPR (eq:GPR (zero_extract:GPR (match_operand:GPR 1 "register_operand")
(const_int 1)
(match_operand 2))
- (const_int 0))))]
+ (const_int 0))))
+ (clobber (match_operand:X 3 "register_operand"))]
"TARGET_ZBS"
- [(set (match_dup 0) (zero_extract:GPR (match_dup 1) (const_int 1) (match_dup 2)))
- (set (match_dup 0) (plus:GPR (match_dup 0) (const_int -1)))])
+ [(set (match_dup 3) (zero_extract:GPR (match_dup 1) (const_int 1) (match_dup 2)))
+ (set (match_dup 0) (plus:GPR (match_dup 3) (const_int -1)))])
;; Catch those cases where we can use a bseti/binvi + ori/xori or
;; bseti/binvi + bseti/binvi instead of a lui + addi + or/xor sequence.
(define_insn_and_split "*<or_optab>i<mode>_extrabit"
[(set (match_operand:X 0 "register_operand" "=r")
(any_or:X (match_operand:X 1 "register_operand" "r")
- (match_operand:X 2 "uimm_extra_bit_or_twobits" "i")))]
+ (match_operand:X 2 "uimm_extra_bit_or_twobits" "i")))
+ (clobber (match_scratch:X 3 "=&r"))]
"TARGET_ZBS && !single_bit_mask_operand (operands[2], VOIDmode)"
"#"
"&& reload_completed"
- [(set (match_dup 0) (<or_optab>:X (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (<or_optab>:X (match_dup 0) (match_dup 4)))]
+ [(set (match_dup 3) (<or_optab>:X (match_dup 1) (match_dup 4)))
+ (set (match_dup 0) (<or_optab>:X (match_dup 3) (match_dup 5)))]
{
unsigned HOST_WIDE_INT bits = UINTVAL (operands[2]);
unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (bits);
- operands[3] = GEN_INT (bits &~ topbit);
- operands[4] = GEN_INT (topbit);
+ operands[4] = GEN_INT (bits &~ topbit);
+ operands[5] = GEN_INT (topbit);
}
[(set_attr "type" "bitmanip")])
;; Same to use blcri + andi and blcri + bclri
-(define_insn_and_split "*andi<mode>_extrabit"
- [(set (match_operand:X 0 "register_operand" "=r")
- (and:X (match_operand:X 1 "register_operand" "r")
- (match_operand:X 2 "not_uimm_extra_bit_or_nottwobits" "i")))]
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (match_operand:X 1 "register_operand")
+ (match_operand:X 2 "not_uimm_extra_bit_or_nottwobits")))
+ (clobber (match_operand:X 3 "register_operand"))]
"TARGET_ZBS && !not_single_bit_mask_operand (operands[2], VOIDmode)"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (and:X (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (and:X (match_dup 0) (match_dup 4)))]
+ [(set (match_dup 3) (and:X (match_dup 1) (match_dup 4)))
+ (set (match_dup 0) (and:X (match_dup 3) (match_dup 5)))]
{
unsigned HOST_WIDE_INT bits = UINTVAL (operands[2]);
unsigned HOST_WIDE_INT topbit = HOST_WIDE_INT_1U << floor_log2 (~bits);
- operands[3] = GEN_INT (bits | topbit);
- operands[4] = GEN_INT (~topbit);
-}
-[(set_attr "type" "bitmanip")])
+ operands[4] = GEN_INT (bits | topbit);
+ operands[5] = GEN_INT (~topbit);
+})
;; If we have the ZBA extension, then we can clear the upper half of a 64
;; bit object with a zext.w. So if we have AND where the constant would
@@ -1222,7 +1222,7 @@
we can't keep it in 64 bit variable.)
then use clmul instruction to implement the CRC,
otherwise (TARGET_ZBKB) generate table based using brev. */
- if ((TARGET_ZBKC || TARGET_ZBC) && <ANYI:MODE>mode < word_mode)
+ if ((TARGET_ZBKC || TARGET_ZBC || TARGET_ZVBC) && <ANYI:MODE>mode < word_mode)
expand_reversed_crc_using_clmul (<ANYI:MODE>mode, <ANYI1:MODE>mode,
operands);
else if (TARGET_ZBKB)
@@ -1254,7 +1254,8 @@
(match_operand:SUBX 3)]
UNSPEC_CRC))]
/* We don't support the case when data's size is bigger than CRC's size. */
- "(TARGET_ZBKC || TARGET_ZBC) && <SUBX:MODE>mode >= <SUBX1:MODE>mode"
+ "(TARGET_ZBKC || TARGET_ZBC || TARGET_ZVBC)
+ && <SUBX:MODE>mode >= <SUBX1:MODE>mode"
{
/* If we have the ZBC or ZBKC extension (ie, clmul) and
it is possible to store the quotient within a single variable
@@ -1302,3 +1303,51 @@
}
DONE;
})
+
+;; More forms of single bit extraction. The RISC-V port does not
+;; define SHIFT_COUNT_TRUNCATED so we need forms where the bit position
+;; is masked.
+;;
+;; We could in theory use this for rv32 as well, but it probably does
+;; not occur in practice. The bit position would need to be QI/HI mode,
+;; otherwise we would not need the zero extension.
+;;
+;; One could also argue that the zero extension is redundant and should
+;; have been optimized away during RTL simplification.
+(define_insn "*bextdi_position_ze_masked"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extract:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 1)
+ (zero_extend:DI
+ (and:SI (match_operand:SI 2 "register_operand" "r")
+ (const_int 63)))))]
+ "TARGET_64BIT && TARGET_ZBS"
+ "bext\t%0,%1,%2"
+ [(set_attr "type" "bitmanip")])
+
+;; Same as above, but without the extraneous zero_extend.
+(define_insn "*bextdi_position_ze_masked"
+ [(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:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "bitpos_mask_operand" "n"))))]
+ "TARGET_64BIT && TARGET_ZBS"
+ "bext\t%0,%1,%2"
+ [(set_attr "type" "bitmanip")])
+
+;; This has shown up in testing. In particular we end up with an
+;; immediate input. We can load that into a register and target
+;; one of the above bext patterns.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (lshiftrt:X (match_operand 1 "immediate_operand")
+ (match_operand:QI 2 "register_operand"))
+ (const_int 1)))
+ (clobber (match_operand:X 3 "register_operand"))]
+ ""
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 0) (zero_extract:X (match_dup 3)
+ (const_int 1)
+ (zero_extend:X (match_dup 2))))])
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 18556a5..ccab1a2 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -43,6 +43,10 @@
(define_register_constraint "cf" "TARGET_HARD_FLOAT ? RVC_FP_REGS : (TARGET_ZFINX ? RVC_GR_REGS : NO_REGS)"
"RVC floating-point registers (f8-f15), if available, reuse GPR as FPR when use zfinx.")
+(define_register_constraint "cR" "RVC_GR_REGS"
+ "Even-odd RVC general purpose register (x8-x15)."
+ "regno % 2 == 0")
+
;; General constraints
(define_constraint "I"
@@ -321,3 +325,7 @@
"A 2-bit unsigned immediate."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, 0, 3)")))
+
+(define_constraint "Q"
+ "An address operand that is valid for a prefetch instruction"
+ (match_operand 0 "prefetch_operand"))
diff --git a/gcc/config/riscv/gen-riscv-ext-opt.cc b/gcc/config/riscv/gen-riscv-ext-opt.cc
new file mode 100644
index 0000000..17b8f5b
--- /dev/null
+++ b/gcc/config/riscv/gen-riscv-ext-opt.cc
@@ -0,0 +1,105 @@
+#include <vector>
+#include <string>
+#include <set>
+#include <stdio.h>
+#include "riscv-opts.h"
+
+struct version_t
+{
+ int major;
+ int minor;
+ version_t (int major, int minor,
+ enum riscv_isa_spec_class spec = ISA_SPEC_CLASS_NONE)
+ : major (major), minor (minor)
+ {}
+ bool operator<(const version_t &other) const
+ {
+ if (major != other.major)
+ return major < other.major;
+ return minor < other.minor;
+ }
+
+ bool operator== (const version_t &other) const
+ {
+ return major == other.major && minor == other.minor;
+ }
+};
+
+static void
+print_ext_doc_entry (const std::string &ext_name, const std::string &full_name,
+ const std::string &desc,
+ const std::vector<version_t> &supported_versions)
+{
+ // Implementation of the function to print the documentation entry
+ // for the extension.
+ std::set<version_t> unique_versions;
+ for (const auto &version : supported_versions)
+ unique_versions.insert (version);
+ printf ("@item %s\n", ext_name.c_str ());
+ printf ("@tab");
+ for (const auto &version : unique_versions)
+ {
+ printf (" %d.%d", version.major, version.minor);
+ }
+ printf ("\n");
+ printf ("@tab %s", full_name.c_str ());
+ if (desc.size ())
+ printf (", %s", desc.c_str ());
+ printf ("\n\n");
+}
+
+int
+main ()
+{
+ puts ("; Target options for the RISC-V port of the compiler");
+ puts (";");
+ puts ("; Copyright (C) 2025 Free Software Foundation, Inc.");
+ puts (";");
+ puts ("; This file is part of GCC.");
+ puts (";");
+ puts (
+ "; GCC is free software; you can redistribute it and/or modify it under");
+ puts (
+ "; the terms of the GNU General Public License as published by the Free");
+ puts (
+ "; Software Foundation; either version 3, or (at your option) any later");
+ puts ("; version.");
+ puts (";");
+ puts ("; GCC is distributed in the hope that it will be useful, but WITHOUT");
+ puts ("; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY");
+ puts ("; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public");
+ puts ("; License for more details.");
+ puts (";");
+ puts ("; You should have received a copy of the GNU General Public License");
+ puts ("; along with GCC; see the file COPYING3. If not see ");
+ puts ("; <http://www.gnu.org/licenses/>.");
+
+ puts ("; This file is generated automatically using");
+ puts ("; gcc/config/riscv/gen-riscv-ext-opt.cc from:");
+ puts ("; gcc/config/riscv/riscv-ext.def");
+ puts ("");
+ puts ("; Please *DO NOT* edit manually.");
+
+ std::set<std::string> all_vars;
+#define DEFINE_RISCV_EXT(NAME, UPPERCAE_NAME, FULL_NAME, DESC, URL, DEP_EXTS, \
+ SUPPORTED_VERSIONS, FLAG_GROUP, BITMASK_GROUP_ID, \
+ BITMASK_BIT_POSITION, EXTRA_EXTENSION_FLAGS) \
+ all_vars.insert ("riscv_" #FLAG_GROUP "_subext");
+#include "riscv-ext.def"
+#undef DEFINE_RISCV_EXT
+
+ for (auto var : all_vars)
+ {
+ puts ("TargetVariable");
+ printf ("int %s\n\n", var.c_str ());
+ }
+
+#define DEFINE_RISCV_EXT(NAME, UPPERCAE_NAME, FULL_NAME, DESC, URL, DEP_EXTS, \
+ SUPPORTED_VERSIONS, FLAG_GROUP, BITMASK_GROUP_ID, \
+ BITMASK_BIT_POSITION, EXTRA_EXTENSION_FLAGS) \
+ puts ("Mask(" #UPPERCAE_NAME ") Var(riscv_" #FLAG_GROUP "_subext)\n");
+#include "riscv-ext.def"
+#undef DEFINE_RISCV_EXT
+
+ return 0;
+}
diff --git a/gcc/config/riscv/gen-riscv-ext-texi.cc b/gcc/config/riscv/gen-riscv-ext-texi.cc
new file mode 100644
index 0000000..c29a375
--- /dev/null
+++ b/gcc/config/riscv/gen-riscv-ext-texi.cc
@@ -0,0 +1,88 @@
+#include <vector>
+#include <string>
+#include <set>
+#include <stdio.h>
+#include "riscv-opts.h"
+
+struct version_t
+{
+ int major_version;
+ int minor_version;
+ version_t (int major, int minor,
+ enum riscv_isa_spec_class spec = ISA_SPEC_CLASS_NONE)
+ : major_version (major), minor_version (minor)
+ {}
+ bool operator<(const version_t &other) const
+ {
+ if (major_version != other.major_version)
+ return major_version < other.major_version;
+ return minor_version < other.minor_version;
+ }
+
+ bool operator== (const version_t &other) const
+ {
+ return major_version == other.major_version && minor_version == other.minor_version;
+ }
+};
+
+static void
+print_ext_doc_entry (const std::string &ext_name, const std::string &full_name,
+ const std::string &desc,
+ const std::vector<version_t> &supported_versions)
+{
+ // Implementation of the function to print the documentation entry
+ // for the extension.
+ std::set<version_t> unique_versions;
+ for (const auto &version : supported_versions)
+ unique_versions.insert (version);
+ printf ("@item %s\n", ext_name.c_str ());
+ printf ("@tab");
+ for (const auto &version : unique_versions)
+ {
+ printf (" %d.%d", version.major_version, version.minor_version);
+ }
+ printf ("\n");
+ printf ("@tab %s", full_name.c_str ());
+ if (desc.size ())
+ printf (", %s", desc.c_str ());
+ printf ("\n\n");
+}
+
+int
+main ()
+{
+ puts ("@c Copyright (C) 2025 Free Software Foundation, Inc.");
+ puts ("@c This is part of the GCC manual.");
+ puts ("@c For copying conditions, see the file gcc/doc/include/fdl.texi.");
+ puts ("");
+ puts ("@c This file is generated automatically using");
+ puts ("@c gcc/config/riscv/gen-riscv-ext-texi.cc from:");
+ puts ("@c gcc/config/riscv/riscv-ext.def");
+ puts ("@c gcc/config/riscv/riscv-opts.h");
+ puts ("");
+ puts ("@c Please *DO NOT* edit manually.");
+ puts ("");
+ puts ("@multitable @columnfractions .10 .10 .80");
+ puts ("@headitem Extension Name @tab Supported Version @tab Description");
+ puts ("");
+
+ /* g extension is a very speical extension that no clear version... */
+ puts ("@item g");
+ puts ("@tab -");
+ puts (
+ "@tab General-purpose computing base extension, @samp{g} will expand to");
+ puts ("@samp{i}, @samp{m}, @samp{a}, @samp{f}, @samp{d}, @samp{zicsr} and");
+ puts ("@samp{zifencei}.");
+ puts ("");
+
+#define DEFINE_RISCV_EXT(NAME, UPPERCAE_NAME, FULL_NAME, DESC, URL, DEP_EXTS, \
+ SUPPORTED_VERSIONS, FLAG_GROUP, BITMASK_GROUP_ID, \
+ BITMASK_BIT_POSITION, EXTRA_EXTENSION_FLAGS) \
+ print_ext_doc_entry (#NAME, FULL_NAME, DESC, \
+ std::vector<version_t> SUPPORTED_VERSIONS);
+#include "riscv-ext.def"
+#undef DEFINE_RISCV_EXT
+
+ puts ("@end multitable");
+ return 0;
+}
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 214c20b..584b345 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -262,6 +262,9 @@
(define_code_attr fix_uns [(fix "fix") (unsigned_fix "fixuns")])
+(define_code_attr OPTAB [(ior "IOR")
+ (xor "XOR")])
+
;; -------------------------------------------------------------------
;; Code Attributes
diff --git a/gcc/config/riscv/mips-p8700.md b/gcc/config/riscv/mips-p8700.md
new file mode 100644
index 0000000..ae0ea8d
--- /dev/null
+++ b/gcc/config/riscv/mips-p8700.md
@@ -0,0 +1,167 @@
+;; DFA-based pipeline description for MIPS P8700.
+;;
+;; Copyright (C) 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_automaton "mips_p8700_agen_alq_pipe, mips_p8700_mdu_pipe, mips_p8700_fpu_pipe")
+
+;; The address generation queue (AGQ) has AL2, CTISTD and LDSTA pipes
+(define_cpu_unit "mips_p8700_agq, mips_p8700_al2, mips_p8700_ctistd, mips_p8700_lsu"
+ "mips_p8700_agen_alq_pipe")
+
+(define_cpu_unit "mips_p8700_gpmul, mips_p8700_gpdiv" "mips_p8700_mdu_pipe")
+
+;; The arithmetic-logic-unit queue (ALQ) has ALU pipe
+(define_cpu_unit "mips_p8700_alq, mips_p8700_alu" "mips_p8700_agen_alq_pipe")
+
+;; The floating-point-unit queue (FPQ) has short and long pipes
+(define_cpu_unit "mips_p8700_fpu_short, mips_p8700_fpu_long" "mips_p8700_fpu_pipe")
+
+;; Long FPU pipeline.
+(define_cpu_unit "mips_p8700_fpu_apu" "mips_p8700_fpu_pipe")
+
+;; P8700 unsupported insns are mapped to dummies reservations
+(define_reservation "mips_p8700_dummies"
+ "mips_p8700_agq | mips_p8700_al2 | mips_p8700_ctistd | mips_p8700_lsu |
+ mips_p8700_fpu_short | mips_p8700_fpu_long")
+
+(define_reservation "mips_p8700_agq_al2" "mips_p8700_agq, mips_p8700_al2")
+(define_reservation "mips_p8700_agq_ctistd" "mips_p8700_agq, mips_p8700_ctistd")
+(define_reservation "mips_p8700_agq_lsu" "mips_p8700_agq, mips_p8700_lsu")
+(define_reservation "mips_p8700_alq_alu" "mips_p8700_alq, mips_p8700_alu")
+
+;;
+;; FPU pipe
+;;
+
+(define_insn_reservation "mips_p8700_fpu_fadd" 4
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fadd"))
+ "mips_p8700_fpu_long, mips_p8700_fpu_apu")
+
+(define_insn_reservation "mips_p8700_fpu_fabs" 2
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fcmp,fmove"))
+ "mips_p8700_fpu_short, mips_p8700_fpu_apu")
+
+(define_insn_reservation "mips_p8700_fpu_fload" 8
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fpload"))
+ "mips_p8700_agq_lsu")
+
+(define_insn_reservation "mips_p8700_fpu_fstore" 1
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fpstore"))
+ "mips_p8700_agq_lsu")
+
+(define_insn_reservation "mips_p8700_fpu_fmadd" 8
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fmadd"))
+ "mips_p8700_fpu_long, mips_p8700_fpu_apu")
+
+(define_insn_reservation "mips_p8700_fpu_fmul" 5
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fmul"))
+ "mips_p8700_fpu_long, mips_p8700_fpu_apu")
+
+(define_insn_reservation "mips_p8700_fpu_div" 17
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fdiv,fsqrt"))
+ "mips_p8700_fpu_long, mips_p8700_fpu_apu*17")
+
+(define_insn_reservation "mips_p8700_fpu_fcvt" 4
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "fcvt,fcvt_i2f,fcvt_f2i"))
+ "mips_p8700_fpu_long, mips_p8700_fpu_apu")
+
+(define_insn_reservation "mips_p8700_fpu_fmtc" 7
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "mtc"))
+ "mips_p8700_agq_lsu")
+
+(define_insn_reservation "mips_p8700_fpu_fmfc" 7
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "mfc"))
+ "mips_p8700_agq_lsu")
+
+;;
+;; Integer pipe
+;;
+
+(define_insn_reservation "mips_p8700_int_load" 4
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "load"))
+ "mips_p8700_agq_lsu")
+
+(define_insn_reservation "mips_p8700_int_store" 3
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "store"))
+ "mips_p8700_agq_lsu")
+
+(define_insn_reservation "mips_p8700_int_arith_1" 1
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "unknown,const,arith,shift,slt,multi,auipc,logical,move,bitmanip,min,max,minu,maxu,clz,ctz,rotate,atomic,condmove,crypto,mvpair,zicond"))
+ "mips_p8700_alq_alu | mips_p8700_agq_al2")
+
+(define_insn_reservation "mips_p8700_int_nop" 0
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "nop"))
+ "mips_p8700_alq_alu | mips_p8700_agq_al2")
+
+(define_insn_reservation "mips_p8700_dsp_mult" 4
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "imul,cpop,clmul"))
+ "mips_p8700_gpmul")
+
+(define_insn_reservation "mips_p8700_int_div" 8
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "idiv"))
+ "mips_p8700_gpdiv*5")
+
+(define_insn_reservation "mips_p8700_int_branch" 1
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "branch,jump,ret,sfb_alu,trap"))
+ "mips_p8700_agq_ctistd")
+
+(define_insn_reservation "mips_p8700_int_call" 2
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "call,jalr"))
+ "mips_p8700_agq_ctistd")
+
+;; mips-p8700 dummies insn and placeholder that had no mapping to p8700 hardware.
+(define_insn_reservation "mips_p8700_unknown" 1
+ (and (eq_attr "tune" "mips_p8700")
+ (eq_attr "type" "rdvlenb,rdvl,wrvxrm,wrfrm,
+ rdfrm,vsetvl,vsetvl_pre,vlde,vste,vldm,vstm,vlds,vsts,
+ vldux,vldox,vstux,vstox,vldff,vldr,vstr,
+ vlsegde,vssegte,vlsegds,vssegts,vlsegdux,vlsegdox,vssegtux,vssegtox,vlsegdff,
+ vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,
+ vimul,vidiv,viwmul,vimuladd,sf_vqmacc,viwmuladd,vimerge,vimov,
+ vsalu,vaalu,vsmul,vsshift,vnclip,sf_vfnrclip,
+ vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,
+ vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,
+ vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,
+ vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,
+ vired,viwred,vfredu,vfredo,vfwredu,vfwredo,
+ vmalu,vmpop,vmffs,vmsfs,vmiota,vmidx,vimovvx,vimovxv,vfmovvf,vfmovfv,
+ vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down,
+ vgather,vcompress,vmov,vector,vandn,vbrev,vbrev8,vrev8,vclz,vctz,vcpop,vrol,vror,vwsll,
+ vclmul,vclmulh,vghsh,vgmul,vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,vaesz,
+ vsha2ms,vsha2ch,vsha2cl,vsm4k,vsm4r,vsm3me,vsm3c,vfncvtbf16,vfwcvtbf16,vfwmaccbf16,
+ sf_vc,sf_vc_se"))
+ "mips_p8700_dummies")
diff --git a/gcc/config/riscv/pipeline-checker b/gcc/config/riscv/pipeline-checker
new file mode 100755
index 0000000..815698b
--- /dev/null
+++ b/gcc/config/riscv/pipeline-checker
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+
+# RISC-V pipeline model checker.
+# Copyright (C) 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/>.
+
+import re
+import sys
+import argparse
+from pathlib import Path
+from typing import List
+import pprint
+
+def remove_line_comments(text: str) -> str:
+ # Remove ';;' and everything after it on each line
+ cleaned_lines = []
+ for line in text.splitlines():
+ comment_index = line.find(';;')
+ if comment_index != -1:
+ line = line[:comment_index]
+ cleaned_lines.append(line)
+ return '\n'.join(cleaned_lines)
+
+
+def tokenize_sexpr(s: str) -> List[str]:
+ # Tokenize input string, including support for balanced {...} C blocks
+ tokens = []
+ i = 0
+ while i < len(s):
+ c = s[i]
+ if c.isspace():
+ i += 1
+ elif c == '(' or c == ')':
+ tokens.append(c)
+ i += 1
+ elif c == '"':
+ # Parse quoted string
+ j = i + 1
+ while j < len(s) and s[j] != '"':
+ if s[j] == '\\':
+ j += 1 # Skip escape
+ j += 1
+ tokens.append(s[i:j+1])
+ i = j + 1
+ elif c == '{':
+ # Parse balanced C block
+ depth = 1
+ j = i + 1
+ while j < len(s) and depth > 0:
+ if s[j] == '{':
+ depth += 1
+ elif s[j] == '}':
+ depth -= 1
+ j += 1
+ tokens.append(s[i:j]) # Include enclosing braces
+ i = j
+ else:
+ # Parse atom
+ j = i
+ while j < len(s) and not s[j].isspace() and s[j] not in '()"{}':
+ j += 1
+ tokens.append(s[i:j])
+ i = j
+ return tokens
+
+
+def parse_sexpr(tokens: List[str]) -> any:
+ # Recursively parse tokenized S-expression
+ token = tokens.pop(0)
+ if token == '(':
+ lst = []
+ while tokens[0] != ')':
+ lst.append(parse_sexpr(tokens))
+ tokens.pop(0) # Discard closing parenthesis
+ return lst
+ elif token.startswith('"') and token.endswith('"'):
+ return token[1:-1] # Remove surrounding quotes
+ elif token.startswith('{') and token.endswith('}'):
+ return token # Keep C code block as-is
+ else:
+ return token
+
+
+def find_define_attr_type(ast: any) -> List[List[str]]:
+ # Traverse AST to find all (define_attr "type" ...) entries
+ result = []
+ if isinstance(ast, list):
+ if ast and ast[0] == 'define_attr' and len(ast) >= 2 and ast[1] == 'type':
+ result.append(ast)
+ for elem in ast:
+ result.extend(find_define_attr_type(elem))
+ return result
+
+
+def parse_md_file(path: Path):
+ # Read file, remove comments, and parse all top-level S-expressions
+ with open(path, encoding='utf-8') as f:
+ raw_content = f.read()
+ clean_content = remove_line_comments(raw_content)
+ tokens = tokenize_sexpr(clean_content)
+ items = []
+ while tokens:
+ items.append(parse_sexpr(tokens))
+ return items
+
+def parsing_str_set(s: str) -> set:
+ s = s.replace('\\','').split(',')
+ s = set(map(lambda x: x.strip(), s))
+ return s
+
+def get_avaliable_types(md_file_path: str):
+ # Main logic: parse input file and print define_attr "type" expressions
+ ast = parse_md_file(Path(md_file_path))
+
+ # Get all type from define_attr type
+ define_attr_types = find_define_attr_type(ast)
+ types = parsing_str_set (define_attr_types[0][2])
+ return types
+
+def get_consumed_type(entry: List[str]) -> set:
+ # Extract the consumed type from a define_insn_reservation entry
+ current_type = entry[0]
+ if current_type in ['and', 'or']:
+ return get_consumed_type(entry[1]) | get_consumed_type(entry[2])
+ elif current_type == 'eq_attr' and entry[1] == 'type':
+ return parsing_str_set(entry[2])
+ return set()
+
+def check_pipemodel(md_file_path: str):
+ # Load the RISCV MD file and check for pipemodel
+ ast = parse_md_file(Path(md_file_path))
+
+ consumed_type = set()
+
+ for entry in ast:
+ entry_type = entry[0]
+ if entry_type not in ["define_insn_reservation"]:
+ continue
+ consumed_type |= get_consumed_type(entry[3])
+ return consumed_type
+
+
+def main():
+ parser = argparse.ArgumentParser(description='Check GCC pipeline model for instruction type coverage')
+ parser.add_argument('pipeline_model', help='Pipeline model file to check')
+ parser.add_argument('--base-md',
+ help='Base machine description file (default: riscv.md in script directory)',
+ default=None)
+ parser.add_argument('-v', '--verbose',
+ help='Show detailed type information',
+ action='store_true')
+ args = parser.parse_args()
+
+ # Set default base-md path if not provided
+ if args.base_md is None:
+ script_dir = Path(__file__).parent
+ base_md_path = script_dir / "riscv.md"
+ else:
+ base_md_path = Path(args.base_md)
+ avaliable_types = get_avaliable_types(str(base_md_path))
+ consumed_type = check_pipemodel(args.pipeline_model)
+
+ if args.verbose:
+ print("Available types:\n", avaliable_types)
+ print("Consumed types:\n", consumed_type)
+
+ if not avaliable_types.issubset(consumed_type):
+ print("Error: Some types are not consumed by the pipemodel")
+ print("Missing types:\n", avaliable_types - consumed_type)
+ sys.exit(1)
+ else:
+ print("All available types are consumed by the pipemodel.")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index f26bafc..8baad2f 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -27,6 +27,18 @@
(ior (match_operand 0 "const_arith_operand")
(match_operand 0 "register_operand")))
+;; REG or REG+D where D fits in a simm12 and has the low 5 bits
+;; off. The REG+D form can be reloaded into a temporary if needed
+;; after FP elimination if that exposes an invalid offset.
+(define_predicate "prefetch_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_test "const_arith_operand (op, VOIDmode)")
+ (match_test "(INTVAL (op) & 0x1f) == 0"))
+ (and (match_code "plus")
+ (match_test "register_operand (XEXP (op, 0), word_mode)")
+ (match_test "const_arith_operand (XEXP (op, 1), VOIDmode)")
+ (match_test "(INTVAL (XEXP (op, 1)) & 0x1f) == 0"))))
+
(define_predicate "lui_operand"
(and (match_code "const_int")
(match_test "LUI_OPERAND (INTVAL (op))")))
@@ -380,14 +392,6 @@
(and (match_code "const_int")
(match_test "SINGLE_BIT_MASK_OPERAND (UINTVAL (op))")))
-;; Register, small constant or single bit constant for use in
-;; bseti/binvi.
-(define_predicate "arith_or_zbs_operand"
- (ior (match_operand 0 "const_arith_operand")
- (match_operand 0 "register_operand")
- (and (match_test "TARGET_ZBS")
- (match_operand 0 "single_bit_mask_operand"))))
-
(define_predicate "not_single_bit_mask_operand"
(and (match_code "const_int")
(match_test "SINGLE_BIT_MASK_OPERAND (~UINTVAL (op))")))
@@ -685,3 +689,11 @@
(and (match_operand 0 "register_operand")
(match_test "REGNO (op) == RETURN_ADDR_REGNUM
|| REGNO (op) == T0_REGNUM")))
+
+(define_predicate "bitpos_mask_operand"
+ (and (match_code "const_int")
+ (match_test "TARGET_64BIT ? INTVAL (op) == 63 : INTVAL (op) == 31")))
+
+(define_predicate "reg_or_const_int_operand"
+ (ior (match_operand 0 "const_int_operand")
+ (match_operand 0 "register_operand")))
diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index ab6dc83..d2c0af3 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -36,10 +36,10 @@ along with GCC; see the file COPYING3. If not see
struct pragma_intrinsic_flags
{
- int intrinsic_target_flags;
+ int intrinsic_riscv_isa_flags;
int intrinsic_riscv_vector_elen_flags;
- int intrinsic_riscv_zvl_flags;
+ int intrinsic_riscv_zvl_subext;
int intrinsic_riscv_zvb_subext;
int intrinsic_riscv_zvk_subext;
};
@@ -47,16 +47,16 @@ struct pragma_intrinsic_flags
static void
riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
{
- flags->intrinsic_target_flags = target_flags;
+ flags->intrinsic_riscv_isa_flags = riscv_isa_flags;
flags->intrinsic_riscv_vector_elen_flags = riscv_vector_elen_flags;
- flags->intrinsic_riscv_zvl_flags = riscv_zvl_flags;
+ flags->intrinsic_riscv_zvl_subext = riscv_zvl_subext;
flags->intrinsic_riscv_zvb_subext = riscv_zvb_subext;
flags->intrinsic_riscv_zvk_subext = riscv_zvk_subext;
- target_flags = target_flags
+ riscv_isa_flags = riscv_isa_flags
| MASK_VECTOR;
- riscv_zvl_flags = riscv_zvl_flags
+ riscv_zvl_subext = riscv_zvl_subext
| MASK_ZVL32B
| MASK_ZVL64B
| MASK_ZVL128B
@@ -97,10 +97,10 @@ riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
static void
riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags *flags)
{
- target_flags = flags->intrinsic_target_flags;
+ riscv_isa_flags = flags->intrinsic_riscv_isa_flags;
riscv_vector_elen_flags = flags->intrinsic_riscv_vector_elen_flags;
- riscv_zvl_flags = flags->intrinsic_riscv_zvl_flags;
+ riscv_zvl_subext = flags->intrinsic_riscv_zvl_subext;
riscv_zvb_subext = flags->intrinsic_riscv_zvb_subext;
riscv_zvk_subext = flags->intrinsic_riscv_zvk_subext;
}
@@ -239,26 +239,22 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
size_t max_ext_len = 0;
/* Figure out the max length of extension name for reserving buffer. */
- for (const riscv_subset_t *subset = subset_list->begin ();
- subset != subset_list->end ();
- subset = subset->next)
- max_ext_len = MAX (max_ext_len, subset->name.length ());
+ for (auto &subset : *subset_list)
+ max_ext_len = MAX (max_ext_len, subset.name.length ());
char *buf = (char *)alloca (max_ext_len + 10 /* For __riscv_ and '\0'. */);
- for (const riscv_subset_t *subset = subset_list->begin ();
- subset != subset_list->end ();
- subset = subset->next)
+ for (auto &subset : *subset_list)
{
- int version_value = riscv_ext_version_value (subset->major_version,
- subset->minor_version);
+ int version_value = riscv_ext_version_value (subset.major_version,
+ subset.minor_version);
/* Special rule for zicsr and zifencei, it's used for ISA spec 2.2 or
earlier. */
- if ((subset->name == "zicsr" || subset->name == "zifencei")
+ if ((subset.name == "zicsr" || subset.name == "zifencei")
&& version_value == 0)
version_value = riscv_ext_version_value (2, 0);
- sprintf (buf, "__riscv_%s", subset->name.c_str ());
+ sprintf (buf, "__riscv_%s", subset.name.c_str ());
builtin_define_with_int_value (buf, version_value);
}
}
diff --git a/gcc/config/riscv/riscv-cores.def b/gcc/config/riscv/riscv-cores.def
index e31afc3..2096c00 100644
--- a/gcc/config/riscv/riscv-cores.def
+++ b/gcc/config/riscv/riscv-cores.def
@@ -33,6 +33,7 @@
#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO)
#endif
+RISCV_TUNE("generic", generic, generic_tune_info)
RISCV_TUNE("rocket", generic, rocket_tune_info)
RISCV_TUNE("sifive-3-series", generic, rocket_tune_info)
RISCV_TUNE("sifive-5-series", generic, rocket_tune_info)
@@ -48,8 +49,10 @@ 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("xiangshan-kunminghu", xiangshan, generic_ooo_tune_info)
RISCV_TUNE("generic-ooo", generic_ooo, generic_ooo_tune_info)
RISCV_TUNE("size", generic, optimize_size_tune_info)
+RISCV_TUNE("mips-p8700", mips_p8700, mips_p8700_tune_info)
#undef RISCV_TUNE
@@ -152,4 +155,21 @@ RISCV_CORE("xiangshan-nanhu", "rv64imafdc_zba_zbb_zbc_zbs_"
"zbkb_zbkc_zbkx_zknd_zkne_zknh_zksed_zksh_"
"svinval_zicbom_zicboz",
"xiangshan-nanhu")
+
+RISCV_CORE("xiangshan-kunminghu", "rv64imafdcbvh_sdtrig_sha_shcounterenw_"
+ "shgatpa_shlcofideleg_shtvala_shvsatpa_shvstvala_shvstvecd_"
+ "smaia_smcsrind_smdbltrp_smmpm_smnpm_smrnmi_smstateen_"
+ "ssaia_ssccptr_sscofpmf_sscounterenw_sscsrind_ssdbltrp_"
+ "ssnpm_sspm_ssstateen_ssstrict_sstc_sstvala_sstvecd_"
+ "ssu64xl_supm_svade_svbare_svinval_svnapot_svpbmt_za64rs_"
+ "zacas_zawrs_zba_zbb_zbc_zbkb_zbkc_zbkx_zbs_zcb_zcmop_"
+ "zfa_zfh_zfhmin_zic64b_zicbom_zicbop_zicboz_ziccif_"
+ "zicclsm_ziccrse_zicntr_zicond_zicsr_zifencei_zihintpause_"
+ "zihpm_zimop_zkn_zknd_zkne_zknh_zksed_zksh_zkt_zvbb_zvfh_"
+ "zvfhmin_zvkt_zvl128b_zvl32b_zvl64b",
+ "xiangshan-kunminghu")
+
+RISCV_CORE("mips-p8700", "rv64imafd_zicsr_zmmul_"
+ "zaamo_zalrsc_zba_zbb",
+ "mips-p8700")
#undef RISCV_CORE
diff --git a/gcc/config/riscv/riscv-ext-corev.def b/gcc/config/riscv/riscv-ext-corev.def
new file mode 100644
index 0000000..eb97399
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext-corev.def
@@ -0,0 +1,87 @@
+/* CORE-V extension definition file for RISC-V.
+ Copyright (C) 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT, please refer to riscv-ext.def. */
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xcvalu,
+ /* UPPERCAE_NAME */ XCVALU,
+ /* FULL_NAME */ "Core-V miscellaneous ALU extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xcv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xcvbi,
+ /* UPPERCAE_NAME */ XCVBI,
+ /* FULL_NAME */ "xcvbi extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xcv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xcvelw,
+ /* UPPERCAE_NAME */ XCVELW,
+ /* FULL_NAME */ "Core-V event load word extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xcv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xcvmac,
+ /* UPPERCAE_NAME */ XCVMAC,
+ /* FULL_NAME */ "Core-V multiply-accumulate extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xcv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xcvsimd,
+ /* UPPERCAE_NAME */ XCVSIMD,
+ /* FULL_NAME */ "xcvsimd extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xcv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
diff --git a/gcc/config/riscv/riscv-ext-sifive.def b/gcc/config/riscv/riscv-ext-sifive.def
new file mode 100644
index 0000000..c8d79da
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext-sifive.def
@@ -0,0 +1,87 @@
+/* SiFive extension definition file for RISC-V.
+ Copyright (C) 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT, please refer to riscv-ext.def. */
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xsfcease,
+ /* UPPERCAE_NAME */ XSFCEASE,
+ /* FULL_NAME */ "xsfcease extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xsf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xsfvcp,
+ /* UPPERCAE_NAME */ XSFVCP,
+ /* FULL_NAME */ "xsfvcp extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xsf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xsfvfnrclipxfqf,
+ /* UPPERCAE_NAME */ XSFVFNRCLIPXFQF,
+ /* FULL_NAME */ "xsfvfnrclipxfqf extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xsf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xsfvqmaccdod,
+ /* UPPERCAE_NAME */ XSFVQMACCDOD,
+ /* FULL_NAME */ "xsfvqmaccdod extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xsf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xsfvqmaccqoq,
+ /* UPPERCAE_NAME */ XSFVQMACCQOQ,
+ /* FULL_NAME */ "xsfvqmaccqoq extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xsf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
diff --git a/gcc/config/riscv/riscv-ext-thead.def b/gcc/config/riscv/riscv-ext-thead.def
new file mode 100644
index 0000000..327d2ae
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext-thead.def
@@ -0,0 +1,191 @@
+/* T-head extension definition file for RISC-V.
+ Copyright (C) 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT, please refer to riscv-ext.def. */
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadba,
+ /* UPPERCAE_NAME */ XTHEADBA,
+ /* FULL_NAME */ "T-head address calculation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadbb,
+ /* UPPERCAE_NAME */ XTHEADBB,
+ /* FULL_NAME */ "T-head basic bit-manipulation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadbs,
+ /* UPPERCAE_NAME */ XTHEADBS,
+ /* FULL_NAME */ "T-head single-bit instructions extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadcmo,
+ /* UPPERCAE_NAME */ XTHEADCMO,
+ /* FULL_NAME */ "T-head cache management operations extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadcondmov,
+ /* UPPERCAE_NAME */ XTHEADCONDMOV,
+ /* FULL_NAME */ "T-head conditional move extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadfmemidx,
+ /* UPPERCAE_NAME */ XTHEADFMEMIDX,
+ /* FULL_NAME */ "T-head indexed memory operations for floating-point registers extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadfmv,
+ /* UPPERCAE_NAME */ XTHEADFMV,
+ /* FULL_NAME */ "T-head double floating-point high-bit data transmission extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadint,
+ /* UPPERCAE_NAME */ XTHEADINT,
+ /* FULL_NAME */ "T-head acceleration interruption extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadmac,
+ /* UPPERCAE_NAME */ XTHEADMAC,
+ /* FULL_NAME */ "T-head multiply-accumulate extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadmemidx,
+ /* UPPERCAE_NAME */ XTHEADMEMIDX,
+ /* FULL_NAME */ "T-head indexed memory operation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadmempair,
+ /* UPPERCAE_NAME */ XTHEADMEMPAIR,
+ /* FULL_NAME */ "T-head two-GPR memory operation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadsync,
+ /* UPPERCAE_NAME */ XTHEADSYNC,
+ /* FULL_NAME */ "T-head multi-core synchronization extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xtheadvector,
+ /* UPPERCAE_NAME */ XTHEADVECTOR,
+ /* FULL_NAME */ "xtheadvector extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xthead,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
diff --git a/gcc/config/riscv/riscv-ext-ventana.def b/gcc/config/riscv/riscv-ext-ventana.def
new file mode 100644
index 0000000..deed47f
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext-ventana.def
@@ -0,0 +1,35 @@
+/* Ventana extension definition file for RISC-V.
+ Copyright (C) 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT, please refer to riscv-ext.def. */
+
+DEFINE_RISCV_EXT(
+ /* NAME */ xventanacondops,
+ /* UPPERCAE_NAME */ XVENTANACONDOPS,
+ /* FULL_NAME */ "Ventana integer conditional operations extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ xventana,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def
new file mode 100644
index 0000000..816acaa
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext.def
@@ -0,0 +1,2084 @@
+/* RISC-V extension definition file for RISC-V.
+ Copyright (C) 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/>.
+
+Please run `make riscv-regen` in build folder to make sure updated anything.
+
+Format of DEFINE_RISCV_EXT:
+ NAME:
+ The name of the extension, e.g. "i".
+ UPPERCASE_NAME:
+ The name of the extension in uppercase, e.g. "ZBA", this used
+ for generate TARGET_<ext-name> marco and MASK_<ext-name> macro.
+ For those extension only named with single letter, it should also come with
+ 'RV', e.g. 'v' should use 'RVV' here.
+ Some of old extension like 'i' and 'm' are not follow the rule.
+ FULL_NAME:
+ The full name of the extension, e.g. "Base integer extension".
+ DESC:
+ A short description of the extension, this will used during generating
+ documentation, GNU Texinfo format can be used this field.
+ URL:
+ A URL for the extension.
+ DEP_EXTS:
+ A list of dependent extensions, this is a list of strings or
+ a list of tuples. The first element of the tuple is the name
+ of the extension and the second element is a function that
+ takes a subset_list and returns true if the extension should be added as
+ a dependent extension, `c` and `zca` are examples of this.
+ SUPPORTED_VERSIONS:
+ A list of tuples, each tuple contains the major version number, minor
+ version number and the class of the specification. The version number is a
+ list of integers, e.g. {2, 0} for version 2.0. The class is
+ a string, e.g. "ISA_SPEC_CLASS_20191213", the class of the
+ specification is not required for any new extension.
+ FLAG_GROUP:
+ The group of the extension, this is used to group extensions
+ together. The group is a string, e.g. "base", "zi", "zm", "za", "zf",
+ "zc", "zb", "zk" and "zi".
+ This should be auto generated in theory in some day...
+ BITMASK_GROUP_ID:
+ The group id of the extension for the __riscv_feature_bits.
+ this field should sync with riscv-c-api-doc, and keep BITMASK_NOT_YET_ALLOCATED
+ if not got allocated.
+ https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc#extension-bitmask-definitions
+ BITMASK_BIT_POSITION:
+ The bit position of the extension for the __riscv_feature_bits.
+ this field should sync with riscv-c-api-doc, and keep BITMASK_NOT_YET_ALLOCATED
+ if not got allocated.
+ https://github.com/riscv-non-isa/riscv-c-api-doc/blob/main/src/c-api.adoc#extension-bitmask-definitions
+ EXTRA_EXTENSION_FLAGS:
+ Extra flags for the extension, this is a bitmask of the
+ extra flags. The extra flags are:
+ - EXT_FLAG_MACRO: Set this flag if this extension is just a macro of set of
+ extensions, and not define any new instrcutions, new CSRs or new
+ behaviors, the example is `b` extension is just a macro of `zba`, `zbb`
+ and `zbs`.
+*/
+
+DEFINE_RISCV_EXT(
+ /* NAME */ e,
+ /* UPPERCASE_NAME */ RVE,
+ /* FULL_NAME */ "Reduced base integer extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ i,
+ /* UPPERCASE_NAME */ RVI,
+ /* FULL_NAME */ "Base integer extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 1, ISA_SPEC_CLASS_20191213},
+ {2, 1, ISA_SPEC_CLASS_20190608},
+ {2, 0, ISA_SPEC_CLASS_2P2}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 8,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ m,
+ /* UPPERCASE_NAME */ MUL,
+ /* FULL_NAME */ "Integer multiplication and division extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zmmul"}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 12,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ a,
+ /* UPPERCASE_NAME */ ATOMIC,
+ /* FULL_NAME */ "Atomic extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zaamo", "zalrsc"}),
+ /* SUPPORTED_VERSIONS */ ({{2, 1, ISA_SPEC_CLASS_20191213},
+ {2, 0, ISA_SPEC_CLASS_20190608},
+ {2, 0, ISA_SPEC_CLASS_2P2}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 0,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ f,
+ /* UPPERCASE_NAME */ HARD_FLOAT,
+ /* FULL_NAME */ "Single-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{2, 2, ISA_SPEC_CLASS_20191213},
+ {2, 2, ISA_SPEC_CLASS_20190608},
+ {2, 0, ISA_SPEC_CLASS_2P2}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 5,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ d,
+ /* UPPERCASE_NAME */ DOUBLE_FLOAT,
+ /* FULL_NAME */ "Double-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"f", "zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{2, 2, ISA_SPEC_CLASS_20191213},
+ {2, 2, ISA_SPEC_CLASS_20190608},
+ {2, 0, ISA_SPEC_CLASS_2P2}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 3,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ c,
+ /* UPPERCASE_NAME */ RVC,
+ /* FULL_NAME */ "Compressed extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca",
+ {"zcf",
+ [] (const riscv_subset_list *subset_list) -> bool
+ {
+ return subset_list->xlen () == 32
+ && subset_list->lookup ("f");
+ }},
+ {"zcd",
+ [] (const riscv_subset_list *subset_list) -> bool
+ {
+ return subset_list->lookup ("d");
+ }}}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 2,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ b,
+ /* UPPERCASE_NAME */ RVB,
+ /* FULL_NAME */ "b extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zba", "zbb", "zbs"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ v,
+ /* UPPERCASE_NAME */ RVV,
+ /* FULL_NAME */ "Vector extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl128b", "zve64d"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 21,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ h,
+ /* UPPERCASE_NAME */ RVH,
+ /* FULL_NAME */ "Hypervisor extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ base,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zic64b,
+ /* UPPERCASE_NAME */ ZIC64B,
+ /* FULL_NAME */ "Cache block size isf 64 bytes",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicbom,
+ /* UPPERCASE_NAME */ ZICBOM,
+ /* FULL_NAME */ "Cache-block management extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicbop,
+ /* UPPERCASE_NAME */ ZICBOP,
+ /* FULL_NAME */ "Cache-block prefetch extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicboz,
+ /* UPPERCASE_NAME */ ZICBOZ,
+ /* FULL_NAME */ "Cache-block zero extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 37,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ziccamoa,
+ /* UPPERCASE_NAME */ ZICCAMOA,
+ /* FULL_NAME */ "Main memory supports all atomics in A",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ziccif,
+ /* UPPERCASE_NAME */ ZICCIF,
+ /* FULL_NAME */ "Main memory supports instruction fetch with atomicity requirement",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicclsm,
+ /* UPPERCASE_NAME */ ZICCLSM,
+ /* FULL_NAME */ "Main memory supports misaligned loads/stores",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ziccrse,
+ /* UPPERCASE_NAME */ ZICCRSE,
+ /* FULL_NAME */ "Main memory supports forward progress on LR/SC sequences",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicfilp,
+ /* UPPERCASE_NAME */ ZICFILP,
+ /* FULL_NAME */ "zicfilp extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicfiss,
+ /* UPPERCASE_NAME */ ZICFISS,
+ /* FULL_NAME */ "zicfiss extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr", "zimop"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicntr,
+ /* UPPERCASE_NAME */ ZICNTR,
+ /* FULL_NAME */ "Standard extension for base counters and timers",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicond,
+ /* UPPERCASE_NAME */ ZICOND,
+ /* FULL_NAME */ "Integer conditional operations extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 38,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zicsr,
+ /* UPPERCASE_NAME */ ZICSR,
+ /* FULL_NAME */ "Control and status register access extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zifencei,
+ /* UPPERCASE_NAME */ ZIFENCEI,
+ /* FULL_NAME */ "Instruction-fetch fence extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zihintntl,
+ /* UPPERCASE_NAME */ ZIHINTNTL,
+ /* FULL_NAME */ "Non-temporal locality hints extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 39,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zihintpause,
+ /* UPPERCASE_NAME */ ZIHINTPAUSE,
+ /* FULL_NAME */ "Pause hint extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 40,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zihpm,
+ /* UPPERCASE_NAME */ ZIHPM,
+ /* FULL_NAME */ "Standard extension for hardware performance counters",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{2, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zimop,
+ /* UPPERCASE_NAME */ ZIMOP,
+ /* FULL_NAME */ "zimop extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 1,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zilsd,
+ /* UPPERCASE_NAME */ ZILSD,
+ /* FULL_NAME */ "Load/Store pair instructions extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zi,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 1,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zmmul,
+ /* UPPERCASE_NAME */ ZMMUL,
+ /* FULL_NAME */ "Integer multiplication extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ za128rs,
+ /* UPPERCASE_NAME */ ZA128RS,
+ /* FULL_NAME */ "Reservation set size of 128 bytes",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ za64rs,
+ /* UPPERCASE_NAME */ ZA64RS,
+ /* FULL_NAME */ "Reservation set size of 64 bytes",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zaamo,
+ /* UPPERCASE_NAME */ ZAAMO,
+ /* FULL_NAME */ "zaamo extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zabha,
+ /* UPPERCASE_NAME */ ZABHA,
+ /* FULL_NAME */ "zabha extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zaamo"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zacas,
+ /* UPPERCASE_NAME */ ZACAS,
+ /* FULL_NAME */ "zacas extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zaamo"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 26,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zalrsc,
+ /* UPPERCASE_NAME */ ZALRSC,
+ /* FULL_NAME */ "zalrsc extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zawrs,
+ /* UPPERCASE_NAME */ ZAWRS,
+ /* FULL_NAME */ "Wait-on-reservation-set extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zalrsc"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 7,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zama16b,
+ /* UPPERCASE_NAME */ ZAMA16B,
+ /* FULL_NAME */ "Zama16b extension",
+ /* DESC */ "Misaligned loads, stores, and AMOs to main memory regions that do"
+ " not cross a naturally aligned 16-byte boundary are atomic.",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ za,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zfa,
+ /* UPPERCASE_NAME */ ZFA,
+ /* FULL_NAME */ "Additional floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"f"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zf,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 34,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zfbfmin,
+ /* UPPERCASE_NAME */ ZFBFMIN,
+ /* FULL_NAME */ "zfbfmin extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zfhmin"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zfh,
+ /* UPPERCASE_NAME */ ZFH,
+ /* FULL_NAME */ "Half-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zfhmin"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zf,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 35,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zfhmin,
+ /* UPPERCASE_NAME */ ZFHMIN,
+ /* FULL_NAME */ "Minimal half-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"f"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zf,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 36,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zfinx,
+ /* UPPERCASE_NAME */ ZFINX,
+ /* FULL_NAME */ "Single-precision floating-point in integer registers extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zinx,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zdinx,
+ /* UPPERCASE_NAME */ ZDINX,
+ /* FULL_NAME */ "Double-precision floating-point in integer registers extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zfinx", "zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zinx,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zca,
+ /* UPPERCASE_NAME */ ZCA,
+ /* FULL_NAME */ "Integer compressed instruction extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({{"c",
+[] (const riscv_subset_list *subset_list) -> bool
+{
+ /* For RV32 Zca implies C for one of these combinations of
+ extensions: Zca, F_Zca_Zcf and FD_Zca_Zcf_Zcd. */
+ if (subset_list->xlen () == 32)
+ {
+ if (subset_list->lookup ("d"))
+ return subset_list->lookup ("zcf") && subset_list->lookup ("zcd");
+
+ if (subset_list->lookup ("f"))
+ return subset_list->lookup ("zcf");
+
+ return true;
+ }
+
+ /* For RV64 Zca implies C for one of these combinations of
+ extensions: Zca and FD_Zca_Zcd (Zcf is not available
+ for RV64). */
+ if (subset_list->xlen () == 64)
+ {
+ if (subset_list->lookup ("d"))
+ return subset_list->lookup ("zcd");
+
+ return true;
+ }
+
+ /* Do nothing for future RV128 specification. Behaviour
+ for this case is not yet well defined. */
+ return false;
+
+}}}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 2,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcb,
+ /* UPPERCASE_NAME */ ZCB,
+ /* FULL_NAME */ "Simple compressed instruction extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 3,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcd,
+ /* UPPERCASE_NAME */ ZCD,
+ /* FULL_NAME */ "Compressed double-precision floating point loads and stores extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 4,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zce,
+ /* UPPERCASE_NAME */ ZCE,
+ /* FULL_NAME */ "Compressed instruction extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca", "zcb", "zcmp", "zcmt",
+ {"zcf",
+ [] (const riscv_subset_list *subset_list) -> bool
+ {
+ return subset_list->xlen () == 32
+ && subset_list->lookup ("f");
+ }}}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcf,
+ /* UPPERCASE_NAME */ ZCF,
+ /* FULL_NAME */ "Compressed single-precision floating point loads and stores extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 5,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcmop,
+ /* UPPERCASE_NAME */ ZCMOP,
+ /* FULL_NAME */ "zcmop extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 6,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcmp,
+ /* UPPERCASE_NAME */ ZCMP,
+ /* FULL_NAME */ "Compressed push pop extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zcmt,
+ /* UPPERCASE_NAME */ ZCMT,
+ /* FULL_NAME */ "Table jump instruction extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca", "zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zclsd,
+ /* UPPERCASE_NAME */ ZCLSD,
+ /* FULL_NAME */ "Compressed load/store pair instructions extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zca", "zilsd"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zc,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zba,
+ /* UPPERCASE_NAME */ ZBA,
+ /* FULL_NAME */ "Address calculation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 27,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbb,
+ /* UPPERCASE_NAME */ ZBB,
+ /* FULL_NAME */ "Basic bit manipulation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 28,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbc,
+ /* UPPERCASE_NAME */ ZBC,
+ /* FULL_NAME */ "Carry-less multiplication extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 29,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbkb,
+ /* UPPERCASE_NAME */ ZBKB,
+ /* FULL_NAME */ "Cryptography bit-manipulation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 30,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbkc,
+ /* UPPERCASE_NAME */ ZBKC,
+ /* FULL_NAME */ "Cryptography carry-less multiply extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 31,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbkx,
+ /* UPPERCASE_NAME */ ZBKX,
+ /* FULL_NAME */ "Cryptography crossbar permutation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 32,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zbs,
+ /* UPPERCASE_NAME */ ZBS,
+ /* FULL_NAME */ "Single-bit operation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 33,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zk,
+ /* UPPERCASE_NAME */ ZK,
+ /* FULL_NAME */ "Standard scalar cryptography extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zkn", "zkr", "zkt"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zkn,
+ /* UPPERCASE_NAME */ ZKN,
+ /* FULL_NAME */ "NIST algorithm suite extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zknd,
+ /* UPPERCASE_NAME */ ZKND,
+ /* FULL_NAME */ "AES Decryption extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 41,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zkne,
+ /* UPPERCASE_NAME */ ZKNE,
+ /* FULL_NAME */ "AES Encryption extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 42,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zknh,
+ /* UPPERCASE_NAME */ ZKNH,
+ /* FULL_NAME */ "Hash function extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 43,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zkr,
+ /* UPPERCASE_NAME */ ZKR,
+ /* FULL_NAME */ "Entropy source extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zks,
+ /* UPPERCASE_NAME */ ZKS,
+ /* FULL_NAME */ "ShangMi algorithm suite extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zbkb", "zbkc", "zbkx", "zksed", "zksh"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zksed,
+ /* UPPERCASE_NAME */ ZKSED,
+ /* FULL_NAME */ "SM4 block cipher extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 44,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zksh,
+ /* UPPERCASE_NAME */ ZKSH,
+ /* FULL_NAME */ "SM3 hash function extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 45,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zkt,
+ /* UPPERCASE_NAME */ ZKT,
+ /* FULL_NAME */ "Data independent execution latency extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 46,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ztso,
+ /* UPPERCASE_NAME */ ZTSO,
+ /* FULL_NAME */ "Total store ordering extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zt,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 47,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvbb,
+ /* UPPERCASE_NAME */ ZVBB,
+ /* FULL_NAME */ "Vector basic bit-manipulation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvkb"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 48,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvbc,
+ /* UPPERCASE_NAME */ ZVBC,
+ /* FULL_NAME */ "Vector carryless multiplication extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve64x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvb,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 49,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zve32f,
+ /* UPPERCASE_NAME */ ZVE32F,
+ /* FULL_NAME */ "Vector extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"f", "zve32x", "zvl32b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zve,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 61,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zve32x,
+ /* UPPERCASE_NAME */ ZVE32X,
+ /* FULL_NAME */ "Vector extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr", "zvl32b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zve,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 60,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zve64d,
+ /* UPPERCASE_NAME */ ZVE64D,
+ /* FULL_NAME */ "Vector extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"d", "zve64f", "zvl64b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zve,
+ /* BITMASK_GROUP_ID */ 1,
+ /* BITMASK_BIT_POSITION*/ 0,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zve64f,
+ /* UPPERCASE_NAME */ ZVE64F,
+ /* FULL_NAME */ "Vector extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"f", "zve32f", "zve64x", "zvl64b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zve,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 63,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zve64x,
+ /* UPPERCASE_NAME */ ZVE64X,
+ /* FULL_NAME */ "Vector extensions for embedded processors",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x", "zvl64b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zve,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 62,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvfbfmin,
+ /* UPPERCASE_NAME */ ZVFBFMIN,
+ /* FULL_NAME */ "Vector BF16 converts extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32f"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvfbfwma,
+ /* UPPERCASE_NAME */ ZVFBFWMA,
+ /* FULL_NAME */ "zvfbfwma extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvfbfmin", "zfbfmin"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvf,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvfh,
+ /* UPPERCASE_NAME */ ZVFH,
+ /* FULL_NAME */ "Vector half-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32f", "zfhmin"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvf,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 50,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvfhmin,
+ /* UPPERCASE_NAME */ ZVFHMIN,
+ /* FULL_NAME */ "Vector minimal half-precision floating-point extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32f"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvf,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 51,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkb,
+ /* UPPERCASE_NAME */ ZVKB,
+ /* FULL_NAME */ "Vector cryptography bit-manipulation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 52,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkg,
+ /* UPPERCASE_NAME */ ZVKG,
+ /* FULL_NAME */ "Vector GCM/GMAC extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 53,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkn,
+ /* UPPERCASE_NAME */ ZVKN,
+ /* FULL_NAME */ "Vector NIST Algorithm Suite extension",
+ /* DESC */ "@samp{zvkn} will expand to",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvkned", "zvknhb", "zvkb", "zvkt"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvknc,
+ /* UPPERCASE_NAME */ ZVKNC,
+ /* FULL_NAME */ "Vector NIST Algorithm Suite with carryless multiply extension, @samp{zvknc}",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvkn", "zvbc"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkned,
+ /* UPPERCASE_NAME */ ZVKNED,
+ /* FULL_NAME */ "Vector AES block cipher extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 54,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkng,
+ /* UPPERCASE_NAME */ ZVKNG,
+ /* FULL_NAME */ "Vector NIST Algorithm Suite with GCM extension, @samp{zvkng} will expand",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvkn", "zvkg"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvknha,
+ /* UPPERCASE_NAME */ ZVKNHA,
+ /* FULL_NAME */ "Vector SHA-2 secure hash extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 55,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvknhb,
+ /* UPPERCASE_NAME */ ZVKNHB,
+ /* FULL_NAME */ "Vector SHA-2 secure hash extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve64x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 56,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvks,
+ /* UPPERCASE_NAME */ ZVKS,
+ /* FULL_NAME */ "Vector ShangMi algorithm suite extension, @samp{zvks} will expand",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvksed", "zvksh", "zvkb", "zvkt"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvksc,
+ /* UPPERCASE_NAME */ ZVKSC,
+ /* FULL_NAME */ "Vector ShangMi algorithm suite with carryless multiplication extension,",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvks", "zvbc"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvksed,
+ /* UPPERCASE_NAME */ ZVKSED,
+ /* FULL_NAME */ "Vector SM4 Block Cipher extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 57,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvksg,
+ /* UPPERCASE_NAME */ ZVKSG,
+ /* FULL_NAME */ "Vector ShangMi algorithm suite with GCM extension, @samp{zvksg} will expand",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvks", "zvkg"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ EXT_FLAG_MACRO)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvksh,
+ /* UPPERCASE_NAME */ ZVKSH,
+ /* FULL_NAME */ "Vector SM3 Secure Hash extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zve32x"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 58,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvkt,
+ /* UPPERCASE_NAME */ ZVKT,
+ /* FULL_NAME */ "Vector data independent execution latency extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvk,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 59,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl1024b,
+ /* UPPERCASE_NAME */ ZVL1024B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl512b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl128b,
+ /* UPPERCASE_NAME */ ZVL128B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl64b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl16384b,
+ /* UPPERCASE_NAME */ ZVL16384B,
+ /* FULL_NAME */ "zvl16384b extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl8192b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl2048b,
+ /* UPPERCASE_NAME */ ZVL2048B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl1024b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl256b,
+ /* UPPERCASE_NAME */ ZVL256B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl128b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl32768b,
+ /* UPPERCASE_NAME */ ZVL32768B,
+ /* FULL_NAME */ "zvl32768b extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl16384b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl32b,
+ /* UPPERCASE_NAME */ ZVL32B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl4096b,
+ /* UPPERCASE_NAME */ ZVL4096B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl2048b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl512b,
+ /* UPPERCASE_NAME */ ZVL512B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl256b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl64b,
+ /* UPPERCASE_NAME */ ZVL64B,
+ /* FULL_NAME */ "Minimum vector length standard extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl32b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl65536b,
+ /* UPPERCASE_NAME */ ZVL65536B,
+ /* FULL_NAME */ "zvl65536b extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl32768b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zvl8192b,
+ /* UPPERCASE_NAME */ ZVL8192B,
+ /* FULL_NAME */ "zvl8192b extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zvl4096b"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zvl,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zhinx,
+ /* UPPERCASE_NAME */ ZHINX,
+ /* FULL_NAME */ "Half-precision floating-point in integer registers extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zhinxmin"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zinx,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ zhinxmin,
+ /* UPPERCASE_NAME */ ZHINXMIN,
+ /* FULL_NAME */ "Minimal half-precision floating-point in integer registers extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zfinx"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ zinx,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sdtrig,
+ /* UPPERCASE_NAME */ SDTRIG,
+ /* FULL_NAME */ "sdtrig extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sd,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sha,
+ /* UPPERCASE_NAME */ SHA,
+ /* FULL_NAME */ "The augmented hypervisor extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h", "shcounterenw", "shgatpa", "shtvala", "shvstvala", "shvstvecd", "shvsatpa", "ssstateen"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shcounterenw,
+ /* UPPERCASE_NAME */ SHCOUNTERENW,
+ /* FULL_NAME */ "Support writeable enables for any supported counter",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h", "zihpm"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shgatpa,
+ /* UPPERCASE_NAME */ SHGATPA,
+ /* FULL_NAME */ "SvNNx4 mode supported for all modes supported by satp",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h", "ssstateen"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shlcofideleg,
+ /* UPPERCASE_NAME */ SHLCOFIDELEG,
+ /* FULL_NAME */ "Delegating LCOFI interrupts to VS-mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shtvala,
+ /* UPPERCASE_NAME */ SHTVALA,
+ /* FULL_NAME */ "The htval register provides all needed values",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shvstvala,
+ /* UPPERCASE_NAME */ SHVSTVALA,
+ /* FULL_NAME */ "The vstval register provides all needed values",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shvstvecd,
+ /* UPPERCASE_NAME */ SHVSTVECD,
+ /* FULL_NAME */ "The vstvec register supports Direct mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ shvsatpa,
+ /* UPPERCASE_NAME */ SHVSATPA,
+ /* FULL_NAME */ "The vsatp register supports all modes supported by satp",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"h"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sh,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smaia,
+ /* UPPERCASE_NAME */ SMAIA,
+ /* FULL_NAME */ "Advanced interrupt architecture extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"ssaia"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smcntrpmf,
+ /* UPPERCASE_NAME */ SMCNTRPMF,
+ /* FULL_NAME */ "Cycle and instret privilege mode filtering",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smcsrind,
+ /* UPPERCASE_NAME */ SMCSRIND,
+ /* FULL_NAME */ "Machine-Level Indirect CSR Access",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr", "sscsrind"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smepmp,
+ /* UPPERCASE_NAME */ SMEPMP,
+ /* FULL_NAME */ "PMP Enhancements for memory access and execution prevention on Machine mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smmpm,
+ /* UPPERCASE_NAME */ SMMPM,
+ /* FULL_NAME */ "smmpm extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smnpm,
+ /* UPPERCASE_NAME */ SMNPM,
+ /* FULL_NAME */ "smnpm extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smrnmi,
+ /* UPPERCASE_NAME */ SMRNMI,
+ /* FULL_NAME */ "Resumable non-maskable interrupts",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smstateen,
+ /* UPPERCASE_NAME */ SMSTATEEN,
+ /* FULL_NAME */ "State enable extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"ssstateen"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ smdbltrp,
+ /* UPPERCASE_NAME */ SMDBLTRP,
+ /* FULL_NAME */ "Double Trap Extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sm,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssaia,
+ /* UPPERCASE_NAME */ SSAIA,
+ /* FULL_NAME */ "Advanced interrupt architecture extension for supervisor-mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssccptr,
+ /* UPPERCASE_NAME */ SSCCPTR,
+ /* FULL_NAME */ "Main memory supports page table reads",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sscofpmf,
+ /* UPPERCASE_NAME */ SSCOFPMF,
+ /* FULL_NAME */ "Count overflow & filtering extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sscounterenw,
+ /* UPPERCASE_NAME */ SSCOUNTERENW,
+ /* FULL_NAME */ "Support writeable enables for any supported counter",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sscsrind,
+ /* UPPERCASE_NAME */ SSCSRIND,
+ /* FULL_NAME */ "Supervisor-Level Indirect CSR Access",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssnpm,
+ /* UPPERCASE_NAME */ SSNPM,
+ /* FULL_NAME */ "ssnpm extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sspm,
+ /* UPPERCASE_NAME */ SSPM,
+ /* FULL_NAME */ "sspm extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssstateen,
+ /* UPPERCASE_NAME */ SSSTATEEN,
+ /* FULL_NAME */ "State-enable extension for supervisor-mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sstc,
+ /* UPPERCASE_NAME */ SSTC,
+ /* FULL_NAME */ "Supervisor-mode timer interrupts extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sstvala,
+ /* UPPERCASE_NAME */ SSTVALA,
+ /* FULL_NAME */ "Stval provides all needed values",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ sstvecd,
+ /* UPPERCASE_NAME */ SSTVECD,
+ /* FULL_NAME */ "Stvec supports Direct mode",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssstrict,
+ /* UPPERCASE_NAME */ SSSTRICT,
+ /* FULL_NAME */ "ssstrict extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssdbltrp,
+ /* UPPERCASE_NAME */ SSDBLTRP,
+ /* FULL_NAME */ "Double Trap Extensions",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ ssu64xl,
+ /* UPPERCASE_NAME */ SSU64XL,
+ /* FULL_NAME */ "UXLEN=64 must be supported",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ ss,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ supm,
+ /* UPPERCASE_NAME */ SUPM,
+ /* FULL_NAME */ "supm extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ su,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svinval,
+ /* UPPERCASE_NAME */ SVINVAL,
+ /* FULL_NAME */ "Fine-grained address-translation cache invalidation extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svnapot,
+ /* UPPERCASE_NAME */ SVNAPOT,
+ /* FULL_NAME */ "NAPOT translation contiguity extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svpbmt,
+ /* UPPERCASE_NAME */ SVPBMT,
+ /* FULL_NAME */ "Page-based memory types extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svvptc,
+ /* UPPERCASE_NAME */ SVVPTC,
+ /* FULL_NAME */ "svvptc extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svadu,
+ /* UPPERCASE_NAME */ SVADU,
+ /* FULL_NAME */ "Hardware Updating of A/D Bits extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svade,
+ /* UPPERCASE_NAME */ SVADE,
+ /* FULL_NAME */ "Cause exception when hardware updating of A/D bits is disabled",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+DEFINE_RISCV_EXT(
+ /* NAME */ svbare,
+ /* UPPERCASE_NAME */ SVBARE,
+ /* FULL_NAME */ "Satp mode bare is supported",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"zicsr"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ sv,
+ /* BITMASK_GROUP_ID */ BITMASK_NOT_YET_ALLOCATED,
+ /* BITMASK_BIT_POSITION*/ BITMASK_NOT_YET_ALLOCATED,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+
+#include "riscv-ext-corev.def"
+#include "riscv-ext-sifive.def"
+#include "riscv-ext-thead.def"
+#include "riscv-ext-ventana.def"
diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt
new file mode 100644
index 0000000..9f8c545
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext.opt
@@ -0,0 +1,447 @@
+; Target options for the RISC-V port of the compiler
+;
+; Copyright (C) 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/>.
+; This file is generated automatically using
+; gcc/config/riscv/gen-riscv-ext-opt.cc from:
+; gcc/config/riscv/riscv-ext.def
+
+; Please *DO NOT* edit manually.
+TargetVariable
+int riscv_base_subext
+
+TargetVariable
+int riscv_sd_subext
+
+TargetVariable
+int riscv_sh_subext
+
+TargetVariable
+int riscv_sm_subext
+
+TargetVariable
+int riscv_ss_subext
+
+TargetVariable
+int riscv_su_subext
+
+TargetVariable
+int riscv_sv_subext
+
+TargetVariable
+int riscv_xcv_subext
+
+TargetVariable
+int riscv_xsf_subext
+
+TargetVariable
+int riscv_xthead_subext
+
+TargetVariable
+int riscv_xventana_subext
+
+TargetVariable
+int riscv_za_subext
+
+TargetVariable
+int riscv_zb_subext
+
+TargetVariable
+int riscv_zc_subext
+
+TargetVariable
+int riscv_zf_subext
+
+TargetVariable
+int riscv_zi_subext
+
+TargetVariable
+int riscv_zinx_subext
+
+TargetVariable
+int riscv_zk_subext
+
+TargetVariable
+int riscv_zm_subext
+
+TargetVariable
+int riscv_zt_subext
+
+TargetVariable
+int riscv_zvb_subext
+
+TargetVariable
+int riscv_zve_subext
+
+TargetVariable
+int riscv_zvf_subext
+
+TargetVariable
+int riscv_zvk_subext
+
+TargetVariable
+int riscv_zvl_subext
+
+Mask(RVE) Var(riscv_base_subext)
+
+Mask(RVI) Var(riscv_base_subext)
+
+Mask(MUL) Var(riscv_base_subext)
+
+Mask(ATOMIC) Var(riscv_base_subext)
+
+Mask(HARD_FLOAT) Var(riscv_base_subext)
+
+Mask(DOUBLE_FLOAT) Var(riscv_base_subext)
+
+Mask(RVC) Var(riscv_base_subext)
+
+Mask(RVB) Var(riscv_base_subext)
+
+Mask(RVV) Var(riscv_base_subext)
+
+Mask(RVH) Var(riscv_base_subext)
+
+Mask(ZIC64B) Var(riscv_zi_subext)
+
+Mask(ZICBOM) Var(riscv_zi_subext)
+
+Mask(ZICBOP) Var(riscv_zi_subext)
+
+Mask(ZICBOZ) Var(riscv_zi_subext)
+
+Mask(ZICCAMOA) Var(riscv_zi_subext)
+
+Mask(ZICCIF) Var(riscv_zi_subext)
+
+Mask(ZICCLSM) Var(riscv_zi_subext)
+
+Mask(ZICCRSE) Var(riscv_zi_subext)
+
+Mask(ZICFILP) Var(riscv_zi_subext)
+
+Mask(ZICFISS) Var(riscv_zi_subext)
+
+Mask(ZICNTR) Var(riscv_zi_subext)
+
+Mask(ZICOND) Var(riscv_zi_subext)
+
+Mask(ZICSR) Var(riscv_zi_subext)
+
+Mask(ZIFENCEI) Var(riscv_zi_subext)
+
+Mask(ZIHINTNTL) Var(riscv_zi_subext)
+
+Mask(ZIHINTPAUSE) Var(riscv_zi_subext)
+
+Mask(ZIHPM) Var(riscv_zi_subext)
+
+Mask(ZIMOP) Var(riscv_zi_subext)
+
+Mask(ZILSD) Var(riscv_zi_subext)
+
+Mask(ZMMUL) Var(riscv_zm_subext)
+
+Mask(ZA128RS) Var(riscv_za_subext)
+
+Mask(ZA64RS) Var(riscv_za_subext)
+
+Mask(ZAAMO) Var(riscv_za_subext)
+
+Mask(ZABHA) Var(riscv_za_subext)
+
+Mask(ZACAS) Var(riscv_za_subext)
+
+Mask(ZALRSC) Var(riscv_za_subext)
+
+Mask(ZAWRS) Var(riscv_za_subext)
+
+Mask(ZAMA16B) Var(riscv_za_subext)
+
+Mask(ZFA) Var(riscv_zf_subext)
+
+Mask(ZFBFMIN) Var(riscv_zf_subext)
+
+Mask(ZFH) Var(riscv_zf_subext)
+
+Mask(ZFHMIN) Var(riscv_zf_subext)
+
+Mask(ZFINX) Var(riscv_zinx_subext)
+
+Mask(ZDINX) Var(riscv_zinx_subext)
+
+Mask(ZCA) Var(riscv_zc_subext)
+
+Mask(ZCB) Var(riscv_zc_subext)
+
+Mask(ZCD) Var(riscv_zc_subext)
+
+Mask(ZCE) Var(riscv_zc_subext)
+
+Mask(ZCF) Var(riscv_zc_subext)
+
+Mask(ZCMOP) Var(riscv_zc_subext)
+
+Mask(ZCMP) Var(riscv_zc_subext)
+
+Mask(ZCMT) Var(riscv_zc_subext)
+
+Mask(ZCLSD) Var(riscv_zc_subext)
+
+Mask(ZBA) Var(riscv_zb_subext)
+
+Mask(ZBB) Var(riscv_zb_subext)
+
+Mask(ZBC) Var(riscv_zb_subext)
+
+Mask(ZBKB) Var(riscv_zb_subext)
+
+Mask(ZBKC) Var(riscv_zb_subext)
+
+Mask(ZBKX) Var(riscv_zb_subext)
+
+Mask(ZBS) Var(riscv_zb_subext)
+
+Mask(ZK) Var(riscv_zk_subext)
+
+Mask(ZKN) Var(riscv_zk_subext)
+
+Mask(ZKND) Var(riscv_zk_subext)
+
+Mask(ZKNE) Var(riscv_zk_subext)
+
+Mask(ZKNH) Var(riscv_zk_subext)
+
+Mask(ZKR) Var(riscv_zk_subext)
+
+Mask(ZKS) Var(riscv_zk_subext)
+
+Mask(ZKSED) Var(riscv_zk_subext)
+
+Mask(ZKSH) Var(riscv_zk_subext)
+
+Mask(ZKT) Var(riscv_zk_subext)
+
+Mask(ZTSO) Var(riscv_zt_subext)
+
+Mask(ZVBB) Var(riscv_zvb_subext)
+
+Mask(ZVBC) Var(riscv_zvb_subext)
+
+Mask(ZVE32F) Var(riscv_zve_subext)
+
+Mask(ZVE32X) Var(riscv_zve_subext)
+
+Mask(ZVE64D) Var(riscv_zve_subext)
+
+Mask(ZVE64F) Var(riscv_zve_subext)
+
+Mask(ZVE64X) Var(riscv_zve_subext)
+
+Mask(ZVFBFMIN) Var(riscv_zvf_subext)
+
+Mask(ZVFBFWMA) Var(riscv_zvf_subext)
+
+Mask(ZVFH) Var(riscv_zvf_subext)
+
+Mask(ZVFHMIN) Var(riscv_zvf_subext)
+
+Mask(ZVKB) Var(riscv_zvk_subext)
+
+Mask(ZVKG) Var(riscv_zvk_subext)
+
+Mask(ZVKN) Var(riscv_zvk_subext)
+
+Mask(ZVKNC) Var(riscv_zvk_subext)
+
+Mask(ZVKNED) Var(riscv_zvk_subext)
+
+Mask(ZVKNG) Var(riscv_zvk_subext)
+
+Mask(ZVKNHA) Var(riscv_zvk_subext)
+
+Mask(ZVKNHB) Var(riscv_zvk_subext)
+
+Mask(ZVKS) Var(riscv_zvk_subext)
+
+Mask(ZVKSC) Var(riscv_zvk_subext)
+
+Mask(ZVKSED) Var(riscv_zvk_subext)
+
+Mask(ZVKSG) Var(riscv_zvk_subext)
+
+Mask(ZVKSH) Var(riscv_zvk_subext)
+
+Mask(ZVKT) Var(riscv_zvk_subext)
+
+Mask(ZVL1024B) Var(riscv_zvl_subext)
+
+Mask(ZVL128B) Var(riscv_zvl_subext)
+
+Mask(ZVL16384B) Var(riscv_zvl_subext)
+
+Mask(ZVL2048B) Var(riscv_zvl_subext)
+
+Mask(ZVL256B) Var(riscv_zvl_subext)
+
+Mask(ZVL32768B) Var(riscv_zvl_subext)
+
+Mask(ZVL32B) Var(riscv_zvl_subext)
+
+Mask(ZVL4096B) Var(riscv_zvl_subext)
+
+Mask(ZVL512B) Var(riscv_zvl_subext)
+
+Mask(ZVL64B) Var(riscv_zvl_subext)
+
+Mask(ZVL65536B) Var(riscv_zvl_subext)
+
+Mask(ZVL8192B) Var(riscv_zvl_subext)
+
+Mask(ZHINX) Var(riscv_zinx_subext)
+
+Mask(ZHINXMIN) Var(riscv_zinx_subext)
+
+Mask(SDTRIG) Var(riscv_sd_subext)
+
+Mask(SHA) Var(riscv_sh_subext)
+
+Mask(SHCOUNTERENW) Var(riscv_sh_subext)
+
+Mask(SHGATPA) Var(riscv_sh_subext)
+
+Mask(SHLCOFIDELEG) Var(riscv_sh_subext)
+
+Mask(SHTVALA) Var(riscv_sh_subext)
+
+Mask(SHVSTVALA) Var(riscv_sh_subext)
+
+Mask(SHVSTVECD) Var(riscv_sh_subext)
+
+Mask(SHVSATPA) Var(riscv_sh_subext)
+
+Mask(SMAIA) Var(riscv_sm_subext)
+
+Mask(SMCNTRPMF) Var(riscv_sm_subext)
+
+Mask(SMCSRIND) Var(riscv_sm_subext)
+
+Mask(SMEPMP) Var(riscv_sm_subext)
+
+Mask(SMMPM) Var(riscv_sm_subext)
+
+Mask(SMNPM) Var(riscv_sm_subext)
+
+Mask(SMRNMI) Var(riscv_sm_subext)
+
+Mask(SMSTATEEN) Var(riscv_sm_subext)
+
+Mask(SMDBLTRP) Var(riscv_sm_subext)
+
+Mask(SSAIA) Var(riscv_ss_subext)
+
+Mask(SSCCPTR) Var(riscv_ss_subext)
+
+Mask(SSCOFPMF) Var(riscv_ss_subext)
+
+Mask(SSCOUNTERENW) Var(riscv_ss_subext)
+
+Mask(SSCSRIND) Var(riscv_ss_subext)
+
+Mask(SSNPM) Var(riscv_ss_subext)
+
+Mask(SSPM) Var(riscv_ss_subext)
+
+Mask(SSSTATEEN) Var(riscv_ss_subext)
+
+Mask(SSTC) Var(riscv_ss_subext)
+
+Mask(SSTVALA) Var(riscv_ss_subext)
+
+Mask(SSTVECD) Var(riscv_ss_subext)
+
+Mask(SSSTRICT) Var(riscv_ss_subext)
+
+Mask(SSDBLTRP) Var(riscv_ss_subext)
+
+Mask(SSU64XL) Var(riscv_ss_subext)
+
+Mask(SUPM) Var(riscv_su_subext)
+
+Mask(SVINVAL) Var(riscv_sv_subext)
+
+Mask(SVNAPOT) Var(riscv_sv_subext)
+
+Mask(SVPBMT) Var(riscv_sv_subext)
+
+Mask(SVVPTC) Var(riscv_sv_subext)
+
+Mask(SVADU) Var(riscv_sv_subext)
+
+Mask(SVADE) Var(riscv_sv_subext)
+
+Mask(SVBARE) Var(riscv_sv_subext)
+
+Mask(XCVALU) Var(riscv_xcv_subext)
+
+Mask(XCVBI) Var(riscv_xcv_subext)
+
+Mask(XCVELW) Var(riscv_xcv_subext)
+
+Mask(XCVMAC) Var(riscv_xcv_subext)
+
+Mask(XCVSIMD) Var(riscv_xcv_subext)
+
+Mask(XSFCEASE) Var(riscv_xsf_subext)
+
+Mask(XSFVCP) Var(riscv_xsf_subext)
+
+Mask(XSFVFNRCLIPXFQF) Var(riscv_xsf_subext)
+
+Mask(XSFVQMACCDOD) Var(riscv_xsf_subext)
+
+Mask(XSFVQMACCQOQ) Var(riscv_xsf_subext)
+
+Mask(XTHEADBA) Var(riscv_xthead_subext)
+
+Mask(XTHEADBB) Var(riscv_xthead_subext)
+
+Mask(XTHEADBS) Var(riscv_xthead_subext)
+
+Mask(XTHEADCMO) Var(riscv_xthead_subext)
+
+Mask(XTHEADCONDMOV) Var(riscv_xthead_subext)
+
+Mask(XTHEADFMEMIDX) Var(riscv_xthead_subext)
+
+Mask(XTHEADFMV) Var(riscv_xthead_subext)
+
+Mask(XTHEADINT) Var(riscv_xthead_subext)
+
+Mask(XTHEADMAC) Var(riscv_xthead_subext)
+
+Mask(XTHEADMEMIDX) Var(riscv_xthead_subext)
+
+Mask(XTHEADMEMPAIR) Var(riscv_xthead_subext)
+
+Mask(XTHEADSYNC) Var(riscv_xthead_subext)
+
+Mask(XTHEADVECTOR) Var(riscv_xthead_subext)
+
+Mask(XVENTANACONDOPS) Var(riscv_xventana_subext)
+
diff --git a/gcc/config/riscv/riscv-ext.opt.urls b/gcc/config/riscv/riscv-ext.opt.urls
new file mode 100644
index 0000000..c4f4710
--- /dev/null
+++ b/gcc/config/riscv/riscv-ext.opt.urls
@@ -0,0 +1,2 @@
+; Autogenerated by regenerate-opt-urls.py from gcc/config/riscv/riscv-ext.opt and generated HTML
+
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 26fe228..e1a820b 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -58,7 +58,8 @@ enum riscv_microarchitecture_type {
sifive_p400,
sifive_p600,
xiangshan,
- generic_ooo
+ generic_ooo,
+ mips_p8700,
};
extern enum riscv_microarchitecture_type riscv_microarchitecture;
@@ -136,16 +137,16 @@ enum rvv_vector_bits_enum {
/* Bit of riscv_zvl_flags will set continually, N-1 bit will set if N-bit is
set, e.g. MASK_ZVL64B has set then MASK_ZVL32B is set, so we can use
popcount to calculate the minimal VLEN. */
-#define TARGET_MIN_VLEN \
- ((riscv_zvl_flags == 0) \
- ? 0 \
- : 32 << (__builtin_popcount (riscv_zvl_flags) - 1))
+#define TARGET_MIN_VLEN \
+ ((riscv_zvl_subext == 0) \
+ ? 0 \
+ : 32 << (__builtin_popcount (riscv_zvl_subext) - 1))
/* Same as TARGET_MIN_VLEN, but take an OPTS as gcc_options. */
#define TARGET_MIN_VLEN_OPTS(opts) \
- ((opts->x_riscv_zvl_flags == 0) \
+ ((opts->x_riscv_zvl_subext == 0) \
? 0 \
- : 32 << (__builtin_popcount (opts->x_riscv_zvl_flags) - 1))
+ : 32 << (__builtin_popcount (opts->x_riscv_zvl_subext) - 1))
/* The maximum LMUL according to user configuration. */
#define TARGET_MAX_LMUL \
@@ -162,4 +163,15 @@ enum riscv_tls_type {
#define TARGET_VECTOR_AUTOVEC_SEGMENT \
(TARGET_VECTOR && riscv_mautovec_segment)
+#define GPR2VR_COST_UNPROVIDED -1
+#define FPR2VR_COST_UNPROVIDED -1
+
+/* Extra extension flags, used for carry extra info for a RISC-V extension. */
+enum
+{
+ EXT_FLAG_MACRO = 1 << 0,
+};
+
+#define BITMASK_NOT_YET_ALLOCATED -1
+
#endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 2e88990..38f63ea 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -137,9 +137,12 @@ extern void riscv_expand_usadd (rtx, rtx, rtx);
extern void riscv_expand_ssadd (rtx, rtx, rtx);
extern void riscv_expand_ussub (rtx, rtx, rtx);
extern void riscv_expand_sssub (rtx, rtx, rtx);
+extern void riscv_expand_usmul (rtx, rtx, rtx);
extern void riscv_expand_ustrunc (rtx, rtx);
extern void riscv_expand_sstrunc (rtx, rtx);
extern int riscv_register_move_cost (machine_mode, reg_class_t, reg_class_t);
+extern bool synthesize_ior_xor (rtx_code, rtx [3]);
+extern bool synthesize_and (rtx [3]);
#ifdef RTX_CODE
extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
@@ -666,6 +669,8 @@ void expand_vec_oct_ustrunc (rtx, rtx, machine_mode, machine_mode,
machine_mode);
void expand_vec_oct_sstrunc (rtx, rtx, machine_mode, machine_mode,
machine_mode);
+void expand_vx_binary_vec_dup_vec (rtx, rtx, rtx, rtx_code, machine_mode);
+void expand_vx_binary_vec_vec_dup (rtx, rtx, rtx, rtx_code, machine_mode);
#endif
bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
bool, void (*)(rtx *, rtx), enum avl_type);
@@ -836,6 +841,8 @@ struct riscv_tune_info {
const struct riscv_tune_info *
riscv_parse_tune (const char *, bool);
const cpu_vector_cost *get_vector_costs ();
+int get_gr2vr_cost ();
+int get_fr2vr_cost ();
enum
{
diff --git a/gcc/config/riscv/riscv-shorten-memrefs.cc b/gcc/config/riscv/riscv-shorten-memrefs.cc
index 60f330e..2e3d9f6 100644
--- a/gcc/config/riscv/riscv-shorten-memrefs.cc
+++ b/gcc/config/riscv/riscv-shorten-memrefs.cc
@@ -189,8 +189,7 @@ pass_shorten_memrefs::transform (regno_map *m, basic_block bb)
}
}
}
- rtx_insn *seq = get_insns ();
- end_sequence ();
+ rtx_insn *seq = end_sequence ();
emit_insn_before (seq, insn);
}
}
diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h
index 559e708..a35537d 100644
--- a/gcc/config/riscv/riscv-subset.h
+++ b/gcc/config/riscv/riscv-subset.h
@@ -82,6 +82,8 @@ private:
const char *parse_single_multiletter_ext (const char *, const char *,
const char *, bool);
+ std::string parse_profiles (const char*);
+
void handle_implied_ext (const char *);
bool check_implied_ext ();
void handle_combine_ext ();
@@ -107,9 +109,6 @@ public:
static riscv_subset_list *parse (const char *, location_t);
const char *parse_single_ext (const char *, bool exact_single_p = true);
- const riscv_subset_t *begin () const {return m_head;};
- const riscv_subset_t *end () const {return NULL;};
-
int match_score (riscv_subset_list *) const;
void set_loc (location_t);
@@ -117,6 +116,65 @@ public:
void set_allow_adding_dup (bool v) { m_allow_adding_dup = v; }
void finalize ();
+
+ class iterator
+ {
+ public:
+ explicit iterator(riscv_subset_t *node) : m_node(node) {}
+
+ riscv_subset_t &operator*() const { return *m_node; }
+ riscv_subset_t *operator->() const { return m_node; }
+
+ iterator &operator++()
+ {
+ if (m_node)
+ m_node = m_node->next;
+ return *this;
+ }
+
+ bool operator!=(const iterator &other) const
+ {
+ return m_node != other.m_node;
+ }
+
+ bool operator==(const iterator &other) const
+ {
+ return m_node == other.m_node;
+ }
+
+ private:
+ riscv_subset_t *m_node;
+ };
+
+ iterator begin() { return iterator(m_head); }
+ iterator end() { return iterator(nullptr); }
+
+ class const_iterator
+ {
+ public:
+ explicit const_iterator(const riscv_subset_t *node) : m_node(node) {}
+
+ const riscv_subset_t &operator*() const { return *m_node; }
+ const riscv_subset_t *operator->() const { return m_node; }
+
+ const_iterator &operator++()
+ {
+ if (m_node)
+ m_node = m_node->next;
+ return *this;
+ }
+
+ bool operator!=(const const_iterator &other) const
+ {
+ return m_node != other.m_node;
+ }
+
+ private:
+ const riscv_subset_t *m_node;
+ };
+
+ const_iterator begin() const { return const_iterator(m_head); }
+ const_iterator end() const { return const_iterator(nullptr); }
};
extern const riscv_subset_list *riscv_cmdline_subset_list (void);
@@ -127,6 +185,5 @@ extern bool riscv_minimal_hwprobe_feature_bits (const char *,
location_t);
extern bool
riscv_ext_is_subset (struct cl_target_option *, struct cl_target_option *);
-extern int riscv_x_target_flags_isa_mask (void);
#endif /* ! GCC_RISCV_SUBSET_H */
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 66c8b29..22d1949 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -408,7 +408,7 @@ emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
gcc_assert (!can_create_pseudo_p ());
machine_mode mode = GET_MODE (ops[0]);
- if (imm_avl_p (mode))
+ if (imm_avl_p (mode) && !TARGET_XTHEADVECTOR)
{
/* Even though VL is a real hardreg already allocated since
it is post-RA now, we still gain benefits that we emit
@@ -1598,7 +1598,7 @@ expand_const_vector_interleaved_stepped_npatterns (rtx target, rtx src,
shifted_vid = gen_reg_rtx (mode);
rtx shift = gen_int_mode (1, Xmode);
rtx shift_ops[] = {shifted_vid, vid, shift};
- emit_vlmax_insn (code_for_pred_scalar (ASHIFT, mode), BINARY_OP,
+ emit_vlmax_insn (code_for_pred_scalar (LSHIFTRT, mode), BINARY_OP,
shift_ops);
}
else
@@ -2821,6 +2821,28 @@ autovectorize_vector_modes (vector_modes *modes, bool)
i++;
size = base_size / (1U << i);
}
+
+ /* If the user specified the exact mode to use look if it is available and
+ remove all other ones before returning. */
+ if (riscv_autovec_mode)
+ {
+ auto_vector_modes ms;
+ ms.safe_splice (*modes);
+ modes->truncate (0);
+
+ for (machine_mode mode : ms)
+ {
+ if (!strcmp (GET_MODE_NAME (mode), riscv_autovec_mode))
+ {
+ modes->safe_push (mode);
+ return 0;
+ }
+ }
+
+ /* Nothing found, fall back to regular handling. */
+ modes->safe_splice (ms);
+ }
+
/* Enable LOOP_VINFO comparison in COST model. */
return VECT_COMPARE_COSTS;
}
@@ -4701,7 +4723,7 @@ prepare_ternary_operands (rtx *ops)
ops[4], ops[1], ops[6], ops[7], ops[9]));
ops[5] = ops[4] = ops[0];
}
- else
+ else if (VECTOR_MODE_P (GET_MODE (ops[2])))
{
/* Swap the multiplication ops if the fallback value is the
second of the two. */
@@ -4711,8 +4733,10 @@ prepare_ternary_operands (rtx *ops)
/* TODO: ??? Maybe we could support splitting FMA (a, 4, b)
into PLUS (ASHIFT (a, 2), b) according to uarchs. */
}
- gcc_assert (rtx_equal_p (ops[5], RVV_VUNDEF (mode))
- || rtx_equal_p (ops[5], ops[2]) || rtx_equal_p (ops[5], ops[4]));
+ gcc_assert (
+ rtx_equal_p (ops[5], RVV_VUNDEF (mode)) || rtx_equal_p (ops[5], ops[2])
+ || (!VECTOR_MODE_P (GET_MODE (ops[2])) && rtx_equal_p (ops[5], ops[3]))
+ || rtx_equal_p (ops[5], ops[4]));
}
/* Expand VEC_MASK_LEN_{LOAD_LANES,STORE_LANES}. */
@@ -5498,6 +5522,80 @@ expand_vec_oct_sstrunc (rtx op_0, rtx op_1, machine_mode vec_mode,
expand_vec_double_sstrunc (op_0, quad_rtx, quad_mode);
}
+/* Expand the binary vx combine with the format like v2 = vop(vec_dup(x), v1).
+ Aka the first op comes from the vec_duplicate, and the second op is
+ the vector reg. */
+
+void
+expand_vx_binary_vec_dup_vec (rtx op_0, rtx op_1, rtx op_2,
+ rtx_code code, machine_mode mode)
+{
+ enum insn_code icode;
+
+ switch (code)
+ {
+ case PLUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case MULT:
+ case SMAX:
+ case UMAX:
+ case SMIN:
+ case UMIN:
+ case US_PLUS:
+ case SS_PLUS:
+ icode = code_for_pred_scalar (code, mode);
+ break;
+ case MINUS:
+ icode = code_for_pred_sub_reverse_scalar (mode);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ rtx ops[] = {op_0, op_1, op_2};
+ emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+}
+
+/* Expand the binary vx combine with the format like v2 = vop(v1, vec_dup(x)).
+ Aka the second op comes from the vec_duplicate, and the first op is
+ the vector reg. */
+
+void
+expand_vx_binary_vec_vec_dup (rtx op_0, rtx op_1, rtx op_2,
+ rtx_code code, machine_mode mode)
+{
+ enum insn_code icode;
+
+ switch (code)
+ {
+ case MINUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case MULT:
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ case SMAX:
+ case UMAX:
+ case SMIN:
+ case UMIN:
+ case US_PLUS:
+ case US_MINUS:
+ case SS_PLUS:
+ icode = code_for_pred_scalar (code, mode);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ rtx ops[] = {op_0, op_1, op_2};
+ emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+}
+
/* Vectorize popcount by the Wilkes-Wheeler-Gill algorithm that libgcc uses as
well. */
void
diff --git a/gcc/config/riscv/riscv-vect-permconst.cc b/gcc/config/riscv/riscv-vect-permconst.cc
index feecc7e..087f26a 100644
--- a/gcc/config/riscv/riscv-vect-permconst.cc
+++ b/gcc/config/riscv/riscv-vect-permconst.cc
@@ -203,15 +203,33 @@ vector_permconst::process_bb (basic_block bb)
if (bias < 0 || bias > 16384 / 8)
continue;
+ /* We need to verify that each element would be a valid value
+ in the inner mode after applying the bias. */
+ machine_mode inner = GET_MODE_INNER (GET_MODE (cvec));
+ HOST_WIDE_INT precision = GET_MODE_PRECISION (inner).to_constant ();
+ int i;
+ for (i = 0; i < CONST_VECTOR_NUNITS (cvec).to_constant (); i++)
+ {
+ HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (cvec, i)) - bias;
+ if (val != sext_hwi (val, precision))
+ break;
+ }
+
+ /* If the loop terminated early, then we found a case where the
+ adjusted constant would not fit, so we can't record the constant
+ for this case (it's unlikely to be useful anyway. */
+ if (i != CONST_VECTOR_NUNITS (cvec).to_constant ())
+ continue;
+
/* At this point we have a load of a constant integer vector from the
constant pool. That constant integer vector is hopefully a
permutation constant. We need to make a copy of the vector and
normalize it to zero.
XXX This violates structure sharing conventions. */
- rtvec_def *nvec = gen_rtvec (CONST_VECTOR_NUNITS (cvec).to_constant ());
+ rtvec_def *nvec = rtvec_alloc (CONST_VECTOR_NUNITS (cvec).to_constant ());
- for (int i = 0; i < CONST_VECTOR_NUNITS (cvec).to_constant (); i++)
+ for (i = 0; i < CONST_VECTOR_NUNITS (cvec).to_constant (); i++)
nvec->elem[i] = GEN_INT (INTVAL (CONST_VECTOR_ELT (cvec, i)) - bias);
rtx copy = gen_rtx_CONST_VECTOR (GET_MODE (cvec), nvec);
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index b855d4c..9832eb9 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -908,6 +908,8 @@ struct vset_def : public build_base
{
poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
poly_int64 inner_size = GET_MODE_SIZE (c.arg_mode (2));
+ if (maybe_eq (inner_size, 0))
+ return false;
unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
return c.require_immediate (1, 0, nvecs - 1);
}
@@ -920,6 +922,8 @@ struct vget_def : public misc_def
{
poly_int64 outer_size = GET_MODE_SIZE (c.arg_mode (0));
poly_int64 inner_size = GET_MODE_SIZE (c.ret_mode ());
+ if (maybe_eq (inner_size, 0))
+ return false;
unsigned int nvecs = exact_div (outer_size, inner_size).to_constant ();
return c.require_immediate (1, 0, nvecs - 1);
}
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc
index f3c706bf..8810af0 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -3842,26 +3842,26 @@ check_required_extensions (const function_instance &instance)
required_extensions |= RVV_REQUIRE_RV64BIT;
}
- uint64_t riscv_isa_flags = 0;
+ uint64_t isa_flags = 0;
if (TARGET_VECTOR_ELEN_BF_16)
- riscv_isa_flags |= RVV_REQUIRE_ELEN_BF_16;
+ isa_flags |= RVV_REQUIRE_ELEN_BF_16;
if (TARGET_VECTOR_ELEN_FP_16)
- riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_16;
+ isa_flags |= RVV_REQUIRE_ELEN_FP_16;
if (TARGET_VECTOR_ELEN_FP_32)
- riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_32;
+ isa_flags |= RVV_REQUIRE_ELEN_FP_32;
if (TARGET_VECTOR_ELEN_FP_64)
- riscv_isa_flags |= RVV_REQUIRE_ELEN_FP_64;
+ isa_flags |= RVV_REQUIRE_ELEN_FP_64;
if (TARGET_VECTOR_ELEN_64)
- riscv_isa_flags |= RVV_REQUIRE_ELEN_64;
+ isa_flags |= RVV_REQUIRE_ELEN_64;
if (TARGET_64BIT)
- riscv_isa_flags |= RVV_REQUIRE_RV64BIT;
+ isa_flags |= RVV_REQUIRE_RV64BIT;
if (TARGET_FULL_V)
- riscv_isa_flags |= RVV_REQUIRE_FULL_V;
+ isa_flags |= RVV_REQUIRE_FULL_V;
if (TARGET_MIN_VLEN > 32)
- riscv_isa_flags |= RVV_REQUIRE_MIN_VLEN_64;
+ isa_flags |= RVV_REQUIRE_MIN_VLEN_64;
- uint64_t missing_extensions = required_extensions & ~riscv_isa_flags;
+ uint64_t missing_extensions = required_extensions & ~isa_flags;
if (missing_extensions != 0)
return false;
return true;
@@ -4977,6 +4977,12 @@ registered_function::overloaded_hash () const
for (unsigned int i = 0; i < argument_types.length (); i++)
{
type = argument_types[i];
+
+ /* If we're passed something entirely unreasonable, just ignore here.
+ We'll warn later anyway. */
+ if (TREE_CODE_CLASS (TREE_CODE (type)) != tcc_type)
+ continue;
+
unsigned_p = POINTER_TYPE_P (type) ? TYPE_UNSIGNED (TREE_TYPE (type))
: TYPE_UNSIGNED (type);
mode_p = POINTER_TYPE_P (type) ? TYPE_MODE (TREE_TYPE (type))
diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h
index ffc2893..1f2587a 100644
--- a/gcc/config/riscv/riscv-vector-builtins.h
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -331,45 +331,7 @@ struct function_group_info
/* Return true if required extension is enabled */
bool match (required_ext ext_value) const
{
- switch (ext_value)
- {
- case VECTOR_EXT:
- return TARGET_VECTOR;
- case ZVBB_EXT:
- return TARGET_ZVBB;
- case ZVBB_OR_ZVKB_EXT:
- return (TARGET_ZVBB || TARGET_ZVKB);
- case ZVBC_EXT:
- return TARGET_ZVBC;
- case ZVKG_EXT:
- return TARGET_ZVKG;
- case ZVKNED_EXT:
- return TARGET_ZVKNED;
- case ZVKNHA_OR_ZVKNHB_EXT:
- return (TARGET_ZVKNHA || TARGET_ZVKNHB);
- case ZVKNHB_EXT:
- return TARGET_ZVKNHB;
- case ZVKSED_EXT:
- return TARGET_ZVKSED;
- case ZVKSH_EXT:
- return TARGET_ZVKSH;
- case XTHEADVECTOR_EXT:
- return TARGET_XTHEADVECTOR;
- case ZVFBFMIN_EXT:
- return TARGET_ZVFBFMIN;
- case ZVFBFWMA_EXT:
- return TARGET_ZVFBFWMA;
- case XSFVQMACCQOQ_EXT:
- return TARGET_XSFVQMACCQOQ;
- case XSFVQMACCDOD_EXT:
- return TARGET_XSFVQMACCDOD;
- case XSFVFNRCLIPXFQF_EXT:
- return TARGET_XSFVFNRCLIPXFQF;
- case XSFVCP_EXT:
- return TARGET_XSFVCP;
- default:
- gcc_unreachable ();
- }
+ return required_extensions_specified (ext_value);
}
/* The base name, as a string. */
const char *base_name;
diff --git a/gcc/config/riscv/riscv-vector-costs.cc b/gcc/config/riscv/riscv-vector-costs.cc
index 167375c..4d8170d 100644
--- a/gcc/config/riscv/riscv-vector-costs.cc
+++ b/gcc/config/riscv/riscv-vector-costs.cc
@@ -205,9 +205,7 @@ compute_local_program_points (
if (!is_gimple_assign_or_call (gsi_stmt (si)))
continue;
stmt_vec_info stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
- enum stmt_vec_info_type type
- = STMT_VINFO_TYPE (vect_stmt_to_vectorize (stmt_info));
- if (type != undef_vec_info_type)
+ if (STMT_VINFO_RELEVANT_P (stmt_info))
{
stmt_point info = {point, gsi_stmt (si), stmt_info};
program_points.safe_push (info);
@@ -626,7 +624,7 @@ compute_estimated_lmul (loop_vec_info loop_vinfo, machine_mode mode)
int regno_alignment = riscv_get_v_regno_alignment (loop_vinfo->vector_mode);
if (riscv_v_ext_vls_mode_p (loop_vinfo->vector_mode))
return regno_alignment;
- else if (known_eq (LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo), 1U))
+ else
{
int estimated_vf = vect_vf_for_cost (loop_vinfo);
int estimated_lmul = estimated_vf * GET_MODE_BITSIZE (mode).to_constant ()
@@ -636,25 +634,6 @@ compute_estimated_lmul (loop_vec_info loop_vinfo, machine_mode mode)
else
return estimated_lmul;
}
- else
- {
- /* Estimate the VLA SLP LMUL. */
- if (regno_alignment > RVV_M1)
- return regno_alignment;
- else if (mode != QImode
- || LOOP_VINFO_SLP_UNROLLING_FACTOR (loop_vinfo).is_constant ())
- {
- int ratio;
- if (can_div_trunc_p (BYTES_PER_RISCV_VECTOR,
- GET_MODE_SIZE (loop_vinfo->vector_mode), &ratio))
- {
- if (ratio == 1)
- return RVV_M4;
- else if (ratio == 2)
- return RVV_M2;
- }
- }
- }
return 0;
}
@@ -1120,8 +1099,8 @@ costs::adjust_stmt_cost (enum vect_cost_for_stmt kind, loop_vec_info loop,
switch (kind)
{
case scalar_to_vec:
- stmt_cost += (FLOAT_TYPE_P (vectype) ? costs->regmove->FR2VR
- : costs->regmove->GR2VR);
+ stmt_cost
+ += (FLOAT_TYPE_P (vectype) ? get_fr2vr_cost () : get_gr2vr_cost ());
break;
case vec_to_scalar:
stmt_cost += (FLOAT_TYPE_P (vectype) ? costs->regmove->VR2FR
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index a8c9256..4fe0ae6 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -100,31 +100,28 @@ using namespace riscv_vector;
static void
bitmap_union_of_preds_with_entry (sbitmap dst, sbitmap *src, basic_block b)
{
- unsigned int set_size = dst->size;
- edge e;
- unsigned ix;
-
- for (ix = 0; ix < EDGE_COUNT (b->preds); ix++)
+ /* Handle case with no predecessors (including ENTRY block). */
+ if (EDGE_COUNT (b->preds) == 0)
{
- e = EDGE_PRED (b, ix);
- bitmap_copy (dst, src[e->src->index]);
- break;
+ bitmap_clear (dst);
+ return;
}
- if (ix == EDGE_COUNT (b->preds))
- bitmap_clear (dst);
- else
- for (ix++; ix < EDGE_COUNT (b->preds); ix++)
- {
- unsigned int i;
- SBITMAP_ELT_TYPE *p, *r;
-
- e = EDGE_PRED (b, ix);
- p = src[e->src->index]->elms;
- r = dst->elms;
- for (i = 0; i < set_size; i++)
- *r++ |= *p++;
- }
+ edge e;
+ edge_iterator ei;
+ /* Union remaining predecessors' bitmaps. */
+ FOR_EACH_EDGE (e, ei, b->preds)
+ {
+ /* Initialize with first predecessor's bitmap. */
+ if (ei.index == 0)
+ {
+ bitmap_copy (dst, src[e->src->index]);
+ continue;
+ }
+
+ /* Perform bitmap OR operation element-wise. */
+ bitmap_ior (dst, dst, src[e->src->index]);
+ }
}
/* Compute the reaching definition in and out based on the gen and KILL
@@ -3419,8 +3416,7 @@ pre_vsetvl::emit_vsetvl ()
}
start_sequence ();
insert_vsetvl_insn (EMIT_DIRECT, footer_info);
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
+ rtx_insn *rinsn = end_sequence ();
default_rtl_profile ();
insert_insn_on_edge (rinsn, eg);
need_commit = true;
@@ -3451,8 +3447,7 @@ pre_vsetvl::emit_vsetvl ()
start_sequence ();
insert_vsetvl_insn (EMIT_DIRECT, info);
- rtx_insn *rinsn = get_insns ();
- end_sequence ();
+ rtx_insn *rinsn = end_sequence ();
default_rtl_profile ();
/* We should not get an abnormal edge here. */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a065732..e09c189 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -107,6 +107,8 @@ along with GCC; see the file COPYING3. If not see
/* True the mode switching has static frm, or false. */
#define STATIC_FRM_P(c) ((c)->machine->mode_sw_info.static_frm_p)
+#define CFUN_IN_CALL(c) ((c)->machine->mode_sw_info.cfun_call)
+
/* True if we can use the instructions in the XTheadInt extension
to handle interrupts, or false. */
#define TH_INT_INTERRUPT(c) \
@@ -176,10 +178,13 @@ struct GTY(()) mode_switching_info {
mode instruction in the function or not. */
bool static_frm_p;
+ bool cfun_call;
+
mode_switching_info ()
{
dynamic_frm = NULL_RTX;
static_frm_p = false;
+ cfun_call = false;
}
};
@@ -297,6 +302,7 @@ struct riscv_tune_param
bool vector_unaligned_access;
bool use_divmod_expansion;
bool overlap_op_by_pieces;
+ bool speculative_sched_vsetvl;
unsigned int fusible_ops;
const struct cpu_vector_cost *vec_costs;
const char *function_align;
@@ -444,6 +450,29 @@ static const struct cpu_vector_cost generic_vector_cost = {
&rvv_regmove_vector_cost, /* regmove */
};
+/* Costs to use when optimizing for generic. */
+static const struct riscv_tune_param generic_tune_info = {
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_mul */
+ {COSTS_N_INSNS (20), COSTS_N_INSNS (20)}, /* fp_div */
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* int_mul */
+ {COSTS_N_INSNS (33), COSTS_N_INSNS (65)}, /* int_div */
+ 1, /* issue_rate */
+ 4, /* branch_cost */
+ 5, /* memory_cost */
+ 8, /* fmv_cost */
+ true, /* slow_unaligned_access */
+ false, /* vector_unaligned_access */
+ false, /* use_divmod_expansion */
+ false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
+ RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
+ NULL, /* function_align */
+ NULL, /* jump_align */
+ NULL, /* loop_align */
+};
+
/* Costs to use when optimizing for rocket. */
static const struct riscv_tune_param rocket_tune_info = {
{COSTS_N_INSNS (4), COSTS_N_INSNS (5)}, /* fp_add */
@@ -459,6 +488,7 @@ static const struct riscv_tune_param rocket_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
NULL, /* vector cost */
NULL, /* function_align */
@@ -481,6 +511,7 @@ static const struct riscv_tune_param sifive_7_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
NULL, /* vector cost */
NULL, /* function_align */
@@ -503,6 +534,7 @@ static const struct riscv_tune_param sifive_p400_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */
&generic_vector_cost, /* vector cost */
NULL, /* function_align */
@@ -525,6 +557,7 @@ static const struct riscv_tune_param sifive_p600_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_LUI_ADDI | RISCV_FUSE_AUIPC_ADDI, /* fusible_ops */
&generic_vector_cost, /* vector cost */
NULL, /* function_align */
@@ -547,6 +580,7 @@ static const struct riscv_tune_param thead_c906_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
NULL, /* vector cost */
NULL, /* function_align */
@@ -569,6 +603,7 @@ static const struct riscv_tune_param xiangshan_nanhu_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_ZEXTW | RISCV_FUSE_ZEXTH, /* fusible_ops */
NULL, /* vector cost */
NULL, /* function_align */
@@ -591,6 +626,7 @@ static const struct riscv_tune_param generic_ooo_tune_info = {
true, /* vector_unaligned_access */
false, /* use_divmod_expansion */
true, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
&generic_vector_cost, /* vector cost */
NULL, /* function_align */
@@ -613,6 +649,7 @@ static const struct riscv_tune_param tt_ascalon_d8_tune_info = {
true, /* vector_unaligned_access */
true, /* use_divmod_expansion */
true, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
&generic_vector_cost, /* vector cost */
NULL, /* function_align */
@@ -635,6 +672,7 @@ static const struct riscv_tune_param optimize_size_tune_info = {
false, /* vector_unaligned_access */
false, /* use_divmod_expansion */
false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
RISCV_FUSE_NOTHING, /* fusible_ops */
NULL, /* vector cost */
NULL, /* function_align */
@@ -642,6 +680,29 @@ static const struct riscv_tune_param optimize_size_tune_info = {
NULL, /* loop_align */
};
+/* Costs to use when optimizing for MIPS P8700 */
+static const struct riscv_tune_param mips_p8700_tune_info = {
+ {COSTS_N_INSNS (4), COSTS_N_INSNS (4)}, /* fp_add */
+ {COSTS_N_INSNS (5), COSTS_N_INSNS (5)}, /* fp_mul */
+ {COSTS_N_INSNS (17), COSTS_N_INSNS (17)}, /* fp_div */
+ {COSTS_N_INSNS (5), COSTS_N_INSNS (5)}, /* int_mul */
+ {COSTS_N_INSNS (8), COSTS_N_INSNS (8)}, /* int_div */
+ 4, /* issue_rate */
+ 8, /* branch_cost */
+ 4, /* memory_cost */
+ 8, /* fmv_cost */
+ true, /* slow_unaligned_access */
+ false, /* vector_unaligned_access */
+ true, /* use_divmod_expansion */
+ false, /* overlap_op_by_pieces */
+ false, /* speculative_sched_vsetvl */
+ RISCV_FUSE_NOTHING, /* fusible_ops */
+ NULL, /* vector cost */
+ NULL, /* function_align */
+ NULL, /* jump_align */
+ NULL, /* loop_align */
+};
+
static bool riscv_avoid_shrink_wrapping_separate ();
static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *);
@@ -776,6 +837,16 @@ void riscv_frame_info::reset(void)
arg_pointer_offset = 0;
}
+/* Check if the mode is twice the size of the XLEN mode. */
+
+static bool
+riscv_2x_xlen_mode_p (machine_mode mode)
+{
+ poly_int64 mode_size = GET_MODE_SIZE (mode);
+ return mode_size.is_constant ()
+ && (mode_size.to_constant () == UNITS_PER_WORD * 2);
+}
+
/* Implement TARGET_MIN_ARITHMETIC_PRECISION. */
static unsigned int
@@ -1007,16 +1078,16 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
/* Now iterate over the bits we want to clear until the cost is
too high or we're done. */
nval = value ^ HOST_WIDE_INT_C (-1);
- nval &= HOST_WIDE_INT_C (~0x7fffffff);
+ nval &= ~HOST_WIDE_INT_C (0x7fffffff);
while (nval && alt_cost < cost)
{
HOST_WIDE_INT bit = ctz_hwi (nval);
alt_codes[alt_cost].code = AND;
- alt_codes[alt_cost].value = ~(1UL << bit);
+ alt_codes[alt_cost].value = ~(HOST_WIDE_INT_UC (1) << bit);
alt_codes[alt_cost].use_uw = false;
alt_codes[alt_cost].save_temporary = false;
alt_cost++;
- nval &= ~(1UL << bit);
+ nval &= ~(HOST_WIDE_INT_UC (1) << bit);
}
if (nval == 0 && alt_cost <= cost)
@@ -2856,9 +2927,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
gen_int_mode (RISCV_CC_BASE, SImode)));
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
- insn = get_insns ();
-
- end_sequence ();
+ insn = end_sequence ();
return insn;
}
@@ -3742,6 +3811,24 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
return true;
}
+ if (TARGET_ZILSD && riscv_2x_xlen_mode_p (mode)
+ && ((REG_P (dest) && MEM_P (src)) || (MEM_P (dest) && REG_P (src)))
+ && can_create_pseudo_p ())
+ {
+ rtx reg = REG_P (dest) ? dest : src;
+ unsigned regno = REGNO (reg);
+ /* ZILSD requires an even-odd register pair, let RA to
+ fix the constraint if the reg is hard reg and not even reg. */
+ if ((regno < FIRST_PSEUDO_REGISTER)
+ && (regno % 2) != 0)
+ {
+ rtx tmp = gen_reg_rtx (GET_MODE (reg));
+ emit_move_insn (tmp, src);
+ emit_move_insn (dest, tmp);
+ return true;
+ }
+ }
+
/* RISC-V GCC may generate non-legitimate address due to we provide some
pattern for optimize access PIC local symbol and it's make GCC generate
unrecognizable instruction during optimizing. */
@@ -3812,7 +3899,7 @@ static int
riscv_binary_cost (rtx x, int single_insns, int double_insns)
{
if (!riscv_v_ext_mode_p (GET_MODE (x))
- && GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2)
+ && riscv_2x_xlen_mode_p (GET_MODE (x)))
return COSTS_N_INSNS (double_insns);
return COSTS_N_INSNS (single_insns);
}
@@ -3851,6 +3938,27 @@ riscv_extend_cost (rtx op, bool unsigned_p)
return COSTS_N_INSNS (2);
}
+/* Return the cost of the vector binary rtx like add, minus, mult.
+ The cost of scalar2vr_cost will be appended if there one of the
+ op comes from the VEC_DUPLICATE. */
+
+static int
+get_vector_binary_rtx_cost (rtx x, int scalar2vr_cost)
+{
+ gcc_assert (riscv_v_ext_mode_p (GET_MODE (x)));
+
+ rtx op_0 = XEXP (x, 0);
+ rtx op_1 = XEXP (x, 1);
+
+ if (GET_CODE (op_0) == VEC_DUPLICATE
+ || GET_CODE (op_1) == VEC_DUPLICATE)
+ return (scalar2vr_cost + 1) * COSTS_N_INSNS (1);
+ else if (GET_CODE (op_0) == NEG && GET_CODE (op_1) == VEC_DUPLICATE)
+ return (scalar2vr_cost + 1) * COSTS_N_INSNS (1);
+ else
+ return COSTS_N_INSNS (1);
+}
+
/* Implement TARGET_RTX_COSTS. */
#define SINGLE_SHIFT_COST 1
@@ -3863,7 +3971,74 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
Cost Model need to be well analyzed and supported in the future. */
if (riscv_v_ext_mode_p (mode))
{
- *total = COSTS_N_INSNS (1);
+ int gr2vr_cost = get_gr2vr_cost ();
+ int fr2vr_cost = get_fr2vr_cost ();
+ int scalar2vr_cost = FLOAT_MODE_P (GET_MODE_INNER (mode))
+ ? fr2vr_cost : gr2vr_cost;
+
+ switch (outer_code)
+ {
+ case SET:
+ {
+ switch (GET_CODE (x))
+ {
+ case VEC_DUPLICATE:
+ *total = gr2vr_cost * COSTS_N_INSNS (1);
+ break;
+ case IF_THEN_ELSE:
+ {
+ rtx op = XEXP (x, 1);
+
+ switch (GET_CODE (op))
+ {
+ case DIV:
+ case UDIV:
+ case MOD:
+ case UMOD:
+ case US_PLUS:
+ case US_MINUS:
+ case SS_PLUS:
+ *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
+ break;
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+ }
+ break;
+ case PLUS:
+ case MINUS:
+ case AND:
+ case IOR:
+ case XOR:
+ case MULT:
+ case SMAX:
+ case UMAX:
+ case SMIN:
+ case UMIN:
+ {
+ rtx op;
+ rtx op_0 = XEXP (x, 0);
+ rtx op_1 = XEXP (x, 1);
+
+ if (GET_CODE (op = op_0) == MULT
+ || GET_CODE (op = op_1) == MULT)
+ *total = get_vector_binary_rtx_cost (op, scalar2vr_cost);
+ else
+ *total = get_vector_binary_rtx_cost (x, scalar2vr_cost);
+ }
+ break;
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+ }
+ break;
+ default:
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+
return true;
}
@@ -3883,10 +4058,41 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
*total = COSTS_N_INSNS (1);
return true;
}
+
+ /* Register move for XLEN * 2. */
+ if (TARGET_ZILSD
+ && register_operand (SET_SRC (x), GET_MODE (SET_SRC (x)))
+ && riscv_2x_xlen_mode_p (mode))
+ {
+ /* We still need two instruction for move with ZILSD,
+ but let minus one cost to let subreg split don't.
+ TODO: Add riscv_tune_param for this. */
+ *total = COSTS_N_INSNS (2) - 1;
+ return true;
+ }
+
+ /* Load for XLEN * 2. */
+ if (TARGET_ZILSD && MEM_P (SET_SRC (x))
+ && riscv_2x_xlen_mode_p (mode))
+ {
+ /* TODO: Add riscv_tune_param for this. */
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+
riscv_rtx_costs (SET_SRC (x), mode, SET, opno, total, speed);
return true;
}
+ /* Store for XLEN * 2. */
+ if (TARGET_ZILSD && MEM_P (SET_DEST (x)) && REG_P (SET_SRC (x))
+ && riscv_2x_xlen_mode_p (mode))
+ {
+ /* TODO: Add riscv_tune_param for this. */
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+
/* Otherwise return FALSE indicating we should recurse into both the
SET_DEST and SET_SRC combining the cost of both. */
return false;
@@ -4486,16 +4692,14 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq,
rtx dest = SET_DEST (x);
- /* Do something similar for the moves that are likely to
+ /* Do something similar for the moves that are likely to
turn into NOP moves by the time the register allocator is
- done. These are also side effects of how our sCC expanders
- work. We'll want to check and update LAST_DEST here too. */
- if (last_dest
- && REG_P (dest)
+ done. We don't require src to be something set in this
+ sequence, just a promoted SUBREG. */
+ if (REG_P (dest)
&& GET_MODE (dest) == SImode
&& SUBREG_P (src)
- && SUBREG_PROMOTED_VAR_P (src)
- && REGNO (SUBREG_REG (src)) == REGNO (last_dest))
+ && SUBREG_PROMOTED_VAR_P (src))
{
riscv_if_info.original_cost += COSTS_N_INSNS (1);
riscv_if_info.max_seq_cost += COSTS_N_INSNS (1);
@@ -4544,6 +4748,19 @@ riscv_split_64bit_move_p (rtx dest, rtx src)
if (TARGET_64BIT)
return false;
+ /* Zilsd provides load/store with even-odd register pair. */
+ if (TARGET_ZILSD
+ && (((REG_P (dest) && MEM_P (src))
+ || (MEM_P (dest) && REG_P (src)))))
+ {
+ rtx reg = REG_P (dest) ? dest : src;
+ unsigned regno = REGNO (reg);
+ /* GCC may still generating some load/store with odd-even reg pair
+ because the ABI handling, but that's fine, just split that later. */
+ if (GP_REG_P (regno))
+ return (regno < FIRST_PSEUDO_REGISTER) && ((regno % 2) != 0);
+ }
+
/* There is no need to split if the FLI instruction in the `Zfa` extension can be used. */
if (satisfies_constraint_zfli (src))
return false;
@@ -5259,34 +5476,81 @@ riscv_expand_conditional_branch (rtx label, rtx_code code, rtx op0, rtx op1)
bool
riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
{
- machine_mode mode = GET_MODE (dest);
+ machine_mode dst_mode = GET_MODE (dest);
+ machine_mode cond_mode = GET_MODE (dest);
rtx_code code = GET_CODE (op);
rtx op0 = XEXP (op, 0);
rtx op1 = XEXP (op, 1);
+ /* General note. This is called from the conditional move
+ expander. That simplifies the cases we need to worry about
+ as we know the destination will have the same mode as the
+ true/false arms. Furthermore we know that mode will be
+ DI/SI for rv64 or SI for rv32. */
+
+ /* For some tests, we can easily construct a 0, -1 value
+ which can then be used to synthesize more efficient
+ sequences that don't use zicond. */
+ if ((code == LT || code == GE)
+ && (REG_P (op0) || SUBREG_P (op0))
+ && op1 == CONST0_RTX (GET_MODE (op0)))
+ {
+ /* The code to expand signed division by a power of 2 uses a
+ conditional add by 2^n-1 idiom. It can be more efficiently
+ synthesized without zicond using srai+srli+add.
+
+ But we don't see the constants here. Just a conditional move
+ with registers as the true/false values. So this is a little
+ over-aggressive and can result in a few missed if-conversions. */
+ if ((REG_P (cons) || SUBREG_P (cons))
+ && (REG_P (alt) || SUBREG_P (alt)))
+ return false;
+
+ /* If one value is a nonzero constant and the other value is
+ not a constant, then avoid zicond as more efficient sequences
+ using the splatted sign bit are often possible. */
+ if (CONST_INT_P (alt)
+ && alt != CONST0_RTX (dst_mode)
+ && !CONST_INT_P (cons))
+ return false;
+
+ if (CONST_INT_P (cons)
+ && cons != CONST0_RTX (dst_mode)
+ && !CONST_INT_P (alt))
+ return false;
+
+ /* If we need more special cases, add them here. */
+ }
+
if (((TARGET_ZICOND_LIKE
- || (arith_operand (cons, mode) && arith_operand (alt, mode)))
- && (GET_MODE_CLASS (mode) == MODE_INT))
+ || (arith_operand (cons, dst_mode) && arith_operand (alt, dst_mode)))
+ && GET_MODE_CLASS (dst_mode) == MODE_INT
+ && GET_MODE_CLASS (cond_mode) == MODE_INT)
|| TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
{
machine_mode mode0 = GET_MODE (op0);
machine_mode mode1 = GET_MODE (op1);
- /* An integer comparison must be comparing WORD_MODE objects. We
- must enforce that so that we don't strip away a sign_extension
- thinking it is unnecessary. We might consider using
- riscv_extend_operands if they are not already properly extended. */
+ /* An integer comparison must be comparing WORD_MODE objects.
+ Extend the comparison arguments as necessary. */
if ((INTEGRAL_MODE_P (mode0) && mode0 != word_mode)
|| (INTEGRAL_MODE_P (mode1) && mode1 != word_mode))
- return false;
+ riscv_extend_comparands (code, &op0, &op1);
+
+ /* We might have been handed back a SUBREG. Just to make things
+ easy, force it into a REG. */
+ if (!REG_P (op0) && !CONST_INT_P (op0))
+ op0 = force_reg (word_mode, op0);
+ if (!REG_P (op1) && !CONST_INT_P (op1))
+ op1 = force_reg (word_mode, op1);
- /* In the fallback generic case use MODE rather than WORD_MODE for
- the output of the SCC instruction, to match the mode of the NEG
+ /* In the fallback generic case use DST_MODE rather than WORD_MODE
+ for the output of the SCC instruction, to match the mode of the NEG
operation below. The output of SCC is 0 or 1 boolean, so it is
valid for input in any scalar integer mode. */
rtx tmp = gen_reg_rtx ((TARGET_ZICOND_LIKE
|| TARGET_SFB_ALU || TARGET_XTHEADCONDMOV)
- ? word_mode : mode);
+ ? word_mode : dst_mode);
bool invert = false;
/* Canonicalize the comparison. It must be an equality comparison
@@ -5315,7 +5579,7 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
else
return false;
- op = gen_rtx_fmt_ee (invert ? EQ : NE, mode, tmp, const0_rtx);
+ op = gen_rtx_fmt_ee (invert ? EQ : NE, cond_mode, tmp, const0_rtx);
/* We've generated a new comparison. Update the local variables. */
code = GET_CODE (op);
@@ -5334,10 +5598,10 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
arm of the conditional move. That allows us to support more
cases for extensions which are more general than SFB. But
does mean we need to force CONS into a register at this point. */
- cons = force_reg (mode, cons);
+ cons = force_reg (dst_mode, cons);
/* With XTheadCondMov we need to force ALT into a register too. */
- alt = force_reg (mode, alt);
- emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond,
+ alt = force_reg (dst_mode, alt);
+ emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
@@ -5346,10 +5610,10 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
if (invert)
std::swap (cons, alt);
- rtx reg1 = gen_reg_rtx (mode);
- rtx reg2 = gen_reg_rtx (mode);
- rtx reg3 = gen_reg_rtx (mode);
- rtx reg4 = gen_reg_rtx (mode);
+ rtx reg1 = gen_reg_rtx (dst_mode);
+ rtx reg2 = gen_reg_rtx (dst_mode);
+ rtx reg3 = gen_reg_rtx (dst_mode);
+ rtx reg4 = gen_reg_rtx (dst_mode);
riscv_emit_unary (NEG, reg1, tmp);
riscv_emit_binary (AND, reg2, reg1, cons);
@@ -5359,48 +5623,52 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
return true;
}
/* 0, reg or 0, imm */
- else if (cons == CONST0_RTX (mode)
- && (REG_P (alt)
- || (CONST_INT_P (alt) && alt != CONST0_RTX (mode))))
+ else if (cons == CONST0_RTX (dst_mode)
+ && ((REG_P (alt) || SUBREG_P (alt))
+ || (CONST_INT_P (alt) && alt != CONST0_RTX (dst_mode))))
{
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- alt = force_reg (mode, alt);
+ alt = force_reg (dst_mode, alt);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
/* imm, imm */
- else if (CONST_INT_P (cons) && cons != CONST0_RTX (mode)
- && CONST_INT_P (alt) && alt != CONST0_RTX (mode))
+ else if (CONST_INT_P (cons) && cons != CONST0_RTX (dst_mode)
+ && CONST_INT_P (alt) && alt != CONST0_RTX (dst_mode))
{
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
HOST_WIDE_INT t = INTVAL (alt) - INTVAL (cons);
- alt = force_reg (mode, gen_int_mode (t, mode));
+ alt = force_reg (dst_mode, gen_int_mode (t, dst_mode));
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
- CONST0_RTX (mode),
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
+ CONST0_RTX (dst_mode),
alt)));
/* CONS might not fit into a signed 12 bit immediate suitable
for an addi instruction. If that's the case, force it
into a register. */
if (!SMALL_OPERAND (INTVAL (cons)))
- cons = force_reg (mode, cons);
+ cons = force_reg (dst_mode, cons);
riscv_emit_binary (PLUS, dest, dest, cons);
return true;
}
/* imm, reg */
- else if (CONST_INT_P (cons) && cons != CONST0_RTX (mode) && REG_P (alt))
+ else if (CONST_INT_P (cons)
+ && cons != CONST0_RTX (dst_mode)
+ && (REG_P (alt) || SUBREG_P (alt)))
{
/* Optimize for register value of 0. */
- if (code == NE && rtx_equal_p (op0, alt) && op1 == CONST0_RTX (mode))
+ if (code == NE
+ && rtx_equal_p (op0, alt)
+ && op1 == CONST0_RTX (dst_mode))
{
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- cons = force_reg (mode, cons);
+ cons = force_reg (dst_mode, cons);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
@@ -5408,47 +5676,51 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- rtx temp1 = gen_reg_rtx (mode);
- rtx temp2 = gen_int_mode (-1 * INTVAL (cons), mode);
+ rtx temp1 = gen_reg_rtx (dst_mode);
+ rtx temp2 = gen_int_mode (-1 * INTVAL (cons), dst_mode);
/* TEMP2 and/or CONS might not fit into a signed 12 bit immediate
suitable for an addi instruction. If that's the case, force it
into a register. */
if (!SMALL_OPERAND (INTVAL (temp2)))
- temp2 = force_reg (mode, temp2);
+ temp2 = force_reg (dst_mode, temp2);
if (!SMALL_OPERAND (INTVAL (cons)))
- cons = force_reg (mode, cons);
+ cons = force_reg (dst_mode, cons);
riscv_emit_binary (PLUS, temp1, alt, temp2);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
- CONST0_RTX (mode),
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
+ CONST0_RTX (dst_mode),
temp1)));
riscv_emit_binary (PLUS, dest, dest, cons);
return true;
}
/* reg, 0 or imm, 0 */
- else if ((REG_P (cons)
- || (CONST_INT_P (cons) && cons != CONST0_RTX (mode)))
- && alt == CONST0_RTX (mode))
+ else if (((REG_P (cons) || SUBREG_P (cons))
+ || (CONST_INT_P (cons) && cons != CONST0_RTX (dst_mode)))
+ && alt == CONST0_RTX (dst_mode))
{
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- cons = force_reg (mode, cons);
- emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons = force_reg (dst_mode, cons);
+ emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
/* reg, imm */
- else if (REG_P (cons) && CONST_INT_P (alt) && alt != CONST0_RTX (mode))
+ else if ((REG_P (cons) || (SUBREG_P (cons)))
+ && CONST_INT_P (alt)
+ && alt != CONST0_RTX (dst_mode))
{
/* Optimize for register value of 0. */
- if (code == EQ && rtx_equal_p (op0, cons) && op1 == CONST0_RTX (mode))
+ if (code == EQ
+ && rtx_equal_p (op0, cons)
+ && op1 == CONST0_RTX (dst_mode))
{
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- alt = force_reg (mode, alt);
+ alt = force_reg (dst_mode, alt);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
@@ -5456,53 +5728,54 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- rtx temp1 = gen_reg_rtx (mode);
- rtx temp2 = gen_int_mode (-1 * INTVAL (alt), mode);
+ rtx temp1 = gen_reg_rtx (dst_mode);
+ rtx temp2 = gen_int_mode (-1 * INTVAL (alt), dst_mode);
/* TEMP2 and/or ALT might not fit into a signed 12 bit immediate
suitable for an addi instruction. If that's the case, force it
into a register. */
if (!SMALL_OPERAND (INTVAL (temp2)))
- temp2 = force_reg (mode, temp2);
+ temp2 = force_reg (dst_mode, temp2);
if (!SMALL_OPERAND (INTVAL (alt)))
- alt = force_reg (mode, alt);
+ alt = force_reg (dst_mode, alt);
riscv_emit_binary (PLUS, temp1, cons, temp2);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
temp1,
- CONST0_RTX (mode))));
+ CONST0_RTX (dst_mode))));
riscv_emit_binary (PLUS, dest, dest, alt);
return true;
}
/* reg, reg */
- else if (REG_P (cons) && REG_P (alt))
+ else if ((REG_P (cons) || SUBREG_P (cons))
+ && (REG_P (alt) || SUBREG_P (alt)))
{
if (((code == EQ && rtx_equal_p (cons, op0))
|| (code == NE && rtx_equal_p (alt, op0)))
- && op1 == CONST0_RTX (mode))
+ && op1 == CONST0_RTX (dst_mode))
{
rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
- alt = force_reg (mode, alt);
+ alt = force_reg (dst_mode, alt);
emit_insn (gen_rtx_SET (dest,
- gen_rtx_IF_THEN_ELSE (mode, cond,
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond,
cons, alt)));
return true;
}
- rtx reg1 = gen_reg_rtx (mode);
- rtx reg2 = gen_reg_rtx (mode);
+ rtx reg1 = gen_reg_rtx (dst_mode);
+ rtx reg2 = gen_reg_rtx (dst_mode);
riscv_emit_int_compare (&code, &op0, &op1, true);
rtx cond1 = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
rtx cond2 = gen_rtx_fmt_ee (code == NE ? EQ : NE,
GET_MODE (op0), op0, op1);
emit_insn (gen_rtx_SET (reg2,
- gen_rtx_IF_THEN_ELSE (mode, cond2,
- CONST0_RTX (mode),
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond2,
+ CONST0_RTX (dst_mode),
cons)));
emit_insn (gen_rtx_SET (reg1,
- gen_rtx_IF_THEN_ELSE (mode, cond1,
- CONST0_RTX (mode),
+ gen_rtx_IF_THEN_ELSE (dst_mode, cond1,
+ CONST0_RTX (dst_mode),
alt)));
riscv_emit_binary (PLUS, dest, reg1, reg2);
return true;
@@ -7885,11 +8158,9 @@ riscv_can_inline_p (tree caller, tree callee)
struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
- int isa_flag_mask = riscv_x_target_flags_isa_mask ();
-
- /* Callee and caller should have the same target options except for ISA. */
- int callee_target_flags = callee_opts->x_target_flags & ~isa_flag_mask;
- int caller_target_flags = caller_opts->x_target_flags & ~isa_flag_mask;
+ /* Callee and caller should have the same target options. */
+ int callee_target_flags = callee_opts->x_target_flags;
+ int caller_target_flags = caller_opts->x_target_flags;
if (callee_target_flags != caller_target_flags)
return false;
@@ -8708,12 +8979,20 @@ riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size)
temp2 = riscv_force_temporary (temp2, gen_int_mode (rounded_size, Pmode));
insn = emit_insn (gen_sub3_insn (temp2, stack_pointer_rtx, temp2));
+ /* The size does not represent actual stack pointer address shift
+ from the top of the frame, as it might be lowered before.
+ To consider the correct SP addresses for the CFA notes, it is needed
+ to correct them with the initial offset value. */
+ HOST_WIDE_INT initial_cfa_offset
+ = cfun->machine->frame.total_size.to_constant () - size;
+
if (!frame_pointer_needed)
{
/* We want the CFA independent of the stack pointer for the
duration of the loop. */
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (Pmode, temp1, rounded_size));
+ plus_constant (Pmode, temp1,
+ initial_cfa_offset + rounded_size));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -8726,7 +9005,8 @@ riscv_allocate_and_probe_stack_space (rtx temp1, HOST_WIDE_INT size)
{
insn = get_last_insn ();
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (Pmode, stack_pointer_rtx, rounded_size));
+ plus_constant (Pmode, stack_pointer_rtx,
+ initial_cfa_offset + rounded_size));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9690,9 +9970,9 @@ riscv_register_move_cost (machine_mode mode,
if (to == V_REGS)
{
if (from_is_gpr)
- return get_vector_costs ()->regmove->GR2VR;
+ return get_gr2vr_cost ();
else if (from_is_fpr)
- return get_vector_costs ()->regmove->FR2VR;
+ return get_fr2vr_cost ();
}
return riscv_secondary_memory_needed (mode, from, to) ? 8 : 2;
@@ -9768,6 +10048,10 @@ riscv_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (riscv_v_ext_mode_p (mode))
return false;
+ /* Zilsd require load/store with even-odd reg pair. */
+ if (TARGET_ZILSD && riscv_2x_xlen_mode_p (mode) && ((regno % 2) != 0))
+ return false;
+
if (!GP_REG_P (regno + nregs - 1))
return false;
}
@@ -9926,17 +10210,33 @@ riscv_fusion_enabled_p(enum riscv_fusion_pairs op)
static bool
riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
{
+ /* If fusion is not enabled, then there's nothing to do. */
+ if (!riscv_macro_fusion_p ())
+ return false;
+
+ /* If PREV is already marked as fused, then we can't fuse CURR with PREV
+ and if we were to fuse them we'd end up with a blob of insns that
+ essentially are an atomic unit which is bad for scheduling. */
+ if (SCHED_GROUP_P (prev))
+ return false;
+
rtx prev_set = single_set (prev);
rtx curr_set = single_set (curr);
/* prev and curr are simple SET insns i.e. no flag setting or branching. */
bool simple_sets_p = prev_set && curr_set && !any_condjump_p (curr);
+ bool sched1 = can_create_pseudo_p ();
- if (!riscv_macro_fusion_p ())
- return false;
+ unsigned int prev_dest_regno = (REG_P (SET_DEST (prev_set))
+ ? REGNO (SET_DEST (prev_set))
+ : FIRST_PSEUDO_REGISTER);
+ unsigned int curr_dest_regno = (REG_P (SET_DEST (curr_set))
+ ? REGNO (SET_DEST (curr_set))
+ : FIRST_PSEUDO_REGISTER);
if (simple_sets_p
&& (riscv_fusion_enabled_p (RISCV_FUSE_ZEXTW)
- || riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS)))
+ || riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS))
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (slli) == (set (reg:DI rD)
@@ -9950,19 +10250,23 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
&& REG_P (SET_DEST (prev_set))
&& REG_P (SET_DEST (curr_set))
- && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == curr_dest_regno
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& INTVAL (XEXP (SET_SRC (prev_set), 1)) == 32
- && (( INTVAL (XEXP (SET_SRC (curr_set), 1)) == 32
- && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTW) )
- || ( INTVAL (XEXP (SET_SRC (curr_set), 1)) < 32
- && riscv_fusion_enabled_p(RISCV_FUSE_ZEXTWS))))
- return true;
+ && ((INTVAL (XEXP (SET_SRC (curr_set), 1)) == 32
+ && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTW) )
+ || (INTVAL (XEXP (SET_SRC (curr_set), 1)) < 32
+ && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTWS))))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_ZEXTWS\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ZEXTH)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (slli) == (set (reg:DI rD)
@@ -9974,16 +10278,20 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& GET_CODE (SET_SRC (curr_set)) == LSHIFTRT
&& REG_P (SET_DEST (prev_set))
&& REG_P (SET_DEST (curr_set))
- && REGNO (SET_DEST (prev_set)) == REGNO (SET_DEST (curr_set))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO(SET_DEST (curr_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == curr_dest_regno
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& INTVAL (XEXP (SET_SRC (prev_set), 1)) == 48
&& INTVAL (XEXP (SET_SRC (curr_set), 1)) == 48)
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file,"RISCV_FUSE_ZEXTH\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDINDEXED))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDINDEXED)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (add) == (set (reg:DI rD)
@@ -9992,12 +10300,17 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
(mem:DI (reg:DI rD))) */
if (MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& REG_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDINDEXED\n");
+ return true;
+ }
/* We are trying to match the following:
prev (add) == (set (reg:DI rD)
@@ -10007,15 +10320,21 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if ((GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
|| (GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND))
&& MEM_P (XEXP (SET_SRC (curr_set), 0))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0))
- && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& REG_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDINDEXED\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LDPREINCREMENT)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (add) == (set (reg:DI rS)
@@ -10024,15 +10343,21 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
(mem:DI (reg:DI rS))) */
if (MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& REG_P (XEXP (SET_SRC (curr_set), 0))
- && REGNO (XEXP (SET_SRC (curr_set), 0)) == REGNO (SET_DEST (prev_set))
+ && REGNO (XEXP (SET_SRC (curr_set), 0)) == prev_dest_regno
&& GET_CODE (SET_SRC (prev_set)) == PLUS
&& REG_P (XEXP (SET_SRC (prev_set), 0))
&& CONST_INT_P (XEXP (SET_SRC (prev_set), 1)))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LDPREINCREMENT\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_ADDI))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_ADDI)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20))
@@ -10046,10 +10371,15 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& (GET_CODE (SET_SRC (prev_set)) == HIGH
|| (CONST_INT_P (SET_SRC (prev_set))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set))))))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_ADDI\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_ADDI))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_ADDI)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC))
@@ -10067,38 +10397,64 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
&& CONST_INT_P (XEXP (SET_SRC (curr_set), 1))
&& SMALL_OPERAND (INTVAL (XEXP (SET_SRC (curr_set), 1))))))
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_AUIPC_ADDI\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_LD))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_LUI_LD)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (lui) == (set (reg:DI rD) (const_int UPPER_IMM_20))
curr (ld) == (set (reg:DI rD)
(mem:DI (plus:DI (reg:DI rD) (const_int IMM12)))) */
+ /* A LUI_OPERAND accepts (const_int 0), but we won't emit that as LUI. So
+ reject that case explicitly. */
if (CONST_INT_P (SET_SRC (prev_set))
+ && SET_SRC (prev_set) != CONST0_RTX (GET_MODE (SET_DEST (prev_set)))
&& LUI_OPERAND (INTVAL (SET_SRC (prev_set)))
&& MEM_P (SET_SRC (curr_set))
- && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
- return true;
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
+ && GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno)
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
if (GET_CODE (SET_SRC (prev_set)) == HIGH
&& MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& GET_CODE (XEXP (SET_SRC (curr_set), 0)) == LO_SUM
- && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)))
- return true;
+ && REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == prev_dest_regno)
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
if (GET_CODE (SET_SRC (prev_set)) == HIGH
&& (GET_CODE (SET_SRC (curr_set)) == SIGN_EXTEND
|| GET_CODE (SET_SRC (curr_set)) == ZERO_EXTEND)
&& MEM_P (XEXP (SET_SRC (curr_set), 0))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& (GET_CODE (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) == LO_SUM
- && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))))
- return true;
+ && (REGNO (XEXP (XEXP (XEXP (SET_SRC (curr_set), 0), 0), 0))
+ == prev_dest_regno)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_LUI_LD\n");
+ return true;
+ }
}
- if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_LD))
+ if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_AUIPC_LD)
+ && (sched1 || prev_dest_regno == curr_dest_regno))
{
/* We are trying to match the following:
prev (auipc) == (set (reg:DI rD) (unspec:DI [...] UNSPEC_AUIPC))
@@ -10108,8 +10464,13 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if (GET_CODE (SET_SRC (prev_set)) == UNSPEC
&& XINT (prev_set, 1) == UNSPEC_AUIPC
&& MEM_P (SET_SRC (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
&& GET_CODE (XEXP (SET_SRC (curr_set), 0)) == PLUS)
- return true;
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_AUIPC_LD\n");
+ return true;
+ }
}
if (simple_sets_p && riscv_fusion_enabled_p (RISCV_FUSE_ALIGNED_STD))
@@ -10122,6 +10483,7 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
if (MEM_P (SET_DEST (prev_set))
&& MEM_P (SET_DEST (curr_set))
+ && SCALAR_INT_MODE_P (GET_MODE (SET_DEST (curr_set)))
/* We can probably relax this condition. The documentation is a bit
unclear about sub-word cases. So we just model DImode for now. */
&& GET_MODE (SET_DEST (curr_set)) == DImode
@@ -10132,43 +10494,36 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr)
extract_base_offset_in_addr (SET_DEST (prev_set), &base_prev, &offset_prev);
extract_base_offset_in_addr (SET_DEST (curr_set), &base_curr, &offset_curr);
- /* Fail if we did not find both bases. */
- if (base_prev == NULL_RTX || base_curr == NULL_RTX)
- return false;
-
- /* Fail if either base is not a register. */
- if (!REG_P (base_prev) || !REG_P (base_curr))
- return false;
-
- /* Fail if the bases are not the same register. */
- if (REGNO (base_prev) != REGNO (base_curr))
- return false;
-
- /* Originally the thought was to check MEM_ALIGN, but that was
- reporting incorrect alignments, even for SP/FP accesses, so we
- gave up on that approach. Instead just check for stack/hfp
- which we know are aligned. */
- if (REGNO (base_prev) != STACK_POINTER_REGNUM
- && REGNO (base_prev) != HARD_FRAME_POINTER_REGNUM)
- return false;
-
- /* The two stores must be contained within opposite halves of the
- same 16 byte aligned block of memory. We know that the stack
- pointer and the frame pointer have suitable alignment. So we
- just need to check the offsets of the two stores for suitable
- alignment. */
- /* Get the smaller offset into OFFSET_PREV. */
- if (INTVAL (offset_prev) > INTVAL (offset_curr))
- std::swap (offset_prev, offset_curr);
-
- /* If the smaller offset (OFFSET_PREV) is not 16 byte aligned,
- then fail. */
- if ((INTVAL (offset_prev) % 16) != 0)
- return false;
-
- /* The higher offset must be 8 bytes more than the lower
- offset. */
- return (INTVAL (offset_prev) + 8 == INTVAL (offset_curr));
+ /* Proceed only if we find both bases, both bases are register and
+ bases are the same register. */
+ if (base_prev != NULL_RTX && base_curr != NULL_RTX
+ && REG_P (base_prev) && REG_P (base_curr)
+ && REGNO (base_prev) != REGNO (base_curr)
+ /* The alignment of hte base pointer is more useful than the
+ alignment of the memory reference for determining if we're
+ on opposite sides of a cache line. */
+ && REGNO_POINTER_ALIGN (ORIGINAL_REGNO (base_prev)) >= 128)
+ {
+ /* The two stores must be contained within opposite halves of the
+ same 16 byte aligned block of memory. We know the pointer
+ has suitable alignment, so we just need to check the offsets
+ of the two stores for suitable alignment. */
+
+ /* Get the smaller offset into OFFSET_PREV. */
+ if (INTVAL (offset_prev) > INTVAL (offset_curr))
+ std::swap (offset_prev, offset_curr);
+
+ /* We have a match if the smaller offset (OFFSET_PREV) is 16
+ byte aligned and the higher offset is 8 bytes more than the
+ lower offset. */
+ if ((INTVAL (offset_prev) % 16) == 0
+ && (INTVAL (offset_prev) + 8 == INTVAL (offset_curr)))
+ {
+ if (dump_file)
+ fprintf (dump_file, "RISCV_FUSE_ALIGNED_STD\n");
+ return true;
+ }
+ }
}
}
@@ -10244,6 +10599,27 @@ riscv_sched_adjust_cost (rtx_insn *, int, rtx_insn *insn, int cost,
return new_cost;
}
+/* Implement TARGET_SCHED_CAN_SPECULATE_INSN hook. Return true if insn can
+ can be scheduled for speculative execution. Reject vsetvl instructions to
+ prevent the scheduler from hoisting them out of basic blocks without
+ checking for data dependencies PR117974. */
+static bool
+riscv_sched_can_speculate_insn (rtx_insn *insn)
+{
+ /* Gate speculative scheduling of vsetvl instructions behind tune param. */
+ if (tune_param->speculative_sched_vsetvl)
+ return true;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_VSETVL:
+ case TYPE_VSETVL_PRE:
+ return false;
+ default:
+ return true;
+ }
+}
+
/* Auxiliary function to emit RISC-V ELF attribute. */
static void
riscv_emit_attribute ()
@@ -11550,11 +11926,10 @@ riscv_gpr_save_operation_p (rtx op)
/* Two CLOBBER and USEs, must check the order. */
unsigned expect_code = i < 3 ? CLOBBER : USE;
if (GET_CODE (elt) != expect_code
- || !REG_P (XEXP (elt, 1))
- || (REGNO (XEXP (elt, 1)) != gpr_save_reg_order[i]))
+ || !REG_P (XEXP (elt, 0))
+ || (REGNO (XEXP (elt, 0)) != gpr_save_reg_order[i]))
return false;
}
- break;
}
return true;
}
@@ -12088,7 +12463,7 @@ riscv_emit_frm_mode_set (int mode, int prev_mode)
&& prev_mode != riscv_vector::FRM_DYN
&& prev_mode != riscv_vector::FRM_DYN_CALL)
/* Restore frm value when switch to DYN mode. */
- || (mode == riscv_vector::FRM_DYN
+ || (STATIC_FRM_P (cfun) && mode == riscv_vector::FRM_DYN
&& prev_mode != riscv_vector::FRM_DYN_CALL);
if (restore_p)
@@ -12115,59 +12490,6 @@ riscv_emit_mode_set (int entity, int mode, int prev_mode,
}
}
-/* Adjust the FRM_NONE insn after a call to FRM_DYN for the
- underlying emit. */
-
-static int
-riscv_frm_adjust_mode_after_call (rtx_insn *cur_insn, int mode)
-{
- rtx_insn *insn = prev_nonnote_nondebug_insn_bb (cur_insn);
-
- if (insn && CALL_P (insn))
- return riscv_vector::FRM_DYN;
-
- return mode;
-}
-
-/* Insert the backup frm insn to the end of the bb if and only if the call
- is the last insn of this bb. */
-
-static void
-riscv_frm_emit_after_bb_end (rtx_insn *cur_insn)
-{
- edge eg;
- bool abnormal_edge_p = false;
- edge_iterator eg_iterator;
- basic_block bb = BLOCK_FOR_INSN (cur_insn);
-
- FOR_EACH_EDGE (eg, eg_iterator, bb->succs)
- {
- if (eg->flags & EDGE_ABNORMAL)
- abnormal_edge_p = true;
- else
- {
- start_sequence ();
- emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
- rtx_insn *backup_insn = get_insns ();
- end_sequence ();
-
- insert_insn_on_edge (backup_insn, eg);
- }
- }
-
- if (abnormal_edge_p)
- {
- start_sequence ();
- emit_insn (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
- rtx_insn *backup_insn = get_insns ();
- end_sequence ();
-
- insert_insn_end_basic_block (backup_insn, bb);
- }
-
- commit_edge_insertions ();
-}
-
/* Return mode that frm must be switched into
prior to the execution of insn. */
@@ -12179,33 +12501,25 @@ riscv_frm_mode_needed (rtx_insn *cur_insn, int code)
/* The dynamic frm will be initialized only onece during cfun. */
DYNAMIC_FRM_RTL (cfun) = gen_reg_rtx (SImode);
emit_insn_at_entry (gen_frrmsi (DYNAMIC_FRM_RTL (cfun)));
+ CFUN_IN_CALL (cfun) = false;
}
if (CALL_P (cur_insn))
{
- rtx_insn *insn = next_nonnote_nondebug_insn_bb (cur_insn);
-
- if (!insn)
- riscv_frm_emit_after_bb_end (cur_insn);
-
+ CFUN_IN_CALL (cfun) = true;
return riscv_vector::FRM_DYN_CALL;
}
int mode = code >= 0 ? get_attr_frm_mode (cur_insn) : riscv_vector::FRM_NONE;
if (mode == riscv_vector::FRM_NONE)
- /* After meet a call, we need to backup the frm because it may be
- updated during the call. Here, for each insn, we will check if
- the previous insn is a call or not. When previous insn is call,
- there will be 2 cases for the emit mode set.
-
- 1. Current insn is not MODE_NONE, then the mode switch framework
- will do the mode switch from MODE_CALL to MODE_NONE natively.
- 2. Current insn is MODE_NONE, we need to adjust the MODE_NONE to
- the MODE_DYN, and leave the mode switch itself to perform
- the emit mode set.
- */
- mode = riscv_frm_adjust_mode_after_call (cur_insn, mode);
+ {
+ if (CFUN_IN_CALL (cfun))
+ {
+ CFUN_IN_CALL (cfun) = false;
+ return riscv_vector::FRM_DYN;
+ }
+ }
return mode;
}
@@ -12232,7 +12546,7 @@ singleton_vxrm_need (void)
/* Walk the IL noting if VXRM is needed and if there's more than one
mode needed. */
bool found = false;
- int saved_vxrm_mode;
+ int saved_vxrm_mode = VXRM_MODE_NONE;
for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (!INSN_P (insn) || DEBUG_INSN_P (insn))
@@ -12298,41 +12612,6 @@ riscv_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET)
}
}
-/* Return TRUE if the rouding mode is dynamic. */
-
-static bool
-riscv_dynamic_frm_mode_p (int mode)
-{
- return mode == riscv_vector::FRM_DYN
- || mode == riscv_vector::FRM_DYN_CALL
- || mode == riscv_vector::FRM_DYN_EXIT;
-}
-
-/* Implement TARGET_MODE_CONFLUENCE. */
-
-static int
-riscv_mode_confluence (int entity, int mode1, int mode2)
-{
- switch (entity)
- {
- case RISCV_VXRM:
- return VXRM_MODE_NONE;
- case RISCV_FRM:
- {
- /* FRM_DYN, FRM_DYN_CALL and FRM_DYN_EXIT are all compatible.
- Although we already try to set the mode needed to FRM_DYN after a
- function call, there are still some corner cases where both FRM_DYN
- and FRM_DYN_CALL may appear on incoming edges. */
- if (riscv_dynamic_frm_mode_p (mode1)
- && riscv_dynamic_frm_mode_p (mode2))
- return riscv_vector::FRM_DYN;
- return riscv_vector::FRM_NONE;
- }
- default:
- gcc_unreachable ();
- }
-}
-
/* Return TRUE that an insn is asm. */
static bool
@@ -12540,6 +12819,36 @@ get_vector_costs ()
return costs;
}
+/* Return the cost of operation that move from gpr to vr.
+ It will take the value of --param=gpr2vr_cost if it is provided.
+ Or the default regmove->GR2VR will be returned. */
+
+int
+get_gr2vr_cost ()
+{
+ int cost = get_vector_costs ()->regmove->GR2VR;
+
+ if (gpr2vr_cost != GPR2VR_COST_UNPROVIDED)
+ cost = gpr2vr_cost;
+
+ return cost;
+}
+
+/* Return the cost of moving data from floating-point to vector register.
+ It will take the value of --param=fpr2vr-cost if it is provided.
+ Otherwise the default regmove->FR2VR will be returned. */
+
+int
+get_fr2vr_cost ()
+{
+ int cost = get_vector_costs ()->regmove->FR2VR;
+
+ if (fpr2vr_cost != FPR2VR_COST_UNPROVIDED)
+ cost = fpr2vr_cost;
+
+ return cost;
+}
+
/* Implement targetm.vectorize.builtin_vectorization_cost. */
static int
@@ -12605,8 +12914,7 @@ riscv_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
case vec_construct:
{
/* TODO: This is too pessimistic in case we can splat. */
- int regmove_cost = fp ? costs->regmove->FR2VR
- : costs->regmove->GR2VR;
+ int regmove_cost = fp ? get_fr2vr_cost () : get_gr2vr_cost ();
return (regmove_cost + common_costs->scalar_to_vec_cost)
* estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype));
}
@@ -13039,6 +13347,88 @@ riscv_expand_sssub (rtx dest, rtx x, rtx y)
emit_move_insn (dest, gen_lowpart (mode, xmode_dest));
}
+/* Implement the Xmode usmul.
+
+ b = SAT_MUL (a, b);
+ =>
+ _1 = a * b;
+ _2 = mulhu (a, b);
+ _overflow_p = _2 == 0;
+ _mask = - _overflow_p;
+ b = _1 | _mask;
+ */
+
+static void
+riscv_expand_xmode_usmul (rtx dest, rtx x, rtx y)
+{
+ machine_mode mode = GET_MODE (dest);
+
+ gcc_assert (mode == Xmode);
+
+ rtx mul = gen_reg_rtx (Xmode);
+ rtx mulhu = gen_reg_rtx (Xmode);
+ rtx overflow_p = gen_reg_rtx (Xmode);
+
+ riscv_emit_binary (MULT, mul, x, y);
+
+ if (TARGET_64BIT)
+ emit_insn (gen_usmuldi3_highpart (mulhu, x, y));
+ else
+ emit_insn (gen_usmulsi3_highpart (mulhu, x, y));
+
+ riscv_emit_binary (NE, overflow_p, mulhu, CONST0_RTX (Xmode));
+ riscv_emit_unary (NEG, overflow_p, overflow_p);
+ riscv_emit_binary (IOR, dest, mul, overflow_p);
+}
+
+/* Implement the non-Xmode usmul.
+
+ b = SAT_MUL (a, b);
+ =>
+ _1 = a * b;
+ _max = (T)-1
+ _overflow_p = _1 > _max;
+ _mask = - _overflow_p;
+ b = _1 | _mask;
+ */
+
+static void
+riscv_expand_non_xmode_usmul (rtx dest, rtx x, rtx y)
+{
+ machine_mode mode = GET_MODE (dest);
+ unsigned bitsize = GET_MODE_BITSIZE (mode).to_constant ();
+
+ gcc_assert (mode != Xmode);
+
+ rtx xmode_x = riscv_extend_to_xmode_reg (x, mode, ZERO_EXTEND);
+ rtx xmode_y = riscv_extend_to_xmode_reg (y, mode, ZERO_EXTEND);
+ rtx xmode_mul = gen_reg_rtx (Xmode);
+ rtx mul_max = gen_reg_rtx (Xmode);
+ rtx overflow_p = gen_reg_rtx (Xmode);
+
+ uint64_t max = ((uint64_t)1 << bitsize) - 1;
+
+ emit_move_insn (mul_max, GEN_INT (max));
+ riscv_emit_binary (MULT, xmode_mul, xmode_x, xmode_y);
+
+ riscv_emit_binary (LTU, overflow_p, mul_max, xmode_mul);
+ riscv_emit_unary (NEG, overflow_p, overflow_p);
+ riscv_emit_binary (IOR, xmode_mul, xmode_mul, overflow_p);
+
+ emit_move_insn (dest, gen_lowpart (mode, xmode_mul));
+}
+
+/* Implements the unsigned saturation mult standard name usmul for int mode. */
+
+void
+riscv_expand_usmul (rtx dest, rtx x, rtx y)
+{
+ if (GET_MODE (dest) == Xmode)
+ return riscv_expand_xmode_usmul (dest, x, y) ;
+ else
+ return riscv_expand_non_xmode_usmul (dest, x, y);
+}
+
/* Implement the unsigned saturation truncation for int mode.
b = SAT_TRUNC (a);
@@ -13792,7 +14182,6 @@ riscv_get_function_versions_dispatcher (void *decl)
struct cgraph_node *node = NULL;
struct cgraph_node *default_node = NULL;
struct cgraph_function_version_info *node_v = NULL;
- struct cgraph_function_version_info *first_v = NULL;
tree dispatch_decl = NULL;
@@ -13809,41 +14198,16 @@ riscv_get_function_versions_dispatcher (void *decl)
if (node_v->dispatcher_resolver != NULL)
return node_v->dispatcher_resolver;
- /* Find the default version and make it the first node. */
- first_v = node_v;
- /* Go to the beginning of the chain. */
- while (first_v->prev != NULL)
- first_v = first_v->prev;
- default_version_info = first_v;
-
- while (default_version_info != NULL)
- {
- struct riscv_feature_bits res;
- int priority; /* Unused. */
- parse_features_for_version (default_version_info->this_node->decl,
- res, priority);
- if (res.length == 0)
- break;
- default_version_info = default_version_info->next;
- }
+ /* The default node is always the beginning of the chain. */
+ default_version_info = node_v;
+ while (default_version_info->prev)
+ default_version_info = default_version_info->prev;
+ default_node = default_version_info->this_node;
/* If there is no default node, just return NULL. */
- if (default_version_info == NULL)
+ if (!is_function_default_version (default_node->decl))
return NULL;
- /* Make default info the first node. */
- if (first_v != default_version_info)
- {
- default_version_info->prev->next = default_version_info->next;
- if (default_version_info->next)
- default_version_info->next->prev = default_version_info->prev;
- first_v->prev = default_version_info;
- default_version_info->next = first_v;
- default_version_info->prev = NULL;
- }
-
- default_node = default_version_info->this_node;
-
if (targetm.has_ifunc_p ())
{
struct cgraph_function_version_info *it_v = NULL;
@@ -13987,17 +14351,53 @@ expand_crc_using_clmul (scalar_mode crc_mode, scalar_mode data_mode,
rtx data = gen_rtx_ZERO_EXTEND (word_mode, operands[2]);
riscv_expand_op (XOR, word_mode, a0, crc, data);
- if (TARGET_64BIT)
- emit_insn (gen_riscv_clmul_di (a0, a0, t0));
- else
- emit_insn (gen_riscv_clmul_si (a0, a0, t0));
+ if (TARGET_ZBKC || TARGET_ZBC)
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_riscv_clmul_di (a0, a0, t0));
+ else
+ emit_insn (gen_riscv_clmul_si (a0, a0, t0));
- riscv_expand_op (LSHIFTRT, word_mode, a0, a0,
- gen_int_mode (crc_size, word_mode));
- if (TARGET_64BIT)
- emit_insn (gen_riscv_clmul_di (a0, a0, t1));
+ riscv_expand_op (LSHIFTRT, word_mode, a0, a0,
+ gen_int_mode (crc_size, word_mode));
+ if (TARGET_64BIT)
+ emit_insn (gen_riscv_clmul_di (a0, a0, t1));
+ else
+ emit_insn (gen_riscv_clmul_si (a0, a0, t1));
+ }
else
- emit_insn (gen_riscv_clmul_si (a0, a0, t1));
+ {
+ machine_mode vmode;
+ if (!riscv_vector::get_vector_mode (DImode, 1).exists (&vmode))
+ gcc_unreachable ();
+
+ rtx vec = gen_reg_rtx (vmode);
+
+ insn_code icode1 = code_for_pred_broadcast (vmode);
+ rtx ops1[] = {vec, a0};
+ emit_nonvlmax_insn (icode1, UNARY_OP, ops1, CONST1_RTX (Pmode));
+
+ rtx rvv1di_reg = gen_rtx_SUBREG (RVVM1DImode, vec, 0);
+ insn_code icode2 = code_for_pred_vclmul_scalar (UNSPEC_VCLMUL,
+ E_RVVM1DImode);
+ rtx ops2[] = {rvv1di_reg, rvv1di_reg, t0};
+ emit_nonvlmax_insn (icode2, riscv_vector::BINARY_OP, ops2, CONST1_RTX
+ (Pmode));
+
+ rtx shift_amount = gen_int_mode (data_size, Pmode);
+ insn_code icode3 = code_for_pred_scalar (LSHIFTRT, vmode);
+ rtx ops3[] = {vec, vec, shift_amount};
+ emit_nonvlmax_insn (icode3, BINARY_OP, ops3, CONST1_RTX (Pmode));
+
+ insn_code icode4 = code_for_pred_vclmul_scalar (UNSPEC_VCLMULH,
+ E_RVVM1DImode);
+ rtx ops4[] = {rvv1di_reg, rvv1di_reg, t1};
+ emit_nonvlmax_insn (icode4, riscv_vector::BINARY_OP, ops4, CONST1_RTX
+ (Pmode));
+
+ rtx vec_low_lane = gen_lowpart (DImode, vec);
+ riscv_emit_move (a0, vec_low_lane);
+ }
if (crc_size > data_size)
{
@@ -14046,19 +14446,53 @@ expand_reversed_crc_using_clmul (scalar_mode crc_mode, scalar_mode data_mode,
rtx a0 = gen_reg_rtx (word_mode);
riscv_expand_op (XOR, word_mode, a0, crc, data);
- if (TARGET_64BIT)
- emit_insn (gen_riscv_clmul_di (a0, a0, t0));
- else
- emit_insn (gen_riscv_clmul_si (a0, a0, t0));
+ if (TARGET_ZBKC || TARGET_ZBC)
+ {
+ if (TARGET_64BIT)
+ emit_insn (gen_riscv_clmul_di (a0, a0, t0));
+ else
+ emit_insn (gen_riscv_clmul_si (a0, a0, t0));
- rtx num_shift = gen_int_mode (GET_MODE_BITSIZE (word_mode) - data_size,
- word_mode);
- riscv_expand_op (ASHIFT, word_mode, a0, a0, num_shift);
+ rtx num_shift = gen_int_mode (BITS_PER_WORD - data_size, word_mode);
+ riscv_expand_op (ASHIFT, word_mode, a0, a0, num_shift);
- if (TARGET_64BIT)
- emit_insn (gen_riscv_clmulh_di (a0, a0, t1));
+ if (TARGET_64BIT)
+ emit_insn (gen_riscv_clmulh_di (a0, a0, t1));
+ else
+ emit_insn (gen_riscv_clmulh_si (a0, a0, t1));
+ }
else
- emit_insn (gen_riscv_clmulh_si (a0, a0, t1));
+ {
+ machine_mode vmode;
+ if (!riscv_vector::get_vector_mode (DImode, 1).exists (&vmode))
+ gcc_unreachable ();
+
+ rtx vec = gen_reg_rtx (vmode);
+ insn_code icode1 = code_for_pred_broadcast (vmode);
+ rtx ops1[] = {vec, a0};
+ emit_nonvlmax_insn (icode1, UNARY_OP, ops1, CONST1_RTX (Pmode));
+
+ rtx rvv1di_reg = gen_rtx_SUBREG (RVVM1DImode, vec, 0);
+ insn_code icode2 = code_for_pred_vclmul_scalar (UNSPEC_VCLMUL,
+ E_RVVM1DImode);
+ rtx ops2[] = {rvv1di_reg, rvv1di_reg, t0};
+ emit_nonvlmax_insn (icode2, riscv_vector::BINARY_OP, ops2, CONST1_RTX
+ (Pmode));
+
+ rtx shift_amount = gen_int_mode (BITS_PER_WORD - data_size, Pmode);
+ insn_code icode3 = code_for_pred_scalar (ASHIFT, vmode);
+ rtx ops3[] = {vec, vec, shift_amount};
+ emit_nonvlmax_insn (icode3, BINARY_OP, ops3, CONST1_RTX (Pmode));
+
+ insn_code icode4 = code_for_pred_vclmul_scalar (UNSPEC_VCLMULH,
+ E_RVVM1DImode);
+ rtx ops4[] = {rvv1di_reg, rvv1di_reg, t1};
+ emit_nonvlmax_insn (icode4, riscv_vector::BINARY_OP, ops4, CONST1_RTX
+ (Pmode));
+
+ rtx vec_low_lane = gen_lowpart (DImode, vec);
+ riscv_emit_move (a0, vec_low_lane);
+ }
if (crc_size > data_size)
{
@@ -14092,6 +14526,427 @@ bool need_shadow_stack_push_pop_p ()
return is_zicfiss_p () && riscv_save_return_addr_reg_p ();
}
+/* Synthesize OPERANDS[0] = OPERANDS[1] CODE OPERANDS[2].
+
+ OPERANDS[0] and OPERANDS[1] will be a REG and may be the same
+ REG.
+
+ OPERANDS[2] is a CONST_INT.
+
+ CODE is IOR or XOR.
+
+ Return TRUE if the operation was fully synthesized and the caller
+ need not generate additional code. Return FALSE if the operation
+ was not synthesized and the caller is responsible for emitting the
+ proper sequence. */
+
+bool
+synthesize_ior_xor (rtx_code code, rtx operands[3])
+{
+ /* Trivial cases that don't need synthesis. */
+ if (SMALL_OPERAND (INTVAL (operands[2]))
+ || ((TARGET_ZBS || TARGET_ZBKB)
+ && single_bit_mask_operand (operands[2], word_mode)))
+ return false;
+
+ /* The number of instructions to synthesize the constant is a good
+ estimate of the budget. That does not account for out of order
+ execution an fusion in the constant synthesis those would naturally
+ decrease the budget. It also does not account for the IOR/XOR at
+ the end of the sequence which would increase the budget. */
+ int budget = (TARGET_ZBS ? riscv_const_insns (operands[2], true) : -1);
+ int original_budget = budget;
+
+ /* Bits we need to set in operands[0]. As we synthesize the operation,
+ we clear bits in IVAL. Once IVAL is zero, then synthesis of the
+ operation is complete. */
+ unsigned HOST_WIDE_INT ival = INTVAL (operands[2]);
+
+ /* Check if we want to use [x]ori. Then get the remaining bits
+ and decrease the budget by one. */
+ if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0)
+ {
+ ival &= ~HOST_WIDE_INT_UC (0x7ff);
+ budget--;
+ }
+
+ /* Check for bseti cases. For each remaining bit in ival,
+ decrease the budget by one. */
+ while (ival)
+ {
+ HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival);
+ ival &= ~tmpval;
+ budget--;
+ }
+
+ /* If we're flipping all but a small number of bits we can pre-flip
+ the outliers, then flip all the bits, which would restore those
+ bits that were pre-flipped. */
+ if ((TARGET_ZBS || TARGET_ZBKB)
+ && budget < 0
+ && code == XOR
+ && popcount_hwi (~INTVAL (operands[2])) < original_budget)
+ {
+ /* Pre-flipping bits we want to preserve. */
+ rtx input = operands[1];
+ rtx output = NULL_RTX;
+ ival = ~INTVAL (operands[2]);
+ while (ival)
+ {
+ HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival);
+ rtx x = GEN_INT (tmpval);
+ x = gen_rtx_XOR (word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ ival &= ~tmpval;
+ }
+
+ gcc_assert (output);
+
+ /* Now flip all the bits, which restores the bits we were
+ preserving. */
+ rtx x = gen_rtx_NOT (word_mode, input);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* One more approach we can try. If our budget is 3+ instructions,
+ then we can try to rotate the source so that the bits we want to
+ set are in the low 11 bits. We then use [x]ori to set those low
+ bits, then rotate things back into their proper place. */
+ if ((TARGET_ZBB || TARGET_XTHEADBB || TARGET_ZBKB)
+ && budget < 0
+ && popcount_hwi (INTVAL (operands[2])) <= 11
+ && riscv_const_insns (operands[2], true) >= 3)
+ {
+ ival = INTVAL (operands[2]);
+ /* First see if the constant trivially fits into 11 bits in the LSB. */
+ int lsb = ctz_hwi (ival);
+ int msb = BITS_PER_WORD - 1 - clz_hwi (ival);
+ if (msb - lsb + 1 <= 11)
+ {
+ rtx output = gen_reg_rtx (word_mode);
+ rtx input = operands[1];
+
+ /* Rotate the source right by LSB bits. */
+ rtx x = GEN_INT (lsb);
+ x = gen_rtx_ROTATERT (word_mode, input, x);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* Shift the constant right by LSB bits. */
+ x = GEN_INT (ival >> lsb);
+
+ /* Perform the IOR/XOR operation. */
+ x = gen_rtx_fmt_ee (code, word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* And rotate left to put everything back in place, we don't
+ have rotate left by a constant, so use rotate right by
+ an adjusted constant. */
+ x = GEN_INT (BITS_PER_WORD - lsb);
+ x = gen_rtx_ROTATERT (word_mode, input, x);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* Maybe the bits are split between the high and low parts
+ of the constant. A bit more complex, but still manageable.
+
+ Conceptually we want to rotate left the constant by the number
+ of leading zeros after masking off all but the low 11 bits. */
+ int rotcount = clz_hwi (ival & 0x7ff) - (BITS_PER_WORD - 11);
+
+ /* Rotate the constant left by MSB bits. */
+ ival = (ival << rotcount) | (ival >> (BITS_PER_WORD - rotcount));
+
+ /* Now we can do the same tests as before. */
+ lsb = ctz_hwi (ival);
+ msb = BITS_PER_WORD - clz_hwi (ival);
+ if ((INTVAL (operands[2]) & HOST_WIDE_INT_UC (0x7ff)) != 0
+ && msb - lsb + 1 <= 11)
+ {
+ rtx output = gen_reg_rtx (word_mode);
+ rtx input = operands[1];
+
+ /* Rotate the source left by ROTCOUNT bits, we don't have
+ rotate left by a constant, so use rotate right by an
+ adjusted constant. */
+ rtx x = GEN_INT (BITS_PER_WORD - rotcount);
+ x = gen_rtx_ROTATERT (word_mode, input, x);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* We've already rotated the constant. So perform the IOR/XOR
+ operation. */
+ x = GEN_INT (ival);
+ x = gen_rtx_fmt_ee (code, word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* And rotate right to put everything into its proper place. */
+ x = GEN_INT (rotcount);
+ x = gen_rtx_ROTATERT (word_mode, input, x);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+ }
+
+ /* If after accounting for bseti the remaining budget has
+ gone to less than zero, it forces the value into a
+ register and performs the IOR operation. It returns
+ TRUE to the caller so the caller knows code generation
+ is complete. */
+ if (budget < 0)
+ {
+ rtx x = force_reg (word_mode, operands[2]);
+ x = gen_rtx_fmt_ee (code, word_mode, operands[1], x);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* Synthesis is better than loading the constant. */
+ ival = INTVAL (operands[2]);
+ rtx input = operands[1];
+ rtx output = NULL_RTX;
+
+ /* Emit the [x]ori insn that sets the low 11 bits into
+ the proper state. */
+ if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0)
+ {
+ rtx x = GEN_INT (ival & HOST_WIDE_INT_UC (0x7ff));
+ x = gen_rtx_fmt_ee (code, word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ ival &= ~HOST_WIDE_INT_UC (0x7ff);
+ }
+
+ /* We figure out a single bit as a constant and
+ generate a CONST_INT node for that. Then we
+ construct the IOR node, then the SET node and
+ emit it. An IOR with a suitable constant that is
+ a single bit will be implemented with a bseti. */
+ while (ival)
+ {
+ HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival);
+ rtx x = GEN_INT (tmpval);
+ x = gen_rtx_fmt_ee (code, word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ ival &= ~tmpval;
+ }
+
+ gcc_assert (output);
+ emit_move_insn (operands[0], output);
+ return true;
+}
+
+/* Synthesize OPERANDS[0] = OPERANDS[1] & OPERANDS[2].
+
+ OPERANDS[0] and OPERANDS[1] will be a REG and may be the same
+ REG.
+
+ OPERANDS[2] is a CONST_INT.
+
+ Return TRUE if the operation was fully synthesized and the caller
+ need not generate additional code. Return FALSE if the operation
+ was not synthesized and the caller is responsible for emitting the
+ proper sequence. */
+
+bool
+synthesize_and (rtx operands[3])
+{
+ /* Trivial cases that don't need synthesis. */
+ if (SMALL_OPERAND (INTVAL (operands[2]))
+ || (TARGET_ZBS && not_single_bit_mask_operand (operands[2], word_mode)))
+ return false;
+
+ /* If the second operand is a mode mask, emit an extension
+ insn instead. */
+ if (CONST_INT_P (operands[2]))
+ {
+ enum machine_mode tmode = VOIDmode;
+ if (UINTVAL (operands[2]) == GET_MODE_MASK (HImode))
+ tmode = HImode;
+ else if (UINTVAL (operands[2]) == GET_MODE_MASK (SImode))
+ tmode = SImode;
+
+ if (tmode != VOIDmode)
+ {
+ rtx tmp = gen_lowpart (tmode, operands[1]);
+ emit_insn (gen_extend_insn (operands[0], tmp, word_mode, tmode, 1));
+ return true;
+ }
+ }
+
+ /* The number of instructions to synthesize the constant is a good
+ estimate of the budget. That does not account for out of order
+ execution an fusion in the constant synthesis those would naturally
+ decrease the budget. It also does not account for the AND at
+ the end of the sequence which would increase the budget. */
+ int budget = riscv_const_insns (operands[2], true);
+ rtx input = NULL_RTX;
+ rtx output = NULL_RTX;
+
+ /* Left shift + right shift to clear high bits. */
+ if (budget >= 2 && p2m1_shift_operand (operands[2], word_mode))
+ {
+ int count = (GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant ()
+ - exact_log2 (INTVAL (operands[2]) + 1));
+ rtx x = gen_rtx_ASHIFT (word_mode, operands[1], GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ x = gen_rtx_LSHIFTRT (word_mode, input, GEN_INT (count));
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* Clears a bunch of low bits with only high bits set. */
+ unsigned HOST_WIDE_INT t = ~INTVAL (operands[2]);
+ if (budget >= 2 && exact_log2 (t + 1) >= 0)
+ {
+ int count = ctz_hwi (INTVAL (operands[2]));
+ rtx x = gen_rtx_LSHIFTRT (word_mode, operands[1], GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* If we shift right to eliminate the trailing zeros and
+ the result is a SMALL_OPERAND, then it's a shift right,
+ andi and shift left. */
+ t = INTVAL (operands[2]);
+ t >>= ctz_hwi (t);
+ if (budget >= 3 && SMALL_OPERAND (t) && popcount_hwi (t) > 2)
+ {
+ /* Shift right to clear the low order bits. */
+ unsigned HOST_WIDE_INT count = ctz_hwi (INTVAL (operands[2]));
+ rtx x = gen_rtx_LSHIFTRT (word_mode, operands[1], GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* Now emit the ANDI. */
+ unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
+ mask >>= ctz_hwi (mask);
+ x = gen_rtx_AND (word_mode, input, GEN_INT (mask));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* Shift left to move bits into position. */
+ count = INTVAL (operands[2]);
+ count = ctz_hwi (count);
+ x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* If there are all zeros, except for a run of 1s somewhere in the middle
+ of the constant, then this is at worst 3 shifts. */
+ t = INTVAL (operands[2]);
+ if (budget >= 3
+ && consecutive_bits_operand (GEN_INT (t), word_mode)
+ && popcount_hwi (t) > 3)
+ {
+ /* Shift right to clear the low order bits. */
+ int count = ctz_hwi (INTVAL (operands[2]));
+ rtx x = gen_rtx_LSHIFTRT (word_mode, operands[1], GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* Shift left to clear the high order bits. */
+ count += clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+ x = gen_rtx_ASHIFT (word_mode, input, GEN_INT (count));
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+
+ /* And shift back right to put the bits into position. */
+ count = clz_hwi (INTVAL (operands[2])) % BITS_PER_WORD;
+ x = gen_rtx_LSHIFTRT (word_mode, input, GEN_INT (count));
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* The special cases didn't apply. It's entirely possible we may
+ want to combine some of the ideas above with bclr, but for now
+ those are deferred until we see them popping up in practice. */
+
+ unsigned HOST_WIDE_INT ival = ~INTVAL (operands[2]);
+
+ /* Clear as many bits using andi as we can. */
+ if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0x0)
+ {
+ ival &= ~HOST_WIDE_INT_UC (0x7ff);
+ budget--;
+ }
+
+ /* And handle remaining bits via bclr. */
+ while (TARGET_ZBS && ival)
+ {
+ unsigned HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival);
+ ival &= ~tmpval;
+ budget--;
+ }
+
+ /* If the remaining budget has gone to less than zero, it
+ forces the value into a register and performs the AND
+ operation. It returns TRUE to the caller so the caller
+ knows code generation is complete.
+ FIXME: This is hacked to always be enabled until the last
+ patch in the series is enabled. */
+ if (ival || budget < 0)
+ {
+ rtx x = force_reg (word_mode, operands[2]);
+ x = gen_rtx_AND (word_mode, operands[1], x);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ return true;
+ }
+
+ /* Synthesis is better than loading the constant. */
+ ival = ~INTVAL (operands[2]);
+ input = operands[1];
+
+ /* Clear any of the lower 11 bits we need. */
+ if ((ival & HOST_WIDE_INT_UC (0x7ff)) != 0)
+ {
+ rtx x = GEN_INT (~(ival & HOST_WIDE_INT_UC (0x7ff)));
+ x = gen_rtx_AND (word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ ival &= ~HOST_WIDE_INT_UC (0x7ff);
+ }
+
+ /* Clear the rest with bclr. */
+ while (ival)
+ {
+ unsigned HOST_WIDE_INT tmpval = HOST_WIDE_INT_UC (1) << ctz_hwi (ival);
+ rtx x = GEN_INT (~tmpval);
+ x = gen_rtx_AND (word_mode, input, x);
+ output = gen_reg_rtx (word_mode);
+ emit_insn (gen_rtx_SET (output, x));
+ input = output;
+ ival &= ~tmpval;
+ }
+
+ emit_move_insn (operands[0], input);
+ return true;
+}
+
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -14125,6 +14980,9 @@ bool need_shadow_stack_push_pop_p ()
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST riscv_sched_adjust_cost
+#undef TARGET_SCHED_CAN_SPECULATE_INSN
+#define TARGET_SCHED_CAN_SPECULATE_INSN riscv_sched_can_speculate_insn
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL riscv_function_ok_for_sibcall
@@ -14416,8 +15274,6 @@ bool need_shadow_stack_push_pop_p ()
#define TARGET_MODE_EMIT riscv_emit_mode_set
#undef TARGET_MODE_NEEDED
#define TARGET_MODE_NEEDED riscv_mode_needed
-#undef TARGET_MODE_CONFLUENCE
-#define TARGET_MODE_CONFLUENCE riscv_mode_confluence
#undef TARGET_MODE_AFTER
#define TARGET_MODE_AFTER riscv_mode_after
#undef TARGET_MODE_ENTRY
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 2759a4c..45fa521 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -43,7 +43,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#ifndef RISCV_TUNE_STRING_DEFAULT
-#define RISCV_TUNE_STRING_DEFAULT "rocket"
+#define RISCV_TUNE_STRING_DEFAULT "generic"
#endif
extern const char *riscv_expand_arch (int argc, const char **argv);
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 15c89ff..c6661f5 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -672,7 +672,7 @@
;; Microarchitectures we know how to tune for.
;; Keep this in sync with enum riscv_microarchitecture.
(define_attr "tune"
- "generic,sifive_7,sifive_p400,sifive_p600,xiangshan,generic_ooo"
+ "generic,sifive_7,sifive_p400,sifive_p600,xiangshan,generic_ooo,mips_p8700"
(const (symbol_ref "((enum attr_tune) riscv_microarchitecture)")))
;; Describe a user's asm statement.
@@ -884,7 +884,7 @@
;; Where C1 is not a LUI operand, but ~C1 is a LUI operand
(define_insn_and_split "*lui_constraint<X:mode>_and_to_or"
- [(set (match_operand:X 0 "register_operand" "=r")
+ [(set (match_operand:X 0 "register_operand" "=r")
(plus:X (and:X (match_operand:X 1 "register_operand" "r")
(match_operand 2 "const_int_operand"))
(match_operand 3 "const_int_operand")))
@@ -898,13 +898,21 @@
<= riscv_const_insns (operands[3], false)))"
"#"
"&& reload_completed"
- [(set (match_dup 4) (match_dup 5))
- (set (match_dup 0) (ior:X (match_dup 1) (match_dup 4)))
- (set (match_dup 4) (match_dup 6))
- (set (match_dup 0) (minus:X (match_dup 0) (match_dup 4)))]
+ [(const_int 0)]
{
operands[5] = GEN_INT (~INTVAL (operands[2]));
operands[6] = GEN_INT ((~INTVAL (operands[2])) | (-INTVAL (operands[3])));
+
+ /* This is always a LUI operand, so it's safe to just emit. */
+ emit_move_insn (operands[4], operands[5]);
+
+ rtx x = gen_rtx_IOR (word_mode, operands[1], operands[4]);
+ emit_move_insn (operands[0], x);
+
+ /* This may require multiple steps to synthesize. */
+ riscv_emit_move (operands[4], operands[6]);
+ x = gen_rtx_MINUS (word_mode, operands[0], operands[4]);
+ emit_move_insn (operands[0], x);
}
[(set_attr "type" "arith")])
@@ -1724,26 +1732,11 @@
(define_expand "and<mode>3"
[(set (match_operand:X 0 "register_operand")
(and:X (match_operand:X 1 "register_operand")
- (match_operand:X 2 "arith_or_mode_mask_or_zbs_operand")))]
+ (match_operand:X 2 "reg_or_const_int_operand")))]
""
{
- /* If the second operand is a mode mask, emit an extension
- insn instead. */
- if (CONST_INT_P (operands[2]))
- {
- enum machine_mode tmode = VOIDmode;
- if (UINTVAL (operands[2]) == GET_MODE_MASK (HImode))
- tmode = HImode;
- else if (UINTVAL (operands[2]) == GET_MODE_MASK (SImode))
- tmode = SImode;
-
- if (tmode != VOIDmode)
- {
- rtx tmp = gen_lowpart (tmode, operands[1]);
- emit_insn (gen_extend_insn (operands[0], tmp, <MODE>mode, tmode, 1));
- DONE;
- }
- }
+ if (CONST_INT_P (operands[2]) && synthesize_and (operands))
+ DONE;
})
(define_insn "*and<mode>3"
@@ -1767,8 +1760,15 @@
(define_expand "<optab><mode>3"
[(set (match_operand:X 0 "register_operand")
(any_or:X (match_operand:X 1 "register_operand" "")
- (match_operand:X 2 "arith_or_zbs_operand" "")))]
- "")
+ (match_operand:X 2 "reg_or_const_int_operand" "")))]
+ ""
+
+{
+ /* If synthesis of the logical op is successful, then no further code
+ generation is necessary. Else just generate code normally. */
+ if (CONST_INT_P (operands[2]) && synthesize_ior_xor (<OPTAB>, operands))
+ DONE;
+})
(define_insn "*<optab><mode>3"
[(set (match_operand:X 0 "register_operand" "=r,r")
@@ -2509,8 +2509,8 @@
})
(define_insn "*movdi_32bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m, *f,*f,*r,*f,*m,r")
- (match_operand:DI 1 "move_operand" " r,i,m,r,*J*r,*m,*f,*f,*f,vp"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, *f,*f,*r,*f,*m,r")
+ (match_operand:DI 1 "move_operand" " r,i,m,rJ,*J*r,*m,*f,*f,*f,vp"))]
"!TARGET_64BIT
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
@@ -2946,7 +2946,14 @@
(match_operand:GPR2 2 "register_operand" "r")
(match_operand 3 "<GPR:shiftm1>"))])))]
""
- "<insn>\t%0,%1,%2"
+{
+ /* If the shift mode is not word mode, then it must be the
+ case that we're generating rv64 code, but this is a 32-bit
+ operation. Thus we need to use the "w" variant. */
+ if (E_<GPR:MODE>mode != word_mode)
+ return "<insn>w\t%0,%1,%2";
+ return "<insn>\t%0,%1,%2";
+}
[(set_attr "type" "shift")
(set_attr "mode" "<GPR:MODE>")])
@@ -3173,15 +3180,25 @@
"#"
"&& reload_completed"
[(set (match_dup 4) (lshiftrt:X (subreg:X (match_dup 2) 0) (match_dup 6)))
- (set (match_dup 4) (and:X (match_dup 4) (match_dup 7)))
+ (set (match_dup 4) (match_dup 8))
(set (pc) (if_then_else (match_op_dup 1 [(match_dup 4) (const_int 0)])
(label_ref (match_dup 0)) (pc)))]
{
- HOST_WIDE_INT mask = INTVAL (operands[3]);
- int trailing = ctz_hwi (mask);
+ HOST_WIDE_INT mask = INTVAL (operands[3]);
+ int trailing = ctz_hwi (mask);
+
+ operands[6] = GEN_INT (trailing);
+ operands[7] = GEN_INT (mask >> trailing);
- operands[6] = GEN_INT (trailing);
- operands[7] = GEN_INT (mask >> trailing);
+ /* This splits after reload, so there's little chance to clean things
+ up. Rather than emit a ton of RTL here, we can just make a new
+ operand for that RHS and use it. For the case where the AND would
+ have been redundant, we can make it a NOP move, which does get
+ cleaned up. */
+ if (operands[7] == CONSTM1_RTX (word_mode))
+ operands[8] = operands[4];
+ else
+ operands[8] = gen_rtx_AND (word_mode, operands[4], operands[7]);
}
[(set_attr "type" "branch")])
@@ -4385,7 +4402,7 @@
)
(define_insn "prefetch"
- [(prefetch (match_operand 0 "address_operand" "r")
+ [(prefetch (match_operand 0 "prefetch_operand" "Qr")
(match_operand 1 "imm5_operand" "i")
(match_operand 2 "const_int_operand" "n"))]
"TARGET_ZICBOP"
@@ -4405,7 +4422,7 @@
(const_string "4")))])
(define_insn "riscv_prefetchi_<mode>"
- [(unspec_volatile:X [(match_operand:X 0 "address_operand" "r")
+ [(unspec_volatile:X [(match_operand:X 0 "prefetch_operand" "Q")
(match_operand:X 1 "imm5_operand" "i")]
UNSPECV_PREI)]
"TARGET_ZICBOP"
@@ -4617,6 +4634,17 @@
}
)
+(define_expand "usmul<mode>3"
+ [(match_operand:ANYI 0 "register_operand")
+ (match_operand:ANYI 1 "register_operand")
+ (match_operand:ANYI 2 "register_operand")]
+ ""
+ {
+ riscv_expand_usmul (operands[0], operands[1], operands[2]);
+ DONE;
+ }
+)
+
(define_expand "ustrunc<mode><anyi_double_truncated>2"
[(match_operand:<ANYI_DOUBLE_TRUNCATED> 0 "register_operand")
(match_operand:ANYI_DOUBLE_TRUNC 1 "register_operand")]
@@ -4695,23 +4723,38 @@
(match_operand 2 "const_int_operand" "n"))
(match_operand 3 "const_int_operand" "n")))
(clobber (match_scratch:DI 4 "=&r"))]
- "(TARGET_64BIT && riscv_const_insns (operands[3], false) == 1)"
+ "(TARGET_64BIT
+ && riscv_const_insns (operands[3], false) == 1
+ && riscv_const_insns (GEN_INT (INTVAL (operands[3])
+ << INTVAL (operands[2])), false) != 1)"
"#"
"&& reload_completed"
[(const_int 0)]
"{
- rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
- emit_insn (gen_rtx_SET (operands[0], x));
-
- /* If the constant fits in a simm12, use it directly as we do not
- get another good chance to optimize things again. */
- if (!SMALL_OPERAND (INTVAL (operands[3])))
+ /* Prefer to generate shNadd when we can, even over using an
+ immediate form. If we're not going to be able to generate
+ a shNadd, then use the constant directly if it fits in a
+ simm12 field since we won't get another chance to optimize this. */
+ if ((TARGET_ZBA && imm123_operand (operands[2], word_mode))
+ || !SMALL_OPERAND (INTVAL (operands[3])))
emit_move_insn (operands[4], operands[3]);
else
operands[4] = operands[3];
- x = gen_rtx_PLUS (DImode, operands[0], operands[4]);
- emit_insn (gen_rtx_SET (operands[0], x));
+ if (TARGET_ZBA && imm123_operand (operands[2], word_mode))
+ {
+ rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
+ x = gen_rtx_PLUS (DImode, x, operands[4]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+ else
+ {
+ rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ x = gen_rtx_PLUS (DImode, operands[0], operands[4]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+
DONE;
}"
[(set_attr "type" "arith")])
@@ -4810,6 +4853,25 @@
[(set_attr "type" "move")
(set_attr "mode" "<MODE>")])
+;; If we're trying to create 0 or 2^n-1 based on the result of
+;; a test such as (lt (reg) (const_int 0)), we'll see a splat of
+;; the sign bit across a GPR using srai, then a logical and to
+;; mask off high bits. We can replace the logical and with
+;; a logical right shift which works without constant synthesis
+;; for larger constants.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (and:X (ashiftrt:X (match_operand:X 1 "register_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand 3 "const_int_operand")))]
+ "(INTVAL (operands[2]) == BITS_PER_WORD - 1
+ && exact_log2 (INTVAL (operands[3]) + 1) >= 0)"
+ [(set (match_dup 0) (ashiftrt:X (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (lshiftrt:X (match_dup 0) (match_dup 3)))]
+ { operands[3] = GEN_INT (BITS_PER_WORD
+ - exact_log2 (INTVAL (operands[3]) + 1)); })
+
+;; Standard extensions and pattern for optimization
(include "bitmanip.md")
(include "crypto.md")
(include "sync.md")
@@ -4817,18 +4879,21 @@
(include "sync-ztso.md")
(include "peephole.md")
(include "pic.md")
-(include "generic.md")
-(include "sifive-7.md")
-(include "sifive-p400.md")
-(include "sifive-p600.md")
-(include "thead.md")
-(include "generic-vector-ooo.md")
-(include "generic-ooo.md")
(include "vector.md")
(include "vector-crypto.md")
(include "vector-bfloat16.md")
(include "zicond.md")
(include "sfb.md")
(include "zc.md")
+;; Vendor extensions
+(include "thead.md")
(include "corev.md")
+;; Pipeline models
+(include "generic.md")
(include "xiangshan.md")
+(include "mips-p8700.md")
+(include "sifive-7.md")
+(include "sifive-p400.md")
+(include "sifive-p600.md")
+(include "generic-vector-ooo.md")
+(include "generic-ooo.md")
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 7515c8e..6543fd1 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -168,23 +168,14 @@ momit-leaf-frame-pointer
Target Mask(OMIT_LEAF_FRAME_POINTER) Save
Omit the frame pointer in leaf functions.
-Mask(64BIT)
-
-Mask(MUL)
-
-Mask(ATOMIC)
-
-Mask(HARD_FLOAT)
-
-Mask(DOUBLE_FLOAT)
-
-Mask(RVC)
+TargetVariable
+int riscv_isa_flags
-Mask(RVE)
+Mask(64BIT) Var(riscv_isa_flags)
-Mask(VECTOR)
+Mask(VECTOR) Var(riscv_isa_flags)
-Mask(FULL_V)
+Mask(FULL_V) Var(riscv_isa_flags)
mriscv-attribute
Target Var(riscv_emit_attribute_p) Init(-1)
@@ -233,93 +224,6 @@ TargetVariable
long riscv_stack_protector_guard_offset = 0
TargetVariable
-int riscv_zi_subext
-
-Mask(ZICSR) Var(riscv_zi_subext)
-
-Mask(ZIFENCEI) Var(riscv_zi_subext)
-
-Mask(ZIHINTNTL) Var(riscv_zi_subext)
-
-Mask(ZIHINTPAUSE) Var(riscv_zi_subext)
-
-Mask(ZICOND) Var(riscv_zi_subext)
-
-Mask(ZICCAMOA) Var(riscv_zi_subext)
-
-Mask(ZICCIF) Var(riscv_zi_subext)
-
-Mask(ZICCLSM) Var(riscv_zi_subext)
-
-Mask(ZICCRSE) Var(riscv_zi_subext)
-
-Mask(ZICFISS) Var(riscv_zi_subext)
-
-Mask(ZICFILP) Var(riscv_zi_subext)
-
-TargetVariable
-int riscv_za_subext
-
-Mask(ZAWRS) Var(riscv_za_subext)
-
-Mask(ZAAMO) Var(riscv_za_subext)
-
-Mask(ZALRSC) Var(riscv_za_subext)
-
-Mask(ZABHA) Var(riscv_za_subext)
-
-Mask(ZACAS) Var(riscv_za_subext)
-
-Mask(ZA64RS) Var(riscv_za_subext)
-
-Mask(ZA128RS) Var(riscv_za_subext)
-
-TargetVariable
-int riscv_zb_subext
-
-Mask(ZBA) Var(riscv_zb_subext)
-
-Mask(ZBB) Var(riscv_zb_subext)
-
-Mask(ZBC) Var(riscv_zb_subext)
-
-Mask(ZBS) Var(riscv_zb_subext)
-
-TargetVariable
-int riscv_zinx_subext
-
-Mask(ZFINX) Var(riscv_zinx_subext)
-
-Mask(ZDINX) Var(riscv_zinx_subext)
-
-Mask(ZHINX) Var(riscv_zinx_subext)
-
-Mask(ZHINXMIN) Var(riscv_zinx_subext)
-
-TargetVariable
-int riscv_zk_subext
-
-Mask(ZBKB) Var(riscv_zk_subext)
-
-Mask(ZBKC) Var(riscv_zk_subext)
-
-Mask(ZBKX) Var(riscv_zk_subext)
-
-Mask(ZKNE) Var(riscv_zk_subext)
-
-Mask(ZKND) Var(riscv_zk_subext)
-
-Mask(ZKNH) Var(riscv_zk_subext)
-
-Mask(ZKR) Var(riscv_zk_subext)
-
-Mask(ZKSED) Var(riscv_zk_subext)
-
-Mask(ZKSH) Var(riscv_zk_subext)
-
-Mask(ZKT) Var(riscv_zk_subext)
-
-TargetVariable
int riscv_vector_elen_flags
Mask(VECTOR_ELEN_32) Var(riscv_vector_elen_flags)
@@ -335,207 +239,6 @@ Mask(VECTOR_ELEN_FP_16) Var(riscv_vector_elen_flags)
Mask(VECTOR_ELEN_BF_16) Var(riscv_vector_elen_flags)
TargetVariable
-int riscv_zvl_flags
-
-Mask(ZVL32B) Var(riscv_zvl_flags)
-
-Mask(ZVL64B) Var(riscv_zvl_flags)
-
-Mask(ZVL128B) Var(riscv_zvl_flags)
-
-Mask(ZVL256B) Var(riscv_zvl_flags)
-
-Mask(ZVL512B) Var(riscv_zvl_flags)
-
-Mask(ZVL1024B) Var(riscv_zvl_flags)
-
-Mask(ZVL2048B) Var(riscv_zvl_flags)
-
-Mask(ZVL4096B) Var(riscv_zvl_flags)
-
-Mask(ZVL8192B) Var(riscv_zvl_flags)
-
-Mask(ZVL16384B) Var(riscv_zvl_flags)
-
-Mask(ZVL32768B) Var(riscv_zvl_flags)
-
-Mask(ZVL65536B) Var(riscv_zvl_flags)
-
-TargetVariable
-int riscv_zvb_subext
-
-Mask(ZVBB) Var(riscv_zvb_subext)
-
-Mask(ZVBC) Var(riscv_zvb_subext)
-
-Mask(ZVKB) Var(riscv_zvb_subext)
-
-TargetVariable
-int riscv_zvk_subext
-
-Mask(ZVKG) Var(riscv_zvk_subext)
-
-Mask(ZVKNED) Var(riscv_zvk_subext)
-
-Mask(ZVKNHA) Var(riscv_zvk_subext)
-
-Mask(ZVKNHB) Var(riscv_zvk_subext)
-
-Mask(ZVKSED) Var(riscv_zvk_subext)
-
-Mask(ZVKSH) Var(riscv_zvk_subext)
-
-Mask(ZVKN) Var(riscv_zvk_subext)
-
-Mask(ZVKNC) Var(riscv_zvk_subext)
-
-Mask(ZVKNG) Var(riscv_zvk_subext)
-
-Mask(ZVKS) Var(riscv_zvk_subext)
-
-Mask(ZVKSC) Var(riscv_zvk_subext)
-
-Mask(ZVKSG) Var(riscv_zvk_subext)
-
-Mask(ZVKT) Var(riscv_zvk_subext)
-
-TargetVariable
-int riscv_zicmo_subext
-
-Mask(ZICBOZ) Var(riscv_zicmo_subext)
-
-Mask(ZICBOM) Var(riscv_zicmo_subext)
-
-Mask(ZICBOP) Var(riscv_zicmo_subext)
-
-Mask(ZIC64B) Var(riscv_zicmo_subext)
-
-TargetVariable
-int riscv_mop_subext
-
-Mask(ZIMOP) Var(riscv_mop_subext)
-
-Mask(ZCMOP) Var(riscv_mop_subext)
-
-TargetVariable
-int riscv_zf_subext
-
-Mask(ZFBFMIN) Var(riscv_zf_subext)
-
-Mask(ZFHMIN) Var(riscv_zf_subext)
-
-Mask(ZFH) Var(riscv_zf_subext)
-
-Mask(ZVFBFMIN) Var(riscv_zf_subext)
-
-Mask(ZVFBFWMA) Var(riscv_zf_subext)
-
-Mask(ZVFHMIN) Var(riscv_zf_subext)
-
-Mask(ZVFH) Var(riscv_zf_subext)
-
-TargetVariable
-int riscv_zfa_subext
-
-Mask(ZFA) Var(riscv_zfa_subext)
-
-TargetVariable
-int riscv_zm_subext
-
-Mask(ZMMUL) Var(riscv_zm_subext)
-
-TargetVariable
-int riscv_zc_subext
-
-Mask(ZCA) Var(riscv_zc_subext)
-
-Mask(ZCB) Var(riscv_zc_subext)
-
-Mask(ZCE) Var(riscv_zc_subext)
-
-Mask(ZCF) Var(riscv_zc_subext)
-
-Mask(ZCD) Var(riscv_zc_subext)
-
-Mask(ZCMP) Var(riscv_zc_subext)
-
-Mask(ZCMT) Var(riscv_zc_subext)
-
-Mask(XCVBI) Var(riscv_xcv_subext)
-
-TargetVariable
-int riscv_sv_subext
-
-Mask(SVINVAL) Var(riscv_sv_subext)
-
-Mask(SVNAPOT) Var(riscv_sv_subext)
-
-Mask(SVVPTC) Var(riscv_sv_subext)
-
-TargetVariable
-int riscv_ztso_subext
-
-Mask(ZTSO) Var(riscv_ztso_subext)
-
-TargetVariable
-int riscv_xcv_subext
-
-Mask(XCVMAC) Var(riscv_xcv_subext)
-
-Mask(XCVALU) Var(riscv_xcv_subext)
-
-Mask(XCVELW) Var(riscv_xcv_subext)
-
-Mask(XCVSIMD) Var(riscv_xcv_subext)
-
-TargetVariable
-int riscv_xthead_subext
-
-Mask(XTHEADBA) Var(riscv_xthead_subext)
-
-Mask(XTHEADBB) Var(riscv_xthead_subext)
-
-Mask(XTHEADBS) Var(riscv_xthead_subext)
-
-Mask(XTHEADCMO) Var(riscv_xthead_subext)
-
-Mask(XTHEADCONDMOV) Var(riscv_xthead_subext)
-
-Mask(XTHEADFMEMIDX) Var(riscv_xthead_subext)
-
-Mask(XTHEADFMV) Var(riscv_xthead_subext)
-
-Mask(XTHEADINT) Var(riscv_xthead_subext)
-
-Mask(XTHEADMAC) Var(riscv_xthead_subext)
-
-Mask(XTHEADMEMIDX) Var(riscv_xthead_subext)
-
-Mask(XTHEADMEMPAIR) Var(riscv_xthead_subext)
-
-Mask(XTHEADSYNC) Var(riscv_xthead_subext)
-
-Mask(XTHEADVECTOR) Var(riscv_xthead_subext)
-
-TargetVariable
-int riscv_xventana_subext
-
-Mask(XVENTANACONDOPS) Var(riscv_xventana_subext)
-
-TargetVariable
-int riscv_sifive_subext
-
-Mask(XSFVCP) Var(riscv_sifive_subext)
-
-Mask(XSFCEASE) Var(riscv_sifive_subext)
-
-Mask(XSFVQMACCQOQ) Var(riscv_sifive_subext)
-
-Mask(XSFVQMACCDOD) Var(riscv_sifive_subext)
-
-Mask(XSFVFNRCLIPXFQF) Var(riscv_sifive_subext)
-
-TargetVariable
int riscv_fmv_priority = 0
Enum
@@ -579,6 +282,18 @@ Inline strlen calls if possible.
Target RejectNegative Joined UInteger Var(riscv_strcmp_inline_limit) Init(64)
Max number of bytes to compare as part of inlined strcmp/strncmp routines (default: 64).
+-param=gpr2vr-cost=
+Target RejectNegative Joined UInteger Var(gpr2vr_cost) Init(GPR2VR_COST_UNPROVIDED)
+Set the cost value of the rvv instruction when operate from GPR to VR.
+
+-param=fpr2vr-cost=
+Target RejectNegative Joined UInteger Var(fpr2vr_cost) Init(FPR2VR_COST_UNPROVIDED)
+Set the cost value of the rvv instruction when operate from FPR to VR.
+
+-param=riscv-autovec-mode=
+Target Undocumented RejectNegative Joined Var(riscv_autovec_mode) Save
+Set the only autovec mode to try.
+
Enum
Name(rvv_max_lmul) Type(enum rvv_max_lmul_enum)
The RVV possible LMUL (-mrvv-max-lmul=):
diff --git a/gcc/config/riscv/sifive-7.md b/gcc/config/riscv/sifive-7.md
index c208541..a04b80b 100644
--- a/gcc/config/riscv/sifive-7.md
+++ b/gcc/config/riscv/sifive-7.md
@@ -1,4 +1,4 @@
-(define_automaton "sifive_7")
+(define_automaton "sifive_7,sifive_7_vec,sifive_7_vec_mem")
;; Sifive 7 Series Base Core
;; This has two pipelines, A (Address) and B (Branch).
@@ -11,6 +11,14 @@
(define_cpu_unit "sifive_7_idiv" "sifive_7")
(define_cpu_unit "sifive_7_fpu" "sifive_7")
+;; Vector command queue
+(define_cpu_unit "sifive_7_vcq" "sifive_7")
+;; Vector arithmetic sequencer
+(define_cpu_unit "sifive_7_va" "sifive_7_vec")
+;; Vector store sequencer
+(define_cpu_unit "sifive_7_vs" "sifive_7_vec_mem")
+;; Vector load sequencer
+(define_cpu_unit "sifive_7_vl" "sifive_7_vec_mem")
(define_insn_reservation "sifive_7_load" 3
(and (eq_attr "tune" "sifive_7")
@@ -60,9 +68,14 @@
(define_insn_reservation "sifive_7_alu" 2
(and (eq_attr "tune" "sifive_7")
(eq_attr "type" "unknown,arith,shift,slt,multi,logical,move,bitmanip,\
- rotate,min,max,minu,maxu,clz,ctz,atomic,condmove,mvpair,zicond"))
+ min,max,minu,maxu,atomic,condmove,mvpair,zicond"))
"sifive_7_A|sifive_7_B")
+(define_insn_reservation "sifive_7_alu_b" 2
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "clz,ctz,rotate"))
+ "sifive_7_B")
+
(define_insn_reservation "sifive_7_load_immediate" 1
(and (eq_attr "tune" "sifive_7")
(eq_attr "type" "nop,const,auipc"))
@@ -91,6 +104,12 @@
(eq_attr "type" "fcvt,fcvt_i2f,fcvt_f2i,fcmp,fmove"))
"sifive_7_B")
+(define_insn_reservation "sifive_7_fdiv_h" 14
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "fdiv,fsqrt")
+ (eq_attr "mode" "HF"))
+ "sifive_7_B,sifive_7_fpu*13")
+
(define_insn_reservation "sifive_7_fdiv_s" 27
(and (eq_attr "tune" "sifive_7")
(eq_attr "type" "fdiv,fsqrt")
@@ -119,6 +138,21 @@
(eq_attr "type" "cpop,clmul"))
"sifive_7_A")
+(define_insn_reservation "sifive_7_csr" 5
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "rdfrm,wrfrm,wrvxrm"))
+ "sifive_7_A")
+
+(define_insn_reservation "sifive_7_crypto" 10
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "crypto"))
+ "sifive_7_A")
+
+(define_insn_reservation "sifive_7_unknown" 10
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "ghost"))
+ "sifive_7_A")
+
(define_bypass 1 "sifive_7_load,sifive_7_alu,sifive_7_mul,sifive_7_f2i,sifive_7_sfb_alu"
"sifive_7_alu,sifive_7_branch")
@@ -129,13 +163,140 @@
"sifive_7_store" "riscv_store_data_bypass_p")
(define_bypass 2 "sifive_7_i2f"
- "sifive_7_sfma,sifive_7_dfma,sifive_7_fp_other,sifive_7_fdiv_s,sifive_7_fdiv_d")
+ "sifive_7_sfma,sifive_7_dfma,sifive_7_fp_other,sifive_7_fdiv_h,sifive_7_fdiv_s,sifive_7_fdiv_d,sifive_7_hfma")
(define_bypass 2 "sifive_7_fp_other"
- "sifive_7_sfma,sifive_7_dfma,sifive_7_fp_other,sifive_7_fdiv_s,sifive_7_fdiv_d")
+ "sifive_7_sfma,sifive_7_dfma,sifive_7_fp_other,sifive_7_fdiv_h,sifive_7_fdiv_s,sifive_7_fdiv_d,sifive_7_hfma")
(define_bypass 2 "sifive_7_fp_other"
"sifive_7_alu,sifive_7_branch")
(define_bypass 2 "sifive_7_fp_other"
"sifive_7_store" "riscv_store_data_bypass_p")
+
+;; Vector pipeline
+;; The latency is depend on LMUL, but we didn't model that yet since we don't
+;; want to expand the rule too much unless we prove model that could get
+;; meaningful performance difference.
+
+(define_insn_reservation "sifive_7_vsetvl" 2
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vsetvl_pre,vsetvl,rdvlenb,rdvl"))
+ "sifive_7_A")
+
+(define_insn_reservation "sifive_7_vec_load" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vlde,vldm,vlds,vldux,vldox,vldff,vldr,
+ vlsegde,vlsegds,vlsegdux,vlsegdox,vlsegdff"))
+ "sifive_7_vcq,sifive_7_vl*3")
+
+(define_insn_reservation "sifive_7_vec_store" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vste,vstm,vsts,vstux,vstox,vstr,
+ vssegte,vssegts,vssegtux,vssegtox"))
+ "sifive_7_vcq,sifive_7_vs*3")
+
+(define_insn_reservation "sifive_7_vec_ialu" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vimovxv,vmov,vimovvx,vialu,vicalu,vext,
+ vshift,viminmax,vimerge,vbrev,vrev8,
+ vimov,vext,vbrev8,vclz,vctz,vcpop,vrol,vror,vandn"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_slow_ialu" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vshift,vimul,vimuladd"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_cmp" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vicmp"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_iwalu" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "viwalu,viwmul,viwmuladd,vnshift,vwsll"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_div" 16
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vidiv,vfdiv"))
+ "sifive_7_vcq,sifive_7_va*15")
+
+(define_insn_reservation "sifive_7_vec_fixed_point" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vsalu,vaalu,vsmul,vsshift"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_narrow_fixed_point" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vnclip"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_fsimple" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vfmovvf,vfmovfv,vfclass"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_falu" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vfalu,vfmul,vfmuladd,vfrecp,
+ vfcvtitof,vfcvtftoi,vfmerge,vfmov,vfsgnj"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_fcmp" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vfcmp,vfminmax"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_fsqrt_fdiv" 16
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vfsqrt,vfdiv"))
+ "sifive_7_vcq,sifive_7_va*15")
+
+(define_insn_reservation "sifive_7_vec_fwalu" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vfwalu,vfwmul,vfwmuladd,vfwmaccbf16,vfwcvtitof,
+ vfwcvtftoi,vfwcvtftof,vfwcvtbf16,
+ vfncvtitof,vfncvtftoi,vfncvtftof,vfncvtbf16,
+ sf_vfnrclip,sf_vqmacc"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_red" 12
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vired,vfredu,vfredo,viwred,vfwredu,vfwredo"))
+ "sifive_7_vcq,sifive_7_va*11")
+
+(define_insn_reservation "sifive_7_vec_mask" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vmalu,vmpop,vmffs,vmsfs"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_mask_special" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vmiota,vmidx"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+(define_insn_reservation "sifive_7_vec_gather" 8
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vgather"))
+ "sifive_7_vcq,sifive_7_va*7")
+
+(define_insn_reservation "sifive_7_vec_compress" 16
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vcompress"))
+ "sifive_7_vcq,sifive_7_va*15")
+
+(define_insn_reservation "sifive_7_vec_slide" 4
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vslideup,vslidedown,vislide1up,vislide1down,vfslide1up,vfslide1down"))
+ "sifive_7_vcq,sifive_7_va*3")
+
+;; Assume that's slow if it's unknown instruction vector type.
+(define_insn_reservation "sifive_7_vec_unknown" 16
+ (and (eq_attr "tune" "sifive_7")
+ (eq_attr "type" "vector,vclmul,vclmulh,vghsh,vgmul,
+ vaesef,vaesem,vaesdf,vaesdm,vaeskf1,vaeskf2,
+ vaesz,vsha2ms,vsha2ch,vsha2cl,
+ vsm4k,vsm4r,vsm3me,vsm3c,sf_vc,sf_vc_se"))
+ "sifive_7_vcq,sifive_7_va*15")
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 726800a..50ec8b3 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -405,18 +405,17 @@
(match_operand:SI 3 "const_int_operand")] ;; model
UNSPEC_SYNC_EXCHANGE))
(set (match_dup 1)
- (match_operand:GPR 2 "register_operand" "0"))
+ (match_operand:GPR 2 "reg_or_0_operand" "rJ"))
(clobber (match_scratch:GPR 4 "=&r"))] ;; tmp_1
"!TARGET_ZAAMO && TARGET_ZALRSC"
{
return "1:\;"
- "lr.<amo>%I3\t%4, %1\;"
- "sc.<amo>%J3\t%0, %0, %1\;"
- "bnez\t%0, 1b\;"
- "mv\t%0, %4";
+ "lr.<amo>%I3\t%0, %1\;"
+ "sc.<amo>%J3\t%4, %z2, %1\;"
+ "bnez\t%4, 1b\";
}
[(set_attr "type" "atomic")
- (set (attr "length") (const_int 16))])
+ (set (attr "length") (const_int 12))])
(define_expand "atomic_exchange<mode>"
[(match_operand:SHORT 0 "register_operand") ;; old value at mem
@@ -628,7 +627,7 @@
(match_operand:SHORT 1 "memory_operand" "+A")) ;; memory
(set (match_dup 1)
(unspec_volatile:SHORT [(match_operand:SHORT 2 "register_operand" "0") ;; expected_val
- (match_operand:SHORT 3 "register_operand" "rJ") ;; desired_val
+ (match_operand:SHORT 3 "reg_or_0_operand" "rJ") ;; desired_val
(match_operand:SI 4 "const_int_operand") ;; mod_s
(match_operand:SI 5 "const_int_operand")] ;; mod_f
UNSPEC_COMPARE_AND_SWAP))]
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 12e2b6e..32092d8 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -187,3 +187,49 @@ s-riscv-vector-type-indexer.gen.defs: build/genrvv-type-indexer$(build_exeext)
$(STAMP) s-riscv-vector-type-indexer.gen.defs
genprog+=rvv-type-indexer
+
+RISCV_EXT_DEFS = \
+ $(srcdir)/config/riscv/riscv-ext.def \
+ $(srcdir)/config/riscv/riscv-ext-corev.def \
+ $(srcdir)/config/riscv/riscv-ext.def \
+ $(srcdir)/config/riscv/riscv-ext-sifive.def \
+ $(srcdir)/config/riscv/riscv-ext-thead.def \
+ $(srcdir)/config/riscv/riscv-ext-ventana.def
+
+$(srcdir)/config/riscv/riscv-ext.opt: $(RISCV_EXT_DEFS)
+
+build/gen-riscv-ext-opt.o: $(srcdir)/config/riscv/gen-riscv-ext-opt.cc \
+ $(RISCV_EXT_DEFS)
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+
+build/gen-riscv-ext-opt$(build_exeext): build/gen-riscv-ext-opt.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
+
+s-riscv-ext.opt: build/gen-riscv-ext-opt$(build_exeext)
+ $(RUN_GEN) build/gen-riscv-ext-opt$(build_exeext) > tmp-riscv-ext.opt
+ $(SHELL) $(srcdir)/../move-if-change tmp-riscv-ext.opt $(srcdir)/config/riscv/riscv-ext.opt
+ $(STAMP) s-riscv-ext.opt
+
+build/gen-riscv-ext-texi.o: $(srcdir)/config/riscv/gen-riscv-ext-texi.cc \
+ $(RISCV_EXT_DEFS)
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+
+build/gen-riscv-ext-texi$(build_exeext): build/gen-riscv-ext-texi.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
+
+$(srcdir)/doc/riscv-ext.texi: $(RISCV_EXT_DEFS)
+$(srcdir)/doc/riscv-ext.texi: s-riscv-ext.texi ; @true
+
+# Generate the doc when generating option file.
+$(srcdir)/config/riscv/riscv-ext.opt: s-riscv-ext.texi ; @true
+
+s-riscv-ext.texi: build/gen-riscv-ext-texi$(build_exeext)
+ $(RUN_GEN) build/gen-riscv-ext-texi$(build_exeext) > tmp-riscv-ext.texi
+ $(SHELL) $(srcdir)/../move-if-change tmp-riscv-ext.texi $(srcdir)/doc/riscv-ext.texi
+ $(STAMP) s-riscv-ext.texi
+
+# Run `riscv-regen' after you changed or added anything from riscv-ext*.def
+
+.PHONY: riscv-regen
+
+riscv-regen: s-riscv-ext.texi s-riscv-ext.opt
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index b4c86909..fd0959c 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4041,6 +4041,14 @@
smax umax smin umin mult div udiv mod umod
])
+(define_code_iterator any_int_binop_no_shift_v_vdup [
+ plus minus and ior xor mult div udiv mod umod smax umax smin umin us_plus us_minus ss_plus
+])
+
+(define_code_iterator any_int_binop_no_shift_vdup_v [
+ plus minus and ior xor mult smax umax smin umin us_plus ss_plus
+])
+
(define_code_iterator any_int_unop [neg not])
(define_code_iterator any_commutative_binop [plus and ior xor
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 851ba4a..6753b01 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -6599,9 +6599,42 @@
(match_operand:<VEL> 2 "register_operand"))
(match_operand:V_VLSF 3 "register_operand"))
(match_operand:V_VLSF 4 "register_operand"))
- (match_operand:V_VLSF 5 "register_operand")))]
+ (match_operand:V_VLSF 5 "vector_merge_operand")))]
"TARGET_VECTOR"
-{})
+{
+ riscv_vector::prepare_ternary_operands (operands);
+})
+
+(define_insn "*pred_mul_<optab><mode>_scalar_undef"
+ [(set (match_operand:V_VLSF 0 "register_operand" "=vd,vd, vr, vr")
+ (if_then_else:V_VLSF
+ (unspec:<VM>
+ [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm,Wc1,Wc1")
+ (match_operand 6 "vector_length_operand" "rvl,rvl,rvl,rvl")
+ (match_operand 7 "const_int_operand" " i, i, i, i")
+ (match_operand 8 "const_int_operand" " i, i, i, i")
+ (match_operand 9 "const_int_operand" " i, i, i, i")
+ (match_operand 10 "const_int_operand" " i, i, i, i")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)
+ (reg:SI FRM_REGNUM)] UNSPEC_VPREDICATE)
+ (plus_minus:V_VLSF
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 3 "register_operand" " f, f, f, f"))
+ (match_operand:V_VLSF 4 "register_operand" " 0, vr, 0, vr"))
+ (match_operand:V_VLSF 5 "register_operand" " vr, 0, vr, 0"))
+ (match_operand:V_VLSF 2 "vector_undef_operand")))]
+ "TARGET_VECTOR"
+ "@
+ vf<madd_msub>.vf\t%0,%3,%5%p1
+ vf<macc_msac>.vf\t%0,%3,%4%p1
+ vf<madd_msub>.vf\t%0,%3,%5%p1
+ vf<macc_msac>.vf\t%0,%3,%4%p1"
+ [(set_attr "type" "vfmuladd")
+ (set_attr "mode" "<MODE>")
+ (set (attr "frm_mode")
+ (symbol_ref "riscv_vector::get_frm_mode (operands[10])"))])
(define_insn "*pred_<madd_msub><mode>_scalar"
[(set (match_operand:V_VLSF 0 "register_operand" "=vd, vr")
@@ -6815,9 +6848,43 @@
(match_operand:<VEL> 2 "register_operand"))
(match_operand:V_VLSF 3 "register_operand")))
(match_operand:V_VLSF 4 "register_operand"))
- (match_operand:V_VLSF 5 "register_operand")))]
+ (match_operand:V_VLSF 5 "vector_merge_operand")))]
"TARGET_VECTOR"
-{})
+{
+ riscv_vector::prepare_ternary_operands (operands);
+})
+
+(define_insn "*pred_mul_neg_<optab><mode>_scalar_undef"
+ [(set (match_operand:V_VLSF 0 "register_operand" "=vd,vd, vr, vr")
+ (if_then_else:V_VLSF
+ (unspec:<VM>
+ [(match_operand:<VM> 1 "vector_mask_operand" " vm, vm,Wc1,Wc1")
+ (match_operand 6 "vector_length_operand" "rvl,rvl,rvl,rvl")
+ (match_operand 7 "const_int_operand" " i, i, i, i")
+ (match_operand 8 "const_int_operand" " i, i, i, i")
+ (match_operand 9 "const_int_operand" " i, i, i, i")
+ (match_operand 10 "const_int_operand" " i, i, i, i")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)
+ (reg:SI FRM_REGNUM)] UNSPEC_VPREDICATE)
+ (plus_minus:V_VLSF
+ (neg:V_VLSF
+ (mult:V_VLSF
+ (vec_duplicate:V_VLSF
+ (match_operand:<VEL> 3 "register_operand" " f, f, f, f"))
+ (match_operand:V_VLSF 4 "register_operand" " 0, vr, 0, vr")))
+ (match_operand:V_VLSF 5 "register_operand" " vr, 0, vr, 0"))
+ (match_operand:V_VLSF 2 "vector_undef_operand")))]
+ "TARGET_VECTOR"
+ "@
+ vf<nmsub_nmadd>.vf\t%0,%3,%5%p1
+ vf<nmsac_nmacc>.vf\t%0,%3,%4%p1
+ vf<nmsub_nmadd>.vf\t%0,%3,%5%p1
+ vf<nmsac_nmacc>.vf\t%0,%3,%4%p1"
+ [(set_attr "type" "vfmuladd")
+ (set_attr "mode" "<MODE>")
+ (set (attr "frm_mode")
+ (symbol_ref "riscv_vector::get_frm_mode (operands[10])"))])
(define_insn "*pred_<nmsub_nmadd><mode>_scalar"
[(set (match_operand:V_VLSF 0 "register_operand" "=vd, vr")
diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
index f87b4f2..d170f6a 100644
--- a/gcc/config/riscv/zicond.md
+++ b/gcc/config/riscv/zicond.md
@@ -234,5 +234,39 @@
(const_int 0)
(match_dup 4)))])
+;; We can splat the sign bit across a GPR with a arithmetic right shift
+;; which gives us a 0, -1 result. We then turn on bit #0 unconditionally
+;; which results in 1, -1. There's probably other cases that could be
+;; handled, this seems particularly important though.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (plus:X (if_then_else:X (ge:X (match_operand:X 1 "register_operand")
+ (const_int 0))
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand"))
+ (match_operand 4 "const_int_operand")))]
+ "((TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV)
+ && INTVAL (operands[2]) + INTVAL (operands[4]) == 1
+ && INTVAL (operands[3]) + INTVAL (operands[4]) == -1)"
+ [(set (match_dup 0) (ashiftrt:X (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (ior:X (match_dup 0) (const_int 1)))]
+ { operands[2] = GEN_INT (GET_MODE_BITSIZE (word_mode) - 1); })
-
+;; Similarly, but the condition and true/false values are reversed
+;;
+;; Note the case where the condition is reversed, but not the true/false
+;; values. Or vice-versa is not handled because we don't support 4->3
+;; splits.
+(define_split
+ [(set (match_operand:X 0 "register_operand")
+ (plus:X (if_then_else:X (lt:X (match_operand:X 1 "register_operand")
+ (const_int 0))
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand"))
+ (match_operand 4 "const_int_operand")))]
+ "((TARGET_ZICOND_LIKE || TARGET_XTHEADCONDMOV)
+ && INTVAL (operands[2]) + INTVAL (operands[4]) == -1
+ && INTVAL (operands[3]) + INTVAL (operands[4]) == 1)"
+ [(set (match_dup 0) (ashiftrt:X (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (ior:X (match_dup 0) (const_int 1)))]
+ { operands[2] = GEN_INT (GET_MODE_BITSIZE (word_mode) - 1); })