On Fri, 5 Jun 2026, Robin Dapp wrote:
> >>> Please give an overview of what APEX is and why LTO currently
> >>> cannot handle it.
> >>>
> >>> Richard.
> >
> >> Luis, is the problem just that we need consistent builtin numbering (which
> >> requires special care with dynamically enabled builtins but should still be
> >> possible) or is there more to it?
> >
> >> --
> >> Regards
> >> Robin
> >
> > Hi Richard, Robin,
> >
> > APEX (ARC Processor EXtension) is a mechanism for integrating custom
> > instructions into GCC without requiring users to have detailed knowledge of
> > compiler internals. It allows users to define custom instructions via C
> > pragmas
> > and assembler directives.
> >
> > A function prototype is used to represent a custom instruction, and a pragma
> > binds it to instruction metadata (e.g., mnemonic, opcode), effectively
> > making it
> > behave like a builtin:
> >
> > ```c
> > int foo_func (int, int);
> > #pragma intrinsic (foo_func, "foo", 7, XD)
> >
> > int main (void)
> > {
> > return foo_func (1, 2);
> > }
> > ```
> >
> > which generate:
> > ```asm
> > .extInstruction foo,7,XD
> > main:
> > li a5,2
> > li a0,1
> > foo a0,a0,a5 # APEX instruction
> > ret
> > ```
> >
> > The issue with LTO is that APEX intrinsics are registered dynamically during
> > front-end processing via pragmas. This registration state is not preserved
> > through LTO.
> >
> > By the time LTO reads the serialized GIMPLE back in, the original pragma
> > processing phase has already completed, so the backend no longer has any
> > record
> > of the intrinsic definition (mnemonic, opcode, operand constraints). As a
> > result, the call cannot be resolved against any known intrinsic entry,
> > leading
> > to an ICE during validation.
> >
> > In response to Robin’s question: it is a bit more than just builtin
> > numbering.
> >
> > It is not only about having a stable identifier across LTO, but also about
> > preserving and restoring the intrinsic registration itself. Even with
> > consistent
> > numbering, the backend still lacks the metadata required to reconstruct the
> > intrinsic after LTO.
>
> But we do know all possible intrinsics, statically?
I don't read it this way.
> Can't we (dummy) "initialize" them so there are placeholders to fall back to?
>
> I haven't looked in detail (sorry) and just saw the "trick GCC into" which
> might already indicate something like that?
The GCC canonical way of doing what APEX does would be
extern inline __attribute__((gnu_inline))
int foo_func (int a, int b)
{
int res;
__asm__ (".byte 7, XD" : "=r" (res) : "r" (a), "r" (b));
return res;
}
and I'd implement "fancy" (producing the appropriate register operand
mnemonic piece) via output templates and assembler extensions.
No need for #pragma or anything, it's just GCC extended asm and
function-as-a-macro extension. This should all work with LTO
already.
Richard.