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. * 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_ULONG and RISCV_ATYPE_LONG. * 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/xandesperf-1.c: New test. * gcc.target/riscv/xandesperf-10.c: New test. * gcc.target/riscv/xandesperf-2.c: New test. * gcc.target/riscv/xandesperf-3.c: New test. * gcc.target/riscv/xandesperf-4.c: New test. * gcc.target/riscv/xandesperf-5.c: New test. * gcc.target/riscv/xandesperf-6.c: New test. * gcc.target/riscv/xandesperf-7.c: New test. * gcc.target/riscv/xandesperf-8.c: New test. * gcc.target/riscv/xandesperf-9.c: New test. --- gcc/config/riscv/andes.def | 10 + gcc/config/riscv/andes.md | 443 ++++++++++++++++++ gcc/config/riscv/constraints.md | 10 + gcc/config/riscv/iterators.md | 12 + gcc/config/riscv/predicates.md | 42 ++ gcc/config/riscv/riscv-builtins.cc | 7 + gcc/config/riscv/riscv-ftypes.def | 1 + gcc/config/riscv/riscv.cc | 32 ++ gcc/config/riscv/riscv.md | 17 +- gcc/config/riscv/vector-iterators.md | 2 +- gcc/testsuite/gcc.target/riscv/xandesperf-1.c | 13 + .../gcc.target/riscv/xandesperf-10.c | 32 ++ gcc/testsuite/gcc.target/riscv/xandesperf-2.c | 13 + gcc/testsuite/gcc.target/riscv/xandesperf-3.c | 11 + gcc/testsuite/gcc.target/riscv/xandesperf-4.c | 11 + gcc/testsuite/gcc.target/riscv/xandesperf-5.c | 11 + gcc/testsuite/gcc.target/riscv/xandesperf-6.c | 18 + gcc/testsuite/gcc.target/riscv/xandesperf-7.c | 22 + gcc/testsuite/gcc.target/riscv/xandesperf-8.c | 26 + gcc/testsuite/gcc.target/riscv/xandesperf-9.c | 31 ++ 20 files changed, 757 insertions(+), 7 deletions(-) create mode 100644 gcc/config/riscv/andes.def create mode 100644 gcc/config/riscv/andes.md create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-10.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-5.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-6.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-7.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-8.c create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-9.c diff --git a/gcc/config/riscv/andes.def b/gcc/config/riscv/andes.def new file mode 100644 index 000000000000..b864ae712c1d --- /dev/null +++ b/gcc/config/riscv/andes.def @@ -0,0 +1,10 @@ +// XANDESPERF +/* Andes Performance Extension */ +RISCV_BUILTIN (nds_ffbsi, "nds_ffb", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32), +RISCV_BUILTIN (nds_ffbdi, "nds_ffb", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64), +RISCV_BUILTIN (nds_ffzmismsi, "nds_ffzmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32), +RISCV_BUILTIN (nds_ffzmismdi, "nds_ffzmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64), +RISCV_BUILTIN (nds_ffmismsi, "nds_ffmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32), +RISCV_BUILTIN (nds_ffmismdi, "nds_ffmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64), +RISCV_BUILTIN (nds_flmismsi, "nds_flmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32), +RISCV_BUILTIN (nds_flmismdi, "nds_flmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64), diff --git a/gcc/config/riscv/andes.md b/gcc/config/riscv/andes.md new file mode 100644 index 000000000000..51f61e58e244 --- /dev/null +++ b/gcc/config/riscv/andes.md @@ -0,0 +1,443 @@ +;; 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 + (match_operator 1 "equality_operator" + [(match_operand:X 2 "register_operand" "r") + (match_operand:X 3 "ads_branch_bimm_operand" "Ou07")]) + (label_ref (match_operand 0 "" "")) + (pc)))] + "TARGET_XANDESPERF" +{ + if (get_attr_length (insn) == 12) + return "nds.b%C1c\t%2,%3,1f; jump\t%l0,ra; 1:"; + + return "nds.b%C1c\t%2,%3,%l0"; +} + [(set_attr "type" "branch") + (set_attr "mode" "none")]) + +(define_insn "*nds_branch_on_bit<X:mode>" + [(set (pc) + (if_then_else + (match_operator 1 "equality_operator" + [(zero_extract:X (match_operand:X 2 "register_operand" "r") + (const_int 1) + (match_operand 3 "ads_branch_bbcs_operand")) + (const_int 0)]) + (label_ref (match_operand 0)) + (pc))) + (clobber (match_scratch:X 4 "=&r"))] + "TARGET_XANDESPERF" +{ + if (GET_CODE (operands[1]) == EQ) + { + if (get_attr_length (insn) == 12) + return "nds.bbc\t%2,%3,%1f; jump\t%l0,ra; 1:"; + + return "nds.bbc\t%2,%3,%l0"; + } + else + { + if (get_attr_length (insn) == 12) + return "nds.bbs\t%2,%3,%1f; jump\t%l0,ra; 1:"; + + return "nds.bbs\t%2,%3,%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: Combine pass doesn't convert (and (ashift) Y) to +;; zero_extract when exact_log2 (Y + 1) < 0. +(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 5ecaa19eb014..60e6dee66ead 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -330,3 +330,13 @@ (define_constraint "Q" "An address operand that is valid for a prefetch instruction" (match_operand 0 "prefetch_operand")) + +(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 584b345f02c4..fdfa3fee01a9 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")]) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 1f9a6b562e53..1e862664ca0e 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -465,6 +465,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)"))) @@ -697,3 +701,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 9f8a9806bd94..8b081e240be4 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 @@ -193,6 +197,8 @@ AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT) #define RISCV_ATYPE_SI intSI_type_node #define RISCV_ATYPE_VOID_PTR ptr_type_node #define RISCV_ATYPE_INT_PTR integer_ptr_type_node +#define RISCV_ATYPE_ULONG long_unsigned_type_node +#define RISCV_ATYPE_LONG long_integer_type_node /* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists their associated RISCV_ATYPEs. */ @@ -212,6 +218,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 f7854dd996bc..fd1314d9d975 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, (LONG, ULONG, ULONG)) 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 a4428f0e96d2..7736c6b963fa 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3928,6 +3928,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); @@ -4216,6 +4220,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) @@ -4275,6 +4285,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)) @@ -4302,6 +4319,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: @@ -4470,6 +4493,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 c6661f5646b3..823e2cb859c5 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1891,6 +1891,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])))" "@ # @@ -1917,7 +1918,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" @@ -1979,7 +1981,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" @@ -1996,7 +1998,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" @@ -3076,6 +3079,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))" @@ -3461,9 +3465,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) @@ -4897,3 +4901,4 @@ (include "sifive-p600.md") (include "generic-vector-ooo.md") (include "generic-ooo.md") +(include "andes.md") diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index e60e3a8399ce..33300a010a1c 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -4307,7 +4307,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/xandesperf-1.c b/gcc/testsuite/gcc.target/riscv/xandesperf-1.c new file mode 100644 index 000000000000..503991416b55 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { 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/xandesperf-10.c b/gcc/testsuite/gcc.target/riscv/xandesperf-10.c new file mode 100644 index 000000000000..6f6598f88274 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-10.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ + +long +test_nds_ffb (unsigned long a, unsigned long b) +{ + return __builtin_riscv_nds_ffb (a, b); +} + +long +test_nds_ffzmism (unsigned long a, unsigned long b) +{ + return __builtin_riscv_nds_ffzmism (a, b); +} + +long +test_nds_ffmism (unsigned long a, unsigned long b) +{ + return __builtin_riscv_nds_ffmism (a, b); +} + +long +test_nds_flmism (unsigned long a, unsigned long b) +{ + return __builtin_riscv_nds_flmism (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/xandesperf-2.c b/gcc/testsuite/gcc.target/riscv/xandesperf-2.c new file mode 100644 index 000000000000..786cb7a64d2d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */ + +long foo (long cond) +{ + if (cond & (1 << 30)) + cond -= 10; + return cond; +} + +/* { dg-final { scan-assembler {\mnds.bbc} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-3.c b/gcc/testsuite/gcc.target/riscv/xandesperf-3.c new file mode 100644 index 000000000000..f5dfe2803b58 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gc_xandesperf" } */ +/* { 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/xandesperf-4.c b/gcc/testsuite/gcc.target/riscv/xandesperf-4.c new file mode 100644 index 000000000000..f49c19c08f97 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { 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/xandesperf-5.c b/gcc/testsuite/gcc.target/riscv/xandesperf-5.c new file mode 100644 index 000000000000..fed87461794c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-5.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gc_xandesperf" } */ +/* { 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/xandesperf-6.c b/gcc/testsuite/gcc.target/riscv/xandesperf-6.c new file mode 100644 index 000000000000..56afdd979a52 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-6.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { 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/xandesperf-7.c b/gcc/testsuite/gcc.target/riscv/xandesperf-7.c new file mode 100644 index 000000000000..b5d0ab9dfd21 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-7.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { 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/xandesperf-8.c b/gcc/testsuite/gcc.target/riscv/xandesperf-8.c new file mode 100644 index 000000000000..e201821bfba4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-8.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_xandesperf" { 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/xandesperf-9.c b/gcc/testsuite/gcc.target/riscv/xandesperf-9.c new file mode 100644 index 000000000000..1eadb10f52c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/xandesperf-9.c @@ -0,0 +1,31 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-options "-march=rv64gc_xandesperf" } */ +/* { 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 } } */ -- 2.34.1