On Fri, 5 Jun 2026, Richard Biener wrote:

> 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.

That said, the extension is probably driven from the LLVM side
where there's an internal assembler available.  So even w/o that
couldn't the target, upon parsing

#pragma intrinsic (foo_func, "foo", 7, XD)

generate the above inline function?  Not sure if

.extInstruction foo,7,XD

is already the assembler extension required, if so then the
asm template can just have "foo %0, %1, %2", no?

> 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.

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to