Skip to content

Commit 81593cf

Browse files
committed
Update IR
IR commit: e4343be0082897510c40a1b57baff427c6858878
1 parent d66e87b commit 81593cf

File tree

8 files changed

+189
-30
lines changed

8 files changed

+189
-30
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ static ir_ref _ir_fold_cse(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir
918918
#define IR_FOLD_EMIT goto ir_fold_emit
919919
#define IR_FOLD_NEXT break
920920

921-
#include "ir_fold_hash.h"
921+
#include <ir_fold_hash.h>
922922

923923
#define IR_FOLD_RULE(x) ((x) >> 21)
924924
#define IR_FOLD_KEY(x) ((x) & 0x1fffff)
@@ -1485,6 +1485,18 @@ void ir_update_op(ir_ctx *ctx, ir_ref ref, uint32_t idx, ir_ref new_val)
14851485
void ir_array_grow(ir_array *a, uint32_t size)
14861486
{
14871487
IR_ASSERT(size > a->size);
1488+
if (size >= 256) {
1489+
size = IR_ALIGNED_SIZE(size, 256);
1490+
} else {
1491+
/* Use big enough power of 2 */
1492+
size -= 1;
1493+
size |= (size >> 1);
1494+
size |= (size >> 2);
1495+
size |= (size >> 4);
1496+
// size |= (size >> 8);
1497+
// size |= (size >> 16);
1498+
size += 1;
1499+
}
14881500
a->refs = ir_mem_realloc(a->refs, size * sizeof(ir_ref));
14891501
a->size = size;
14901502
}
@@ -1820,7 +1832,7 @@ int ir_mem_flush(void *ptr, size_t size)
18201832
#else
18211833
void *ir_mem_mmap(size_t size)
18221834
{
1823-
int prot_flags = PROT_EXEC;
1835+
int prot_flags = PROT_EXEC;
18241836
#if defined(__NetBSD__)
18251837
prot_flags |= PROT_MPROTECT(PROT_READ|PROT_WRITE);
18261838
#endif

ext/opcache/jit/ir/ir.h

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,27 @@ typedef enum _ir_type {
154154
} ir_type;
155155

156156
#ifdef IR_64
157-
# define IR_SIZE_T IR_U64
158-
# define IR_SSIZE_T IR_I64
159-
# define IR_UINTPTR_T IR_U64
160-
# define IR_INTPTR_T IR_I64
161-
# define IR_C_UINTPTR IR_U64
162-
# define IR_C_INTPTR IR_I64
157+
# define IR_SIZE_T IR_U64
158+
# define IR_SSIZE_T IR_I64
159+
# define IR_UINTPTR_T IR_U64
160+
# define IR_INTPTR_T IR_I64
161+
# define IR_C_UINTPTR IR_U64
162+
# define IR_C_INTPTR IR_I64
163+
# define ir_const_size_t ir_const_u64
164+
# define ir_const_ssize_t ir_const_i64
165+
# define ir_const_uintptr_t ir_const_u64
166+
# define ir_const_intptr_t ir_const_i64
163167
#else
164-
# define IR_SIZE_T IR_U32
165-
# define IR_SSIZE_T IR_I32
166-
# define IR_UINTPTR_T IR_U32
167-
# define IR_INTPTR_T IR_I32
168-
# define IR_C_UINTPTR IR_U32
169-
# define IR_C_INTPTR IR_I32
168+
# define IR_SIZE_T IR_U32
169+
# define IR_SSIZE_T IR_I32
170+
# define IR_UINTPTR_T IR_U32
171+
# define IR_INTPTR_T IR_I32
172+
# define IR_C_UINTPTR IR_U32
173+
# define IR_C_INTPTR IR_I32
174+
# define ir_const_size_t ir_const_u32
175+
# define ir_const_ssize_t ir_const_i32
176+
# define ir_const_uintptr_t ir_const_u32
177+
# define ir_const_intptr_t ir_const_i32
170178
#endif
171179

172180
/* List of IR opcodes
@@ -401,8 +409,10 @@ typedef int32_t ir_ref;
401409
#define IR_CONSTS_LIMIT_MIN (-(IR_TRUE - 1))
402410
#define IR_INSNS_LIMIT_MIN (IR_UNUSED + 1)
403411

412+
/* ADDR_MEMBER is neccessary to workaround MSVC C preprocessor bug */
404413
#ifndef IR_64
405-
# define ADDR_MEMBER uintptr_t addr;
414+
# define ADDR_MEMBER uintptr_t addr; \
415+
void *ptr;
406416
#else
407417
# define ADDR_MEMBER
408418
#endif
@@ -412,6 +422,7 @@ typedef union _ir_val {
412422
int64_t i64;
413423
#ifdef IR_64
414424
uintptr_t addr;
425+
void *ptr;
415426
#endif
416427
IR_STRUCT_LOHI(
417428
union {
@@ -466,6 +477,7 @@ typedef struct _ir_insn {
466477
},
467478
union {
468479
ir_ref op1;
480+
ir_ref ref;
469481
ir_ref prev_const;
470482
}
471483
);

ext/opcache/jit/ir/ir_cfg.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,51 @@ void ir_reset_cfg(ir_ctx *ctx)
7777
}
7878
}
7979

80+
static uint32_t IR_NEVER_INLINE ir_cfg_remove_dead_inputs(ir_ctx *ctx, uint32_t *_blocks, ir_block *blocks, uint32_t bb_count)
81+
{
82+
uint32_t b, count = 0;
83+
ir_block *bb = blocks + 1;
84+
ir_insn *insn;
85+
ir_ref i, j, n, *ops, input;
86+
87+
for (b = 1; b <= bb_count; b++, bb++) {
88+
bb->successors = count;
89+
count += ctx->use_lists[bb->end].count;
90+
bb->successors_count = 0;
91+
bb->predecessors = count;
92+
insn = &ctx->ir_base[bb->start];
93+
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
94+
n = insn->inputs_count;
95+
ops = insn->ops;
96+
for (i = 1, j = 1; i <= n; i++) {
97+
input = ops[i];
98+
if (_blocks[input]) {
99+
if (i != j) {
100+
ops[j] = ops[i];
101+
}
102+
j++;
103+
} else if (input > 0) {
104+
ir_use_list_remove_one(ctx, input, bb->start);
105+
}
106+
}
107+
j--;
108+
if (j != n) {
109+
if (j == 1) {
110+
insn->op = IR_BEGIN;
111+
}
112+
insn->inputs_count = j;
113+
bb->predecessors_count = j;
114+
j++;
115+
for (;j <= n; j++) {
116+
ops[j] = IR_UNUSED;
117+
}
118+
}
119+
}
120+
count += bb->predecessors_count;
121+
}
122+
return count;
123+
}
124+
80125
int ir_build_cfg(ir_ctx *ctx)
81126
{
82127
ir_ref n, *p, ref, start, end;
@@ -239,7 +284,10 @@ int ir_build_cfg(ir_ctx *ctx)
239284
bb++;
240285
} IR_BITSET_FOREACH_END();
241286
bb_count = b - 1;
242-
IR_ASSERT(count == edges_count * 2);
287+
if (UNEXPECTED(count != edges_count * 2)) {
288+
count = ir_cfg_remove_dead_inputs(ctx, _blocks, blocks, bb_count);
289+
IR_ASSERT(count != edges_count * 2);
290+
}
243291
ir_mem_free(bb_starts);
244292

245293
/* Create an array of successor/predecessors control edges */

ext/opcache/jit/ir/ir_emit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,9 @@ static int ir_const_label(ir_ctx *ctx, ir_ref ref)
415415
}
416416

