Skip to content

Commit e2710a2

Browse files
committed
Merge branch 'PHP-8.6'
* PHP-8.6: Update IR (#24013)
2 parents 111e785 + e16872c commit e2710a2

7 files changed

Lines changed: 118 additions & 48 deletions

File tree

‎.github/scripts/download-bundled/jit-ir.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cd "$(dirname "$0")/../../.."
55
tmp_dir=/tmp/php-src-download-bundled/jit-ir
66
rm -rf "$tmp_dir"
77

8-
revision=00bec1ca490b8bc51f636a42040c5e9f64c1a91b
8+
revision=93f92f5b5a49a02295685e340ebb0b83562cbe79
99

1010
git clone --depth 1 --revision="$revision" https://github.com/dstogov/ir.git "$tmp_dir"
1111

‎ext/opcache/jit/ir/ir_emit.c‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,9 @@ static ir_reg _get_free_reg2(ir_ctx *ctx, ir_type type, ir_reg_alloc_simple_data
15281528

15291529
reg = IR_REGSET_FIRST(available);
15301530
if (IR_REGSET_IN(x->preserved_regs, reg)) {
1531-
IR_REGSET_INCL(ctx->used_preserved_regs, reg);
1531+
ir_regset tmp = ctx->used_preserved_regs;
1532+
IR_REGSET_INCL(tmp, reg);
1533+
ctx->used_preserved_regs = tmp;
15321534
}
15331535
return reg;
15341536
}

‎ext/opcache/jit/ir/ir_fold.h‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,8 +1840,7 @@ IR_FOLD(REPLACE(LONG_CONST, _))
18401840
if (IR_IS_CONST_REF(op3)
18411841
&& IR_IS_CONST_REF(op2)
18421842
&& IR_IS_TYPE_INT(op2_insn->type)
1843-
&& op2_insn->val.i64 >= 0
1844-
&& op2_insn->val.i64 < IR_VECTOR_LENGTH(op1_insn->type)) {
1843+
&& op2_insn->val.u64 < (uint64_t)IR_VECTOR_LENGTH(op1_insn->type)) {
18451844
IR_ASSERT(IR_IS_TYPE_VECTOR(op1_insn->type)
18461845
&& (IR_VECTOR_BASE_TYPE(op1_insn->type) == op3_insn->type
18471846
|| (IR_IS_TYPE_INT(IR_VECTOR_BASE_TYPE(op1_insn->type))
@@ -1942,8 +1941,7 @@ IR_FOLD(EXTRACT(LONG_CONST, _))
19421941
{
19431942
if (IR_IS_CONST_REF(op2)
19441943
&& IR_IS_TYPE_INT(op2_insn->type)
1945-
&& op2_insn->val.i64 >= 0
1946-
&& op2_insn->val.i64 < IR_VECTOR_LENGTH(op1_insn->type)) {
1944+
&& op2_insn->val.u64 < (uint64_t)IR_VECTOR_LENGTH(op1_insn->type)) {
19471945
uint32_t idx = op2_insn->val.u32;
19481946
void *ptr;
19491947

@@ -3212,7 +3210,7 @@ IR_FOLD(LT(ABS, C_FLOAT))
32123210
IR_FOLD(LT(ABS, C_DOUBLE))
32133211
{
32143212
if (op2_insn->val.u64 == 0) {
3215-
/* abs() < 0 => false */
3213+
/* abs() < 0 => false (abs(INT_MIN) is UB, so this optimization may change the result) */
32163214
IR_FOLD_COPY(IR_FALSE);
32173215
}
32183216
IR_FOLD_NEXT;
@@ -3226,7 +3224,7 @@ IR_FOLD(GE(ABS, C_FLOAT))
32263224
IR_FOLD(GE(ABS, C_DOUBLE))
32273225
{
32283226
if (op2_insn->val.u64 == 0) {
3229-
/* abs() >= 0 => true */
3227+
/* abs() >= 0 => true (abs(INT_MIN) is UB, so this optimization may change the result) */
32303228
IR_FOLD_COPY(IR_TRUE);
32313229
}
32323230
IR_FOLD_NEXT;

‎ext/opcache/jit/ir/ir_private.h‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,24 +1273,29 @@ typedef struct _ir_use_pos ir_use_pos;
12731273
#define IR_USE_MUST_BE_IN_REG (1<<0)
12741274
#define IR_USE_SHOULD_BE_IN_REG (1<<1)
12751275
#define IR_HINT_TWO_REGS (1<<2)
1276+
#define IR_HINT_NEEDS_HOLE (1<<3) /* create a fake hole in live ranges to avoid conflict with fxed reg */
1277+
12761278
#define IR_DEF_REUSES_OP1_REG (1<<3)
12771279
#define IR_DEF_CONFLICTS_WITH_INPUT_REGS (1<<4)
12781280
#define IR_EXTEND_INPUTS_TO_NEXT (1<<5) /* used for SNAPSHOT followed by GUARD */
12791281

12801282
#define IR_FUSED_USE (1<<6)
12811283
#define IR_PHI_USE (1<<7)
12821284

1283-
#define IR_OP1_MUST_BE_IN_REG (1<<8)
1284-
#define IR_OP1_SHOULD_BE_IN_REG (1<<9)
1285-
#define IR_OP1_HINT_TWO_REGS (1<<10)
1286-
#define IR_OP2_MUST_BE_IN_REG (1<<11)
1287-
#define IR_OP2_SHOULD_BE_IN_REG (1<<12)
1288-
#define IR_OP2_HINT_TWO_REGS (1<<13)
1289-
#define IR_OP3_MUST_BE_IN_REG (1<<14)
1290-
#define IR_OP3_SHOULD_BE_IN_REG (1<<15)
1291-
#define IR_OP3_HINT_TWO_REGS (1<<16)
1292-
1293-
#define IR_USE_FLAGS(def_flags, op_num) (((def_flags) >> (5 + (IR_MIN((op_num), 3) * 3))) & 7)
1285+
#define IR_OP1_MUST_BE_IN_REG (1<<16)
1286+
#define IR_OP1_SHOULD_BE_IN_REG (1<<17)
1287+
#define IR_OP1_HINT_TWO_REGS (1<<18)
1288+
#define IR_OP1_HINT_NEEDS_HOLE (1<<19)
1289+
#define IR_OP2_MUST_BE_IN_REG (1<<20)
1290+
#define IR_OP2_SHOULD_BE_IN_REG (1<<21)
1291+
#define IR_OP2_HINT_TWO_REGS (1<<22)
1292+
#define IR_OP2_HINT_NEEDS_HOLE (1<<23)
1293+
#define IR_OP3_MUST_BE_IN_REG (1<<24)
1294+
#define IR_OP3_SHOULD_BE_IN_REG (1<<25)
1295+
#define IR_OP3_HINT_TWO_REGS (1<<26)
1296+
#define IR_OP3_HINT_NEEDS_HOLE (1<<27)
1297+
1298+
#define IR_USE_FLAGS(def_flags, op_num) (((def_flags) >> (12 + (IR_MIN((op_num), 3) * 4))) & 15)
12941299

12951300
struct _ir_use_pos {
12961301
uint16_t op_num; /* 0 - means result */

‎ext/opcache/jit/ir/ir_ra.c‎

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,10 @@ static void ir_add_fusion_ranges(ir_ctx *ctx, ir_ref ref, ir_ref input, ir_block
564564
/* intervals[opd].addRange(b.from, op.id) */
565565
ival = ir_add_live_range(ctx, v,
566566
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
567+
} else if (reg != IR_REG_NONE && (IR_USE_FLAGS(def_flags, j) & IR_HINT_NEEDS_HOLE)) {
568+
ir_fix_live_range(ctx, v,
569+
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos + IR_DEF_SUB_REF);
570+
ival = ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
567571
} else {
568572
ival = ctx->live_intervals[v];
569573
}
@@ -692,14 +696,15 @@ int ir_compute_live_ranges(ir_ctx *ctx)
692696
if (input > 0) {
693697
uint32_t v = ctx->vregs[input];
694698

695-
/* live.add(phi.inputOf(b)) */
696-
IR_ASSERT(v);
697-
ir_bitset_incl(live, v);
698-
/* intervals[phi.inputOf(b)].addRange(b.from, b.to) */
699-
ival = ir_add_prev_live_range(ctx, v,
700-
IR_START_LIVE_POS_FROM_REF(bb->start),
701-
IR_END_LIVE_POS_FROM_REF(bb->end));
702-
ir_add_phi_use(ctx, ival, k, IR_DEF_LIVE_POS_FROM_REF(bb->end), use);
699+
if (v) {
700+
/* live.add(phi.inputOf(b)) */
701+
ir_bitset_incl(live, v);
702+
/* intervals[phi.inputOf(b)].addRange(b.from, b.to) */
703+
ival = ir_add_prev_live_range(ctx, v,
704+
IR_START_LIVE_POS_FROM_REF(bb->start),
705+
IR_END_LIVE_POS_FROM_REF(bb->end));
706+
ir_add_phi_use(ctx, ival, k, IR_DEF_LIVE_POS_FROM_REF(bb->end), use);
707+
}
703708
}
704709
}
705710
}
@@ -766,8 +771,6 @@ int ir_compute_live_ranges(ir_ctx *ctx)
766771
insn = &ctx->ir_base[ref];
767772
v = ctx->vregs[ref];
768773
if (v) {
769-
IR_ASSERT(ir_bitset_in(live, v));
770-
771774
if (insn->op != IR_PHI) {
772775
ir_live_pos def_pos;
773776
ir_ref hint_ref = 0;
@@ -878,6 +881,17 @@ int ir_compute_live_ranges(ir_ctx *ctx)
878881
} else
879882
#endif
880883
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
884+
if ((use_flags & IR_HINT_NEEDS_HOLE) && ir_bitset_in(live, v)) {
885+
/* This is a special case for x86 SHIFT instructions that uses %rcx for op2.
886+
* SHIFT adds short fixed live range for %rcx and this makes a conflict with
887+
* operand live interval, if the operand is still alive after the SHIFT.
888+
* To avoid the conflict we create a "fake" hole in the operand live interval.
889+
* See: ./tests/debug/ra_004.irt
890+
*/
891+
ir_fix_live_range(ctx, v,
892+
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos + IR_DEF_SUB_REF);
893+
ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
894+
}
881895
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
882896
if (j == 1) {
883897
use_pos = IR_LOAD_LIVE_POS_FROM_REF(ref);
@@ -1286,6 +1300,10 @@ static void ir_add_fusion_ranges(ir_ctx *ctx, ir_ref ref, ir_ref input, ir_block
12861300
/* intervals[opd].addRange(b.from, op.id) */
12871301
ival = ir_add_live_range(ctx, v,
12881302
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
1303+
} else if (reg != IR_REG_NONE && (IR_USE_FLAGS(def_flags, j) & IR_HINT_NEEDS_HOLE)) {
1304+
ir_fix_live_range(ctx, v,
1305+
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos + IR_DEF_SUB_REF);
1306+
ival = ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
12891307
} else {
12901308
ival = ctx->live_intervals[v];
12911309
}
@@ -1559,6 +1577,17 @@ int ir_compute_live_ranges(ir_ctx *ctx)
15591577
} else
15601578
#endif
15611579
ir_add_fixed_live_range(ctx, reg, use_pos, use_pos + IR_USE_SUB_REF);
1580+
if ((use_flags & IR_HINT_NEEDS_HOLE) && IS_LIVE_IN_BLOCK(v, b)) {
1581+
/* This is a special case for x86 SHIFT instructions that uses %rcx for op2.
1582+
* SHIFT adds short fixed live range for %rcx and this makes a conflict with
1583+
* operand live interval, if the operand is still alive after the SHIFT.
1584+
* To avoid the conflict we create a "fake" hole in the operand live interval.
1585+
* See: ./tests/debug/ra_004.irt
1586+
*/
1587+
ir_fix_live_range(ctx, v,
1588+
IR_START_LIVE_POS_FROM_REF(bb->start), use_pos + IR_DEF_SUB_REF);
1589+
ir_add_live_range(ctx, v, IR_START_LIVE_POS_FROM_REF(bb->start), use_pos);
1590+
}
15621591
} else if (def_flags & IR_DEF_REUSES_OP1_REG) {
15631592
if (j == 1) {
15641593
if (def_flags & IR_DEF_CONFLICTS_WITH_INPUT_REGS) {

‎ext/opcache/jit/ir/ir_sccp.c‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,20 @@ static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn)
24512451
&& ir_is_loop_invariant(ctx, insn->op1, ctx->ir_base[insn->op2].op1)) {
24522452
return ir_try_promote_induction_var_ext(ctx, ext_ref, insn->op2, ref);
24532453
}
2454+
} else if (insn->op == IR_COND
2455+
&& IR_IS_CONST_REF(insn->op2)
2456+
&& IR_IS_CONST_REF(insn->op3)
2457+
&& ctx->use_lists[ref].count == 1) {
2458+
IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op));
2459+
IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op3].op));
2460+
2461+
ir_op op = ctx->ir_base[ext_ref].op;
2462+
ir_type type = ctx->ir_base[ext_ref].type;
2463+
2464+
insn->type = type;
2465+
insn->op2 = ir_ext_const(ctx, &ctx->ir_base[insn->op2], op, type);;
2466+
insn->op3 = ir_ext_const(ctx, &ctx->ir_base[insn->op3], op, type);;
2467+
ir_iter_replace_insn(ctx, ext_ref, ref);
24542468
}
24552469

24562470
return 0;
@@ -2837,6 +2851,8 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
28372851
MAKE_NOP(end2); CLEAR_USES(end2_ref);
28382852
MAKE_NOP(merge); CLEAR_USES(merge_ref);
28392853

2854+
ir_bitqueue_add(ctx->iter_worklist, ref);
2855+
ir_iter_add_uses(ctx, ref, ctx->iter_worklist);
28402856
if (ctx->ir_base[next->op1].op == IR_BEGIN || ctx->ir_base[next->op1].op == IR_MERGE) {
28412857
ir_bitqueue_add(ctx->iter_worklist, next->op1);
28422858
}
@@ -2928,6 +2944,8 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
29282944
MAKE_NOP(merge); CLEAR_USES(merge_ref);
29292945
MAKE_NOP(&ctx->ir_base[neg_ref]); CLEAR_USES(neg_ref);
29302946

2947+
ir_bitqueue_add(ctx->iter_worklist, ref);
2948+
ir_iter_add_uses(ctx, ref, ctx->iter_worklist);
29312949
if (ctx->ir_base[next->op1].op == IR_BEGIN || ctx->ir_base[next->op1].op == IR_MERGE) {
29322950
ir_bitqueue_add(ctx->iter_worklist, next->op1);
29332951
}
@@ -2997,6 +3015,7 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
29973015
MAKE_NOP(merge); CLEAR_USES(merge_ref);
29983016

29993017
ir_bitqueue_add(ctx->iter_worklist, ref);
3018+
ir_iter_add_uses(ctx, ref, ctx->iter_worklist);
30003019
if (ctx->ir_base[next->op1].op == IR_BEGIN || ctx->ir_base[next->op1].op == IR_MERGE) {
30013020
ir_bitqueue_add(ctx->iter_worklist, next->op1);
30023021
}

‎ext/opcache/jit/ir/ir_x86.dasc‎

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,11 @@ IR_ALWAYS_INLINE ir_mem IR_MEM(ir_reg base, int32_t offset, ir_reg index, int32_
685685
|| }
686686
|.endmacro
687687

688+
/* Zero a register. A 32-bit xor has a shorter encoding and also clears the upper 32 bits. */
689+
|.macro ASM_REG_ZERO, type, reg
690+
| xor Rd(reg), Rd(reg)
691+
|.endmacro
692+
688693
|.macro ASM_REG_REG_OP2, op, type, op1, op2
689694
|| switch (ir_type_size[type]) {
690695
|| default:
@@ -1851,9 +1856,10 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
18511856
break;
18521857
case IR_SHIFT:
18531858
if (rule & IR_FUSED) {
1854-
flags = IR_OP2_MUST_BE_IN_REG;
1859+
flags = IR_OP2_MUST_BE_IN_REG | IR_OP2_HINT_NEEDS_HOLE;
18551860
} else {
1856-
flags = IR_DEF_REUSES_OP1_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
1861+
flags = IR_DEF_REUSES_OP1_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG |
1862+
IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG | IR_OP2_HINT_NEEDS_HOLE;
18571863
}
18581864
constraints->hints[1] = IR_REG_NONE;
18591865
constraints->hints[2] = IR_REG_RCX;
@@ -3268,6 +3274,15 @@ static bool ir_match_has_flags_deps(ir_ctx *ctx, ir_ref ref, ir_ref root)
32683274
return pos != ref;
32693275
}
32703276

3277+
static uint32_t ir_match_fuse_load_const_addr(ir_ctx *ctx, ir_ref ref, const ir_insn *addr_insn)
3278+
{
3279+
if (ir_may_fuse_addr(ctx, addr_insn)) {
3280+
return IR_FUSED | IR_SIMPLE | IR_LOAD;
3281+
}
3282+
/* The address doesn't fit into the displacement. Load it into a temporary register. */
3283+
return IR_FUSED | (IR_IS_TYPE_INT(ctx->ir_base[ref].type) ? IR_LOAD_INT : IR_LOAD_FP);
3284+
}
3285+
32713286
static void ir_match_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
32723287
{
32733288
if (ir_in_same_block(ctx, ref) &&
@@ -3279,10 +3294,8 @@ static void ir_match_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
32793294
ir_insn *addr_insn = &ctx->ir_base[addr_ref];
32803295

32813296
if (IR_IS_CONST_REF(addr_ref)) {
3282-
if (ir_may_fuse_addr(ctx, addr_insn)) {
3283-
ctx->rules[ref] = IR_FUSED | IR_SIMPLE | IR_LOAD;
3284-
return;
3285-
}
3297+
ctx->rules[ref] = ir_match_fuse_load_const_addr(ctx, ref, addr_insn);
3298+
return;
32863299
} else if (addr_insn->op == IR_TLS_ADDR) {
32873300
// TODO: try to fuse static TLS addr ???
32883301
return;
@@ -3307,10 +3320,8 @@ static bool ir_match_try_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
33073320
ir_insn *addr_insn = &ctx->ir_base[addr_ref];
33083321

33093322
if (IR_IS_CONST_REF(addr_ref)) {
3310-
if (ir_may_fuse_addr(ctx, addr_insn)) {
3311-
ctx->rules[ref] = IR_FUSED | IR_SIMPLE | IR_LOAD;
3312-
return 1;
3313-
}
3323+
ctx->rules[ref] = ir_match_fuse_load_const_addr(ctx, ref, addr_insn);
3324+
return 1;
33143325
} else if (addr_insn->op == IR_TLS_ADDR) {
33153326
// TODO: try to fuse static TLS addr ???
33163327
return 0;
@@ -5348,7 +5359,11 @@ static void ir_match_insn2(ir_ctx *ctx, ir_ref ref, uint32_t rule)
53485359
if (rule == IR_LEA_IB) {
53495360
if (!ir_match_try_revert_lea_to_add(ctx, ref) && !(ctx->flags & IR_OPT_CODEGEN)) {
53505361
/* revert to ADD to avoid extra register spill load with -O0 */
5351-
ctx->rules[ref] = IR_BINOP_INT | IR_MAY_SWAP;
5362+
ir_insn *insn = &ctx->ir_base[ref];
5363+
5364+
if (ctx->ir_base[insn->op1].op != IR_ALLOCA && ctx->ir_base[insn->op2].op != IR_ALLOCA) {
5365+
ctx->rules[ref] = IR_BINOP_INT | IR_MAY_SWAP;
5366+
}
53525367
}
53535368
}
53545369
}
@@ -5458,7 +5473,7 @@ static void ir_emit_load_imm_int(ir_ctx *ctx, ir_type type, ir_reg reg, int64_t
54585473

54595474
IR_ASSERT(IR_IS_TYPE_INT(type));
54605475
if (val == 0) {
5461-
| ASM_REG_REG_OP xor, type, reg, reg
5476+
| ASM_REG_ZERO type, reg
54625477
} else {
54635478
ir_emit_mov_imm_int(ctx, type, reg, val);
54645479
}
@@ -8234,7 +8249,7 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn)
82348249
if (ir_type_size[type] == 1) {
82358250
| movzx ax, al
82368251
} else {
8237-
| ASM_REG_REG_OP xor, type, IR_REG_RDX, IR_REG_RDX
8252+
| ASM_REG_ZERO type, IR_REG_RDX
82388253
}
82398254
if (op2_reg != IR_REG_NONE) {
82408255
| ASM_REG_OP div, type, op2_reg
@@ -8801,7 +8816,7 @@ static void ir_emit_cmp_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
88018816
if (IR_IS_CONST_REF(op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2].op) && ctx->ir_base[op2].val.u64 == 0) {
88028817
if (op == IR_ULT) {
88038818
/* always false */
8804-
| xor Ra(def_reg), Ra(def_reg)
8819+
| xor Rd(def_reg), Rd(def_reg)
88058820
if (IR_REG_SPILLED(ctx->regs[def][0])) {
88068821
ir_emit_store(ctx, insn->type, def, def_reg);
88078822
}
@@ -14572,7 +14587,7 @@ static void ir_emit_cmp_i64(ir_ctx *ctx, ir_ref def, ir_insn *insn)
1457214587
if (IR_IS_CONST_REF(op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2].op) && ctx->ir_base[op2].val.u64 == 0) {
1457314588
if (op == IR_ULT) {
1457414589
/* always false */
14575-
| xor Ra(def_reg), Ra(def_reg)
14590+
| xor Rd(def_reg), Rd(def_reg)
1457614591
if (IR_REG_SPILLED(ctx->regs[def][0])) {
1457714592
ir_emit_store(ctx, insn->type, def, def_reg);
1457814593
}
@@ -22205,7 +22220,7 @@ static void ir_emit_vector_binop_expand(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2220522220
} else if (element_size == 1) {
2220622221
| movzx ax, al
2220722222
} else {
22208-
| ASM_REG_REG_OP xor, element_type, IR_REG_RDX, IR_REG_RDX
22223+
| ASM_REG_ZERO element_type, IR_REG_RDX
2220922224
}
2221022225
if (IR_IS_TYPE_SIGNED(element_type)) {
2221122226
| ASM_REG_OP idiv, element_type, tmp2_reg
@@ -22652,7 +22667,7 @@ static void ir_emit_vector_binop_expand(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2265222667
} else if (element_size == 1) {
2265322668
| movzx ax, al
2265422669
} else {
22655-
| ASM_REG_REG_OP xor, element_type, IR_REG_RDX, IR_REG_RDX
22670+
| ASM_REG_ZERO element_type, IR_REG_RDX
2265622671
}
2265722672
if (IR_IS_TYPE_SIGNED(element_type)) {
2265822673
| ASM_MEM_OP idiv, element_type, mem
@@ -25988,8 +26003,10 @@ void ir_fix_stack_frame(ir_ctx *ctx)
2598826003

2598926004
#ifdef IR_TARGET_X86
2599026005
if (ctx->flags2 & IR_HAS_MEMCPY) {
25991-
IR_REGSET_INCL(ctx->used_preserved_regs, IR_REG_RSI);
25992-
IR_REGSET_INCL(ctx->used_preserved_regs, IR_REG_RDI);
26006+
ir_regset tmp = ctx->used_preserved_regs;
26007+
IR_REGSET_INCL(tmp, IR_REG_RSI);
26008+
IR_REGSET_INCL(tmp, IR_REG_RDI);
26009+
ctx->used_preserved_regs = tmp;
2599326010
}
2599426011
#endif
2599526012

0 commit comments

Comments
 (0)