Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gcc/config.gcc
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,7 @@ riscv*)
extra_objs="${extra_objs} riscv-v.o riscv-vsetvl.o riscv-vector-costs.o riscv-avlprop.o riscv-vect-permconst.o"
extra_objs="${extra_objs} riscv-vector-builtins.o riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o sifive-vector-builtins-bases.o andes-vector-builtins-bases.o"
extra_objs="${extra_objs} thead.o riscv-target-attr.o riscv-zicfilp.o riscv-bclr-lowest-set-bit.o riscv-opt-popretz.o"
extra_objs="${extra_objs} arcv-builtins.o arcv.o"
d_target_objs="riscv-d.o"
extra_headers="riscv_vector.h riscv_crypto.h riscv_bitmanip.h riscv_th_vector.h sifive_vector.h andes_vector.h"
target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
Expand Down
367 changes: 367 additions & 0 deletions gcc/config/riscv/arcv-apex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
;; Machine description for the APEX instructions
;; Copyright (C) 2026 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" [

;; ARC-V APEX
UNSPEC_ARCV_APEX_VOID_V
UNSPEC_ARCV_APEX_VOID_SRC0_V
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V
UNSPEC_ARCV_APEX_DEST
UNSPEC_ARCV_APEX_DEST_V
UNSPEC_ARCV_APEX_DEST_SRC0
UNSPEC_ARCV_APEX_DEST_SRC0_V
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V
])

;; Used by XD (volatile): insn
(define_insn "riscv_arcv_apex_void_ftype_v"
[(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXD")]
UNSPEC_ARCV_APEX_VOID_V)]
""
{
return xasprintf ("%s",
arcv_apex_asm_mnemonic (operands[0], false));
}
[(set_attr "type" "arith")]
)

;; Used by XI and XD (volatile): insn src0
(define_insn "riscv_arcv_apex_void_ftype_<APEX_SRC0:mode>_v"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXI,xAVpXD")
(match_operand:APEX_SRC0 1 "nonmemory_operand" "I,r")]
UNSPEC_ARCV_APEX_VOID_SRC0_V)]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%d",
arcv_apex_asm_mnemonic (operands[0], true),
(int) INTVAL (operands[1]));
case 1:
return xasprintf ("%s\t%s",
arcv_apex_asm_mnemonic (operands[0], false),
reg_names[REGNO (operands[1])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith")]
)

(define_expand "riscv_arcv_apex_void_ftype_src0_v"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand")
(match_operand 1 "nonmemory_operand")]
UNSPEC_ARCV_APEX_VOID_SRC0_V)]
""
{
emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
gen_rtvec (2, operands[0],
operands[1]),
UNSPEC_ARCV_APEX_VOID_SRC0_V));
DONE;
})

;; Used by XS and XD (volatile): insn src0, src1
(define_insn "riscv_arcv_apex_void_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>_v"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXS,xAVpXD")
(match_operand:APEX_SRC0 1 "register_operand" "r,r")
(match_operand:APEX_SRC1 2 "nonmemory_operand" "Os08,r")]
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%s,%d",
arcv_apex_asm_mnemonic (operands[0], true),
reg_names[REGNO (operands[1])],
(int) INTVAL (operands[2]));
case 1:
return xasprintf ("%s\t%s,%s",
arcv_apex_asm_mnemonic (operands[0], false),
reg_names[REGNO (operands[1])],
reg_names[REGNO (operands[2])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith")]
)

(define_expand "riscv_arcv_apex_void_ftype_src0_src1_v"
[(unspec_volatile [(match_operand:SI 0 "const_int_operand")
(match_operand 1 "register_operand")
(match_operand 2 "nonmemory_operand")]
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
""
{
emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
gen_rtvec (3, operands[0],
operands[1],
operands[2]),
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V));
DONE;
})

;; Used by XD (volatile): insn rd
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_v"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r")
(unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
UNSPEC_ARCV_APEX_DEST_V))]
""
{
return xasprintf ("%s\t%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])]);
}
[(set_attr "type" "arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype_v"
[(set (match_operand 0 "register_operand")
(unspec_volatile [(match_operand:SI 1 "const_int_operand")]
UNSPEC_ARCV_APEX_DEST_V))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
gen_rtvec (1, operands[1]),
UNSPEC_ARCV_APEX_DEST_V)));
DONE;
})

;; Used by XD: insn rd
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r")
(unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
UNSPEC_ARCV_APEX_DEST))]
""
{
return xasprintf ("%s\t%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])]);
}
[(set_attr "type" "arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype"
[(set (match_operand 0 "register_operand")
(unspec [(match_operand:SI 1 "const_int_operand")]
UNSPEC_ARCV_APEX_DEST))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC (GET_MODE (operands[0]),
gen_rtvec (1, operands[1]),
UNSPEC_ARCV_APEX_DEST)));
DONE;
})

