Skip to content

Commit 940ff20

Browse files
authored
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
1 parent fe3d1ba commit 940ff20

1 file changed

Lines changed: 5 additions & 59 deletions

File tree

‎ext/opcache/jit/zend_jit_ir.c‎

Lines changed: 5 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@
8989
# define IR_OPCODE_HANDLER_RET IR_ADDR
9090
#endif
9191

92-
#undef ir_CONST_ADDR
93-
#define ir_CONST_ADDR(_addr) jit_CONST_ADDR(jit, (uintptr_t)(_addr))
9492
#define ir_CONST_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), 0)
9593
#define ir_CONST_FC_FUNC(_addr) jit_CONST_FUNC(jit, (uintptr_t)(_addr), IR_FASTCALL_FUNC)
9694
#define ir_CAST_FC_FUNC(_addr) ir_fold2(_ir_CTX, IR_OPT(IR_PROTO, IR_ADDR), (_addr), \
@@ -101,7 +99,7 @@
10199
ir_proto_0(_ir_CTX, IR_FASTCALL_FUNC, IR_OPCODE_HANDLER_RET))
102100

103101
#define ir_CONST_FUNC_PROTO(_addr, _proto) \
104-
jit_CONST_FUNC_PROTO(jit, (uintptr_t)(_addr), (_proto))
102+
ir_const_func_addr(_ir_CTX, (uintptr_t)(_addr), (_proto))
105103

106104
#undef ir_ADD_OFFSET
107105
#define ir_ADD_OFFSET(_addr, _offset) \
@@ -317,7 +315,6 @@ typedef struct _zend_jit_ctx {
317315
int delay_var;
318316
ir_refs *delay_refs;
319317
ir_ref eg_exception_addr;
320-
HashTable addr_hash;
321318
ir_ref stub_addr[jit_last_stub];
322319
} zend_jit_ctx;
323320

@@ -531,46 +528,6 @@ static ir_ref jit_TLS(zend_jit_ctx *jit)
531528
}
532529
#endif
533530

534-
static ir_ref jit_CONST_ADDR(zend_jit_ctx *jit, uintptr_t addr)
535-
{
536-
ir_ref ref;
537-
zval *zv;
538-
539-
if (addr == 0) {
540-
return IR_NULL;
541-
}
542-
zv = zend_hash_index_lookup(&jit->addr_hash, addr);
543-
if (Z_TYPE_P(zv) == IS_LONG) {
544-
ref = Z_LVAL_P(zv);
545-
ZEND_ASSERT(jit->ctx.ir_base[ref].opt == IR_OPT(IR_ADDR, IR_ADDR));
546-
} else {
547-
ref = ir_unique_const_addr(&jit->ctx, addr);
548-
ZVAL_LONG(zv, ref);
549-
}
550-
return ref;
551-
}
552-
553-
static ir_ref jit_CONST_FUNC_PROTO(zend_jit_ctx *jit, uintptr_t addr, ir_ref proto)
554-
{
555-
ir_ref ref;
556-
ir_insn *insn;
557-
zval *zv;
558-
559-
ZEND_ASSERT(addr != 0);
560-
zv = zend_hash_index_lookup(&jit->addr_hash, addr);
561-
if (Z_TYPE_P(zv) == IS_LONG) {
562-
ref = Z_LVAL_P(zv);
563-
ZEND_ASSERT(jit->ctx.ir_base[ref].opt == IR_OPT(IR_FUNC_ADDR, IR_ADDR) && jit->ctx.ir_base[ref].proto == proto);
564-
} else {
565-
ref = ir_unique_const_addr(&jit->ctx, addr);
566-
insn = &jit->ctx.ir_base[ref];
567-
insn->optx = IR_OPT(IR_FUNC_ADDR, IR_ADDR);
568-
insn->proto = proto;
569-
ZVAL_LONG(zv, ref);
570-
}
571-
return ref;
572-
}
573-
574531
static ir_ref jit_CONST_FUNC(zend_jit_ctx *jit, uintptr_t addr, uint16_t flags)
575532
{
576533
#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)
580537
ir_ref proto = 0;
581538
#endif
582539

583-
return jit_CONST_FUNC_PROTO(jit, addr, proto);
540+
return ir_const_func_addr(&jit->ctx, addr, proto);
584541
}
585542

586543
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)
604561
ir_ref ref = jit->eg_exception_addr;
605562

606563
if (UNEXPECTED(!ref)) {
607-
ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)&EG(exception));
564+
ref = ir_CONST_ADDR(&EG(exception));
608565
jit->eg_exception_addr = ref;
609566
}
610567
return ref;
@@ -616,7 +573,7 @@ static ir_ref jit_STUB_ADDR(zend_jit_ctx *jit, jit_stub_id id)
616573
ir_ref ref = jit->stub_addr[id];
617574

618575
if (UNEXPECTED(!ref)) {
619-
ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)zend_jit_stub_handlers[id]);
576+
ref = ir_CONST_ADDR(zend_jit_stub_handlers[id]);
620577
jit->stub_addr[id] = ref;
621578
}
622579
return ref;
@@ -625,18 +582,9 @@ static ir_ref jit_STUB_ADDR(zend_jit_ctx *jit, jit_stub_id id)
625582
static ir_ref jit_STUB_FUNC_ADDR(zend_jit_ctx *jit, jit_stub_id id, uint16_t flags)
626583
{
627584
ir_ref ref = jit->stub_addr[id];
628-
ir_insn *insn;
629585

630586
if (UNEXPECTED(!ref)) {
631-
ref = ir_unique_const_addr(&jit->ctx, (uintptr_t)zend_jit_stub_handlers[id]);
632-
insn = &jit->ctx.ir_base[ref];
633-
insn->optx = IR_OPT(IR_FUNC_ADDR, IR_ADDR);
634-
#if defined(IR_TARGET_X86)
635-
/* TODO: dummy prototype (only flags matter) ??? */
636-
insn->proto = flags ? ir_proto_0(&jit->ctx, flags, IR_I32) : 0;
637-
#else
638-
insn->proto = 0;
639-
#endif
587+
ref = jit_CONST_FUNC(jit, (uintptr_t)zend_jit_stub_handlers[id], flags);
640588
jit->stub_addr[id] = ref;
641589
}
642590
return ref;
@@ -2842,7 +2790,6 @@ static void zend_jit_init_ctx(zend_jit_ctx *jit, uint32_t flags)
28422790
jit->delay_var = -1;
28432791
jit->delay_refs = NULL;
28442792
jit->eg_exception_addr = 0;
2845-
zend_hash_init(&jit->addr_hash, 64, NULL, NULL, 0);
28462793
memset(jit->stub_addr, 0, sizeof(jit->stub_addr));
28472794

28482795
ir_START();
@@ -2853,7 +2800,6 @@ static int zend_jit_free_ctx(zend_jit_ctx *jit)
28532800
if (jit->name) {
28542801
zend_string_release(jit->name);
28552802
}
2856-
zend_hash_destroy(&jit->addr_hash);
28572803
ir_free(&jit->ctx);
28582804
return 1;
28592805
}

0 commit comments

Comments
 (0)