This series adds support for the RISC-V APEX (ARC Processor EXtension) custom instruction mechanism to GCC. APEX allows users to declare custom instructions at the C source level using #pragma intrinsic and have the compiler generate the appropriate assembly, including .extInstruction directives for the assembler.
This work was presented at the GNU Cauldron 2025. - https://www.youtube.com/watch?v=jHfxkAN3Qtw Jeff Law also attended the presentation and is CC'd on this series. APEX is not a new ISA extension in the traditional sense -- it does not add new -march bits or predefined builtins. Instead, it provides a pragma-driven interface where users bind C function declarations to custom instruction opcodes at compile time. The compiler then replaces calls to those functions with custom instructions. source file: int foo_func (int, int); #pragma intrinsic (foo_func, "foo", 7, XD) int main (void) { return foo_func (1, 2); } output: main: li a5,2 li a0,1 foo a0,a0,a5 # APEX insn. ret Four instruction formats are supported: - XD: register-register (up to 3 operands, 8-bit opcode) - XS: short-immediate (two registers + 8-bit signed immediate, 6-bit opcode) - XI: immediate (one register + immediate, 5-bit opcode) - XC: accumulator (dest = src0, 5-bit opcode) When no format is explicitly specified, the compiler infers it from the function signature and opcode range. Multiple formats can be specified for a single intrinsic (except XI, which is exclusive); the compiler selects the appropriate encoding at each call site. Since APEX intrinsics are registered dynamically via pragmas, their metadata must be explicitly serialized to survive link-time optimization. The implementation adds a dedicated LTO section (LTO_section_riscv_apex) with read/write hooks guarded by TARGET_RISCV_APEX. I initially considered a generic target hook for LTO section read/write, but since this is currently RISC-V specific, that would impose interface requirements on other architectures that do not need it. If other targets develop similar needs in the future, a common hook can be factored out at that point. The directive syntax and instruction formats in this RISCV-V APEX port are intentionally aligned with existing proprietary compiler and architecture to maintain compatibility across toolchains. The binutils-gdb patch series adding APEX assembler and disassembler support has been submitted for review: https://sourceware.org/pipermail/binutils/2026-May/149426.html The "[4/4] RISC-V: Add APEX LTO serialization for intrinsics" patch depends on: 1. The binutils APEX support above (for testing) 2. The previously submitted patch: "testsuite: Add dg-lto-error directive and ltrans assembly scanning" https://gcc.gnu.org/pipermail/gcc-patches/2026-May/716427.html which adds generic LTO test infrastructure used by the APEX LTO tests. The series is structured as follows: [1/4] RISC-V: Add APEX backend machine description and constraints RTL patterns (define_insn/define_expand) for all APEX instruction formats, mode iterators, constraints, and the .extInstruction emission helper. [2/4] RISC-V: Add APEX middle-end builtin registration and expansion Dynamic builtin table, format inference, opcode validation, immediate range checks, and RTL expansion. [3/4] RISC-V: Add APEX #pragma intrinsic frontend C pragma parser, mnemonic validation, function lookup, format flag parsing, and user-facing documentation in extend.texi. [4/4] RISC-V: Add APEX LTO serialization for intrinsics Custom LTO section serialization/deserialization with cross-translation-unit conflict detection, plus LTO tests. Tested on riscv64-unknown-elf and riscv32-unknown-elf with no regressions. Luis Silva (4): RISC-V: Add APEX backend machine description and constraints RISC-V: Add APEX middle-end builtin registration and expansion RISC-V: Add APEX #pragma intrinsic frontend RISC-V: Add APEX LTO serialization for intrinsics gcc/config.gcc | 1 + gcc/config/riscv/arcv-apex.md | 367 +++++++++ gcc/config/riscv/arcv-builtins.cc | 760 ++++++++++++++++++ gcc/config/riscv/arcv.cc | 102 +++ gcc/config/riscv/constraints.md | 34 + gcc/config/riscv/iterators.md | 6 + gcc/config/riscv/riscv-builtins.cc | 14 + gcc/config/riscv/riscv-c.cc | 224 ++++++ gcc/config/riscv/riscv-protos.h | 20 +- gcc/config/riscv/riscv-vector-builtins.h | 8 +- gcc/config/riscv/riscv.h | 42 + gcc/config/riscv/riscv.md | 1 + gcc/config/riscv/t-riscv | 16 + gcc/doc/extend.texi | 85 ++ gcc/fold-const.cc | 12 + gcc/lto-section-in.cc | 1 + gcc/lto-streamer-out.cc | 6 + gcc/lto-streamer.h | 6 + gcc/lto/lto-common.cc | 6 + gcc/testsuite/g++.target/riscv/apex/apex.exp | 30 + .../g++.target/riscv/apex/arcv-apex-test1.C | 22 + .../g++.target/riscv/apex/arcv-apex-test2.C | 14 + .../g++.target/riscv/apex/arcv-apex-test3.C | 21 + .../g++.target/riscv/apex/arcv-apex-test4.C | 33 + .../g++.target/riscv/apex/arcv-apex-test5.C | 16 + gcc/testsuite/gcc.target/riscv/apex/apex.exp | 53 ++ .../gcc.target/riscv/apex/arcv-apex-err1.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err10.c | 14 + .../gcc.target/riscv/apex/arcv-apex-err11.c | 11 + .../gcc.target/riscv/apex/arcv-apex-err12.c | 11 + .../gcc.target/riscv/apex/arcv-apex-err13.c | 13 + .../gcc.target/riscv/apex/arcv-apex-err14.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err15.c | 9 + .../riscv/apex/arcv-apex-err16-32.c | 14 + .../riscv/apex/arcv-apex-err16-64.c | 14 + .../riscv/apex/arcv-apex-err17-32.c | 13 + .../riscv/apex/arcv-apex-err17-64.c | 13 + .../gcc.target/riscv/apex/arcv-apex-err18.c | 7 + .../gcc.target/riscv/apex/arcv-apex-err19.c | 13 + .../gcc.target/riscv/apex/arcv-apex-err2.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err20.c | 16 + .../gcc.target/riscv/apex/arcv-apex-err3.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err4.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err5.c | 6 + .../gcc.target/riscv/apex/arcv-apex-err6.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err7.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err8.c | 4 + .../gcc.target/riscv/apex/arcv-apex-err9.c | 12 + .../riscv/apex/arcv-apex-lto-err1_0.c | 16 + .../riscv/apex/arcv-apex-lto-err1_1.c | 9 + .../riscv/apex/arcv-apex-lto-err2_0.c | 17 + .../riscv/apex/arcv-apex-lto-err2_1.c | 9 + .../riscv/apex/arcv-apex-lto-err3_0.c | 17 + .../riscv/apex/arcv-apex-lto-err3_1.c | 9 + .../riscv/apex/arcv-apex-lto-err4_0.c | 19 + .../riscv/apex/arcv-apex-lto-err4_1.c | 9 + .../riscv/apex/arcv-apex-lto-test1_0.c | 49 ++ .../riscv/apex/arcv-apex-lto-test1_1.c | 25 + .../riscv/apex/arcv-apex-lto-test2_0.c | 36 + .../riscv/apex/arcv-apex-lto-test2_1.c | 15 + .../riscv/apex/arcv-apex-lto-test3_0.c | 49 ++ .../riscv/apex/arcv-apex-lto-test3_1.c | 25 + .../riscv/apex/arcv-apex-lto-test4_0.c | 25 + .../riscv/apex/arcv-apex-lto-test4_1.c | 12 + .../riscv/apex/arcv-apex-lto-test5_0.c | 52 ++ .../riscv/apex/arcv-apex-lto-test5_1.c | 20 + .../gcc.target/riscv/apex/arcv-apex-test1.c | 22 + .../gcc.target/riscv/apex/arcv-apex-test10.c | 22 + .../gcc.target/riscv/apex/arcv-apex-test11.c | 22 + .../gcc.target/riscv/apex/arcv-apex-test12.c | 21 + .../gcc.target/riscv/apex/arcv-apex-test13.c | 22 + .../gcc.target/riscv/apex/arcv-apex-test14.c | 20 + .../gcc.target/riscv/apex/arcv-apex-test15.c | 20 + .../gcc.target/riscv/apex/arcv-apex-test16.c | 20 + .../gcc.target/riscv/apex/arcv-apex-test2.c | 16 + .../gcc.target/riscv/apex/arcv-apex-test3.c | 15 + .../gcc.target/riscv/apex/arcv-apex-test4.c | 39 + .../gcc.target/riscv/apex/arcv-apex-test5.c | 63 ++ .../gcc.target/riscv/apex/arcv-apex-test6.c | 63 ++ .../gcc.target/riscv/apex/arcv-apex-test7.c | 17 + .../gcc.target/riscv/apex/arcv-apex-test8.c | 17 + .../gcc.target/riscv/apex/arcv-apex-test9.c | 20 + 82 files changed, 2923 insertions(+), 7 deletions(-) create mode 100644 gcc/config/riscv/arcv-apex.md create mode 100644 gcc/config/riscv/arcv-builtins.cc create mode 100644 gcc/config/riscv/arcv.cc create mode 100644 gcc/testsuite/g++.target/riscv/apex/apex.exp create mode 100644 gcc/testsuite/g++.target/riscv/apex/arcv-apex-test1.C create mode 100644 gcc/testsuite/g++.target/riscv/apex/arcv-apex-test2.C create mode 100644 gcc/testsuite/g++.target/riscv/apex/arcv-apex-test3.C create mode 100644 gcc/testsuite/g++.target/riscv/apex/arcv-apex-test4.C create mode 100644 gcc/testsuite/g++.target/riscv/apex/arcv-apex-test5.C create mode 100644 gcc/testsuite/gcc.target/riscv/apex/apex.exp create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err10.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err11.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err12.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err13.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err14.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err15.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err16-32.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err16-64.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err17-32.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err17-64.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err18.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err19.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err2.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err20.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err3.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err4.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err5.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err6.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err7.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err8.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-err9.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err1_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err1_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err2_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err2_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err3_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err3_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err4_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-err4_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test1_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test1_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test2_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test2_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test3_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test3_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test4_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test4_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test5_0.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-lto-test5_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test1.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test10.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test11.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test12.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test13.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test14.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test15.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test16.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test2.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test3.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test4.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test5.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test6.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test7.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test8.c create mode 100644 gcc/testsuite/gcc.target/riscv/apex/arcv-apex-test9.c -- 2.34.0
