aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKuan-Lin Chen <rufus@andestech.com>2025-09-03 16:52:49 -0600
committerJeff Law <jlaw@ventanamicro.com>2025-09-03 16:53:27 -0600
commite1fb7db6954d08860119f6b34db0c7d2490681de (patch)
treea4574e8649c41c09ffac3a392d44a7510c1ec3f2
parentfdcab349326c228617d143a3a4c9106712c2d58e (diff)
downloadgcc-e1fb7db6954d08860119f6b34db0c7d2490681de.zip
gcc-e1fb7db6954d08860119f6b34db0c7d2490681de.tar.gz
gcc-e1fb7db6954d08860119f6b34db0c7d2490681de.tar.bz2
RISC-V: Add support for the XAndesperf ISA extension.
This patch adds support for the XAndesperf ISA extension. The 32-bit AndeStar V5 extension includes branch instructions, load effective address instructions, and string processing instructions for performance improvement. New INSN patterns are added into the new file andes.md as a seprated vender extension. gcc/ChangeLog: * config/riscv/constraints.md (Ou07): New constraint. (ads_Bext): New constraint. * config/riscv/iterators.md (ANYLE32): New iterator. (sizen): New iterator. (sh_limit): New iterator. (sh_bit): New iterator. (cs): New iterator. * config/riscv/predicates.md (ads_branch_bbcs_operand): New predicate. (ads_branch_bimm_operand): New predicate. (ads_imm_extract_operand): New predicate. (ads_extract_size_imm_si): New predicate. (ads_extract_size_imm_di): New predicate. (const_int5_operand): New predicate. * config/riscv/riscv-builtins.cc: Add new AVAIL andesperf32 and andesperf64. Add new define RISCV_ATYPE_DI. * config/riscv/riscv-ftypes.def: New DEF_RISCV_FTYPE. * config/riscv/riscv.cc (riscv_extend_cost): Cost for pattern 'bfo'. (riscv_rtx_costs): Cost for XAndesperf extension. * config/riscv/riscv.md: Add support for XAndesperf to patterns zero_extendsidi2_internal, zero_extendhi2, extendsidi2_internal, extend<SHORT:mode><SUPERQI:mode>2, <any_extract:optab><GPR:mode>3 and branch_on_bit. * config/riscv/vector-iterators.md (sz): Add sign_extract and zero_extract. * config/riscv/andes.def: New file for vender Andes. * config/riscv/andes.md: New file for vender Andes. gcc/testsuite/ChangeLog: * gcc.target/riscv/riscv.exp: Add runtest for subdir xandes. * gcc.target/riscv/xandes/xandesperf-1.c: New test. * gcc.target/riscv/xandes/xandesperf-10.c: New test. * gcc.target/riscv/xandes/xandesperf-2.c: New test. * gcc.target/riscv/xandes/xandesperf-3.c: New test. * gcc.target/riscv/xandes/xandesperf-4.c: New test. * gcc.target/riscv/xandes/xandesperf-5.c: New test. * gcc.target/riscv/xandes/xandesperf-6.c: New test. * gcc.target/riscv/xandes/xandesperf-7.c: New test. * gcc.target/riscv/xandes/xandesperf-8.c: New test. * gcc.target/riscv/xandes/xandesperf-9.c: New test.
-rw-r--r--gcc/config/riscv/andes.def10
-rw-r--r--gcc/config/riscv/andes.md429
-rw-r--r--gcc/config/riscv/constraints.md10
-rw-r--r--gcc/config/riscv/iterators.md15
-rw-r--r--gcc/config/riscv/predicates.md42
-rw-r--r--gcc/config/riscv/riscv-builtins.cc6
-rw-r--r--gcc/config/riscv/riscv-ftypes.def1
-rw-r--r--gcc/config/riscv/riscv.cc32
-rw-r--r--gcc/config/riscv/riscv.md17
-rw-r--r--gcc/config/riscv/vector-iterators.md2
-rw-r--r--gcc/testsuite/gcc.target/riscv/riscv.exp2
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-1.c13
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-10.c32
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-11.c32
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-2.c13
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-3.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-4.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-5.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-6.c18
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-7.c22
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-8.c26
-rw-r--r--gcc/testsuite/gcc.target/riscv/xandes/xandesperf-9.c31
22 files changed, 779 insertions, 7 deletions
diff --git a/gcc/config/riscv/andes.def b/gcc/config/riscv/andes.def
new file mode 100644
index 0000000..e2d67b8b
--- /dev/null
+++ b/gcc/config/riscv/andes.def
@@ -0,0 +1,10 @@
+// XANDESPERF
+/* Andes Performance Extension */
+RISCV_BUILTIN (nds_ffbsi, "nds_ffb_32", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_USI_USI, andesperf32),
+RISCV_BUILTIN (nds_ffbdi, "nds_ffb_64", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_UDI_UDI, andesperf64),
+RISCV_BUILTIN (nds_ffzmismsi, "nds_ffzmism_32", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_USI_USI, andesperf32),
+RISCV_BUILTIN (nds_ffzmismdi, "nds_ffzmism_64", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_UDI_UDI, andesperf64),
+RISCV_BUILTIN (nds_ffmismsi, "nds_ffmism_32", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_USI_USI, andesperf32),
+RISCV_BUILTIN (nds_ffmismdi, "nds_ffmism_64", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_UDI_UDI, andesperf64),
+RISCV_BUILTIN (nds_flmismsi, "nds_flmism_32", RISCV_BUILTIN_DIRECT, RISCV_SI_FTYPE_USI_USI, andesperf32),
+RISCV_BUILTIN (nds_flmismdi, "nds_flmism_64", RISCV_BUILTIN_DIRECT, RISCV_DI_FTYPE_UDI_UDI, andesperf64),
diff --git a/gcc/config/riscv/andes.md b/gcc/config/riscv/andes.md
new file mode 100644
index 0000000..0f303ca
--- /dev/null
+++ b/gcc/config/riscv/andes.md
@@ -0,0 +1,429 @@
+;; Machine description for Andes vendor extensions
+;; 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_c_enum "unspec" [
+ ;; XANDESPERF string
+ UNSPEC_NDS_FFB
+ UNSPEC_NDS_FFZMISM
+ UNSPEC_NDS_FFMISM
+ UNSPEC_NDS_FLMISM
+])
+
+;; AndesPerf
+;; ....................
+;;
+;; BRANCH OPERATION
+;;
+;; ....................
+;;
+
+(define_insn "*nds_branch_imms7<mode>"
+ [(set (pc)
+ (if_then_else (any_eq (match_operand:X 1 "register_operand" "r")
+ (match_operand:X 2 "ads_branch_bimm_operand" "Ou07"))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "TARGET_XANDESPERF"
+{
+ if (get_attr_length (insn) == 12)
+ return "nds.b<optab>c\t%1,%2,1f; jump\t%l0,ra; 1:";
+
+ return "nds.b<optab>c\t%1,%2,%l0";
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+(define_insn "*nds_branch_on_bit<X:mode>"
+ [(set (pc)
+ (if_then_else (any_eq (zero_extract:X (match_operand:X 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand 2 "ads_branch_bbcs_operand"))
+ (const_int 0))
+ (label_ref (match_operand 0))
+ (pc)))
+ (clobber (match_scratch:X 3 "=&r"))]
+ "TARGET_XANDESPERF"
+{
+ if (get_attr_length (insn) == 12)
+ return "nds.bb<any_eq:cs>\t%1,%2,%1f; jump\t%l0,ra; 1:";
+
+ return "nds.bb<any_eq:cs>\t%1,%2,%l0";
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+;;
+;; ....................
+;;
+;; EXTENSION OPERATION
+;;
+;; ....................
+;;
+
+(define_insn "*nds_zero_extendsidi2_internal"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (zero_extend:DI
+ (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ "@
+ nds.bfoz\t%0,%1,31,0
+ lwu\t%0,%1"
+ [(set_attr "move_type" "arith,load")
+ (set_attr "type" "arith,load")
+ (set_attr "mode" "DI")])
+
+(define_insn "*nds_zero_extendhi<GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=r,r")
+ (zero_extend:GPR
+ (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
+ "TARGET_XANDESPERF"
+ "@
+ nds.bfoz\t%0,%1,15,0
+ lhu\t%0,%1"
+ [(set_attr "move_type" "arith,load")
+ (set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>, HI")])
+
+(define_insn "*nds_extendsidi2_internal"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (sign_extend:DI
+ (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ "@
+ nds.bfos\t%0,%1,31,0
+ lw\t%0,%1"
+ [(set_attr "move_type" "arith,load")
+ (set_attr "type" "arith,load")
+ (set_attr "mode" "DI")])
+
+(define_insn "*nds_extend<SHORT:mode><SUPERQI:mode>2"
+ [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
+ (sign_extend:SUPERQI
+ (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+ "TARGET_XANDESPERF"
+ "@
+ nds.bfos\t%0,%1,<SHORT:sh_limit>,0
+ l<SHORT:size>\t%0,%1"
+ [(set_attr "move_type" "arith,load")
+ (set_attr "type" "arith,load")
+ (set_attr "mode" "<SHORT:MODE>")])
+
+;;
+;; ....................
+;;
+;; BIT FIELD OPERATION
+;;
+;; ....................
+;;
+
+;; BFO[SZ]: msb >= lsb: Extract sequence tail bits.
+(define_insn "*nds_bfo_<sz>extra<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (any_extract:GPR (match_operand:GPR 1 "register_operand" " r")
+ (match_operand 2 "ads_extract_size_imm_<mode>" " n")
+ (match_operand 3 "const_int<sh_bit>_operand" " n")))]
+ "TARGET_XANDESPERF
+ && IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+ 1, GET_MODE_BITSIZE (<MODE>mode))"
+ {
+ operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
+ return "nds.bfo<sz>\t%0,%1,%2,%3";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb >= lsb: Mask sequence bits.
+(define_insn "*nds_bfoz_and<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (and:GPR (match_operand:GPR 1 "register_operand" " r")
+ (match_operand:GPR 2 "ads_imm_extract_operand" " ads_Bext")))]
+ "TARGET_XANDESPERF"
+ {
+ operands[2] = GEN_INT (__builtin_popcountll (INTVAL (operands[2])) - 1);
+ return "nds.bfoz\t%0,%1,%2,0";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb >= lsb: Extract sequence bits.
+(define_insn "*nds_zero_extend<GPR:mode>_lshr<SHORT:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (zero_extend:GPR (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" " r")
+ (match_operand 2 "const_int_operand" " n"))))]
+ "TARGET_XANDESPERF
+ && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
+ "nds.bfoz\t%0, %1, <SHORT:sh_limit>, %2"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOS: msb >= lsb
+(define_insn "*nds_extend<GPR:mode>_ashr<SHORT:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (sign_extend:GPR (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" " r")
+ (match_operand 2 "const_int_operand" " n"))))]
+ "TARGET_XANDESPERF
+ && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
+ "nds.bfos\t%0, %1, <SHORT:sh_limit>, %2"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO[SZ]: msb < lsb: The pattern doesn't match zero_extract when
+;; exact_log2 (Y + 1) < 0 of (and (ashift) Y).
+(define_insn "*nds_bfoz<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (and:GPR (ashift:GPR (match_operand:GPR 1 "register_operand" " r")
+ (match_operand 2 "const_int<sh_bit>_operand" " n"))
+ (match_operand 3 "const_int_operand" " i")))]
+ "TARGET_XANDESPERF
+ && (UINTVAL (operands[2]) != 0)
+ && (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1) > 1)
+ && ((UINTVAL (operands[3]) & ((1 << UINTVAL (operands[2])) - 1)) == 0)"
+ {
+ operands[3] =
+ GEN_INT (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1)
+ + UINTVAL (operands[2]) - 1) ;
+ return "nds.bfoz\t%0,%1,%2,%3";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb = 0.
+(define_insn "*nds_bfoz0<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (and:GPR (ashift:GPR (match_operand:GPR 1 "register_operand" " r")
+ (match_operand 2 "const_int<sh_bit>_operand" " n"))
+ (match_operand 3 "const_int_operand" " i")))]
+ "TARGET_XANDESPERF
+ && (UINTVAL (operands[2]) != 0)
+ && (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1) == 1)
+ && ((UINTVAL (operands[3]) & ((1 << UINTVAL (operands[2])) - 1)) == 0)"
+ {
+ return "nds.bfoz\t%0,%1,0,%2";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb = 0.
+(define_insn "*nds_bfos0<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (ashift:GPR (any_extract:GPR (match_operand:GPR 1 "register_operand" " r")
+ (const_int 1)
+ (const_int 0))
+ (match_operand 2 "const_int<sh_bit>_operand" " n")))]
+ "TARGET_XANDESPERF"
+ {
+ return "nds.bfo<sz>\t%0,%1,0,%2";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb < lsb.
+(define_insn "*nds_bfos_<sz>extra_<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (ashift:GPR (any_extract:GPR (match_operand:GPR 1 "register_operand" " r")
+ (match_operand 2 "ads_extract_size_imm_<mode>" " n")
+ (const_int 0))
+ (match_operand 3 "const_int<sh_bit>_operand" " n")))]
+ "TARGET_XANDESPERF
+ && UINTVAL (operands[2]) != 1"
+ {
+ operands[2] = GEN_INT (UINTVAL (operands[2]) + UINTVAL (operands[3]) - 1);
+ return "nds.bfo<sz>\t%0,%1,%3,%2";
+ }
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb < lsb
+(define_insn "*nds_<optab><ANYLE32:mode>_shft_<GPR:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (ashift:GPR (any_extend:GPR
+ (match_operand:ANYLE32 1 "register_operand" " r"))
+ (match_operand 2 "const_int_operand" " n")))]
+ "TARGET_XANDESPERF
+ && (UINTVAL (operands[2]) < <ANYLE32:sizen>)
+ && ((INTVAL (operands[2]) + <ANYLE32:sizen>) <= <GPR:sizen>)"
+{
+ operands[3] = GEN_INT (<ANYLE32:sizen> + INTVAL (operands[2]) - 1);
+ return "nds.bfo<sz>\t%0, %1, %2, %3";
+}
+ [(set_attr "type" "shift")])
+
+;; BFO: msb < lsb
+(define_insn "*nds_<optab><GPR:mode>_ashl<ANYLE32:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (any_extend:GPR
+ (ashift:ANYLE32 (match_operand:ANYLE32 1 "register_operand" " r")
+ (match_operand 2 "const_int_operand" " n"))))]
+ "TARGET_XANDESPERF
+ && UINTVAL (operands[2]) < ((<ANYLE32:sizen>) - 1)"
+{
+ operands[3] = GEN_INT (<ANYLE32:sizen> - 1);
+ return "nds.bfo<sz>\t%0, %1, %2, %3";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;;
+;; ....................
+;;
+;; LOAD ADDRESS
+;;
+;; ....................
+;;
+
+(define_insn "lea_h<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+ (const_int 1))
+ (match_operand:P 2 "register_operand" " r")))]
+ "TARGET_XANDESPERF"
+ { return "nds.lea.h\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_w<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+ (const_int 2))
+ (match_operand:P 2 "register_operand" " r")))]
+ "TARGET_XANDESPERF"
+ { return "nds.lea.w\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_d<mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+ (const_int 3))
+ (match_operand:P 2 "register_operand" " r")))]
+ "TARGET_XANDESPERF"
+ { return "nds.lea.d\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_b_ze"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (match_operand:DI 2 "register_operand" " r")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ { return "nds.lea.b.ze\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "lea_h_ze"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (const_int 1))
+ (match_operand:DI 2 "register_operand" " r")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ { return "nds.lea.h.ze\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "lea_w_ze"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (const_int 2))
+ (match_operand:DI 2 "register_operand" " r")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ { return "nds.lea.w.ze\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "lea_d_ze"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+ (const_int 3))
+ (match_operand:DI 2 "register_operand" " r")))]
+ "TARGET_64BIT && TARGET_XANDESPERF"
+ { return "nds.lea.d.ze\t%0,%2,%1"; }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn "lea_andim_ashift"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (and:DI (ashift:DI (match_operand:DI 1 "register_operand" " r")
+ (match_operand 2 "const_int_operand" " i"))
+ (match_operand 3 "const_int_operand" " i"))
+ (match_operand:DI 4 "register_operand" " r")))]
+ "TARGET_64BIT && TARGET_XANDESPERF
+ && IN_RANGE (UINTVAL (operands[2]), 0, 3)
+ && exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) == 32
+ && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
+ {
+ switch (UINTVAL (operands[2]))
+ {
+ case 0:
+ return "nds.lea.b.ze %0, %4, %1";
+ case 1:
+ return "nds.lea.h.ze %0, %4, %1";
+ case 2:
+ return "nds.lea.w.ze %0, %4, %1";
+ case 3:
+ return "nds.lea.d.ze %0, %4, %1";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+;;
+;; ....................
+;;
+;; String Extension
+;;
+;; ....................
+;;
+
+(define_insn "riscv_nds_ffb<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+ (match_operand:GPR 2 "nonmemory_operand" "rJ")] UNSPEC_NDS_FFB))]
+ ""
+ "nds.ffb\t%0, %z1, %z2"
+ [(set_attr "mode" "<MODE>")
+ (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_ffzmism<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+ (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FFZMISM))]
+ ""
+ "nds.ffzmism\t%0, %z1, %z2"
+ [(set_attr "mode" "<MODE>")
+ (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_ffmism<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+ (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FFMISM))]
+ ""
+ "nds.ffmism\t%0, %z1, %z2"
+ [(set_attr "mode" "<MODE>")
+ (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_flmism<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+ (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FLMISM))]
+ ""
+ "nds.flmism\t%0, %z1, %z2"
+ [(set_attr "mode" "<MODE>")
+ (set_attr "type" "arith")])
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 979e0df..dd462c6 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -334,3 +334,13 @@
(define_address_constraint "ZD"
"An address operand that is valid for a mips prefetch instruction"
(match_test "riscv_prefetch_offset_address_p (op, mode)"))
+
+(define_constraint "Ou07"
+ "A 7-bit unsigned immediate."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, 0, 127)")))
+
+(define_constraint "ads_Bext"
+ "Sequence bit extract."
+ (and (match_code "const_int")
+ (match_test "(ival & (ival + 1)) == 0")))
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 584b345..d300224 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -71,6 +71,9 @@
;; Iterator for hardware integer modes narrower than XLEN, same as ANYI.
(define_mode_iterator ANYI1 [QI HI SI (DI "TARGET_64BIT")])
+;; Iterator for integer modes less than or equal to 32bit.
+(define_mode_iterator ANYLE32 [QI HI SI])
+
(define_mode_iterator ANYI_DOUBLE_TRUNC [HI SI (DI "TARGET_64BIT")])
(define_mode_iterator ANYI_QUAD_TRUNC [SI (DI "TARGET_64BIT")])
@@ -169,10 +172,19 @@
;; the controlling mode.
(define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
+;; Give the number of bits in the mode
+(define_mode_attr sizen [(QI "8") (HI "16") (SI "32") (DI "64")])
+
; bitmanip mode attribute
(define_mode_attr shiftm1 [(SI "const_si_mask_operand") (DI "const_di_mask_operand")])
(define_mode_attr shiftm1p [(SI "DsS") (DI "DsD")])
+; mode shift limit attribute
+(define_mode_attr sh_limit [(QI "7") (HI "15")])
+
+; mode shift bit limit attribute
+(define_mode_attr sh_bit [(SI "5") (DI "6")])
+
; zcmp mode attribute
(define_mode_attr slot0_offset [(SI "-4") (DI "-8")])
(define_mode_attr slot1_offset [(SI "-8") (DI "-16")])
@@ -284,6 +296,9 @@
;; <su> is like <u>, but the signed form expands to "s" rather than "".
(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+;; eq expand to "c" and ne expand to "s".
+(define_code_attr cs [(eq "c") (ne "s")])
+
;; <optab> expands to the name of the optab for a particular code.
(define_code_attr optab [(ashift "ashl")
(ashiftrt "ashr")
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index bdb3d22..777e71b 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -483,6 +483,10 @@
(ior (match_operand 0 "const_int6_operand")
(match_operand 0 "register_operand")))
+(define_predicate "const_int5_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
+
(define_predicate "const_int5s_operand"
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), -16, 15)")))
@@ -728,3 +732,41 @@
(define_predicate "reg_or_const_int_operand"
(ior (match_operand 0 "const_int_operand")
(match_operand 0 "register_operand")))
+
+;; Branch-on-bit for AndesPerf.
+(define_predicate "ads_branch_bbcs_operand"
+ (match_code "const_int")
+{
+ if (TARGET_XANDESPERF && (INTVAL (op) >= 0))
+ {
+ if (TARGET_64BIT && INTVAL (op) <= 63)
+ return true;
+ else if (INTVAL (op) <=31)
+ return true;
+ else
+ return false;
+ }
+
+ return false;
+})
+
+;; Branch on small immediate range.
+(define_predicate "ads_branch_bimm_operand"
+ (match_code "const_int")
+{
+ if (TARGET_XANDESPERF)
+ return satisfies_constraint_Ou07 (op);
+ else
+ return false;
+})
+
+(define_predicate "ads_imm_extract_operand"
+ (match_test "satisfies_constraint_ads__Bext (op)"))
+
+(define_predicate "ads_extract_size_imm_si"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 1, 32)")))
+
+(define_predicate "ads_extract_size_imm_di"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 1, 64)")))
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 9f8a980..cfcacf4 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -137,6 +137,10 @@ AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
AVAIL (cvelw, TARGET_XCVELW && !TARGET_64BIT)
AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT)
+/* ANDES AVAIL. */
+AVAIL (andesperf32, !TARGET_64BIT && TARGET_XANDESPERF)
+AVAIL (andesperf64, TARGET_64BIT && TARGET_XANDESPERF)
+
/* Construct a riscv_builtin_description from the given arguments.
INSN is the name of the associated instruction pattern, without the
@@ -191,6 +195,7 @@ AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT)
#define RISCV_ATYPE_QI intQI_type_node
#define RISCV_ATYPE_HI intHI_type_node
#define RISCV_ATYPE_SI intSI_type_node
+#define RISCV_ATYPE_DI intDI_type_node
#define RISCV_ATYPE_VOID_PTR ptr_type_node
#define RISCV_ATYPE_INT_PTR integer_ptr_type_node
@@ -212,6 +217,7 @@ static const struct riscv_builtin_description riscv_builtins[] = {
#include "riscv-cmo.def"
#include "riscv-scalar-crypto.def"
#include "corev.def"
+ #include "andes.def"
DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE, hard_float),
DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float),
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index f7854dd..6db41ad 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -52,6 +52,7 @@ DEF_RISCV_FTYPE (2, (UDI, UDI, USI))
DEF_RISCV_FTYPE (2, (UDI, UDI, UDI))
DEF_RISCV_FTYPE (2, (SI, USI, USI))
DEF_RISCV_FTYPE (2, (SI, SI, SI))
+DEF_RISCV_FTYPE (2, (DI, UDI, UDI))
DEF_RISCV_FTYPE (3, (USI, USI, USI, UQI))
DEF_RISCV_FTYPE (3, (USI, USI, USI, QI))
DEF_RISCV_FTYPE (3, (USI, USI, UQI, USI))
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 591122f..d5a656c 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3933,6 +3933,10 @@ riscv_extend_cost (rtx op, bool unsigned_p)
if (MEM_P (op))
return 0;
+ /* Andes bfo patterns. */
+ if (TARGET_XANDESPERF)
+ return COSTS_N_INSNS (1);
+
if (unsigned_p && GET_MODE (op) == QImode)
/* We can use ANDI. */
return COSTS_N_INSNS (1);
@@ -4162,6 +4166,12 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
return false;
case AND:
+ /* Andes bfo patterns. */
+ if (TARGET_XANDESPERF && GET_CODE (XEXP (x, 0)) == ASHIFT)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
/* slli.uw pattern for zba. */
if (TARGET_ZBA && TARGET_64BIT && mode == DImode
&& GET_CODE (XEXP (x, 0)) == ASHIFT)
@@ -4221,6 +4231,13 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
return false;
case ZERO_EXTRACT:
+ /* Andes bbcs patterns. */
+ if (TARGET_XANDESPERF
+ && (outer_code == NE || outer_code == EQ))
+ {
+ *total = 0;
+ return true;
+ }
/* This is an SImode shift. */
if (outer_code == SET
&& CONST_INT_P (XEXP (x, 1))
@@ -4248,6 +4265,12 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
*total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
return true;
}
+ /* Andes bfo patterns. */
+ if (TARGET_XANDESPERF)
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
return false;
case ASHIFT:
@@ -4416,6 +4439,15 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
} while (false);
}
+ /* Andes lea patterns. */
+ if (TARGET_XANDESPERF
+ && ((TARGET_64BIT && GET_CODE (XEXP (x, 0)) == AND)
+ || GET_CODE (XEXP (x, 0)) == ASHIFT))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+
if (float_mode_p)
*total = tune_param->fp_add[mode == DFmode];
else
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index d34405c..63d7daa 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1912,6 +1912,7 @@
(zero_extend:DI
(match_operand:SI 1 "nonimmediate_operand" " r,m")))]
"TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+ && !TARGET_XANDESPERF
&& !(REG_P (operands[1]) && VL_REG_P (REGNO (operands[1])))"
"@
#
@@ -1938,7 +1939,8 @@
[(set (match_operand:GPR 0 "register_operand" "=r,r")
(zero_extend:GPR
(match_operand:HI 1 "nonimmediate_operand" " r,m")))]
- "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
+ "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+ && !TARGET_XANDESPERF"
"@
#
lhu\t%0,%1"
@@ -2000,7 +2002,7 @@
[(set (match_operand:DI 0 "register_operand" "=r,r")
(sign_extend:DI
(match_operand:SI 1 "nonimmediate_operand" " r,m")))]
- "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
+ "TARGET_64BIT && !TARGET_XTHEADMEMIDX && !TARGET_XANDESPERF"
"@
sext.w\t%0,%1
lw\t%0,%1"
@@ -2017,7 +2019,8 @@
[(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
(sign_extend:SUPERQI
(match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
- "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
+ "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+ && !TARGET_XANDESPERF"
"@
#
l<SHORT:size>\t%0,%1"
@@ -3109,6 +3112,7 @@
|| TARGET_XVENTANACONDOPS || TARGET_SFB_ALU)
&& (INTVAL (operands[2]) == 1))
&& !TARGET_XTHEADBB
+ && !TARGET_XANDESPERF
&& !(TARGET_64BIT
&& (INTVAL (operands[3]) > 0)
&& (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
@@ -3494,9 +3498,9 @@
(label_ref (match_operand 1))
(pc)))
(clobber (match_scratch:X 4 "=&r"))]
- ""
- "#"
- "reload_completed"
+ "!TARGET_XANDESPERF"
+ "#"
+ "&& reload_completed"
[(set (match_dup 4)
(ashift:X (match_dup 2) (match_dup 3)))
(set (pc)
@@ -4932,6 +4936,7 @@
;; Vendor extensions
(include "thead.md")
(include "corev.md")
+(include "andes.md")
;; Pipeline models
(include "generic.md")
(include "xiangshan.md")
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index aa3b6fb..db89b36 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4364,7 +4364,7 @@
(umax "%3,%4")
(mult "%3,%4")])
-(define_code_attr sz [(sign_extend "s") (zero_extend "z")])
+(define_code_attr sz [(sign_extend "s") (zero_extend "z") (sign_extract "s") (zero_extract "z")])
;; VLS modes that has NUNITS < 32.
(define_mode_iterator VLS_AVL_IMM [
diff --git a/gcc/testsuite/gcc.target/riscv/riscv.exp b/gcc/testsuite/gcc.target/riscv/riscv.exp
index b3222c5..b5e7618 100644
--- a/gcc/testsuite/gcc.target/riscv/riscv.exp
+++ b/gcc/testsuite/gcc.target/riscv/riscv.exp
@@ -40,6 +40,8 @@ gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
"" $DEFAULT_CFLAGS
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/sched1-spills/*.{\[cS\],cpp}]] \
"" $DEFAULT_CFLAGS
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/xandes/*.\[cS\]]] \
+ "" $DEFAULT_CFLAGS
# Saturation alu
foreach opt {
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-1.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-1.c
new file mode 100644
index 0000000..b8db0d8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long cond)
+{
+ if (cond != 63)
+ cond += 10;
+ return cond;
+}
+
+/* { dg-final { scan-assembler {\mnds.beqc} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-10.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-10.c
new file mode 100644
index 0000000..1ac2246
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-10.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv32 } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" } */
+
+int
+test_nds_ffb (unsigned int a, unsigned int b)
+{
+ return __builtin_riscv_nds_ffb_32 (a, b);
+}
+
+int
+test_nds_ffzmism (unsigned int a, unsigned int b)
+{
+ return __builtin_riscv_nds_ffzmism_32 (a, b);
+}
+
+int
+test_nds_ffmism (unsigned int a, unsigned int b)
+{
+ return __builtin_riscv_nds_ffmism_32 (a, b);
+}
+
+int
+test_nds_flmism (unsigned int a, unsigned int b)
+{
+ return __builtin_riscv_nds_flmism_32 (a, b);
+}
+
+/* { dg-final { scan-assembler-times {nds\.ffb} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffzmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.flmism} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-11.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-11.c
new file mode 100644
index 0000000..08fdd56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-11.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" } */
+
+long
+test_nds_ffb (unsigned long a, unsigned long b)
+{
+ return __builtin_riscv_nds_ffb_64 (a, b);
+}
+
+long
+test_nds_ffzmism (unsigned long a, unsigned long b)
+{
+ return __builtin_riscv_nds_ffzmism_64 (a, b);
+}
+
+long
+test_nds_ffmism (unsigned long a, unsigned long b)
+{
+ return __builtin_riscv_nds_ffmism_64 (a, b);
+}
+
+long
+test_nds_flmism (unsigned long a, unsigned long b)
+{
+ return __builtin_riscv_nds_flmism_64 (a, b);
+}
+
+/* { dg-final { scan-assembler-times {nds\.ffb} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffzmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.flmism} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-2.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-2.c
new file mode 100644
index 0000000..c3ef29b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long cond)
+{
+ if (cond & (1 << 30))
+ cond -= 10;
+ return cond;
+}
+
+/* { dg-final { scan-assembler "nds\.bb\[cs\]" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-3.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-3.c
new file mode 100644
index 0000000..65ff59e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+unsigned long foo (long a)
+{
+ unsigned int lala = a;
+ return lala;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfoz} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-4.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-4.c
new file mode 100644
index 0000000..f97b98c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+unsigned short foo (long a)
+{
+ return (unsigned short) a;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfoz} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-5.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-5.c
new file mode 100644
index 0000000..4b34baf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long a)
+{
+ int lala = a;
+ return lala;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfos} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-6.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-6.c
new file mode 100644
index 0000000..85c8581
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+short foo (long a)
+{
+ short lala = a;
+ return lala;
+}
+
+signed char foo1 (long a)
+{
+ signed char lala = a;
+ return lala;
+}
+
+/* { dg-final { scan-assembler-times {\mnds.bfos} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-7.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-7.c
new file mode 100644
index 0000000..e8cbf45
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-7.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long a)
+{
+ return (a & 0xffe0) >> 5;
+}
+
+unsigned long foo1 (unsigned long a)
+{
+ return (a & 0xffe0) >> 5;
+}
+
+signed char foo2 (long a)
+{
+ return (signed char) ((a & 0xff00) >> 8);
+}
+
+/* { dg-final { scan-assembler-times {\mnds.bfoz} 2 } } */
+/* { dg-final { scan-assembler-times {\mnds.bfos} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-8.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-8.c
new file mode 100644
index 0000000..357b8fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-8.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf -mabi=ilp32" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+short *ptr_h;
+short foo_h (long a)
+{
+ return *(ptr_h + a);
+}
+
+int *ptr_i;
+int foo_i (long a)
+{
+ return *(ptr_i + a);
+}
+
+long long *ptr_d;
+long long foo_d (long a)
+{
+ return *(ptr_d + a);
+}
+
+/* { dg-final { scan-assembler-times {\mnds.lea.h} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.w} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.d} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-9.c b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-9.c
new file mode 100644
index 0000000..b21a13c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandes/xandesperf-9.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+char *ptr_ub;
+char foo_ub (unsigned int a)
+{
+ return *(ptr_ub + a);
+}
+
+short *ptr_uh;
+short foo_uh (unsigned int a)
+{
+ return *(ptr_uh + a);
+}
+
+int *ptr_ui;
+int foo_ui (unsigned int a)
+{
+ return *(ptr_ui + a);
+}
+
+long long *ptr_ud;
+long long foo_ud (unsigned int a)
+{
+ return *(ptr_ud + a);
+}
+/* { dg-final { scan-assembler-times {\mnds.lea.b.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.h.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.w.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.d.ze} 1 } } */