Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -2432,6 +2432,20 @@ static inline uint32_t zend_emit_cond_jump(uint8_t opcode, znode *cond, uint32_t
}
/* }}} */

/* Compile `!` in a condition as an inverted jump instead of a BOOL_NOT
* opcode followed by a jump. Both evaluate the operand with the same
* boolean semantics, and removing the intermediate temporary also lets
* comparisons fuse with the jump (smart branch). */
static zend_ast *zend_unwrap_bool_not(zend_ast *cond_ast, uint8_t *jump_opcode) /* {{{ */
{
while (cond_ast->kind == ZEND_AST_UNARY_OP && cond_ast->attr == ZEND_BOOL_NOT) {
*jump_opcode = (*jump_opcode == ZEND_JMPZ) ? ZEND_JMPNZ : ZEND_JMPZ;
cond_ast = cond_ast->child[0];
}
return cond_ast;
}
/* }}} */

static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
{
zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
Expand Down Expand Up @@ -6448,9 +6462,11 @@ static void zend_compile_while(const zend_ast *ast) /* {{{ */

opnum_cond = get_next_op_number();
zend_update_jump_target(opnum_jmp, opnum_cond);
uint8_t jump_opcode = ZEND_JMPNZ;
cond_ast = zend_unwrap_bool_not(cond_ast, &jump_opcode);
zend_compile_expr(&cond_node, cond_ast);

zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
zend_emit_cond_jump(jump_opcode, &cond_node, opnum_start);

zend_end_loop(opnum_cond, NULL);
}
Expand All @@ -6470,9 +6486,11 @@ static void zend_compile_do_while(const zend_ast *ast) /* {{{ */
zend_compile_stmt(stmt_ast);

opnum_cond = get_next_op_number();
uint8_t jump_opcode = ZEND_JMPNZ;
cond_ast = zend_unwrap_bool_not(cond_ast, &jump_opcode);
zend_compile_expr(&cond_node, cond_ast);

zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
zend_emit_cond_jump(jump_opcode, &cond_node, opnum_start);

zend_end_loop(opnum_cond, NULL);
}
Expand Down Expand Up @@ -6661,8 +6679,10 @@ static void zend_compile_if(zend_ast *ast) /* {{{ */
zend_do_extended_stmt(NULL);
}

uint8_t jump_opcode = ZEND_JMPZ;
cond_ast = zend_unwrap_bool_not(cond_ast, &jump_opcode);
zend_compile_expr(&cond_node, cond_ast);
opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
opnum_jmpz = zend_emit_cond_jump(jump_opcode, &cond_node, 0);

zend_compile_stmt(stmt_ast);

Expand Down Expand Up @@ -11128,9 +11148,11 @@ static void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
return;
}

uint8_t jump_opcode = ZEND_JMPZ;
cond_ast = zend_unwrap_bool_not(cond_ast, &jump_opcode);
zend_compile_expr(&cond_node, cond_ast);

opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
opnum_jmpz = zend_emit_cond_jump(jump_opcode, &cond_node, 0);

zend_compile_expr(&true_node, true_ast);

Expand Down
10 changes: 5 additions & 5 deletions ext/opcache/tests/opt/gh18107_1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ $_main:
; %s
0000 T1 = ISSET_ISEMPTY_CV (isset) CV0($badvar)
0001 JMPNZ T1 0006
0002 T3 = NEW 1 string("Exception")
0002 T2 = NEW 1 string("Exception")
0003 SEND_VAL%S string("Should happen") 1
0004 DO_FCALL
0005 THROW T3
0005 THROW T2
0006 JMP 0006
0007 T6 = NEW 1 string("Exception")
0007 T5 = NEW 1 string("Exception")
0008 SEND_VAL%S string("Should not happen") 1
0009 DO_FCALL
0010 THROW T6
0011 FAST_RET T5
0010 THROW T5
0011 FAST_RET T4
EXCEPTION TABLE:
0006, -, 0007, 0011

Expand Down
12 changes: 6 additions & 6 deletions ext/opcache/tests/opt/gh18107_2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ $_main:
; %s
0000 T2 = ISSET_ISEMPTY_CV (isset) CV0($badvar)
0001 JMPNZ T2 0008
0002 T4 = NEW 1 string("Exception")
0002 T3 = NEW 1 string("Exception")
0003 SEND_VAL%S string("Should happen") 1
0004 DO_FCALL
0005 THROW T4
0005 THROW T3
0006 CV1($e) = CATCH string("Throwable")
0007 ECHO string("foo")
0008 T6 = FAST_CALL 0010
0008 T5 = FAST_CALL 0010
0009 JMP 0015
0010 T7 = NEW 1 string("Exception")
0010 T6 = NEW 1 string("Exception")
0011 SEND_VAL%S string("Should not happen") 1
0012 DO_FCALL
0013 THROW T7
0014 FAST_RET T6
0013 THROW T6
0014 FAST_RET T5
0015 RETURN int(1)
EXCEPTION TABLE:
0006, 0006, 0010, 0014
Expand Down
Loading