Skip to content

Commit a3620cd

Browse files
committed
Update IR
IR commit: d2ab283e3c3bb4b5ba21701a4d18f14fd9b3d798
1 parent 71cccc0 commit a3620cd

File tree

4 files changed

+291
-29
lines changed

4 files changed

+291
-29
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,7 @@ static ir_ref _ir_fold_cse(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir
878878

879879
#define IR_FOLD_CONST_F(_val) do { \
880880
val.f = (_val); \
881+
val.u32_hi = 0; \
881882
goto ir_fold_const; \
882883
} while (0)
883884

@@ -1756,7 +1757,7 @@ static ir_ref ir_find_aliasing_load(ir_ctx *ctx, ir_ref ref, ir_type type, ir_re
17561757
}
17571758
} else if (insn->op == IR_RSTORE) {
17581759
modified_regset |= (1 << insn->op3);
1759-
} else if (insn->op >= IR_START || insn->op == IR_CALL || insn->op == IR_VSTORE) {
1760+
} else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || insn->op == IR_CALL || insn->op == IR_VSTORE) {
17601761
return IR_UNUSED;
17611762
}
17621763
ref = insn->op1;
@@ -2322,7 +2323,7 @@ void _ir_GUARD(ir_ctx *ctx, ir_ref condition, ir_ref addr)
23222323
condition = IR_FALSE;
23232324
break;
23242325
}
2325-
} else if (insn->op >= IR_START) {
2326+
} else if (insn->op == IR_START || insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
23262327
break;
23272328
}
23282329
ref = insn->op1;
@@ -2354,7 +2355,7 @@ void _ir_GUARD_NOT(ir_ctx *ctx, ir_ref condition, ir_ref addr)
23542355
condition = IR_TRUE;
23552356
break;
23562357
}
2357-
} else if (insn->op >= IR_START) {
2358+
} else if (insn->op == IR_START || insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
23582359
break;
23592360
}
23602361
ref = insn->op1;

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,14 @@ static bool aarch64_may_encode_addr_offset(int64_t offset, uint32_t type_size)
160160
|| }
161161
|.endmacro
162162

163+
|.macro ASM_REG_REG_REG_TXT_OP, op, type, dst, src1, src2, txt
164+
|| if (ir_type_size[type] == 8) {
165+
| op Rx(dst), Rx(src1), Rx(src2), txt
166+
|| } else {
167+
| op Rw(dst), Rw(src1), Rw(src2), txt
168+
|| }
169+
|.endmacro
170+
163171
|.macro ASM_REG_REG_REG_REG_OP, op, type, dst, src1, src2, src3
164172
|| if (ir_type_size[type] == 8) {
165173
| op Rx(dst), Rx(src1), Rx(src2), Rx(src3)
@@ -280,6 +288,7 @@ const char *ir_reg_name(int8_t reg, ir_type type)
280288
_(DIV_PWR2) \
281289
_(MOD_PWR2) \
282290
_(SDIV_PWR2) \
291+
_(SMOD_PWR2) \
283292
_(OP_INT) \
284293
_(OP_FP) \
285294
_(BINOP_INT) \
@@ -378,10 +387,6 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
378387
n++;
379388
}
380389
break;
381-
case IR_SEXT:
382-
case IR_ZEXT:
383-
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
384-
IR_FALLTHROUGH;
385390
case IR_MUL_PWR2:
386391
case IR_DIV_PWR2:
387392
case IR_MOD_PWR2:
@@ -432,6 +437,17 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
432437
}
433438
}
434439
break;
440+
case IR_SMOD_PWR2:
441+
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
442+
insn = &ctx->ir_base[ref];
443+
n = 0;
444+
if (IR_IS_CONST_REF(insn->op1)) {
445+
constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
446+
n++;
447+
}
448+
constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_USE_SUB_REF, IR_SAVE_SUB_REF);
449+
n++;
450+
break;
435451
case IR_CTPOP:
436452
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG;
437453
insn = &ctx->ir_base[ref];
@@ -565,6 +581,13 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
565581
break;
566582
case IR_COPY_INT:
567583
case IR_COPY_FP:
584+
case IR_TRUNC:
585+
case IR_BITCAST:
586+
case IR_PROTO:
587+
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
588+
break;
589+
case IR_ZEXT:
590+
case IR_SEXT:
568591
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG;
569592
break;
570593
case IR_PARAM:
@@ -582,11 +605,6 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
582605
case IR_EXITCALL:
583606
constraints->def_reg = IR_REG_INT_RET1;
584607
break;
585-
case IR_TRUNC:
586-
case IR_BITCAST:
587-
case IR_PROTO:
588-
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
589-
break;
590608
case IR_RSTORE:
591609
flags = IR_OP3_SHOULD_BE_IN_REG;
592610
break;
@@ -750,9 +768,12 @@ binop_fp:
750768
/* pass */
751769
} else if (IR_IS_CONST_REF(insn->op1)) {
752770
// const
753-
} else if (IR_IS_TYPE_UNSIGNED(insn->type) && IR_IS_POWER_OF_TWO(op2_insn->val.u64)) {
754-
// TODO: signed division by power of two ???
755-
return IR_MOD_PWR2;
771+
} else if (IR_IS_POWER_OF_TWO(op2_insn->val.u64)) {
772+
if (IR_IS_TYPE_UNSIGNED(insn->type)) {
773+
return IR_MOD_PWR2;
774+
} else {
775+
return IR_SMOD_PWR2;
776+
}
756777
}
757778
}
758779
return IR_BINOP_INT;
@@ -2073,11 +2094,9 @@ static void ir_emit_mul_div_mod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
20732094
}
20742095
} else if (insn->op == IR_DIV) {
20752096
uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
2076-
IR_ASSERT(IR_IS_TYPE_UNSIGNED(type));
20772097
| ASM_REG_REG_IMM_OP lsr, type, def_reg, op1_reg, shift
20782098
} else {
20792099
IR_ASSERT(insn->op == IR_MOD);
2080-
IR_ASSERT(IR_IS_TYPE_UNSIGNED(type));
20812100
uint64_t mask = ctx->ir_base[insn->op2].val.u64 - 1;
20822101
| ASM_REG_REG_IMM_OP and, type, def_reg, op1_reg, mask
20832102
}
@@ -2142,6 +2161,50 @@ static void ir_emit_sdiv_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
21422161
}
21432162
}
21442163

