Skip to content

Commit 2b3c7ec

Browse files
committed
Simplify branching logic
1 parent a0fe09d commit 2b3c7ec

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

ext/opcache/jit/zend_jit_ir.c

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4477,16 +4477,26 @@ static int zend_jit_update_regs(zend_jit_ctx *jit, uint32_t var, zend_jit_addr s
44774477
return 1;
44784478
}
44794479

4480-
static ir_ref jit_observer_fcall_is_unobserved(zend_jit_ctx *jit, const zend_function *func, ir_ref *observer_handler, ir_ref rx, ir_ref func_ref) {
4481-
ir_ref run_time_cache, if_trampoline_or_generator = IR_UNUSED, if_rt_cache = IR_UNUSED;
4480+
struct jit_observer_fcall_is_unobserved_data {
4481+
ir_ref if_unobserved;
4482+
ir_ref if_rt_cache;
4483+
ir_ref if_trampoline_or_generator;
4484+
};
4485+
4486+
static struct jit_observer_fcall_is_unobserved_data jit_observer_fcall_is_unobserved_start(zend_jit_ctx *jit, const zend_function *func, ir_ref *observer_handler, ir_ref rx, ir_ref func_ref) {
4487+
ir_ref run_time_cache;
4488+
struct jit_observer_fcall_is_unobserved_data data = {
4489+
.if_rt_cache = IS_UNUSED,
4490+
.if_trampoline_or_generator = IS_UNUSED,
4491+
};
44824492
if (func) {
44834493
ZEND_ASSERT((func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0);
44844494
} else {
44854495
ZEND_ASSERT(rx != IR_UNUSED);
4486-
if_trampoline_or_generator = ir_IF(ir_AND_U32(
4496+
data.if_trampoline_or_generator = ir_IF(ir_AND_U32(
44874497
ir_LOAD_U32(ir_ADD_OFFSET(func_ref, offsetof(zend_function, common.fn_flags))),
44884498
ir_CONST_U32(ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)));
4489-
ir_IF_FALSE(if_trampoline_or_generator);
4499+
ir_IF_FALSE(data.if_trampoline_or_generator);
44904500
}
44914501
if (func && ZEND_MAP_PTR_IS_OFFSET(func->common.run_time_cache)) {
44924502
// Closures may be duplicated and have a different runtime cache. Use the regular run_time_cache access pattern for these
@@ -4506,22 +4516,25 @@ static ir_ref jit_observer_fcall_is_unobserved(zend_jit_ctx *jit, const zend_fun
45064516
} else {
45074517
ZEND_ASSERT(rx != IR_UNUSED);
45084518
run_time_cache = ir_LOAD_A(ir_ADD_OFFSET(ir_LOAD_A(jit_CALL(rx, func)), offsetof(zend_op_array, run_time_cache__ptr)));
4509-
if_rt_cache = ir_IF(ir_EQ(run_time_cache, IR_NULL));
4510-
ir_IF_TRUE(if_rt_cache);
4519+
data.if_rt_cache = ir_IF(ir_NE(run_time_cache, IR_NULL));
4520+
ir_IF_TRUE(data.if_rt_cache);
45114521
}
45124522
*observer_handler = ir_ADD_OFFSET(run_time_cache, zend_observer_fcall_op_array_extension * sizeof(void *));
45134523
ir_ref is_unobserved = ir_EQ(ir_LOAD_A(*observer_handler), ir_CONST_ADDR(ZEND_OBSERVER_NONE_OBSERVED));
4514-
if (if_rt_cache != IR_UNUSED) {
4515-
ir_MERGE_WITH_EMPTY_FALSE(if_rt_cache);
4516-
is_unobserved = ir_PHI_2(IR_BOOL, is_unobserved, IR_TRUE);
4517-
*observer_handler = ir_PHI_2(IR_ADDR, *observer_handler, IR_NULL);
4524+
4525+
data.if_unobserved = ir_IF(is_unobserved);
4526+
ir_IF_FALSE(data.if_unobserved);
4527+
return data;
4528+
}
4529+
4530+
static void jit_observer_fcall_is_unobserved_end(zend_jit_ctx *jit, struct jit_observer_fcall_is_unobserved_data *data) {
4531+
if (data->if_rt_cache != IR_UNUSED) {
4532+
ir_MERGE_WITH_EMPTY_FALSE(data->if_rt_cache);
45184533
}
4519-
if (if_trampoline_or_generator != IR_UNUSED) {
4520-
ir_MERGE_WITH_EMPTY_TRUE(if_trampoline_or_generator);
4521-
is_unobserved = ir_PHI_2(IR_BOOL, is_unobserved, IR_TRUE);
4522-
*observer_handler = ir_PHI_2(IR_ADDR, *observer_handler, IR_NULL);
4534+
if (data->if_trampoline_or_generator != IR_UNUSED) {
4535+
ir_MERGE_WITH_EMPTY_TRUE(data->if_trampoline_or_generator);
45234536
}
4524-
return is_unobserved;
4537+
ir_MERGE_WITH_EMPTY_TRUE(data->if_unobserved);
45254538
}
45264539

45274540
static void jit_observer_fcall_begin(zend_jit_ctx *jit, ir_ref rx, ir_ref observer_handler) {
@@ -9947,15 +9960,13 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
99479960
if (ZEND_OBSERVER_ENABLED && (!func || (func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0)) {
99489961
ir_ref observer_handler;
99499962
ir_ref rx = jit_FP(jit); // Not sure why we cannot reuse rx here, but have to refetch
9950-
ir_ref is_unobserved = jit_observer_fcall_is_unobserved(jit, func, &observer_handler, rx, func_ref);
9951-
ir_ref if_is_unobserved = ir_IF(is_unobserved);
9952-
ir_IF_FALSE(if_is_unobserved);
9963+
struct jit_observer_fcall_is_unobserved_data unobserved_data = jit_observer_fcall_is_unobserved_start(jit, func, &observer_handler, rx, func_ref);
99539964
if (GCC_GLOBAL_REGS) {
99549965
// EX(opline) = opline
99559966
ir_STORE(jit_EX(opline), jit_IP(jit));
99569967
}
99579968
jit_observer_fcall_begin(jit, rx, observer_handler);
9958-
ir_MERGE_WITH_EMPTY_TRUE(if_is_unobserved);
9969+
jit_observer_fcall_is_unobserved_end(jit, &unobserved_data);
99599970
}
99609971

99619972
if (trace) {
@@ -10083,14 +10094,11 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1008310094
ir_STORE(jit_EG(current_execute_data), rx);
1008410095

1008510096
bool may_have_observer = ZEND_OBSERVER_ENABLED && (!func || (func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0);
10086-
ir_ref is_unobserved;
1008710097
if (may_have_observer) {
1008810098
ir_ref observer_handler;
10089-
is_unobserved = jit_observer_fcall_is_unobserved(jit, func, &observer_handler, rx, func_ref ? func_ref : ir_LOAD_A(jit_CALL(rx, func)));
10090-
ir_ref if_is_unobserved = ir_IF(is_unobserved);
10091-
ir_IF_FALSE(if_is_unobserved);
10099+
struct jit_observer_fcall_is_unobserved_data unobserved_data = jit_observer_fcall_is_unobserved_start(jit, func, &observer_handler, rx, func_ref ? func_ref : ir_LOAD_A(jit_CALL(rx, func)));
1009210100
jit_observer_fcall_begin(jit, rx, observer_handler);
10093-
ir_MERGE_WITH_EMPTY_TRUE(if_is_unobserved);
10101+
jit_observer_fcall_is_unobserved_end(jit, &unobserved_data);
1009410102
}
1009510103

1009610104
// JIT: ZVAL_NULL(EX_VAR(opline->result.var));
@@ -10131,10 +10139,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1013110139
}
1013210140

1013310141
if (may_have_observer) {
10134-
ir_ref if_is_unobserved = ir_IF(is_unobserved);
10135-
ir_IF_FALSE(if_is_unobserved);
1013610142
jit_observer_fcall_end(jit, rx, res_addr);
10137-
ir_MERGE_WITH_EMPTY_TRUE(if_is_unobserved);
1013810143
}
1013910144

1014010145
// JIT: EG(current_execute_data) = execute_data;
@@ -16765,7 +16770,7 @@ static bool zend_jit_may_be_in_reg(const zend_op_array *op_array, zend_ssa *ssa,
1676516770
}
1676616771

1676716772
struct jit_frameless_observer_data {
16768-
ir_ref if_is_unobserved;
16773+
ir_ref if_unobserved;
1676916774
ir_ref reused_jit_ip;
1677016775
};
1677116776

@@ -16774,30 +16779,31 @@ static struct jit_frameless_observer_data jit_frameless_observer_begin(zend_jit_
1677416779
// JIT: zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(fbc))
1677516780
ir_ref observer_handler;
1677616781
zend_function *fbc = ZEND_FLF_FUNC(opline);
16777-
ir_ref is_unobserved = jit_observer_fcall_is_unobserved(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED);
16778-
data.if_is_unobserved = ir_IF(is_unobserved);
16782+
// Not need for runtime cache or generator checks here, we just need if_unobserved
16783+
data.if_unobserved = jit_observer_fcall_is_unobserved_start(jit, fbc, &observer_handler, IR_UNUSED, IR_UNUSED).if_unobserved;
1677916784

1678016785
// push args to a valid call frame, without copying
16781-
ir_IF_FALSE(data.if_is_unobserved);
16782-
16783-
// yes, we'll temporarily reuse the IP, but we don't want to handle this via the reuse_ip mechanism for simiplicity
1678416786
bool track_last_valid_opline = jit->track_last_valid_opline;
1678516787
const zend_op *last_valid_opline = jit->last_valid_opline;
1678616788
bool reuse_ip = jit->reuse_ip;
1678716789
if (reuse_ip) {
1678816790
data.reused_jit_ip = jit_IP(jit);
1678916791
}
1679016792
zend_jit_push_call_frame(jit, opline, NULL, fbc, 0, 0, checked_stack, ir_CONST_ADDR(fbc), IR_NULL);
16793+
// yes, we'll temporarily reuse the IP, but we don't want to handle this via the reuse_ip mechanism for simiplicity - we just reset IP to original in end
1679116794
jit->track_last_valid_opline = track_last_valid_opline;
1679216795
jit->last_valid_opline = last_valid_opline;
1679316796
jit->reuse_ip = reuse_ip;
1679416797

16798+
// push all args
1679516799
uint32_t call_num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1679616800
switch (call_num_args) {
1679716801
case 3: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(3)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_data_ref), op1_data_info, 0); ZEND_FALLTHROUGH;
1679816802
case 2: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(2)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op2_ref), op2_info, 0); ZEND_FALLTHROUGH;
1679916803
case 1: jit_ZVAL_COPY(jit, ZEND_ADDR_MEM_ZVAL(ZREG_RX, EX_NUM_TO_VAR(1)), MAY_BE_ANY & ~MAY_BE_REF, ZEND_ADDR_REF_ZVAL(op1_ref), op1_info, 0);
1680016804
}
16805+
16806+
// Make call frame externally visible
1680116807
ir_ref rx = jit_IP(jit);
1680216808
ir_STORE(jit_CALL(rx, prev_execute_data), jit_FP(jit));
1680316809
ir_STORE(jit_EG(current_execute_data), rx);
@@ -16845,7 +16851,7 @@ static ir_ref jit_frameless_observer_end(zend_jit_ctx *jit, struct jit_frameless
1684516851
}
1684616852

1684716853
ir_ref skip = ir_END();
16848-
ir_IF_TRUE(data->if_is_unobserved);
16854+
ir_IF_TRUE(data->if_unobserved);
1684916855
return skip;
1685016856
}
1685116857

0 commit comments

Comments
 (0)