Skip to content

Commit d9dfad8

Browse files
committed
Update IR
IR commit: a6cfbffb0da4e11c45537dd83159c36eece6efa9
1 parent 16c1c49 commit d9dfad8

File tree

1 file changed

+142
-54
lines changed

1 file changed

+142
-54
lines changed

ext/opcache/jit/ir/ir_sccp.c

Lines changed: 142 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ IR_ALWAYS_INLINE ir_ref ir_sccp_identity(ir_insn *_values, ir_ref a)
2929
{
3030
if (a > 0 && _values[a].op == IR_COPY) {
3131
a = _values[a].op1;
32-
IR_ASSERT(a <= 0 || _values[a].op != IR_COPY);
32+
IR_ASSERT(a > 0 && _values[a].op != IR_COPY);
3333
}
3434
return a;
3535
}
@@ -69,16 +69,23 @@ static ir_ref ir_sccp_fold(ir_ctx *ctx, ir_insn *_values, ir_ref res, uint32_t o
6969
if (IR_IS_CONST_OP(insn->op)) {
7070
/* pass */
7171
#if IR_COMBO_COPY_PROPAGATION
72-
} else if (IR_IS_TOP(res)) {
72+
} else if (_values[res].optx == IR_TOP) {
7373
_values[res].optx = IR_OPT(IR_COPY, insn->type);
7474
_values[res].op1 = op1;
7575
return 1;
7676
} else if (_values[res].op == IR_COPY && _values[res].op1 == op1) {
7777
return 0; /* not changed */
78-
#endif
78+
} else {
79+
IR_ASSERT(_values[res].optx != IR_BOTTOM);
80+
/* we don't check for widening */
81+
_values[res].optx = IR_OPT(IR_COPY, insn->type);
82+
_values[res].op1 = op1;
83+
return 1;
84+
#else
7985
} else {
8086
IR_MAKE_BOTTOM(res);
8187
return 1;
88+
#endif
8289
}
8390
break;
8491
case IR_FOLD_DO_CONST:
@@ -100,36 +107,148 @@ static ir_ref ir_sccp_fold(ir_ctx *ctx, ir_insn *_values, ir_ref res, uint32_t o
100107
return 0; /* not changed */
101108
}
102109

103-
static bool ir_sccp_join_values(ir_ctx *ctx, ir_insn *_values, ir_ref a, ir_ref b)
110+
static bool ir_sccp_meet_phi(ir_ctx *ctx, ir_insn *_values, ir_ref i, ir_insn *insn, ir_bitqueue *worklist)
104111
{
105-
ir_insn *v;
112+
ir_ref j, n, input, *merge_input, *p;
113+
ir_insn *v, *new_const = NULL;
114+
#if IR_COMBO_COPY_PROPAGATION
115+
ir_ref new_copy;
116+
#endif
117+
118+
if (!IR_IS_FEASIBLE(insn->op1)) {
119+
return 0;
120+
}
121+
n = insn->inputs_count;
122+
if (n > 3 && _values[i].optx == IR_TOP) {
123+
for (j = 0; j < (n>>2); j++) {
124+
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
125+
}
126+
}
127+
128+
p = insn->ops + 2;
129+
merge_input = ctx->ir_base[insn->op1].ops + 1;
130+
for (; --n > 0; p++, merge_input++) {
131+
IR_ASSERT(*merge_input > 0);
132+
if (_values[*merge_input].optx == IR_TOP) {
133+
continue;
134+
}
106135

107-
if (!IR_IS_BOTTOM(a) && !IR_IS_TOP(b)) {
108-
b = ir_sccp_identity(_values, b);
109-
v = IR_IS_CONST_REF(b) ? &ctx->ir_base[b] : &_values[b];
110-
if (IR_IS_TOP(a)) {
136+
input = *p;
137+
if (IR_IS_CONST_REF(input)) {
138+
v = &ctx->ir_base[input];
139+
} else if (input == i) {
140+
continue;
141+
} else {
142+
v = &_values[input];
143+
if (v->op == IR_TOP) {
144+
/* do backward propagaton only once */
145+
if (!v->op1) {
146+
v->op1 = 1;
147+
ir_bitqueue_add(worklist, input);
148+
}
149+
continue;
111150
#if IR_COMBO_COPY_PROPAGATION
112-
if (v->op == IR_BOTTOM) {
113-
_values[a].optx = IR_OPT(IR_COPY, ctx->ir_base[b].type);
114-
_values[a].op1 = b;
151+
} else if (v->op == IR_COPY) {
152+
input = v->op1;
153+
IR_ASSERT(input > 0 && _values[input].op != IR_COPY);
154+
new_copy = input;
155+
goto next;
156+
} else if (v->op == IR_BOTTOM) {
157+
new_copy = input;
158+
goto next;
159+
#else
160+
} else if (v->op == IR_BOTTOM) {
161+
IR_MAKE_BOTTOM(i);
115162
return 1;
116-
}
117163
#endif
118-
_values[a].optx = v->opt;
119-
_values[a].val.u64 = v->val.u64;
120-
return 1;
121-
} else if (_values[a].opt == v->opt && _values[a].val.u64 == v->val.u64) {
122-
/* pass */
164+
}
165+
}
166+
new_copy = IR_UNUSED;
167+
new_const = v;
168+
goto next;
169+
}
170+
171+
IR_ASSERT(_values[i].optx == IR_TOP);
172+
return 0;
173+
174+
next:
175+
p++;
176+
merge_input++;
177+
/* for all live merge inputs */
178+
for (; --n > 0; p++, merge_input++) {
179+
IR_ASSERT(*merge_input > 0);
180+
if (_values[*merge_input].optx == IR_TOP) {
181+
continue;
182+
}
183+
184+
input = *p;
185+
if (IR_IS_CONST_REF(input)) {
186+
v = &ctx->ir_base[input];
187+
} else if (input == i) {
188+
continue;
189+
} else {
190+
v = &_values[input];
191+
if (v->op == IR_TOP) {
192+
/* do backward propagaton only once */
193+
if (!v->op1) {
194+
v->op1 = 1;
195+
ir_bitqueue_add(worklist, input);
196+
}
197+
continue;
123198
#if IR_COMBO_COPY_PROPAGATION
124-
} else if (_values[a].op == IR_COPY && _values[a].op1 == b) {
125-
/* pass */
199+
} else if (v->op == IR_COPY) {
200+
input = v->op1;
201+
IR_ASSERT(input > 0 && _values[input].op != IR_COPY);
202+
if (new_copy == input) {
203+
continue;
204+
} else {
205+
IR_MAKE_BOTTOM(i);
206+
return 1;
207+
}
208+
} else if (v->op == IR_BOTTOM) {
209+
if (new_copy == input) {
210+
continue;
211+
} else {
212+
IR_MAKE_BOTTOM(i);
213+
return 1;
214+
}
215+
#else
216+
} else if (v->op == IR_BOTTOM) {
217+
IR_MAKE_BOTTOM(i);
218+
return 1;
126219
#endif
220+
}
221+
}
222+
if (!new_const || new_const->opt != v->opt || new_const->val.u64 != v->val.u64) {
223+
IR_MAKE_BOTTOM(i);
224+
return 1;
225+
}
226+
}
227+
228+
#if IR_COMBO_COPY_PROPAGATION
229+
if (new_copy) {
230+
if (_values[i].op == IR_COPY && _values[i].op1 == new_copy) {
231+
return 0; /* not changed */
127232
} else {
128-
IR_MAKE_BOTTOM(a);
233+
IR_ASSERT(_values[i].optx != IR_BOTTOM);
234+
/* we don't check for widening */
235+
_values[i].optx = IR_OPT(IR_COPY, ctx->ir_base[new_copy].type);
236+
_values[i].op1 = new_copy;
129237
return 1;
130238
}
131239
}
132-
return 0;
240+
#endif
241+
242+
if (_values[i].optx == IR_TOP) {
243+
_values[i].optx = new_const->opt;
244+
_values[i].val.u64 = new_const->val.u64;
245+
return 1;
246+
} else if (_values[i].opt == new_const->opt && _values[i].val.u64 == new_const->val.u64) {
247+
return 0;
248+
} else {
249+
IR_MAKE_BOTTOM(i);
250+
return 1;
251+
}
133252
}
134253

135254
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)
585704
flags = ir_op_flags[insn->op];
586705
if (flags & IR_OP_FLAG_DATA) {
587706
if (insn->op == IR_PHI) {
588-
ir_insn *merge_insn = &ctx->ir_base[insn->op1];
589-
bool changed = 0;
590-
591-
if (!IR_IS_FEASIBLE(insn->op1)) {
592-
continue;
593-
}
594-
n = merge_insn->inputs_count + 1;
595-
if (n > 3 && _values[i].optx == IR_TOP) {
596-
for (j = 0; j < (n>>2); j++) {
597-
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
598-
}
599-
}
600-
/* for all live merge inputs */
601-
for (j = 1; j < n; j++) {
602-
ir_ref merge_input = ir_insn_op(merge_insn, j);
603-
604-
IR_ASSERT(merge_input > 0);
605-
if (_values[merge_input].optx != IR_TOP) {
606-
ir_ref input = ir_insn_op(insn, j + 1);
607-
608-
if (input > 0 && IR_IS_TOP(input)) {
609-
/* do backward propagaton only once */
610-
if (!_values[input].op1) {
611-
_values[input].op1 = 1;
612-
ir_bitqueue_add(&worklist, input);
613-
}
614-
} else if (ir_sccp_join_values(ctx, _values, i, input)) {
615-
changed = 1;
616-
}
617-
}
618-
}
619-
if (!changed) {
707+
if (!ir_sccp_meet_phi(ctx, _values, i, insn, &worklist)) {
620708
continue;
621709
}
622710
} else if (ctx->use_lists[i].count == 0) {

0 commit comments

Comments
 (0)