Skip to content

Commit 191430d

Browse files
committed
Update IR
IR commit: 5a81104e650ebd7ac24eb63d4dff67db723a5278
1 parent 55f4d4c commit 191430d

File tree

7 files changed

+268
-60
lines changed

7 files changed

+268
-60
lines changed

ext/opcache/jit/ir/ir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ typedef enum _ir_type {
257257
_(UGE, d2, def, def, ___) /* unsigned greater or equal */ \
258258
_(ULE, d2, def, def, ___) /* unsigned less or equal */ \
259259
_(UGT, d2, def, def, ___) /* unsigned greater */ \
260+
_(ORDERED, d2, def, def, ___) /* both operands are not NAN */ \
261+
_(UNORDERED, d2, def, def, ___) /* one of operands is NAN */ \
260262
\
261263
/* arithmetic ops */ \
262264
_(ADD, d2C, def, def, ___) /* addition */ \

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref)
747747
return IR_CMP_FP;
748748
}
749749
break;
750+
case IR_ORDERED:
751+
case IR_UNORDERED:
752+
return IR_CMP_FP;
750753
case IR_ADD:
751754
case IR_SUB:
752755
if (IR_IS_TYPE_INT(insn->type)) {
@@ -1043,7 +1046,7 @@ binop_fp:
10431046
case IR_IF:
10441047
if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
10451048
op2_insn = &ctx->ir_base[insn->op2];
1046-
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT) {
1049+
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED) {
10471050
if (IR_IS_TYPE_INT(ctx->ir_base[op2_insn->op1].type)) {
10481051
ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
10491052
return IR_CMP_AND_BRANCH_INT;
@@ -1066,7 +1069,7 @@ binop_fp:
10661069
case IR_GUARD_NOT:
10671070
if (!IR_IS_CONST_REF(insn->op2) && ctx->use_lists[insn->op2].count == 1) {
10681071
op2_insn = &ctx->ir_base[insn->op2];
1069-
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UGT
1072+
if (op2_insn->op >= IR_EQ && op2_insn->op <= IR_UNORDERED
10701073
// TODO: register allocator may clobber operands of CMP before they are used in the GUARD_CMP
10711074
&& (insn->op2 == ref - 1 ||
10721075
(insn->op2 == ctx->prev_ref[ref] - 1
@@ -1110,6 +1113,9 @@ binop_fp:
11101113
ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP;
11111114
}
11121115
}
1116+
} else {
1117+
/* va_list may escape */
1118+
ctx->flags2 |= IR_HAS_VA_ARG_GP|IR_HAS_VA_ARG_FP;
11131119
}
11141120
return IR_VA_START;
11151121
case IR_VA_END:
@@ -2991,6 +2997,12 @@ static void ir_emit_cmp_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
29912997
case IR_UGT:
29922998
| cset Rw(def_reg), hi
29932999
break;
3000+
case IR_ORDERED:
3001+
| cset Rw(def_reg), vc
3002+
break;
3003+
case IR_UNORDERED:
3004+
| cset Rw(def_reg), vs
3005+
break;
29943006
}
29953007
if (IR_REG_SPILLED(ctx->regs[def][0])) {
29963008
ir_emit_store(ctx, insn->type, def, def_reg);
@@ -3065,7 +3077,7 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint
30653077
ir_get_true_false_blocks(ctx, b, &true_block, &false_block);
30663078
if (true_block == next_block) {
30673079
/* swap to avoid unconditional JMP */
3068-
if (int_cmp || op == IR_EQ || op == IR_NE) {
3080+
if (int_cmp || op == IR_EQ || op == IR_NE || op == IR_ORDERED || op == IR_UNORDERED) {
30693081
op ^= 1; // reverse
30703082
} else {
30713083
op ^= 5; // reverse
@@ -3145,6 +3157,11 @@ static void ir_emit_jcc(ir_ctx *ctx, uint32_t b, ir_ref def, ir_insn *insn, uint
31453157
case IR_UGT:
31463158
| bhi =>true_block
31473159
break;
3160+
case IR_ORDERED:
3161+
| bvc =>true_block
3162+
break;
3163+
case IR_UNORDERED:
3164+
| bvs =>true_block
31483165
// case IR_ULT: fprintf(stderr, "\tjb .LL%d\n", true_block); break;
31493166
// case IR_UGE: fprintf(stderr, "\tjae .LL%d\n", true_block); break;
31503167
// case IR_ULE: fprintf(stderr, "\tjbe .LL%d\n", true_block); break;
@@ -4462,11 +4479,7 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
44624479
ir_reg tmp_reg = ctx->regs[def][3];
44634480
int32_t offset;
44644481

4465-
if (ctx->use_lists[def].count == 1) {
4466-
/* dead load */
4467-
return;
4468-
}
4469-
IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE);
4482+
IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE);
44704483
if (op2_reg != IR_REG_NONE) {
44714484
if (IR_REG_SPILLED(op2_reg)) {
44724485
op2_reg = IR_REG_NUM(op2_reg);
@@ -4479,10 +4492,12 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
44794492
offset = ir_local_offset(ctx, &ctx->ir_base[insn->op2]);
44804493
}
44814494
| ldr Rx(tmp_reg), [Rx(op2_reg), #offset]
4482-
ir_emit_load_mem(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0));
4495+
if (def_reg != IR_REG_NONE) {
4496+
ir_emit_load_mem(ctx, type, def_reg, IR_MEM_BO(tmp_reg, 0));
4497+
}
44834498
| add Rx(tmp_reg), Rx(tmp_reg), #IR_MAX(ir_type_size[type], sizeof(void*))
44844499
| str Rx(tmp_reg), [Rx(op2_reg), #offset]
4485-
if (IR_REG_SPILLED(ctx->regs[def][0])) {
4500+
if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) {
44864501
ir_emit_store(ctx, type, def, def_reg);
44874502
}
44884503
#else
@@ -4494,11 +4509,7 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
44944509
ir_reg tmp_reg = ctx->regs[def][3];
44954510
int32_t offset;
44964511

4497-
if (ctx->use_lists[def].count == 1) {
4498-
/* dead load */
4499-
return;
4500-
}
4501-
IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE);
4512+
IR_ASSERT((def_reg != IR_REG_NONE || ctx->use_lists[def].count == 1) && tmp_reg != IR_REG_NONE);
45024513
if (op2_reg != IR_REG_NONE) {
45034514
if (IR_REG_SPILLED(op2_reg)) {
45044515
op2_reg = IR_REG_NUM(op2_reg);
@@ -4517,13 +4528,17 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
45174528
| ldr Rx(IR_REG_INT_TMP), [Rx(op2_reg), #(offset+offsetof(ir_va_list, gr_top))]
45184529
| sxtw Rx(tmp_reg), Rw(tmp_reg)
45194530
| add Rx(IR_REG_INT_TMP), Rx(tmp_reg), Rx(IR_REG_INT_TMP)
4520-
| ldr Rx(def_reg), [Rx(IR_REG_INT_TMP)]
4531+
if (def_reg != IR_REG_NONE) {
4532+
| ldr Rx(def_reg), [Rx(IR_REG_INT_TMP)]
4533+
}
45214534
| add Rw(tmp_reg), Rw(tmp_reg), #sizeof(void*)
45224535
| str Rw(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, gr_offset))]
45234536
| b >2
45244537
|1:
45254538
| ldr Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))]
4526-
| ldr Rx(def_reg), [Rx(tmp_reg)]
4539+
if (def_reg != IR_REG_NONE) {
4540+
| ldr Rx(def_reg), [Rx(tmp_reg)]
4541+
}
45274542
| add Rx(tmp_reg), Rx(tmp_reg), #sizeof(void*)
45284543
| str Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))]
45294544
|2:
@@ -4534,18 +4549,22 @@ static void ir_emit_va_arg(ir_ctx *ctx, ir_ref def, ir_insn *insn)
45344549
| ldr Rx(IR_REG_INT_TMP), [Rx(op2_reg), #(offset+offsetof(ir_va_list, vr_top))]
45354550
| sxtw Rx(tmp_reg), Rw(tmp_reg)
45364551
| add Rx(IR_REG_INT_TMP), Rx(tmp_reg), Rx(IR_REG_INT_TMP)
4537-
| ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(IR_REG_INT_TMP)]
4552+
if (def_reg != IR_REG_NONE) {
4553+
| ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(IR_REG_INT_TMP)]
4554+
}
45384555
| add Rw(tmp_reg), Rw(tmp_reg), #16
45394556
| str Rw(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, vr_offset))]
45404557
| b >2
45414558
|1:
45424559
| ldr Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))]
4543-
| ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(tmp_reg)]
4560+
if (def_reg != IR_REG_NONE) {
4561+
| ldr Rd(def_reg-IR_REG_FP_FIRST), [Rx(tmp_reg)]
4562+
}
45444563
| add Rx(tmp_reg), Rx(tmp_reg), #sizeof(void*)
45454564
| str Rx(tmp_reg), [Rx(op2_reg), #(offset+offsetof(ir_va_list, stack))]
45464565
|2:
45474566
}
4548-
if (IR_REG_SPILLED(ctx->regs[def][0])) {
4567+
if (def_reg != IR_REG_NONE && IR_REG_SPILLED(ctx->regs[def][0])) {
45494568
ir_emit_store(ctx, type, def, def_reg);
45504569
}
45514570
#endif
@@ -5378,6 +5397,11 @@ static void ir_emit_guard_jcc(ir_ctx *ctx, uint8_t op, void *addr, bool int_cmp)
53785397
case IR_GT:
53795398
| bgt &addr
53805399
break;
5400+
case IR_ORDERED:
5401+
| bvc &addr
5402+
break;
5403+
case IR_UNORDERED:
5404+
| bvs &addr
53815405
// case IR_ULT: fprintf(stderr, "\tjb .LL%d\n", true_block); break;
53825406
// case IR_UGE: fprintf(stderr, "\tjae .LL%d\n", true_block); break;
53835407
// case IR_ULE: fprintf(stderr, "\tjbe .LL%d\n", true_block); break;

ext/opcache/jit/ir/ir_check.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void ir_consistency_check(void)
3636
IR_ASSERT((IR_UGT ^ 3) == IR_ULT);
3737
IR_ASSERT((IR_ULE ^ 3) == IR_UGE);
3838
IR_ASSERT((IR_UGE ^ 3) == IR_ULE);
39+
IR_ASSERT((IR_ORDERED ^ 1) == IR_UNORDERED);
3940

4041
IR_ASSERT(IR_ADD + 1 == IR_SUB);
4142
}

