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

Reply via email to