[php-src] master: Update IR

From: Date: Thu, 14 Mar 2024 19:37:13 +0000
Subject: [php-src] master: Update IR
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-127735@lists.php.net to get a copy of this message
Author: Dmitry Stogov (dstogov) Date: 2024-03-14T22:23:05+03:00 Commit: https://github.com/php/php-src/commit/586153b9ef85d63d722e0017b7509fb0e893482e Raw diff: https://github.com/php/php-src/commit/586153b9ef85d63d722e0017b7509fb0e893482e.diff Update IR IR commit: 2c5b63d4b89b25a323444f6629e6d7c9e9d17300 Changed paths: M ext/opcache/jit/ir/gen_ir_fold_hash.c M ext/opcache/jit/ir/ir.h M ext/opcache/jit/ir/ir_aarch64.dasc M ext/opcache/jit/ir/ir_cfg.c M ext/opcache/jit/ir/ir_private.h M ext/opcache/jit/ir/ir_ra.c M ext/opcache/jit/ir/ir_x86.dasc Diff: diff --git a/ext/opcache/jit/ir/gen_ir_fold_hash.c b/ext/opcache/jit/ir/gen_ir_fold_hash.c index efd656f5b7a5..535714094667 100644 --- a/ext/opcache/jit/ir/gen_ir_fold_hash.c +++ b/ext/opcache/jit/ir/gen_ir_fold_hash.c @@ -25,10 +25,11 @@ void print_hash(uint32_t *mask, uint32_t count) { uint32_t i; - printf("static const uint32_t _ir_fold_hash[%d] = {\n", count); + printf("static const uint32_t _ir_fold_hash[%d] = {\n", count + 1); for (i = 0; i < count; i++) { printf("\t0x%08x,\n", mask[i]); } + printf("\t0x%08x\n", 0); printf("};\n\n"); } diff --git a/ext/opcache/jit/ir/ir.h b/ext/opcache/jit/ir/ir.h index 89909952318d..14ebc942e6e4 100644 --- a/ext/opcache/jit/ir/ir.h +++ b/ext/opcache/jit/ir/ir.h @@ -36,6 +36,21 @@ extern "C" { # endif #endif +/* target auto detection */ +#if !defined(IR_TARGET_X86) && !defined(IR_TARGET_X64) && !defined(IR_TARGET_AARCH64) +# if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +# define IR_TARGET_X64 +# elif defined(i386) || defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define IR_TARGET_X86 +# elif defined(__aarch64__) || defined(_M_ARM64) +# define IR_TARGET_AARCH64 +# elif defined (_WIN64) +# define IR_TARGET_X64 +# elif defined (_WIN32) +# define IR_TARGET_X86 +# endif +#endif + #if defined(IR_TARGET_X86) # define IR_TARGET "x86" #elif defined(IR_TARGET_X64) diff --git a/ext/opcache/jit/ir/ir_aarch64.dasc b/ext/opcache/jit/ir/ir_aarch64.dasc index 08634a910150..faca8ed08813 100644 --- a/ext/opcache/jit/ir/ir_aarch64.dasc +++ b/ext/opcache/jit/ir/ir_aarch64.dasc @@ -11,6 +11,8 @@ |.globals ir_lb |.section code, cold_code, rodata, jmp_table +|.define IR_LOOP_ALIGNMENT, 8 + #ifdef IR_DEBUG typedef struct _ir_mem {uint64_t v;} ir_mem; @@ -5700,6 +5702,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) if ((bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_EMPTY)) == IR_BB_EMPTY) { continue; } + if (bb->flags & IR_BB_ALIGN_LOOP) { + | .align IR_LOOP_ALIGNMENT + } |=>b: i = bb->start; diff --git a/ext/opcache/jit/ir/ir_cfg.c b/ext/opcache/jit/ir/ir_cfg.c index 824cdb61c939..ce3dbeb26e50 100644 --- a/ext/opcache/jit/ir/ir_cfg.c +++ b/ext/opcache/jit/ir/ir_cfg.c @@ -2359,7 +2359,19 @@ static int ir_schedule_blocks_bottom_up(ir_ctx *ctx) #endif } - /* 5. Group chains according to the most frequent edge between them */ + /* 5. Align loop headers */ + for (b = 1; b <= ctx->cfg_blocks_count; b++) { + if (chains[b].head == b) { + bb = &ctx->cfg_blocks[b]; + if (bb->loop_depth) { + if ((bb->flags & IR_BB_LOOP_HEADER) || ir_chain_head(chains, bb->loop_header) == b) { + bb->flags |= IR_BB_ALIGN_LOOP; + } + } + } + } + + /* 6. Group chains according to the most frequent edge between them */ // TODO: Try to find a better heuristic for (e = edges, i = edges_count; i > 0; e++, i--) { #if !IR_DEBUG_BB_SCHEDULE_GRAPH @@ -2380,7 +2392,7 @@ static int ir_schedule_blocks_bottom_up(ir_ctx *ctx) ir_dump_chains(ctx, chains); #endif - /* 6. Form a final BB order */ + /* 7. Form a final BB order */ count = 0; for (b = 1; b <= ctx->cfg_blocks_count; b++) { if (chains[b].head == b) { diff --git a/ext/opcache/jit/ir/ir_private.h b/ext/opcache/jit/ir/ir_private.h index 71a6400c6444..414cefe0e85c 100644 --- a/ext/opcache/jit/ir/ir_private.h +++ b/ext/opcache/jit/ir/ir_private.h @@ -953,6 +953,8 @@ bool ir_use_list_add(ir_ctx *ctx, ir_ref to, ir_ref new_use); #define IR_BB_HAS_PARAM (1<<12) #define IR_BB_HAS_VAR (1<<13) +/* The following flags are set by BB scheduler */ +#define IR_BB_ALIGN_LOOP (1<<14) struct _ir_block { uint32_t flags; diff --git a/ext/opcache/jit/ir/ir_ra.c b/ext/opcache/jit/ir/ir_ra.c index 44d00e27cb35..db2972a05ea4 100644 --- a/ext/opcache/jit/ir/ir_ra.c +++ b/ext/opcache/jit/ir/ir_ra.c @@ -3926,7 +3926,6 @@ static void assign_regs(ir_ctx *ctx) } } if (use_pos->hint_ref < 0 - && ctx->use_lists[-use_pos->hint_ref].count > 1 && (old_reg = ir_get_alocated_reg(ctx, -use_pos->hint_ref, use_pos->op_num)) != IR_REG_NONE) { if (top_ival->flags & IR_LIVE_INTERVAL_SPILL_SPECIAL) { reg |= IR_REG_SPILL_SPECIAL; @@ -3950,7 +3949,6 @@ static void assign_regs(ir_ctx *ctx) reg = IR_REG_NONE; } } else if (use_pos->hint_ref < 0 - && ctx->use_lists[-use_pos->hint_ref].count > 1 && (old_reg = ir_get_alocated_reg(ctx, -use_pos->hint_ref, use_pos->op_num)) != IR_REG_NONE) { if (reg != old_reg) { IR_ASSERT(ctx->rules[-use_pos->hint_ref] & IR_FUSED); diff --git a/ext/opcache/jit/ir/ir_x86.dasc b/ext/opcache/jit/ir/ir_x86.dasc index 9afd8ace1d3c..2c8507fec062 100644 --- a/ext/opcache/jit/ir/ir_x86.dasc +++ b/ext/opcache/jit/ir/ir_x86.dasc @@ -15,6 +15,8 @@ |.globals ir_lb |.section code, cold_code, rodata, jmp_table +|.define IR_LOOP_ALIGNMENT, 16 + #ifdef IR_DEBUG typedef struct _ir_mem {uint64_t v;} ir_mem; @@ -1402,6 +1404,7 @@ op2_const: case IR_TRUNC: case IR_BITCAST: case IR_PROTO: + case IR_FP2FP: flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG; break; case IR_ABS_INT: @@ -1771,7 +1774,7 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref) } else if ((ir_type_size[insn->type] >= 4 && insn->op == IR_ADD && IR_IS_SIGNED_32BIT(op2_insn->val.i64)) || (ir_type_size[insn->type] >= 4 && insn->op == IR_SUB && IR_IS_SIGNED_NEG_32BIT(op2_insn->val.i64))) { lea: - if (ir_in_same_block(ctx, insn->op1) && ctx->use_lists[insn->op1].count == 1) { + if (ctx->use_lists[insn->op1].count == 1) { uint32_t rule = ctx->rules[insn->op1]; if (!rule) { @@ -1814,14 +1817,14 @@ lea: } } else if ((ctx->flags & IR_OPT_CODEGEN) && insn->op == IR_ADD && ir_type_size[insn->type] >= 4) { if (insn->op1 != insn->op2) { - if (ir_in_same_block(ctx, insn->op1) && ctx->use_lists[insn->op1].count == 1) { + if (ctx->use_lists[insn->op1].count == 1) { uint32_t rule =ctx->rules[insn->op1]; if (!rule) { ctx->rules[insn->op1] = rule = ir_match_insn(ctx, insn->op1); } if (rule == IR_LEA_OB) { ctx->rules[insn->op1] = IR_FUSED | IR_SIMPLE | IR_LEA_OB; - if (ir_in_same_block(ctx, insn->op2) && ctx->use_lists[insn->op2].count == 1) { + if (ctx->use_lists[insn->op2].count == 1) { rule = ctx->rules[insn->op2]; if (!rule) { ctx->rules[insn->op2] = rule = ir_match_insn(ctx, insn->op2); @@ -1836,7 +1839,7 @@ lea: return IR_LEA_OB_I; } else if (rule == IR_LEA_SI) { ctx->rules[insn->op1] = IR_FUSED | IR_SIMPLE | IR_LEA_SI; - if (ir_in_same_block(ctx, insn->op2) && ctx->use_lists[insn->op2].count == 1) { + if (ctx->use_lists[insn->op2].count == 1) { rule = ctx->rules[insn->op2]; if (!rule) { ctx->rules[insn->op2] = rule = ir_match_insn(ctx, insn->op2); @@ -1851,7 +1854,7 @@ lea: return IR_LEA_SI_B; } } - if (ir_in_same_block(ctx, insn->op2) && ctx->use_lists[insn->op2].count == 1) { + if (ctx->use_lists[insn->op2].count == 1) { uint32_t rule = ctx->rules[insn->op2]; if (!rule) { ctx->rules[insn->op2] = rule = ir_match_insn(ctx, insn->op2); @@ -3227,43 +3230,48 @@ static void ir_emit_prologue(ir_ctx *ctx) { ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; + int offset = ctx->stack_frame_size + ctx->call_stack_size; if (ctx->flags & IR_USE_FRAME_POINTER) { | push Ra(IR_REG_RBP) | mov Ra(IR_REG_RBP), Ra(IR_REG_RSP) } + if (IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP)) { + int i; + ir_regset used_preserved_regs = IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP); + + for (i = IR_REG_GP_FIRST; i <= IR_REG_GP_LAST; i++) { + if (IR_REGSET_IN(used_preserved_regs, i)) { + offset -= sizeof(void*); + | push Ra(i) + } + } + } if (ctx->stack_frame_size + ctx->call_stack_size) { if (ctx->fixed_stack_red_zone) { IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone); - } else { - | sub Ra(IR_REG_RSP), (ctx->stack_frame_size + ctx->call_stack_size) + } else if (offset) { + | sub Ra(IR_REG_RSP), offset } } - if (ctx->used_preserved_regs) { + if (IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_FP)) { ir_reg fp; - int offset; - uint32_t i; - ir_regset used_preserved_regs = (ir_regset)ctx->used_preserved_regs; + int i; + ir_regset used_preserved_regs = IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_FP); if (ctx->flags & IR_USE_FRAME_POINTER) { fp = IR_REG_FRAME_POINTER; - offset = 0; + offset -= ctx->stack_frame_size + ctx->call_stack_size; } else { fp = IR_REG_STACK_POINTER; - offset = ctx->stack_frame_size + ctx->call_stack_size; } - for (i = 0; i < IR_REG_NUM; i++) { + for (i = IR_REG_FP_FIRST; i <= IR_REG_FP_LAST; i++) { if (IR_REGSET_IN(used_preserved_regs, i)) { - if (i < IR_REG_FP_FIRST) { - offset -= sizeof(void*); - | mov aword [Ra(fp)+offset], Ra(i) + offset -= sizeof(void*); + if (ctx->mflags & IR_X86_AVX) { + | vmovsd qword [Ra(fp)+offset], xmm(i-IR_REG_FP_FIRST) } else { - offset -= sizeof(void*); - if (ctx->mflags & IR_X86_AVX) { - | vmovsd qword [Ra(fp)+offset], xmm(i-IR_REG_FP_FIRST) - } else { - | movsd qword [Ra(fp)+offset], xmm(i-IR_REG_FP_FIRST) - } + | movsd qword [Ra(fp)+offset], xmm(i-IR_REG_FP_FIRST) } } } @@ -3330,26 +3338,24 @@ static void ir_emit_epilogue(ir_ctx *ctx) ir_backend_data *data = ctx->data; dasm_State **Dst = &data->dasm_state; - if (ctx->used_preserved_regs) { + if (IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_FP)) { + int i; int offset; - uint32_t i; + ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; ir_regset used_preserved_regs = (ir_regset)ctx->used_preserved_regs; if (ctx->flags & IR_USE_FRAME_POINTER) { + fp = IR_REG_FRAME_POINTER; offset = 0; } else { + fp = IR_REG_STACK_POINTER; offset = ctx->stack_frame_size + ctx->call_stack_size; } for (i = 0; i < IR_REG_NUM; i++) { if (IR_REGSET_IN(used_preserved_regs, i)) { if (i < IR_REG_FP_FIRST) { - ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset -= sizeof(void*); - | mov Ra(i), aword [Ra(fp)+offset] } else { - ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER; - offset -= sizeof(void*); if (ctx->mflags & IR_X86_AVX) { | vmovsd xmm(i-IR_REG_FP_FIRST), qword [Ra(fp)+offset] @@ -3361,7 +3367,40 @@ static void ir_emit_epilogue(ir_ctx *ctx) } } - if (ctx->flags & IR_USE_FRAME_POINTER) { + if (IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP)) { + int i; + ir_regset used_preserved_regs = IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP); + int offset; + + if (ctx->flags & IR_USE_FRAME_POINTER) { + offset = 0; + } else { + offset = ctx->stack_frame_size + ctx->call_stack_size; + } + if (IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP)) { + int i; + ir_regset used_preserved_regs = IR_REGSET_INTERSECTION((ir_regset)ctx->used_preserved_regs, IR_REGSET_GP); + + for (i = IR_REG_GP_LAST; i >= IR_REG_GP_FIRST; i--) { + if (IR_REGSET_IN(used_preserved_regs, i)) { + offset -= sizeof(void*); + } + } + } + if (ctx->flags & IR_USE_FRAME_POINTER) { + | lea Ra(IR_REG_RSP), [Ra(IR_REG_RBP)+offset] + } else if (offset) { + | add Ra(IR_REG_RSP), offset + } + for (i = IR_REG_GP_LAST; i >= IR_REG_GP_FIRST; i--) { + if (IR_REGSET_IN(used_preserved_regs, i)) { + | pop Ra(i) + } + } + if (ctx->flags & IR_USE_FRAME_POINTER) { + | pop Ra(IR_REG_RBP) + } + } else if (ctx->flags & IR_USE_FRAME_POINTER) { | mov Ra(IR_REG_RSP), Ra(IR_REG_RBP) | pop Ra(IR_REG_RBP) } else if (ctx->stack_frame_size + ctx->call_stack_size) { @@ -9742,6 +9781,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr) if ((bb->flags & (IR_BB_START|IR_BB_ENTRY|IR_BB_EMPTY)) == IR_BB_EMPTY) { continue; } + if (bb->flags & IR_BB_ALIGN_LOOP) { + | .align IR_LOOP_ALIGNMENT + } |=>b: i = bb->start;

« previous php.cvs (#127735) next »