diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-04-07 21:34:18 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-04-07 21:34:18 +0300 |
commit | cff7703a6185803e22bd3543d5bcd114d0a6f514 (patch) | |
tree | 8754b3aa76283319fa414d0bcbb17480cecf708b | |
parent | 5db5f71f2831df4d32484a5638f6f6aa72e364a5 (diff) | |
download | php-git-cff7703a6185803e22bd3543d5bcd114d0a6f514.tar.gz |
Revert "cleanup" (wrong commit)
This reverts commit 5db5f71f2831df4d32484a5638f6f6aa72e364a5.
-rw-r--r-- | ext/opcache/jit/zend_jit_trace.c | 801 |
1 files changed, 3 insertions, 798 deletions
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 9f17f681d6..171ecd7d51 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -803,11 +803,6 @@ static int is_checked_guard(const zend_ssa *tssa, const zend_op **ssa_opcodes, u return 0; } -typedef struct _zend_tssa { - zend_ssa ssa; - const zend_op **tssa_opcodes; -} zend_tssa; - static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num, zend_script *script, const zend_op_array **op_arrays, int *num_op_arrays_ptr) { zend_ssa *tssa; @@ -918,7 +913,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin *num_op_arrays_ptr = num_op_arrays; /* 2. Construct TSSA */ - tssa = zend_arena_calloc(&CG(arena), 1, sizeof(zend_tssa)); + tssa = zend_arena_calloc(&CG(arena), 1, sizeof(zend_ssa)); tssa->cfg.blocks = zend_arena_calloc(&CG(arena), 2, sizeof(zend_basic_block)); tssa->blocks = zend_arena_calloc(&CG(arena), 2, sizeof(zend_ssa_block)); tssa->cfg.predecessors = zend_arena_calloc(&CG(arena), 2, sizeof(int)); @@ -926,7 +921,6 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin memset(ssa_ops, -1, ssa_ops_count * sizeof(zend_ssa_op)); ssa_opcodes = zend_arena_calloc(&CG(arena), ssa_ops_count, sizeof(zend_op*)); JIT_G(current_frame) = frame = (zend_jit_trace_stack_frame*)((char*)zend_arena_alloc(&CG(arena), stack_bottom + stack_size) + stack_bottom); - ((zend_tssa*)tssa)->tssa_opcodes = ssa_opcodes; if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) { tssa->cfg.blocks_count = 2; @@ -1684,784 +1678,6 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin return tssa; } -static int zend_jit_trace_try_allocate_free_reg(zend_jit_trace_rec *trace_buffer, const zend_op **ssa_opcodes, zend_ssa *ssa, zend_lifetime_interval *current, zend_regset available, zend_regset *hints, zend_lifetime_interval *active, zend_lifetime_interval *inactive, zend_lifetime_interval **list, zend_lifetime_interval **free) -{ - zend_lifetime_interval *it; - uint32_t freeUntilPos[ZREG_NUM]; - uint32_t pos, pos2; - zend_reg i, reg, reg2; - zend_reg hint = ZREG_NONE; - zend_regset low_priority_regs; - zend_life_range *range; - - if ((ssa->var_info[current->ssa_var].type & MAY_BE_ANY) == MAY_BE_DOUBLE) { - available = ZEND_REGSET_INTERSECTION(available, ZEND_REGSET_FP); - } else { - available = ZEND_REGSET_INTERSECTION(available, ZEND_REGSET_GP); - } - - /* TODO: Allow usage of preserved registers ??? - * Their values have to be stored in prologuee and restored in epilogue - */ - available = ZEND_REGSET_DIFFERENCE(available, ZEND_REGSET_PRESERVED); - - if (ZEND_REGSET_IS_EMPTY(available)) { - return 0; - } - - /* Set freeUntilPos of all physical registers to maxInt */ - for (i = 0; i < ZREG_NUM; i++) { - freeUntilPos[i] = 0xffffffff; - } - - /* for each interval it in active do */ - /* freeUntilPos[it.reg] = 0 */ - it = active; - if (ssa->vars[current->ssa_var].definition == current->range.start) { - while (it) { - if (current->range.start != zend_interval_end(it)) { - freeUntilPos[it->reg] = 0; - } else if (zend_jit_may_reuse_reg(ssa_opcodes[current->range.start], ssa->ops + current->range.start, ssa, current->ssa_var, it->ssa_var)) { - if (!ZEND_REGSET_IN(*hints, it->reg) && - /* TODO: Avoid most often scratch registers. Find a better way ??? */ - (!current->used_as_hint || - (it->reg != ZREG_R0 && it->reg != ZREG_R1 && it->reg != ZREG_XMM0 && it->reg != ZREG_XMM1))) { - hint = it->reg; - } - } else { - freeUntilPos[it->reg] = 0; - } - it = it->list_next; - } - } else { - while (it) { - freeUntilPos[it->reg] = 0; - it = it->list_next; - } - } - if (current->hint) { - hint = current->hint->reg; - if (hint != ZREG_NONE && current->hint->used_as_hint == current) { - ZEND_REGSET_EXCL(*hints, hint); - } - } - - /* See "Linear Scan Register Allocation on SSA Form", Christian Wimmer and - Michael Franz, CGO'10 (2010), Figure 6. */ - if (current->split) { - /* for each interval it in inactive intersecting with current do */ - /* freeUntilPos[it.reg] = next intersection of it with current */ - it = inactive; - while (it) { - uint32_t next = zend_interval_intersection(current, it); - - //ZEND_ASSERT(next != 0xffffffff && !current->split); - if (next < freeUntilPos[it->reg]) { - freeUntilPos[it->reg] = next; - } - it = it->list_next; - } - } - - /* Handle Scratch Registers */ - /* TODO: Optimize ??? */ - range = ¤t->range; - do { - uint32_t line = range->start; - zend_regset regset; - zend_reg reg; - - if (ssa->ops[line].op1_def == current->ssa_var || - ssa->ops[line].op2_def == current->ssa_var || - ssa->ops[line].result_def == current->ssa_var) { - line++; - } - while (line <= range->end) { - regset = zend_jit_get_scratch_regset( - ssa_opcodes[line], - ssa->ops + line, - // TODO: Support for nested call frames ??? - trace_buffer->op_array, ssa, current->ssa_var); - ZEND_REGSET_FOREACH(regset, reg) { - if (line < freeUntilPos[reg]) { - freeUntilPos[reg] = line; - } - } ZEND_REGSET_FOREACH_END(); - line++; - } - range = range->next; - } while (range); - -#if 0 - /* Coalesing */ - if (ssa->vars[current->ssa_var].definition == current->start) { - zend_op *opline = op_array->opcodes + current->start; - int hint = -1; - - switch (opline->opcode) { - case ZEND_ASSIGN: - hint = ssa->ops[current->start].op2_use; - case ZEND_QM_ASSIGN: - hint = ssa->ops[current->start].op1_use; - break; - case ZEND_ADD: - case ZEND_SUB: - case ZEND_MUL: - hint = ssa->ops[current->start].op1_use; - break; - case ZEND_ASSIGN_OP: - if (opline->extended_value == ZEND_ADD - || opline->extended_value == ZEND_SUB - || opline->extended_value == ZEND_MUL) { - hint = ssa->ops[current->start].op1_use; - } - break; - } - if (hint >= 0) { - } - } -#endif - - if (hint != ZREG_NONE && freeUntilPos[hint] > zend_interval_end(current)) { - current->reg = hint; - if (current->used_as_hint) { - ZEND_REGSET_INCL(*hints, hint); - } - return 1; - } - - pos = 0; reg = ZREG_NONE; - pos2 = 0; reg2 = ZREG_NONE; - low_priority_regs = *hints; - if (current->used_as_hint) { - /* TODO: Avoid most often scratch registers. Find a better way ??? */ - ZEND_REGSET_INCL(low_priority_regs, ZREG_R0); - ZEND_REGSET_INCL(low_priority_regs, ZREG_R1); - ZEND_REGSET_INCL(low_priority_regs, ZREG_XMM0); - ZEND_REGSET_INCL(low_priority_regs, ZREG_XMM1); - } - - ZEND_REGSET_FOREACH(available, i) { - if (ZEND_REGSET_IN(low_priority_regs, i)) { - if (freeUntilPos[i] > pos2) { - reg2 = i; - pos2 = freeUntilPos[i]; - } - } else if (freeUntilPos[i] > pos) { - reg = i; - pos = freeUntilPos[i]; - } - } ZEND_REGSET_FOREACH_END(); - - if (reg == ZREG_NONE) { - if (reg2 != ZREG_NONE) { - reg = reg2; - pos = pos2; - reg2 = ZREG_NONE; - } - } - - if (reg == ZREG_NONE) { - /* no register available without spilling */ - return 0; - } else if (zend_interval_end(current) < pos) { - /* register available for the whole interval */ - current->reg = reg; - if (current->used_as_hint) { - ZEND_REGSET_INCL(*hints, reg); - } - return 1; -#if 0 - // TODO: allow low prioirity register usage - } else if (reg2 != ZREG_NONE && zend_interval_end(current) < pos2) { - /* register available for the whole interval */ - current->reg = reg2; - if (current->used_as_hint) { - ZEND_REGSET_INCL(*hints, reg2); - } - return 1; -#endif - } else { - /* TODO: enable interval splitting ??? */ - /* register available for the first part of the interval */ - if (1 || zend_jit_split_interval(current, pos, list, free) != SUCCESS) { - return 0; - } - current->reg = reg; - if (current->used_as_hint) { - ZEND_REGSET_INCL(*hints, reg); - } - return 1; - } -} - -static zend_lifetime_interval* zend_jit_trace_linear_scan(zend_jit_trace_rec *trace_buffer, const zend_op **ssa_opcodes, zend_ssa *ssa, zend_lifetime_interval *list) -{ - zend_lifetime_interval *unhandled, *active, *inactive, *handled, *free; - zend_lifetime_interval *current, **p, *q; - uint32_t position; - zend_regset available = ZEND_REGSET_UNION(ZEND_REGSET_GP, ZEND_REGSET_FP); - zend_regset hints = ZEND_REGSET_EMPTY; - - unhandled = list; - /* active = inactive = handled = free = {} */ - active = inactive = handled = free = NULL; - while (unhandled != NULL) { - current = unhandled; - unhandled = unhandled->list_next; - position = current->range.start; - - p = &active; - while (*p) { - uint32_t end = zend_interval_end(*p); - - q = *p; - if (end < position) { - /* move ival from active to handled */ - ZEND_REGSET_INCL(available, q->reg); - *p = q->list_next; - q->list_next = handled; - handled = q; - } else if (!zend_interval_covers(q, position)) { - /* move ival from active to inactive */ - ZEND_REGSET_INCL(available, q->reg); - *p = q->list_next; - q->list_next = inactive; - inactive = q; - } else { - p = &q->list_next; - } - } - - p = &inactive; - while (*p) { - uint32_t end = zend_interval_end(*p); - - q = *p; - if (end < position) { - /* move ival from inactive to handled */ - *p = q->list_next; - q->list_next = handled; - handled = q; - } else if (zend_interval_covers(q, position)) { - /* move ival from inactive to active */ - ZEND_REGSET_EXCL(available, q->reg); - *p = q->list_next; - q->list_next = active; - active = q; - } else { - p = &q->list_next; - } - } - - if (zend_jit_trace_try_allocate_free_reg(trace_buffer, ssa_opcodes, ssa, current, available, &hints, active, inactive, &unhandled, &free) || - zend_jit_allocate_blocked_reg()) { - ZEND_REGSET_EXCL(available, current->reg); - current->list_next = active; - active = current; - } else { - current->list_next = free; - free = current; - } - } - - /* move active to handled */ - while (active) { - current = active; - active = active->list_next; - current->list_next = handled; - handled = current; - } - - /* move inactive to handled */ - while (inactive) { - current = inactive; - inactive = inactive->list_next; - current->list_next = handled; - handled = current; - } - - return handled; -} - -static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace_rec *trace_buffer, zend_ssa *ssa) -{ - const zend_op **ssa_opcodes = ((zend_tssa*)ssa)->tssa_opcodes; - zend_jit_trace_rec *p; - const zend_op_array *op_array; - const zend_ssa_op *ssa_op; - int i, j, idx, count, level; - int *start, *end; - zend_lifetime_interval **intervals, *list; - void *checkpoint; - ALLOCA_FLAG(use_heap); - - ZEND_ASSERT(ssa->var_info != NULL); - - start =do_alloca(sizeof(int) * ssa->vars_count * 2, use_heap); - if (!start) { - return NULL; - } - end = start + ssa->vars_count; - - memset(start, -1, sizeof(int) * ssa->vars_count * 2); - - op_array = trace_buffer->op_array; - count = 0; - - i = 0; - j = op_array->last_var; - if (trace_buffer->start != ZEND_JIT_TRACE_START_ENTER) { - j += op_array->T; - } - while (i < j) { - /* We don't start intervals for variables used in Phi */ - if ((ssa->vars[i].use_chain >= 0 /*|| ssa->vars[i].phi_use_chain*/) - && zend_jit_var_supports_reg(ssa, i)) { - start[i] = 0; - count++; - } - i++; - } - - if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) { - zend_ssa_phi *phi = ssa->blocks[1].phis; - - while (phi) { - if (ssa->vars[phi->ssa_var].use_chain >= 0 - && zend_jit_var_supports_reg(ssa, phi->ssa_var)) { - start[phi->ssa_var] = 0; - count++; - } - phi = phi->next; - } - } - - p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE; - level = 0; - ssa_op = ssa->ops; - idx = 0; - for (;;p++) { - if (p->op == ZEND_JIT_TRACE_VM) { - const zend_op *opline = p->opline; - int len; - zend_bool support_opline; - - support_opline = - zend_jit_opline_supports_reg(op_array, ssa, opline, ssa_op); - if (support_opline) { - if (ssa_op->op1_use >= 0 - && start[ssa_op->op1_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) { - end[ssa_op->op1_use] = idx; - } - if (ssa_op->op2_use >= 0 - && start[ssa_op->op2_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op2_use)) { - end[ssa_op->op2_use] = idx; - } - if (ssa_op->result_use >= 0 - && start[ssa_op->result_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->result_use)) { - end[ssa_op->result_use] = idx; - } - if (ssa_op->result_def >= 0 - && (ssa->vars[ssa_op->result_def].use_chain >= 0 - || ssa->vars[ssa_op->result_def].phi_use_chain) - && zend_jit_var_supports_reg(ssa, ssa_op->result_def)) { - start[ssa_op->result_def] = idx; - count++; - } - if (ssa_op->op1_def >= 0 - && (ssa->vars[ssa_op->op1_def].use_chain >= 0 - || ssa->vars[ssa_op->op1_def].phi_use_chain) - && zend_jit_var_supports_reg(ssa, ssa_op->op1_def)) { - start[ssa_op->op1_def] = idx; - count++; - } - if (ssa_op->op2_def >= 0 - && (ssa->vars[ssa_op->op2_def].use_chain >= 0 - || ssa->vars[ssa_op->op2_def].phi_use_chain) - && zend_jit_var_supports_reg(ssa, ssa_op->op2_def)) { - start[ssa_op->op2_def] = idx; - count++; - } - } else { - if (ssa_op->op1_use >= 0 - && start[ssa_op->op1_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) { - start[ssa_op->op1_use] = -1; - end[ssa_op->op1_use] = -1; - count--; - } - if (ssa_op->op2_use >= 0 - && start[ssa_op->op2_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op2_use)) { - start[ssa_op->op2_use] = -1; - end[ssa_op->op2_use] = -1; - count--; - } - if (ssa_op->result_use >= 0 - && start[ssa_op->result_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->result_use)) { - start[ssa_op->result_use] = -1; - end[ssa_op->result_use] = -1; - count--; - } - } - - len = zend_jit_trace_op_len(opline); - switch (opline->opcode) { - case ZEND_ASSIGN_DIM: - case ZEND_ASSIGN_OBJ: - case ZEND_ASSIGN_STATIC_PROP: - case ZEND_ASSIGN_DIM_OP: - case ZEND_ASSIGN_OBJ_OP: - case ZEND_ASSIGN_STATIC_PROP_OP: - case ZEND_ASSIGN_OBJ_REF: - case ZEND_ASSIGN_STATIC_PROP_REF: - /* OP_DATA */ - ssa_op++; - opline++; - if (support_opline) { - if (ssa_op->op1_use >= 0 - && start[ssa_op->op1_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) { - end[ssa_op->op1_use] = idx; - } - if (ssa_op->op1_def >= 0 - && (ssa->vars[ssa_op->op1_def].use_chain >= 0 - || ssa->vars[ssa_op->op1_def].phi_use_chain) - && zend_jit_var_supports_reg(ssa, ssa_op->op1_def)) { - start[ssa_op->op1_def] = idx; - count++; - } - } else { - if (ssa_op->op1_use >= 0 - && start[ssa_op->op1_use] >= 0 - && !zend_ssa_is_no_val_use(opline, ssa_op, ssa_op->op1_use)) { - start[ssa_op->op1_use] = -1; - end[ssa_op->op1_use] = -1; - count--; - } - } - ssa_op++; - opline++; - idx+=2; - break; - case ZEND_RECV_INIT: - ssa_op++; - opline++; - idx++; - while (opline->opcode == ZEND_RECV_INIT) { - /* RECV_INIT doesn't support registers */ - ssa_op++; - opline++; - idx++; - } - break; - case ZEND_BIND_GLOBAL: - ssa_op++; - opline++; - idx++; - while (opline->opcode == ZEND_BIND_GLOBAL) { - /* BIND_GLOBAL doesn't support registers */ - ssa_op++; - opline++; - idx++; - } - break; - default: - ssa_op += len; - idx += len; - break; - } - } else if (p->op == ZEND_JIT_TRACE_ENTER) { - op_array = p->op_array; - /* New call frames */ - i = op_array->last_var; - j = p->first_ssa_var; - while (i) { - if (ssa->vars[j].use_chain >= 0 - && zend_jit_var_supports_reg(ssa, j)) { - start[j] = idx; - count++; - } - j++; - i--; - } - level++; - } else if (p->op == ZEND_JIT_TRACE_BACK) { - // TODO: Close exiting call frames ??? - op_array = p->op_array; - if (level == 0) { - /* New return frames */ - i = op_array->last_var + op_array->T; - j = p->first_ssa_var; - while (i) { - if (ssa->vars[j].use_chain >= 0 - && zend_jit_var_supports_reg(ssa, j)) { - start[j] = idx; - count++; - } - j++; - i--; - } - } else { - level--; - } - } else if (p->op == ZEND_JIT_TRACE_END) { - break; - } - } - - if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) { - zend_ssa_phi *phi = ssa->blocks[1].phis; - - while (phi) { - if (start[phi->sources[1]] >= 0) { - end[phi->sources[1]] = idx - 1; - } - phi = phi->next; - } - } - - if (!count) { - free_alloca(start, use_heap); - return NULL; - } - - checkpoint = zend_arena_checkpoint(CG(arena)); - intervals = zend_arena_calloc(&CG(arena), ssa->vars_count, sizeof(zend_lifetime_interval)); - memset(intervals, 0, sizeof(zend_lifetime_interval*) * ssa->vars_count); - list = zend_arena_alloc(&CG(arena), sizeof(zend_lifetime_interval) * count); - j = 0; -//fprintf(stderr, "(%d)\n", count); - for (i = 0; i < ssa->vars_count; i++) { - if (start[i] >= 0) { - if (end[i] < 0) { - // TODO: ??? - end[i] = idx; - // continue; - } -//fprintf(stderr, "#%d: %d..%d\n", i, start[i], end[i]); - ZEND_ASSERT(j < count); - intervals[i] = &list[j]; - list[j].ssa_var = i; - list[j].reg = ZREG_NONE; - list[j].split = 0; - list[j].store = 0; - list[j].load = 0; - list[j].range.start = start[i]; - list[j].range.end = end[i]; - list[j].range.next = NULL; - list[j].hint = NULL; - list[j].used_as_hint = NULL; - list[j].list_next = NULL; - j++; - } - } - ZEND_ASSERT(j == count); - free_alloca(start, use_heap); - start = end = NULL; - - /* Add hints */ - if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) { - zend_ssa_phi *phi = ssa->blocks[1].phis; - - while (phi) { - if (intervals[phi->ssa_var]) { - if (intervals[phi->sources[1]]) { - intervals[phi->sources[1]]->hint = intervals[phi->ssa_var]; - } - } - phi = phi->next; - } - } - - for (i = 0; i < ssa->vars_count; i++) { - if (intervals[i] && !intervals[i]->hint) { - - if (ssa->vars[i].definition >= 0) { - uint32_t line = ssa->vars[i].definition; - const zend_op *opline = ssa_opcodes[line]; - - switch (opline->opcode) { - case ZEND_QM_ASSIGN: - case ZEND_POST_INC: - case ZEND_POST_DEC: - if (ssa->ops[line].op1_use >= 0 && - intervals[ssa->ops[line].op1_use] && - (i == ssa->ops[line].op1_def || - (i == ssa->ops[line].result_def && - (ssa->ops[line].op1_def < 0 || - !intervals[ssa->ops[line].op1_def])))) { - zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use); - } - break; - case ZEND_SEND_VAR: - case ZEND_PRE_INC: - case ZEND_PRE_DEC: - if (i == ssa->ops[line].op1_def && - ssa->ops[line].op1_use >= 0 && - intervals[ssa->ops[line].op1_use]) { - zend_jit_add_hint(intervals, i, ssa->ops[line].op1_use); - } - break; - case ZEND_ASSIGN: - if (ssa->ops[line].op2_use >= 0 && - intervals[ssa->ops[line].op2_use] && - (i == ssa->ops[line].op2_def || - (i == ssa->ops[line].op1_def && - (ssa->ops[line].op2_def < 0 || - !intervals[ssa->ops[line].op2_def])) || - (i == ssa->ops[line].result_def && - (ssa->ops[line].op2_def < 0 || - !intervals[ssa->ops[line].op2_def]) && - (ssa->ops[line].op1_def < 0 || - !intervals[ssa->ops[line].op1_def])))) { - zend_jit_add_hint(intervals, i, ssa->ops[line].op2_use); - } - break; - } - } - } - } - - list = zend_jit_sort_intervals(intervals, ssa->vars_count); - - if (list) { - zend_lifetime_interval *ival = list; - while (ival) { - if (ival->hint) { - ival->hint->used_as_hint = ival; - } - ival = ival->list_next; - } - - if (ZCG(accel_directives).jit_debug & ZEND_JIT_DEBUG_REG_ALLOC) { - // TODO: Support for nested call frames ??? - op_array = trace_buffer->op_array; - ival = list; - while (ival) { - zend_life_range *range; - int var_num = ssa->vars[ival->ssa_var].var; - - fprintf(stderr, "#%d.", ival->ssa_var); - // TODO: Support for nested call frames ??? - zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num); - fprintf(stderr, ": %u-%u", ival->range.start, ival->range.end); - range = ival->range.next; - while (range) { - fprintf(stderr, ", %u-%u", range->start, range->end); - range = range->next; - } - if (ival->load) { - fprintf(stderr, " load"); - } - if (ival->store) { - fprintf(stderr, " store"); - } - if (ival->hint) { - var_num = ssa->vars[ival->hint->ssa_var].var; - fprintf(stderr, " hint=#%d.", ival->hint->ssa_var); - // TODO: Support for nested call frames ??? - zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num); - } - fprintf(stderr, "\n"); - ival = ival->list_next; - } - fprintf(stderr, "\n"); - } - } - - /* Linear Scan Register Allocation */ - list = zend_jit_trace_linear_scan(trace_buffer, ssa_opcodes, ssa, list); - - if (list) { - zend_lifetime_interval *ival, *next; - - memset(intervals, 0, ssa->vars_count * sizeof(zend_lifetime_interval*)); - ival = list; - while (ival != NULL) { - ZEND_ASSERT(ival->reg != ZREG_NONE); - next = ival->list_next; - ival->list_next = intervals[ival->ssa_var]; - intervals[ival->ssa_var] = ival; - ival = next; - } - - /* SSA resolution */ - if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP) { - zend_ssa_phi *phi = ssa->blocks[1].phis; - - while (phi) { - int def = phi->ssa_var; - int use = phi->sources[1]; - - if (intervals[def]) { - if (!intervals[use]) { - intervals[def]->load = 1; - } else if (intervals[def]->reg != intervals[use]->reg) { - intervals[def]->load = 1; - intervals[use]->store = 1; - } - } else if (intervals[use]) { - intervals[use]->store = 1; - } - phi = phi->next; - } - } - - // Remove useless register allocation ??? - // Remove intervals used once ??? - - if (ZCG(accel_directives).jit_debug & ZEND_JIT_DEBUG_REG_ALLOC) { - // TODO: Support for nested call frames ??? - fprintf(stderr, "---- TRACE %d Allocated Live Ranges\n", ZEND_JIT_TRACE_NUM); - for (i = 0; i < ssa->vars_count; i++) { - ival = intervals[i]; - while (ival) { - zend_life_range *range; - int var_num = ssa->vars[ival->ssa_var].var; - - fprintf(stderr, "#%d.", ival->ssa_var); - zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num); - fprintf(stderr, ": %u-%u", ival->range.start, ival->range.end); - range = ival->range.next; - while (range) { - fprintf(stderr, ", %u-%u", range->start, range->end); - range = range->next; - } - fprintf(stderr, " (%s)", zend_reg_name[ival->reg]); - if (ival->load) { - fprintf(stderr, " load"); - } - if (ival->store) { - fprintf(stderr, " store"); - } - if (ival->hint) { - var_num = ssa->vars[ival->hint->ssa_var].var; - fprintf(stderr, " hint=#%d.", ival->hint->ssa_var); - zend_dump_var(op_array, (var_num < op_array->last_var ? IS_CV : 0), var_num); - if (ival->hint->reg != ZREG_NONE) { - fprintf(stderr, " (%s)", zend_reg_name[ival->hint->reg]); - } - } - fprintf(stderr, "\n"); - ival = ival->list_next; - } - } - fprintf(stderr, "\n"); - } - - return intervals; - } - - zend_arena_release(&CG(arena), checkpoint); //??? - return NULL; -} - static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t parent_trace, uint32_t exit_num) { const void *handler = NULL; @@ -2495,11 +1711,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par ssa = zend_jit_trace_build_tssa(trace_buffer, parent_trace, exit_num, script, op_arrays, &num_op_arrays); - /* Register allocation */ - if (zend_jit_reg_alloc) { - ra = zend_jit_trace_allocate_registers(trace_buffer, ssa); - } - p = trace_buffer; ZEND_ASSERT(p->op == ZEND_JIT_TRACE_START); op_array = p->op_array; @@ -2561,6 +1772,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); op_array_ssa = &jit_extension->func_info.ssa; + // TODO: register allocation ??? + dasm_growpc(&dasm_state, 1); /* trace needs just one global label for loop */ zend_jit_align_func(&dasm_state); @@ -2604,14 +1817,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par SET_STACK_TYPE(stack, i, concrete_type(info)); } } - if (ra) { - zend_ssa_phi *phi = ssa->vars[i].phi_use_chain; - if (phi && ra[phi->ssa_var] && !ra[phi->ssa_var]->load) { - if (!zend_jit_load_var(&dasm_state, ssa->var_info[i].type, i, ra[phi->ssa_var]->reg)) { - goto jit_failure; - } - } - } } } |