417417
#if defined(IR_TARGET_X86) || defined(IR_TARGET_X64)
418-
# include "ir_emit_x86.h"
418+
# include <ir_emit_x86.h>
419419
#elif defined(IR_TARGET_AARCH64)
420-
# include "ir_emit_aarch64.h"
420+
# include <ir_emit_aarch64.h>
421421
#else
422422
# error "Unknown IR target"
423423
#endif

ext/opcache/jit/ir/ir_fold.h

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,36 @@ IR_FOLD(MUL(C_FLOAT, C_FLOAT))
486486
}
487487

488488
IR_FOLD(DIV(C_U8, C_U8))
489+
{
490+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
491+
if (op2_insn->val.u64 == 0) {
492+
/* division by zero */
493+
IR_FOLD_EMIT;
494+
}
495+
IR_FOLD_CONST_U(op1_insn->val.u8 / op2_insn->val.u8);
496+
}
497+
489498
IR_FOLD(DIV(C_U16, C_U16))
499+
{
500+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
501+
if (op2_insn->val.u64 == 0) {
502+
/* division by zero */
503+
IR_FOLD_EMIT;
504+
}
505+
IR_FOLD_CONST_U(op1_insn->val.u16 / op2_insn->val.u16);
506+
}
507+
490508
IR_FOLD(DIV(C_U32, C_U32))
509+
{
510+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
511+
if (op2_insn->val.u64 == 0) {
512+
/* division by zero */
513+
IR_FOLD_EMIT;
514+
}
515+
IR_FOLD_CONST_U(op1_insn->val.u32 / op2_insn->val.u32);
516+
}
517+
491518
IR_FOLD(DIV(C_U64, C_U64))
492-
IR_FOLD(DIV(C_ADDR, C_ADDR))
493519
{
494520
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
495521
if (op2_insn->val.u64 == 0) {
@@ -499,9 +525,46 @@ IR_FOLD(DIV(C_ADDR, C_ADDR))
499525
IR_FOLD_CONST_U(op1_insn->val.u64 / op2_insn->val.u64);
500526
}
501527

528+
IR_FOLD(DIV(C_ADDR, C_ADDR))
529+
{
530+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
531+
if (op2_insn->val.u64 == 0) {
532+
/* division by zero */
533+
IR_FOLD_EMIT;
534+
}
535+
IR_FOLD_CONST_U(op1_insn->val.addr / op2_insn->val.addr);
536+
}
537+
502538
IR_FOLD(DIV(C_I8, C_I8))
539+
{
540+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
541+
if (op2_insn->val.i64 == 0) {
542+
/* division by zero */
543+
IR_FOLD_EMIT;
544+
}
545+
IR_FOLD_CONST_I(op1_insn->val.i8 / op2_insn->val.i8);
546+
}
547+
503548
IR_FOLD(DIV(C_I16, C_I16))
549+
{
550+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
551+
if (op2_insn->val.i64 == 0) {
552+
/* division by zero */
553+
IR_FOLD_EMIT;
554+
}
555+
IR_FOLD_CONST_I(op1_insn->val.i16 / op2_insn->val.i16);
556+
}
557+
504558
IR_FOLD(DIV(C_I32, C_I32))
559+
{
560+
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
561+
if (op2_insn->val.i64 == 0) {
562+
/* division by zero */
563+
IR_FOLD_EMIT;
564+
}
565+
IR_FOLD_CONST_I(op1_insn->val.i32 / op2_insn->val.i32);
566+
}
567+
505568
IR_FOLD(DIV(C_I64, C_I64))
506569
{
507570
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
@@ -1135,6 +1198,7 @@ IR_FOLD(MAX(C_FLOAT, C_FLOAT))
11351198
IR_FOLD(SEXT(C_I8))
11361199
IR_FOLD(SEXT(C_U8))
11371200
IR_FOLD(SEXT(C_BOOL))
1201+
IR_FOLD(SEXT(C_CHAR))
11381202
{
11391203
IR_ASSERT(IR_IS_TYPE_INT(IR_OPT_TYPE(opt)));
11401204
IR_ASSERT(ir_type_size[IR_OPT_TYPE(opt)] > ir_type_size[op1_insn->type]);
@@ -1160,6 +1224,7 @@ IR_FOLD(SEXT(C_U32))
11601224
IR_FOLD(ZEXT(C_I8))
11611225
IR_FOLD(ZEXT(C_U8))
11621226
IR_FOLD(ZEXT(C_BOOL))
1227+
IR_FOLD(ZEXT(C_CHAR))
11631228
{
11641229
IR_ASSERT(IR_IS_TYPE_INT(IR_OPT_TYPE(opt)));
11651230
IR_ASSERT(ir_type_size[IR_OPT_TYPE(opt)] > ir_type_size[op1_insn->type]);
@@ -1195,12 +1260,14 @@ IR_FOLD(TRUNC(C_U64))
11951260
default:
11961261
IR_ASSERT(0);
11971262
case IR_I8:
1263+
case IR_CHAR:
11981264
IR_FOLD_CONST_I(op1_insn->val.i8);
11991265
case IR_I16:
12001266
IR_FOLD_CONST_I(op1_insn->val.i16);
12011267
case IR_I32:
12021268
IR_FOLD_CONST_I(op1_insn->val.i32);
12031269
case IR_U8:
1270+
case IR_BOOL:
12041271
IR_FOLD_CONST_U(op1_insn->val.u8);
12051272
case IR_U16:
12061273
IR_FOLD_CONST_U(op1_insn->val.u16);
@@ -1474,6 +1541,10 @@ IR_FOLD(EQ(SEXT, C_ADDR))
14741541
} else {
14751542
ir_type type = ctx->ir_base[op1_insn->op1].type;
14761543

1544+
if (op1_insn->op == IR_ZEXT
1545+
&& (op2_insn->val.u64 >> (ir_type_size[type] * 8)) != 0) {
1546+
IR_FOLD_NEXT;
1547+
}
14771548
if (IR_IS_TYPE_SIGNED(type)) {
14781549
switch (ir_type_size[type]) {
14791550
case 1: val.i64 = op2_insn->val.i8; break;
@@ -1493,6 +1564,7 @@ IR_FOLD(EQ(SEXT, C_ADDR))
14931564
op2 = ir_const(ctx, val, type);
14941565
IR_FOLD_RESTART;
14951566
}
1567+
14961568
IR_FOLD_NEXT;
14971569
}
14981570

@@ -1518,6 +1590,10 @@ IR_FOLD(NE(SEXT, C_ADDR))
15181590
} else {
15191591
ir_type type = ctx->ir_base[op1_insn->op1].type;
15201592

1593+
if (op1_insn->op == IR_ZEXT
1594+
&& (op2_insn->val.u64 >> (ir_type_size[type] * 8)) != 0) {
1595+
IR_FOLD_NEXT;
1596+
}
15211597
if (IR_IS_TYPE_SIGNED(type)) {
15221598
switch (ir_type_size[type]) {
15231599
case 1: val.i64 = op2_insn->val.i8; break;

ext/opcache/jit/ir/ir_private.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,7 @@ IR_ALWAYS_INLINE void ir_arena_free(ir_arena *arena)
255255
IR_ALWAYS_INLINE void* ir_arena_alloc(ir_arena **arena_ptr, size_t size)
256256
{
257257
ir_arena *arena = *arena_ptr;
258-
char *ptr = arena->ptr;
259-
260-
size = IR_ALIGNED_SIZE(size, 8);
258+
char *ptr = (char*)IR_ALIGNED_SIZE((uintptr_t)arena->ptr, 8);
261259

262260
if (EXPECTED(size <= (size_t)(arena->end - ptr))) {
263261
arena->ptr = ptr + size;
@@ -283,7 +281,7 @@ IR_ALWAYS_INLINE void* ir_arena_checkpoint(ir_arena *arena)
283281
return arena->ptr;
284282
}
285283

286-
IR_ALWAYS_INLINE void ir_release(ir_arena **arena_ptr, void *checkpoint)
284+
IR_ALWAYS_INLINE void ir_arena_release(ir_arena **arena_ptr, void *checkpoint)
287285
{
288286
ir_arena *arena = *arena_ptr;
289287

ext/opcache/jit/ir/ir_sccp.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,10 +1994,16 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref
19941994

19951995
if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) {
19961996
if (use_insn->op1 == phi_ref) {
1997+
if (IR_IS_TYPE_SIGNED(type) != IR_IS_TYPE_SIGNED(ctx->ir_base[use_insn->op2].type)) {
1998+
return 0;
1999+
}
19972000
if (ir_is_cheaper_ext(ctx, use_insn->op2, ctx->ir_base[phi_ref].op1, ext_ref, op)) {
19982001
continue;
19992002
}
20002003
} else if (use_insn->op2 == phi_ref) {
2004+
if (IR_IS_TYPE_SIGNED(type) != IR_IS_TYPE_SIGNED(ctx->ir_base[use_insn->op1].type)) {
2005+
return 0;
2006+
}
20012007
if (ir_is_cheaper_ext(ctx, use_insn->op1, ctx->ir_base[phi_ref].op1, ext_ref, op)) {
20022008
continue;
20032009
}
@@ -2027,10 +2033,16 @@ static bool ir_try_promote_induction_var_ext(ir_ctx *ctx, ir_ref ext_ref, ir_ref
20272033

20282034
if (use_insn->op >= IR_EQ && use_insn->op <= IR_UGT) {
20292035
if (use_insn->op1 == phi_ref) {
2036+
if (IR_IS_TYPE_SIGNED(type) != IR_IS_TYPE_SIGNED(ctx->ir_base[use_insn->op2].type)) {
2037+
return 0;
2038+
}
20302039
if (ir_is_cheaper_ext(ctx, use_insn->op2, ctx->ir_base[phi_ref].op1, ext_ref, op)) {
20312040
continue;
20322041
}
20332042
} else if (use_insn->op2 == phi_ref) {
2043+
if (IR_IS_TYPE_SIGNED(type) != IR_IS_TYPE_SIGNED(ctx->ir_base[use_insn->op1].type)) {
2044+
return 0;
2045+
}
20342046
if (ir_is_cheaper_ext(ctx, use_insn->op1, ctx->ir_base[phi_ref].op1, ext_ref, op)) {
20352047
continue;
20362048
}
@@ -3570,11 +3582,12 @@ void ir_iter_opt(ir_ctx *ctx, ir_bitqueue *worklist)
35703582
if (val_insn->type == insn->type) {
35713583
ir_iter_replace_insn(ctx, i, val, worklist);
35723584
} else {
3573-
IR_ASSERT(!IR_IS_CONST_REF(insn->op2));
3574-
ir_use_list_remove_one(ctx, insn->op2, i);
3575-
if (ir_is_dead(ctx, insn->op2)) {
3576-
/* schedule DCE */
3577-
ir_bitqueue_add(worklist, insn->op2);
3585+
if (!IR_IS_CONST_REF(insn->op2)) {
3586+
ir_use_list_remove_one(ctx, insn->op2, i);
3587+
if (ir_is_dead(ctx, insn->op2)) {
3588+
/* schedule DCE */
3589+
ir_bitqueue_add(worklist, insn->op2);
3590+
}
35783591
}
35793592
if (!IR_IS_CONST_REF(val)) {
35803593
ir_use_list_add(ctx, val, i);

0 commit comments

Comments
 (0)