Skip to content

Commit 3e84217

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0: JIT: Fix register clobbering
2 parents c8d10a8 + 7c674e1 commit 3e84217

File tree

2 files changed

+61
-21
lines changed

2 files changed

+61
-21
lines changed

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -763,17 +763,12 @@ static size_t tsrm_tls_offset;
763763
|| }
764764
|.endmacro
765765

766-
|.macro LONG_OP, long_ins, reg, addr
766+
|.macro LONG_OP, long_ins, reg, addr, tmp_reg
767767
|| if (Z_MODE(addr) == IS_CONST_ZVAL) {
768768
| .if X64
769769
|| if (!IS_SIGNED_32BIT(Z_LVAL_P(Z_ZV(addr)))) {
770-
|| if (reg != ZREG_R0) {
771-
| mov64 r0, Z_LVAL_P(Z_ZV(addr))
772-
| long_ins Ra(reg), r0
773-
|| } else {
774-
| mov64 r1, Z_LVAL_P(Z_ZV(addr))
775-
| long_ins Ra(reg), r1
776-
|| }
770+
| mov64 tmp_reg, Z_LVAL_P(Z_ZV(addr))
771+
| long_ins Ra(reg), tmp_reg
777772
|| } else {
778773
| long_ins Ra(reg), Z_LVAL_P(Z_ZV(addr))
779774
|| }
@@ -853,25 +848,25 @@ static size_t tsrm_tls_offset;
853848
|| }
854849
|.endmacro
855850

856-
|.macro LONG_MATH, opcode, reg, addr
851+
|.macro LONG_MATH, opcode, reg, addr, tmp_reg
857852
|| switch (opcode) {
858853
|| case ZEND_ADD:
859-
| LONG_OP add, reg, addr
854+
| LONG_OP add, reg, addr, Ra(tmp_reg)
860855
|| break;
861856
|| case ZEND_SUB:
862-
| LONG_OP sub, reg, addr
857+
| LONG_OP sub, reg, addr, Ra(tmp_reg)
863858
|| break;
864859
|| case ZEND_MUL:
865-
| LONG_OP imul, reg, addr
860+
| LONG_OP imul, reg, addr, Ra(tmp_reg)
866861
|| break;
867862
|| case ZEND_BW_OR:
868-
| LONG_OP or, reg, addr
863+
| LONG_OP or, reg, addr, Ra(tmp_reg)
869864
|| break;
870865
|| case ZEND_BW_AND:
871-
| LONG_OP and, reg, addr
866+
| LONG_OP and, reg, addr, Ra(tmp_reg)
872867
|| break;
873868
|| case ZEND_BW_XOR:
874-
| LONG_OP xor, reg, addr
869+
| LONG_OP xor, reg, addr, Ra(tmp_reg)
875870
|| break;
876871
|| default:
877872
|| ZEND_UNREACHABLE();
@@ -4423,7 +4418,16 @@ static int zend_jit_math_long_long(dasm_State **Dst,
44234418
} else if (same_ops && opcode != ZEND_DIV) {
44244419
| LONG_MATH_REG opcode, Ra(result_reg), Ra(result_reg)
44254420
} else {
4426-
| LONG_MATH opcode, result_reg, op2_addr
4421+
zend_reg tmp_reg;
4422+
4423+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) {
4424+
tmp_reg = ZREG_R1;
4425+
} else if (result_reg != ZREG_R0) {
4426+
tmp_reg = ZREG_R0;
4427+
} else {
4428+
tmp_reg = ZREG_R1;
4429+
}
4430+
| LONG_MATH opcode, result_reg, op2_addr, tmp_reg
44274431
}
44284432
}
44294433
if (may_overflow) {
@@ -5174,12 +5178,20 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51745178
} else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->min >= 0) {
51755179
zval tmp;
51765180
zend_jit_addr tmp_addr;
5181+
zend_reg tmp_reg;
51775182

51785183
/* Optimisation for mod of power of 2 */
51795184
ZVAL_LONG(&tmp, op2_lval - 1);
51805185
tmp_addr = ZEND_ADDR_CONST_ZVAL(&tmp);
5186+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) {
5187+
tmp_reg = ZREG_R1;
5188+
} else if (result_reg != ZREG_R0) {
5189+
tmp_reg = ZREG_R0;
5190+
} else {
5191+
tmp_reg = ZREG_R1;
5192+
}
51815193
| GET_ZVAL_LVAL result_reg, op1_addr
5182-
| LONG_MATH ZEND_BW_AND, result_reg, tmp_addr
5194+
| LONG_MATH ZEND_BW_AND, result_reg, tmp_addr, tmp_reg
51835195
} else {
51845196
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
51855197
| mov aword T1, r0 // save
@@ -5267,8 +5279,17 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
52675279
| GET_ZVAL_LVAL result_reg, op1_addr
52685280
| LONG_MATH_REG opcode, Ra(result_reg), Ra(result_reg)
52695281
} else {
5282+
zend_reg tmp_reg;
5283+
5284+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_R0) {
5285+
tmp_reg = ZREG_R1;
5286+
} else if (result_reg != ZREG_R0) {
5287+
tmp_reg = ZREG_R0;
5288+
} else {
5289+
tmp_reg = ZREG_R1;
5290+
}
52705291
| GET_ZVAL_LVAL result_reg, op1_addr
5271-
| LONG_MATH opcode, result_reg, op2_addr
5292+
| LONG_MATH opcode, result_reg, op2_addr, tmp_reg
52725293
}
52735294

52745295
if (Z_MODE(res_addr) != IS_REG || Z_REG(res_addr) != result_reg) {
@@ -7047,13 +7068,13 @@ static int zend_jit_cmp_long_long(dasm_State **Dst,
70477068
if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 0) {
70487069
| test Ra(Z_REG(op1_addr)), Ra(Z_REG(op1_addr))
70497070
} else {
7050-
| LONG_OP cmp, Z_REG(op1_addr), op2_addr
7071+
| LONG_OP cmp, Z_REG(op1_addr), op2_addr, r0
70517072
}
70527073
} else if (Z_MODE(op2_addr) == IS_REG) {
70537074
if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op1_addr)) == 0) {
70547075
| test Ra(Z_REG(op2_addr)), Ra(Z_REG(op2_addr))
70557076
} else {
7056-
| LONG_OP cmp, Z_REG(op2_addr), op1_addr
7077+
| LONG_OP cmp, Z_REG(op2_addr), op1_addr, r0
70577078
}
70587079
swap = 1;
70597080
} else if (Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_MODE(op2_addr) != IS_CONST_ZVAL) {
@@ -7066,7 +7087,7 @@ static int zend_jit_cmp_long_long(dasm_State **Dst,
70667087
if (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 0) {
70677088
| test r0, r0
70687089
} else {
7069-
| LONG_OP cmp, ZREG_R0, op2_addr
7090+
| LONG_OP cmp, ZREG_R0, op2_addr, r0
70707091
}
70717092
}
70727093

ext/opcache/tests/jit/add_012.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
JIT ADD: 012 register allocation for 64-bit constant
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
--SKIPIF--
9+
<?php if (PHP_INT_SIZE != 8) die("skip: 64-bit only"); ?>
10+
--FILE--
11+
<?php
12+
$x = 0;
13+
$y = [0];
14+
$y[$x]++;
15+
$y[$x] += 4467793343;
16+
?>
17+
DONE
18+
--EXPECT--
19+
DONE

0 commit comments

Comments
 (0)