[php-src] master: JIT: Use interned constants for offsets in jit_ADD_OFFSET() (#23952)

From: Date: Wed, 30 Sep 2026 21:08:24 +0000
Subject: [php-src] master: JIT: Use interned constants for offsets in jit_ADD_OFFSET() (#23952)
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141822@lists.php.net to get a copy of this message
Author: Nora Dossche (ndossche) Committer: GitHub (web-flow) Pusher: ndossche Date: 2026-09-30T23:08:20+02:00 Commit: https://github.com/php/php-src/commit/940ff2098ea4cbc1ce711a07df958f7d531e51fa Raw diff: https://github.com/php/php-src/commit/940ff2098ea4cbc1ce711a07df958f7d531e51fa.diff JIT: Use interned constants for offsets in jit_ADD_OFFSET() (#23952) * JIT: Use interned constants for offsets in jit_ADD_OFFSET() jit_ADD_OFFSET() created the offset through jit_CONST_ADDR(), which returns a unique (non-interned) constant. IR's own folding of nested offsets, ADD(ADD(x, c1), c2), creates an interned constant for c1+c2. The same address can therefore end up with two different offset refs, and CSE and store-to-load forwarding, which both need an identical address ref, miss it. The uniqueing exists likely for the exit addresses mostly, but for offsets this is wrong. For example, the type store and the type load of the same zval end up with different refs: ```php function count_big($n) { $c = 0; for ($i = 0; $i < $n; $i++) { $big = $i > 5; if ($big) { $c++; } } return $c; } ``` Loop body before: ```asm movl %esi, 0x88(%r14) cmpb $3, 0x88(%r14) jne jit$$trace_exit_4 ``` After: ```asm movl %esi, 0x88(%r14) cmpb $3, %sil ; no reload jne jit$$trace_exit_4 ``` In general, more redundant loads can be avoided, and in some cases type guards can be eliminated due to store->load forwarding. * get rid of php-specific interning table * restore some static cache Changed paths: M ext/opcache/jit/zend_jit_ir.c Diff: diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 627b1f9437a2..c6d4927d41bd 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -89,8 +89,6 @@ # define IR_OPCODE_HANDLER_RET IR_ADDR #endif -#undef ir_CONST_ADDR -#define ir_CONST_ADDR(_addr) jit_CONST_ADDR(jit, (uintptr_t)(_addr)) #define ir_CONST_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), 0) #define ir_CONST_FC_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), IR_FASTCALL_FUNC) #define ir_CAST_FC_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \ @@ -101,7 +99,7 @@ ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC, IR_OPCODE_HANDLER_RET)) #define ir_CONST_FUNC_PROTO(_addr, _proto) \ - jit_CONST_FUNC_PROTO(jit, (uintptr_t)(_addr), (_proto)) + ir_const_func_addr(_ir_CTX, (uintptr_t)(_addr), (_proto)) #undef ir_ADD_OFFSET #define ir_ADD_OFFSET(_addr, _offset) \ @@ -317,7 +315,6 @@ typedef struct _zend_jit_ctx { int delay_var; ir_refs *delay_refs; ir_ref eg_exception_addr; - HashTable addr_hash; ir_ref stub_addr[jit_last_stub]; } zend_jit_ctx; @@ -531,46 +528,6 @@ static ir_ref jit_TLS(zend_jit_ctx *jit) } #endif -static ir_ref jit_CONST_ADDR(zend_jit_ctx *jit, uintptr_t addr) -{ - ir_ref ref; - zval *zv; - - if (addr == 0) { - return IR_NULL; - } - zv = zend_hash_index_lookup(&jit->addr_hash, addr); - if (Z_TYPE_P(zv) == IS_LONG) { - ref = Z_LVAL_P(zv); - ZEND_ASSERT(jit->ctx.ir_base[ref].opt == IR_OPT(IR_ADDR, IR_ADDR)); - } else { - ref = ir_unique_const_addr(&jit->ctx, addr); - ZVAL_LONG(zv, ref); - } - return ref; -} - -static ir_ref jit_CONST_FUNC_PROTO(zend_jit_ctx *jit, uintptr_t addr, ir_ref proto) -{ - ir_ref ref; - ir_insn *insn; - zval *zv; - - ZEND_ASSERT(addr != 0); - zv = zend_hash_index_lookup(&jit->addr_hash, addr); - if (Z_TYPE_P(zv) == IS_LONG) { - ref = Z_LVAL_P(zv); - ZEND_ASSERT(jit->ctx.ir_base[ref].opt == IR_OPT(IR_FUNC_ADDR, IR_ADDR) && jit->ctx.ir_base[ref].proto == proto); - } else { - ref = ir_unique_const_addr(&jit->ctx, addr); - insn = &jit->ctx.ir_base[ref]; - insn->optx = IR_OPT(IR_FUNC_ADDR, IR_ADDR); - insn->proto = proto; - ZVAL_LONG(zv, ref); - } - return ref; -} - static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags) { #if defined(IR_TARGET_X86) @@ -580,7 +537,7 @@ static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags) ir_ref proto = 0; #endif - return jit_CONST_FUNC_PROTO(jit, addr, proto); + return ir_const_func_addr(&jit->ctx, addr, proto); } static ir_ref jit_CONST_OPCODE_HANDLER_FUNC(zend_jit_ctx *jit, zend_vm_opcode_handler_t handler) @@ -604,7 +561,7 @@ static ir_ref jit_EG_exception(zend_jit_ctx *jit) ir_ref ref = jit->eg_exception_addr; if (UNEXPECTED(!ref)) { - ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)&EG(exception)); + ref = ir_CONST_ADDR(&EG(exception)); jit->eg_exception_addr = ref; } return ref; @@ -616,7 +573,7 @@ static ir_ref jit_STUB_ADDR(zend_jit_ctx *jit, jit_stub_id id) ir_ref ref = jit->stub_addr[id]; if (UNEXPECTED(!ref)) { - ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)zend_jit_stub_handlers[id]); + ref = ir_CONST_ADDR(zend_jit_stub_handlers[id]); jit->stub_addr[id] = ref; } return ref; @@ -625,18 +582,9 @@ static ir_ref jit_STUB_ADDR(zend_jit_ctx *jit, jit_stub_id id) static ir_ref jit_STUB_FUNC_ADDR(zend_jit_ctx *jit, jit_stub_id id, uint16_t flags) { ir_ref ref = jit->stub_addr[id]; - ir_insn *insn; if (UNEXPECTED(!ref)) { - ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)zend_jit_stub_handlers[id]); - insn = &jit->ctx.ir_base[ref]; - insn->optx = IR_OPT(IR_FUNC_ADDR, IR_ADDR); -#if defined(IR_TARGET_X86) - /* TODO: dummy prototype (only flags matter) ??? */ - insn->proto = flags ? ir_proto_0(&jit->ctx, flags, IR_I32) : 0; -#else - insn->proto = 0; -#endif + ref = jit_CONST_FUNC(jit, (uintptr_t)zend_jit_stub_handlers[id], flags); jit->stub_addr[id] = ref; } return ref; @@ -2842,7 +2790,6 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags) jit->delay_var = -1; jit->delay_refs = NULL; jit->eg_exception_addr = 0; - zend_hash_init(&jit->addr_hash, 64, NULL, NULL, 0); memset(jit->stub_addr, 0, sizeof(jit->stub_addr)); ir_START(); @@ -2853,7 +2800,6 @@ static int zend_jit_free_ctx(zend_jit_ctx *jit) if (jit->name) { zend_string_release(jit->name); } - zend_hash_destroy(&jit->addr_hash); ir_free(&jit->ctx); return 1; }

« previous php.cvs (#141822) next »