ext/opcache/jit/ir/ir_fold.h

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,106 @@ IR_FOLD(UGT(C_FLOAT, C_FLOAT))
274274
IR_FOLD_BOOL(!(op1_insn->val.f <= op2_insn->val.f));
275275
}
276276

277+
IR_FOLD(ORDERED(C_FLOAT, C_FLOAT))
278+
{
279+
IR_FOLD_BOOL(!isnan(op1_insn->val.f) && !isnan(op2_insn->val.f));
280+
}
281+
282+
IR_FOLD(ORDERED(C_DOUBLE, C_DOUBLE))
283+
{
284+
IR_FOLD_BOOL(!isnan(op1_insn->val.d) && !isnan(op2_insn->val.d));
285+
}
286+
287+
IR_FOLD(UNORDERED(C_FLOAT, C_FLOAT))
288+
{
289+
IR_FOLD_BOOL(isnan(op1_insn->val.f) || isnan(op2_insn->val.f));
290+
}
291+
292+
IR_FOLD(UNORDERED(C_DOUBLE, C_DOUBLE))
293+
{
294+
IR_FOLD_BOOL(isnan(op1_insn->val.d) || isnan(op2_insn->val.d));
295+
}
296+
297+
IR_FOLD(EQ(_, C_FLOAT))
298+
IR_FOLD(LT(_, C_FLOAT))
299+
IR_FOLD(GE(_, C_FLOAT))
300+
IR_FOLD(LE(_, C_FLOAT))
301+
IR_FOLD(GT(_, C_FLOAT))
302+
{
303+
if (isnan(op2_insn->val.f)) {
304+
IR_FOLD_COPY(IR_FALSE);
305+
}
306+
IR_FOLD_NEXT;
307+
}
308+
309+
IR_FOLD(NE(_, C_FLOAT))
310+
{
311+
if (isnan(op2_insn->val.f)) {
312+
IR_FOLD_COPY(IR_TRUE);
313+
}
314+
IR_FOLD_NEXT;
315+
}
316+
317+
IR_FOLD(ORDERED(_, C_FLOAT))
318+
{
319+
if (isnan(op2_insn->val.f)) {
320+
IR_FOLD_COPY(IR_FALSE);
321+
} else {
322+
op2 = op1;
323+
IR_FOLD_RESTART;
324+
}
325+
}
326+
327+
IR_FOLD(UNORDERED(_, C_FLOAT))
328+
{
329+
if (isnan(op2_insn->val.f)) {
330+
IR_FOLD_COPY(IR_TRUE);
331+
} else {
332+
op2 = op1;
333+
IR_FOLD_RESTART;
334+
}
335+
}
336+
337+
IR_FOLD(EQ(_, C_DOUBLE))
338+
IR_FOLD(LT(_, C_DOUBLE))
339+
IR_FOLD(GE(_, C_DOUBLE))
340+
IR_FOLD(LE(_, C_DOUBLE))
341+
IR_FOLD(GT(_, C_DOUBLE))
342+
{
343+
if (isnan(op2_insn->val.d)) {
344+
IR_FOLD_COPY(IR_FALSE);
345+
}
346+
IR_FOLD_NEXT;
347+
}
348+
349+
IR_FOLD(NE(_, C_DOUBLE))
350+
{
351+
if (isnan(op2_insn->val.d)) {
352+
IR_FOLD_COPY(IR_TRUE);
353+
}
354+
IR_FOLD_NEXT;
355+
}
356+
357+
IR_FOLD(ORDERED(_, C_DOUBLE))
358+
{
359+
if (isnan(op2_insn->val.d)) {
360+
IR_FOLD_COPY(IR_FALSE);
361+
} else {
362+
op2 = op1;
363+
IR_FOLD_RESTART;
364+
}
365+
}
366+
367+
IR_FOLD(UNORDERED(_, C_DOUBLE))
368+
{
369+
if (isnan(op2_insn->val.d)) {
370+
IR_FOLD_COPY(IR_TRUE);
371+
} else {
372+
op2 = op1;
373+
IR_FOLD_RESTART;
374+
}
375+
}
376+
277377
IR_FOLD(ADD(C_U8, C_U8))
278378
{
279379
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
@@ -1645,6 +1745,8 @@ IR_FOLD(NOT(ULT))
16451745
IR_FOLD(NOT(UGE))
16461746
IR_FOLD(NOT(ULE))
16471747
IR_FOLD(NOT(UGT))
1748+
IR_FOLD(NOT(ORDERED))
1749+
IR_FOLD(NOT(UNORDERED))
16481750
{
16491751
if (IR_IS_TYPE_INT(ctx->ir_base[op1_insn->op1].type)) {
16501752
opt = op1_insn->opt ^ 1;
@@ -3182,6 +3284,8 @@ IR_FOLD(ADD(SHR, SHL))
31823284

31833285
/* Swap operands (move lower ref to op2) for better CSE */
31843286
IR_FOLD(MUL(_, _))
3287+
IR_FOLD(ORDERED(_, _))
3288+
IR_FOLD(UNORDERED(_, _))
31853289
IR_FOLD_NAMED(swap_ops)
31863290
{
31873291
if (op1 < op2) { /* move lower ref to op2 */

ext/opcache/jit/ir/ir_gcm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,8 @@ int ir_schedule(ir_ctx *ctx)
13791379
switch (new_insn->op) {
13801380
case IR_EQ:
13811381
case IR_NE:
1382+
case IR_ORDERED:
1383+
case IR_UNORDERED:
13821384
case IR_ADD:
13831385
case IR_MUL:
13841386
case IR_ADD_OV:

0 commit comments

Comments
 (0)