;; Used by XI and XD (volatile): insn rd, src0
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_v"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r,r")
(unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
(match_operand:APEX_SRC0 2 "nonmemory_operand" "I,r")]
UNSPEC_ARCV_APEX_DEST_SRC0_V))]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
(int) INTVAL (operands[2]));
case 1:
return xasprintf ("%s\t%s,%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype_src0_v"
[(set (match_operand 0 "register_operand")
(unspec_volatile [(match_operand:SI 1 "const_int_operand")
(match_operand 2 "nonmemory_operand")]
UNSPEC_ARCV_APEX_DEST_SRC0_V))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
gen_rtvec (2, operands[1],
operands[2]),
UNSPEC_ARCV_APEX_DEST_SRC0_V)));
DONE;
})

;; Used by XI and XD: insn rd, src0
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r,r")
(unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
(match_operand:APEX_SRC0 2 "nonmemory_operand" "I,r")]
UNSPEC_ARCV_APEX_DEST_SRC0))]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
(int) INTVAL (operands[2]));
case 1:
return xasprintf ("%s\t%s,%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype_src0"
[(set (match_operand 0 "register_operand")
(unspec [(match_operand:SI 1 "const_int_operand")
(match_operand 2 "nonmemory_operand")]
UNSPEC_ARCV_APEX_DEST_SRC0))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC (GET_MODE (operands[0]),
gen_rtvec (2, operands[1],
operands[2]),
UNSPEC_ARCV_APEX_DEST_SRC0)));
DONE;
})

;; Used by XS, XC and XD (volatile): insn rd, src0, imm/src1
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>_v"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r,r,r")
(unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
(match_operand:APEX_SRC0 2 "register_operand" "r,0,r")
(match_operand:APEX_SRC1 3 "nonmemory_operand" "Os08,I,r")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to generate some apex insn that has operand 3 a value that is large. I think this will then crash the compiler. in the expand is advised to have large predicates but in the define_insn the predicate = reunion of the constrants.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after you do this then check how the compiler fixes the case where the immediate is large.

UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%s,%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
(int) INTVAL (operands[3]));
case 1:
return xasprintf ("%s\t%s,%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
(int) INTVAL (operands[3]));
case 2:
return xasprintf ("%s\t%s,%s,%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
reg_names[REGNO (operands[3])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith,arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype_src0_src1_v"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can merged with riscv_arcv_apex_dest_ftype_src0_src1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also the corresponding insn

[(set (match_operand 0 "register_operand")
(unspec_volatile [(match_operand:SI 1 "const_int_operand")
(match_operand 2 "register_operand")
(match_operand 3 "nonmemory_operand")]
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
gen_rtvec (3, operands[1],
operands[2],
operands[3]),
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V)));
DONE;
})

;; Used by XS, XC and XD: insn rd, src0, imm/src1
(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>"
[(set (match_operand:APEX_DEST 0 "register_operand" "=r,r,r")
(unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
(match_operand:APEX_SRC0 2 "register_operand" "r,0,r")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here (and where else you use input operand 0) is a problem.
after reload_completed there may not be possible to have operand 0 same as operand 0 of your instruction - imagine the case where the input operand 2 is used later by another instruction. But at the same time you overwrite it as your operand 0 is output.
You need to make a split and in that split next to your instruction to add a move from reg 2 to reg 0. as this move is a set will be later optimized away if not needed.
You can look to my push for target arc64 where i have several define_insn_and_split

(match_operand:APEX_SRC1 3 "nonmemory_operand" "Os08,I,r")]
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
""
{
switch (which_alternative)
{
case 0:
return xasprintf ("%s\t%s,%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
(int) INTVAL (operands[3]));
case 1:
return xasprintf ("%s\t%s,%s,%d",
arcv_apex_asm_mnemonic (operands[1], true),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
(int) INTVAL (operands[3]));
case 2:
return xasprintf ("%s\t%s,%s,%s",
arcv_apex_asm_mnemonic (operands[1], false),
reg_names[REGNO (operands[0])],
reg_names[REGNO (operands[2])],
reg_names[REGNO (operands[3])]);
default:
gcc_unreachable ();
}
}
[(set_attr "type" "arith,arith,arith")]
)

(define_expand "riscv_arcv_apex_dest_ftype_src0_src1"
[(set (match_operand 0 "register_operand")
(unspec [(match_operand:SI 1 "const_int_operand")
(match_operand 2 "register_operand")
(match_operand 3 "nonmemory_operand")]
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
""
{
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC (GET_MODE (operands[0]),
gen_rtvec (3, operands[1],
operands[2],
operands[3]),
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1)));
DONE;
})
Loading