Hello internals,
I would like to raise the question of adding a LoongArch64 backend to the
OPcache JIT, and to ask for guidance before writing any substantial amount of
code.
Status today (PHP 8.5 / master):
- ext/opcache/config.m4 gates the JIT on the host CPU:
AS_CASE([$host_cpu],
[[i[34567]86*|x86*|aarch64|amd64]], [],
[AC_MSG_WARN([JIT not supported by host architecture])
PHP_OPCACHE_JIT=no])
On loongarch64 this silently disables --enable-opcache-jit.
- ext/opcache/jit/ir/ contains ir_x86.dasc (~930 KB) and ir_aarch64.dasc
(~328 KB) and their headers. There is no ir_loongarch64.dasc.
- The bundled DynASM provides dasm_arm, dasm_arm64, dasm_mips, dasm_ppc
and dasm_x86/x64, but no LoongArch64 target, so a backend needs a
DynASM target first.
- Fibers already work on LoongArch64 (make_loongarch64_sysv_elf_gas.S and
jump_loongarch64_sysv_elf_gas.S under Zend/asm/, plus loongarch64 in
configure.ac), so the LP64D calling convention is already used in-tree.
- PCRE2's SLJIT has a LoongArch64 backend (sljitNativeLOONGARCH_64.c), so
pcre.jit=1 reports "PCRE JIT Target => LOONGARCH 64bit". The gap is
specific to the Zend JIT, not to the platform.
Why it matters: LoongArch64 is a supported Linux target for several
distributions (Debian loong64 ports, AOSC OS, Loongnix) and the hardware
family (3A6000, 3B6000, 3C6000) is used as desktop and server hardware. PHP is
a mainstream workload there, and without the JIT these systems are
structurally 10-30% behind on JIT-friendly code. Frequency scaling is also
not exposed on several of these platforms, so the JIT is one of the few
remaining single-thread levers.
Scope, as far as I can tell from ir_aarch64.dasc:
1. A DynASM target: dasm_loongarch64.lua and dasm_loongarch64.h
(encoding tables, relocations).
2. ir_loongarch64.dasc and ir_loongarch64.h: all IR opcodes, register
constraints, calling convention, stack frames, safepoints,
exception/GC handling, JIT helper ABI.
3. Wiring in config.m4 (IR_TARGET, DASM_ARCH) and the guards in
zend_jit.c / zend_jit_ir.c.
4. Running the test matrix, e.g.
make test TESTS="-d opcache.jit_buffer_size=16M -d opcache.enable=1
-d opcache.enable_cli=1 -d opcache.protect_memory=1
-d opcache.jit=tracing --repeat 2 -j$(nproc) ext/opcache Zend"
and the same with opcache.jit=function and opcache.jit=off.
Questions:
1. Would an in-tree LoongArch64 IR backend be acceptable in principle, or
are JIT backends expected to stay limited to architectures the core team
can test and maintain?
2. Is there a porting checklist beyond using ir_aarch64.dasc as a reference?
3. Given that the legacy zend_jit_*.dasc backends were removed, is the
IR-based JIT (8.4+) the only sensible target?
4. Would an initial patch limited to the DynASM target plus a skeleton IR
backend (builds, passes a small opcode subset) be reviewable, or is a
complete backend expected before discussion?
I have Loongson 3B6000M hardware (LA664, 8 cores, LSX, no LASX) running
AOSC OS 14 and Debian loong64, and can run tests and publish benchmark
numbers. I would prefer to agree on the approach first rather than write
several thousand lines of assembler that upstream would not want to carry.
Thanks,
tsuibin