mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Update IR
IR commit: a6cfbffb0da4e11c45537dd83159c36eece6efa9
This commit is contained in:
parent
16c1c49f1b
commit
d9dfad8ea9
1 changed files with 147 additions and 59 deletions
|
@ -29,7 +29,7 @@ IR_ALWAYS_INLINE ir_ref ir_sccp_identity(ir_insn *_values, ir_ref a)
|
|||
{
|
||||
if (a > 0 && _values[a].op == IR_COPY) {
|
||||
a = _values[a].op1;
|
||||
IR_ASSERT(a <= 0 || _values[a].op != IR_COPY);
|
||||
IR_ASSERT(a > 0 && _values[a].op != IR_COPY);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
@ -69,16 +69,23 @@ restart:
|
|||
if (IR_IS_CONST_OP(insn->op)) {
|
||||
/* pass */
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
} else if (IR_IS_TOP(res)) {
|
||||
} else if (_values[res].optx == IR_TOP) {
|
||||
_values[res].optx = IR_OPT(IR_COPY, insn->type);
|
||||
_values[res].op1 = op1;
|
||||
return 1;
|
||||
} else if (_values[res].op == IR_COPY && _values[res].op1 == op1) {
|
||||
return 0; /* not changed */
|
||||
#endif
|
||||
} else {
|
||||
IR_ASSERT(_values[res].optx != IR_BOTTOM);
|
||||
/* we don't check for widening */
|
||||
_values[res].optx = IR_OPT(IR_COPY, insn->type);
|
||||
_values[res].op1 = op1;
|
||||
return 1;
|
||||
#else
|
||||
} else {
|
||||
IR_MAKE_BOTTOM(res);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case IR_FOLD_DO_CONST:
|
||||
|
@ -100,36 +107,148 @@ restart:
|
|||
return 0; /* not changed */
|
||||
}
|
||||
|
||||
static bool ir_sccp_join_values(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b)
|
||||
static bool ir_sccp_meet_phi(ir_ctx *ctx, ir_insn *_values, ir_ref i, ir_insn *insn, ir_bitqueue *worklist)
|
||||
{
|
||||
ir_insn *v;
|
||||
ir_ref j, n, input, *merge_input, *p;
|
||||
ir_insn *v, *new_const = NULL;
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
ir_ref new_copy;
|
||||
#endif
|
||||
|
||||
if (!IR_IS_BOTTOM(a) && !IR_IS_TOP(b)) {
|
||||
b = ir_sccp_identity(_values, b);
|
||||
v = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b];
|
||||
if (IR_IS_TOP(a)) {
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
if (v->op == IR_BOTTOM) {
|
||||
_values[a].optx = IR_OPT(IR_COPY, ctx->ir_base[b].type);
|
||||
_values[a].op1 = b;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
_values[a].optx = v->opt;
|
||||
_values[a].val.u64 = v->val.u64;
|
||||
return 1;
|
||||
} else if (_values[a].opt == v->opt && _values[a].val.u64 == v->val.u64) {
|
||||
/* pass */
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
} else if (_values[a].op == IR_COPY && _values[a].op1 == b) {
|
||||
/* pass */
|
||||
#endif
|
||||
if (!IR_IS_FEASIBLE(insn->op1)) {
|
||||
return 0;
|
||||
}
|
||||
n = insn->inputs_count;
|
||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||
for (j = 0; j < (n>>2); j++) {
|
||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
||||
}
|
||||
}
|
||||
|
||||
p = insn->ops + 2;
|
||||
merge_input = ctx->ir_base[insn->op1].ops + 1;
|
||||
for (; --n > 0; p++, merge_input++) {
|
||||
IR_ASSERT(*merge_input > 0);
|
||||
if (_values[*merge_input].optx == IR_TOP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
input = *p;
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
v = &ctx->ir_base[input];
|
||||
} else if (input == i) {
|
||||
continue;
|
||||
} else {
|
||||
IR_MAKE_BOTTOM(a);
|
||||
v = &_values[input];
|
||||
if (v->op == IR_TOP) {
|
||||
/* do backward propagaton only once */
|
||||
if (!v->op1) {
|
||||
v->op1 = 1;
|
||||
ir_bitqueue_add(worklist, input);
|
||||
}
|
||||
continue;
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
} else if (v->op == IR_COPY) {
|
||||
input = v->op1;
|
||||
IR_ASSERT(input > 0 && _values[input].op != IR_COPY);
|
||||
new_copy = input;
|
||||
goto next;
|
||||
} else if (v->op == IR_BOTTOM) {
|
||||
new_copy = input;
|
||||
goto next;
|
||||
#else
|
||||
} else if (v->op == IR_BOTTOM) {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
new_copy = IR_UNUSED;
|
||||
new_const = v;
|
||||
goto next;
|
||||
}
|
||||
|
||||
IR_ASSERT(_values[i].optx == IR_TOP);
|
||||
return 0;
|
||||
|
||||
next:
|
||||
p++;
|
||||
merge_input++;
|
||||
/* for all live merge inputs */
|
||||
for (; --n > 0; p++, merge_input++) {
|
||||
IR_ASSERT(*merge_input > 0);
|
||||
if (_values[*merge_input].optx == IR_TOP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
input = *p;
|
||||
if (IR_IS_CONST_REF(input)) {
|
||||
v = &ctx->ir_base[input];
|
||||
} else if (input == i) {
|
||||
continue;
|
||||
} else {
|
||||
v = &_values[input];
|
||||
if (v->op == IR_TOP) {
|
||||
/* do backward propagaton only once */
|
||||
if (!v->op1) {
|
||||
v->op1 = 1;
|
||||
ir_bitqueue_add(worklist, input);
|
||||
}
|
||||
continue;
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
} else if (v->op == IR_COPY) {
|
||||
input = v->op1;
|
||||
IR_ASSERT(input > 0 && _values[input].op != IR_COPY);
|
||||
if (new_copy == input) {
|
||||
continue;
|
||||
} else {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
}
|
||||
} else if (v->op == IR_BOTTOM) {
|
||||
if (new_copy == input) {
|
||||
continue;
|
||||
} else {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
} else if (v->op == IR_BOTTOM) {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!new_const || new_const->opt != v->opt || new_const->val.u64 != v->val.u64) {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
#if IR_COMBO_COPY_PROPAGATION
|
||||
if (new_copy) {
|
||||
if (_values[i].op == IR_COPY && _values[i].op1 == new_copy) {
|
||||
return 0; /* not changed */
|
||||
} else {
|
||||
IR_ASSERT(_values[i].optx != IR_BOTTOM);
|
||||
/* we don't check for widening */
|
||||
_values[i].optx = IR_OPT(IR_COPY, ctx->ir_base[new_copy].type);
|
||||
_values[i].op1 = new_copy;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_values[i].optx == IR_TOP) {
|
||||
_values[i].optx = new_const->opt;
|
||||
_values[i].val.u64 = new_const->val.u64;
|
||||
return 1;
|
||||
} else if (_values[i].opt == new_const->opt && _values[i].val.u64 == new_const->val.u64) {
|
||||
return 0;
|
||||
} else {
|
||||
IR_MAKE_BOTTOM(i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ir_sccp_is_true(ir_ctx *ctx, ir_insn *_values, ir_ref a)
|
||||
|
@ -585,38 +704,7 @@ int ir_sccp(ir_ctx *ctx)
|
|||
flags = ir_op_flags[insn->op];
|
||||
if (flags & IR_OP_FLAG_DATA) {
|
||||
if (insn->op == IR_PHI) {
|
||||
ir_insn *merge_insn = &ctx->ir_base[insn->op1];
|
||||
bool changed = 0;
|
||||
|
||||
if (!IR_IS_FEASIBLE(insn->op1)) {
|
||||
continue;
|
||||
}
|
||||
n = merge_insn->inputs_count + 1;
|
||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||
for (j = 0; j < (n>>2); j++) {
|
||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
||||
}
|
||||
}
|
||||
/* for all live merge inputs */
|
||||
for (j = 1; j < n; j++) {
|
||||
ir_ref merge_input = ir_insn_op(merge_insn, j);
|
||||
|
||||
IR_ASSERT(merge_input > 0);
|
||||
if (_values[merge_input].optx != IR_TOP) {
|
||||
ir_ref input = ir_insn_op(insn, j + 1);
|
||||
|
||||
if (input > 0 && IR_IS_TOP(input)) {
|
||||
/* do backward propagaton only once */
|
||||
if (!_values[input].op1) {
|
||||
_values[input].op1 = 1;
|
||||
ir_bitqueue_add(&worklist, input);
|
||||
}
|
||||
} else if (ir_sccp_join_values(ctx, _values, i, input)) {
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!changed) {
|
||||
if (!ir_sccp_meet_phi(ctx, _values, i, insn, &worklist)) {
|
||||
continue;
|
||||
}
|
||||
} else if (ctx->use_lists[i].count == 0) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue