Skip to content

Commit 8da693f

Browse files
committed
try to fix JIT/Optimizations
1 parent 6892199 commit 8da693f

File tree

7 files changed

+68
-8
lines changed

7 files changed

+68
-8
lines changed

Zend/Optimizer/dce.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ static inline bool may_have_side_effects(
9595
case ZEND_DIV:
9696
case ZEND_MOD:
9797
case ZEND_BOOL_XOR:
98-
case ZEND_BOOL:
99-
case ZEND_BOOL_NOT:
10098
case ZEND_BW_NOT:
10199
case ZEND_SL:
102100
case ZEND_SR:
@@ -106,7 +104,6 @@ static inline bool may_have_side_effects(
106104
case ZEND_IS_SMALLER_OR_EQUAL:
107105
case ZEND_CASE:
108106
case ZEND_CASE_STRICT:
109-
case ZEND_CAST:
110107
case ZEND_ROPE_INIT:
111108
case ZEND_ROPE_ADD:
112109
case ZEND_INIT_ARRAY:
@@ -126,6 +123,27 @@ static inline bool may_have_side_effects(
126123
case ZEND_ARRAY_KEY_EXISTS:
127124
/* No side effects */
128125
return 0;
126+
case ZEND_CAST: {
127+
uint32_t t1 = OP1_INFO();
128+
/* Cast from NAN emits warning */
129+
if (t1 & MAY_BE_DOUBLE) {
130+
return true;
131+
}
132+
if (t1 & MAY_BE_ARRAY) {
133+
/* Array cast to string emits warning */
134+
return opline->extended_value == IS_STRING;
135+
}
136+
return false;
137+
}
138+
case ZEND_BOOL:
139+
case ZEND_BOOL_NOT: {
140+
uint32_t t1 = OP1_INFO();
141+
/* Cast from NAN emits warning */
142+
if (t1 & MAY_BE_DOUBLE) {
143+
return true;
144+
}
145+
return false;
146+
}
129147
case ZEND_FREE:
130148
return opline->extended_value == ZEND_FREE_VOID_CAST;
131149
case ZEND_ADD_ARRAY_ELEMENT:

Zend/Optimizer/sccp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ static inline zend_result ct_eval_bool_cast(zval *result, zval *op) {
335335
ZVAL_TRUE(result);
336336
return SUCCESS;
337337
}
338+
/* NAN warns when casting */
339+
if (Z_TYPE_P(op) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op))) {
340+
return FAILURE;
341+
}
338342

339343
ZVAL_BOOL(result, zend_is_true(op));
340344
return SUCCESS;

Zend/Optimizer/zend_inference.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5105,14 +5105,16 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
51055105
case ZEND_PRE_DEC:
51065106
case ZEND_POST_DEC:
51075107
return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
5108-
case ZEND_BOOL_NOT:
51095108
case ZEND_JMPZ:
51105109
case ZEND_JMPNZ:
51115110
case ZEND_JMPZ_EX:
51125111
case ZEND_JMPNZ_EX:
5113-
case ZEND_BOOL:
51145112
case ZEND_JMP_SET:
51155113
return (t1 & MAY_BE_OBJECT);
5114+
case ZEND_BOOL:
5115+
case ZEND_BOOL_NOT:
5116+
/* NAN Cast to bool will warn */
5117+
return (t1 & MAY_BE_OBJECT) || (t1 & MAY_BE_DOUBLE);
51165118
case ZEND_BOOL_XOR:
51175119
return (t1 & MAY_BE_OBJECT) || (t2 & MAY_BE_OBJECT);
51185120
case ZEND_IS_EQUAL:

Zend/zend_compile.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10027,6 +10027,19 @@ ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, const zval *op)
1002710027
}
1002810028
return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op);
1002910029
}
10030+
/* Can happen when called from zend_optimizer_eval_unary_op() */
10031+
if (
10032+
opcode == ZEND_IS_EQUAL
10033+
|| opcode == ZEND_IS_NOT_EQUAL
10034+
|| opcode == ZEND_BOOL
10035+
|| opcode == ZEND_BOOL_NOT
10036+
) {
10037+
/* BW_NOT on string does not convert the string into an integer. */
10038+
if (Z_TYPE_P(op) == IS_DOUBLE) {
10039+
return true;
10040+
}
10041+
return false;
10042+
}
1003010043

1003110044
return 0;
1003210045
}
@@ -10210,7 +10223,7 @@ static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
1021010223
}
1021110224