2164+
static void ir_emit_smod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2165+
{
2166+
ir_backend_data *data = ctx->data;
2167+
dasm_State **Dst = &data->dasm_state;
2168+
ir_type type = insn->type;
2169+
ir_ref op1 = insn->op1;
2170+
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
2171+
ir_reg op1_reg = ctx->regs[def][1];
2172+
ir_reg tmp_reg = ctx->regs[def][3];
2173+
// uint32_t shift = IR_LOG2(ctx->ir_base[insn->op2].val.u64);
2174+
uint64_t mask = ctx->ir_base[insn->op2].val.u64 - 1;
2175+
2176+
IR_ASSERT(IR_IS_CONST_REF(insn->op2));
2177+
IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op));
2178+
IR_ASSERT(def_reg != IR_REG_NONE && tmp_reg != IR_REG_NONE && def_reg != tmp_reg);
2179+
2180+
if (op1_reg != IR_REG_NONE && IR_REG_SPILLED(op1_reg)) {
2181+
op1_reg = IR_REG_NUM(op1_reg);
2182+
ir_emit_load(ctx, type, op1_reg, op1);
2183+
}
2184+
if (def_reg != op1_reg) {
2185+
if (op1_reg != IR_REG_NONE) {
2186+
ir_emit_mov(ctx, type, def_reg, op1_reg);
2187+
} else {
2188+
ir_emit_load(ctx, type, def_reg, op1);
2189+
}
2190+
}
2191+
2192+
// | ASM_REG_REG_IMM_OP asr, type, tmp_reg, def_reg, (ir_type_size[type]*8-1)
2193+
// | ASM_REG_REG_IMM_OP lsr, type, tmp_reg, tmp_reg, (ir_type_size[type]*8-shift)
2194+
// | ASM_REG_REG_REG_OP add, type, def_reg, def_reg, tmp_reg
2195+
// | ASM_REG_REG_IMM_OP and, type, def_reg, def_reg, mask
2196+
// | ASM_REG_REG_REG_OP sub, type, def_reg, def_reg, tmp_reg
2197+
2198+
| ASM_REG_REG_OP negs, type, tmp_reg, def_reg
2199+
| ASM_REG_REG_IMM_OP and, type, def_reg, def_reg, mask
2200+
| ASM_REG_REG_IMM_OP and, type, tmp_reg, tmp_reg, mask
2201+
| ASM_REG_REG_REG_TXT_OP csneg, type, def_reg, def_reg, tmp_reg, mi
2202+
2203+
if (IR_REG_SPILLED(ctx->regs[def][0])) {
2204+
ir_emit_store(ctx, type, def, def_reg);
2205+
}
2206+
}
2207+
21452208
static void ir_emit_shift(ir_ctx *ctx, ir_ref def, ir_insn *insn)
21462209
{
21472210
ir_backend_data *data = ctx->data;
@@ -5625,6 +5688,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
56255688
case IR_SDIV_PWR2:
56265689
ir_emit_sdiv_pwr2(ctx, i, insn);
56275690
break;
5691+
case IR_SMOD_PWR2:
5692+
ir_emit_smod_pwr2(ctx, i, insn);
5693+
break;
56285694
case IR_SHIFT:
56295695
ir_emit_shift(ctx, i, insn);
56305696
break;

ext/opcache/jit/ir/ir_fold.h

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,6 +1992,104 @@ IR_FOLD(GE(ABS, C_DOUBLE))
19921992
}
19931993