1021210225
do {
10213-
// TODO do not do this for NAN?
10226+
/* TODO: Do this optimization when other side is not float as NAN will warn and we don't want that
1021410227
if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
1021510228
if (left_node.op_type == IS_CONST) {
1021610229
if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
@@ -10233,7 +10246,8 @@ static void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
1023310246
break;
1023410247
}
1023510248
}
10236-
} else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
10249+
} else */
10250+
if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) {
1023710251
/* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */
1023810252
if (left_node.op_type == IS_CONST) {
1023910253
if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) {
@@ -12040,6 +12054,10 @@ static zend_op *zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t
1204012054

1204112055
bool zend_try_ct_eval_cast(zval *result, uint32_t type, zval *op1)
1204212056
{
12057+
/* NAN warns when casting */
12058+
if (UNEXPECTED(Z_TYPE_P(op1) == IS_DOUBLE && zend_isnan(Z_DVAL_P(op1)))) {
12059+
return false;
12060+
}
1204312061
switch (type) {
1204412062
case _IS_BOOL:
1204512063
ZVAL_BOOL(result, zval_is_true(op1));

Zend/zend_execute.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ static zend_always_inline void zend_cast_zval_to_object(zval *result, zval *expr
233233
}
234234
Z_OBJ_P(result)->properties = ht;
235235
} else if (Z_TYPE_P(expr) != IS_NULL) {
236+
if (UNEXPECTED(Z_TYPE_P(expr) == IS_DOUBLE && zend_isnan(Z_DVAL_P(expr)))) {
237+
zend_nan_coerced_to_type_warning(IS_OBJECT);
238+
}
236239
Z_OBJ_P(result)->properties = ht = zend_new_array(1);
237240
expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
238241
if (op1_type == IS_CONST) {
@@ -247,6 +250,9 @@ static zend_always_inline void zend_cast_zval_to_array(zval *result, zval *expr,
247250
extern zend_class_entry *zend_ce_closure;
248251
if (op1_type == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
249252
if (Z_TYPE_P(expr) != IS_NULL) {
253+
if (UNEXPECTED(Z_TYPE_P(expr) == IS_DOUBLE && zend_isnan(Z_DVAL_P(expr)))) {
254+
zend_nan_coerced_to_type_warning(IS_ARRAY);
255+
}
250256
ZVAL_ARR(result, zend_new_array(1));
251257
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
252258
if (op1_type == IS_CONST) {

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
+----------------------------------------------------------------------+
1717
*/
1818

19+
#include "../../../Zend/zend_portability.h"
1920
#include "Zend/zend_API.h"
2021

2122
static ZEND_COLD void undef_result_after_exception(void) {
@@ -2566,6 +2567,13 @@ static void ZEND_FASTCALL zend_jit_invalid_array_access(zval *container)
25662567
zend_error(E_WARNING, "Trying to access array offset on %s", zend_zval_value_name(container));
25672568
}
25682569

2570+
static void ZEND_FASTCALL zend_jit_check_nan_to_bool_coercion(double dval)
2571+
{
2572+
if (zend_isnan(dval)) {
2573+
zend_nan_coerced_to_type_warning(_IS_BOOL);
2574+
}
2575+
}
2576+
25692577
static void ZEND_FASTCALL zend_jit_invalid_property_read(zval *container, const char *property_name)
25702578
{
25712579
zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", property_name, zend_zval_value_name(container));

ext/opcache/jit/zend_jit_ir.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7728,7 +7728,11 @@ static int zend_jit_bool_jmpznz(zend_jit_ctx *jit, const zend_op *opline, uint32
77287728
if_double = ir_IF(ir_EQ(type, ir_CONST_U8(IS_DOUBLE)));
77297729
ir_IF_TRUE(if_double);
77307730
}
7731-
ref = ir_NE(jit_Z_DVAL(jit, op1_addr), ir_CONST_DOUBLE(0.0));
7731+
7732+
ir_ref dval = jit_Z_DVAL(jit, op1_addr);
7733+
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_check_nan_to_bool_coercion), dval);
7734+
7735+
ref = ir_NE(dval, ir_CONST_DOUBLE(0.0));
77327736
if (branch_opcode == ZEND_BOOL || branch_opcode == ZEND_BOOL_NOT) {
77337737
if (set_bool_not) {
77347738
jit_set_Z_TYPE_INFO_ref(jit, jit_ZVAL_ADDR(jit, res_addr),

0 commit comments

Comments
 (0)