19941994
// TODO: conversions
1995+
IR_FOLD(FP2FP(FP2FP))
1996+
{
1997+
if (IR_OPT_TYPE(opt) == IR_FLOAT) {
1998+
/* (float)(double)f => f */
1999+
IR_ASSERT(op1_insn->type == IR_DOUBLE);
2000+
IR_ASSERT(ctx->ir_base[op1_insn->op1].type == IR_FLOAT);
2001+
IR_FOLD_COPY(op1_insn->op1);
2002+
}
2003+
IR_FOLD_NEXT;
2004+
}
2005+
2006+
IR_FOLD(FP2INT(INT2FP))
2007+
{
2008+
ir_type dst_type = IR_OPT_TYPE(opt);
2009+
ir_type src_type = ctx->ir_base[op1_insn->op1].type;
2010+
2011+
if (ir_type_size[src_type] >= ir_type_size[op1_insn->type]) {
2012+
/* source integer type can not fit into intermediate floating point */
2013+
IR_FOLD_NEXT;
2014+
}
2015+
/* (int)(double)i => i */
2016+
if (src_type == dst_type) {
2017+
IR_FOLD_COPY(op1_insn->op1);
2018+
}
2019+
IR_FOLD_NEXT;
2020+
}
2021+
2022+
IR_FOLD(TRUNC(ZEXT))
2023+
IR_FOLD(TRUNC(SEXT))
2024+
{
2025+
ir_type dst_type = IR_OPT_TYPE(opt);
2026+
ir_type src_type = ctx->ir_base[op1_insn->op1].type;
2027+
2028+
/* (int32_t)(int64_t)i => i */
2029+
if (src_type == dst_type) {
2030+
IR_FOLD_COPY(op1_insn->op1);
2031+
} else if (ir_type_size[src_type] == ir_type_size[dst_type]) {
2032+
opt = IR_OPT(IR_BITCAST, dst_type);
2033+
op1 = op1_insn->op1;
2034+
IR_FOLD_RESTART;
2035+
} else if (ir_type_size[src_type] > ir_type_size[dst_type]) {
2036+
opt = IR_OPT(IR_TRUNC, dst_type);
2037+
op1 = op1_insn->op1;
2038+
IR_FOLD_RESTART;
2039+
} else {
2040+
opt = IR_OPT(op1_insn->op, dst_type);
2041+
op1 = op1_insn->op1;
2042+
IR_FOLD_RESTART;
2043+
}
2044+
IR_FOLD_NEXT;
2045+
}
2046+
2047+
IR_FOLD(TRUNC(AND))
2048+
{
2049+
if (IR_IS_CONST_REF(op1_insn->op2)) {
2050+
size_t size = ir_type_size[IR_OPT_TYPE(opt)];
2051+
uint64_t mask = ctx->ir_base[op1_insn->op2].val.u64;
2052+
2053+
if (size == 1) {
2054+
if (mask == 0xff) {
2055+
op1 = op1_insn->op1;
2056+
IR_FOLD_RESTART;
2057+
}
2058+
} else if (size == 2) {
2059+
if (mask == 0xffff) {
2060+
op1 = op1_insn->op1;
2061+
IR_FOLD_RESTART;
2062+
}
2063+
} else if (size == 4) {
2064+
if (mask == 0xffffffff) {
2065+
op1 = op1_insn->op1;
2066+
IR_FOLD_RESTART;
2067+
}
2068+
}
2069+
}
2070+
IR_FOLD_NEXT;
2071+
}
2072+
2073+
IR_FOLD(EQ(FP2FP, C_DOUBLE))
2074+
IR_FOLD(NE(FP2FP, C_DOUBLE))
2075+
IR_FOLD(LT(FP2FP, C_DOUBLE))
2076+
IR_FOLD(GE(FP2FP, C_DOUBLE))
2077+
IR_FOLD(LE(FP2FP, C_DOUBLE))
2078+
IR_FOLD(GT(FP2FP, C_DOUBLE))
2079+
IR_FOLD(ULT(FP2FP, C_DOUBLE))
2080+
IR_FOLD(UGE(FP2FP, C_DOUBLE))
2081+
IR_FOLD(ULE(FP2FP, C_DOUBLE))
2082+
IR_FOLD(UGT(FP2FP, C_DOUBLE))
2083+
{
2084+
IR_ASSERT(op1_insn->type == IR_DOUBLE);
2085+
IR_ASSERT(ctx->ir_base[op1_insn->op1].type == IR_FLOAT);
2086+
if (op2_insn->val.d == (double)(float)op2_insn->val.d) {
2087+
op1 = op1_insn->op1;
2088+
op2 = ir_const_float(ctx, (float)op2_insn->val.d);
2089+
IR_FOLD_RESTART;
2090+
}
2091+
IR_FOLD_NEXT;
2092+
}
19952093

19962094
// TODO: Reassociation
19972095
IR_FOLD(ADD(ADD, C_U8))

0 commit comments

Comments
 (0)