Skip to content

Commit 01f7960

Browse files
committed
Update IR
IR commit: 86685504274b0c71d9985b3c926dccaca2cacf9b
1 parent 265d605 commit 01f7960

15 files changed

+332
-88
lines changed

ext/opcache/jit/ir/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ir_emit_aarch64.h
88
minilua
99
gen_ir_fold_hash
1010
ir_test
11+
tester
1112
ir
1213
b.c
1314

ext/opcache/jit/ir/ir.c

Lines changed: 179 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Representation" In ACM SIGPLAN Workshop on Intermediate Representations
1010
* (IR '95), pages 35-49, Jan. 1995.
1111
*
12-
* The phisical IR representation is based on Mike Pall's LuaJIT IR.
12+
* The physical IR representation is based on Mike Pall's LuaJIT IR.
1313
* See: M. Pall. "LuaJIT 2.0 intellectual property disclosure and research
1414
* opportunities" November 2009 http://lua-users.org/lists/lua-l/2009-11/msg00089.html
1515
*/
@@ -134,10 +134,18 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
134134
fprintf(f, "%" PRIi64, insn->val.i64);
135135
break;
136136
case IR_DOUBLE:
137-
fprintf(f, "%g", insn->val.d);
137+
if (isnan(insn->val.d)) {
138+
fprintf(f, "nan");
139+
} else {
140+
fprintf(f, "%g", insn->val.d);
141+
}
138142
break;
139143
case IR_FLOAT:
140-
fprintf(f, "%f", insn->val.f);
144+
if (isnan(insn->val.f)) {
145+
fprintf(f, "nan");
146+
} else {
147+
fprintf(f, "%f", insn->val.f);
148+
}
141149
break;
142150
default:
143151
IR_ASSERT(0);
@@ -806,7 +814,7 @@ ir_ref ir_folding(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3,
806814
}
807815
}
808816
if (any == 0x7f) {
809-
/* All parrerns ar checked. Pass on to CSE. */
817+
/* All parrerns are checked. Pass on to CSE. */
810818
goto ir_fold_cse;
811819
}
812820
/* op2/op1/op op2/_/op _/op1/op _/_/op
@@ -1307,6 +1315,104 @@ void ir_hashtab_key_sort(ir_hashtab *tab)
13071315
} while (--i);
13081316
}
13091317

1318+
static void ir_addrtab_resize(ir_hashtab *tab)
1319+
{
1320+
uint32_t old_hash_size = (uint32_t)(-(int32_t)tab->mask);
1321+
char *old_data = tab->data;
1322+
uint32_t size = tab->size * 2;
1323+
uint32_t hash_size = ir_hashtab_hash_size(size);
1324+
char *data = ir_mem_malloc(hash_size * sizeof(uint32_t) + size * sizeof(ir_addrtab_bucket));
1325+
ir_addrtab_bucket *p;
1326+
uint32_t pos, i;
1327+
1328+
memset(data, -1, hash_size * sizeof(uint32_t));
1329+
tab->data = data + (hash_size * sizeof(uint32_t));
1330+
tab->mask = (uint32_t)(-(int32_t)hash_size);
1331+
tab->size = size;
1332+
1333+
memcpy(tab->data, old_data, tab->count * sizeof(ir_addrtab_bucket));
1334+
ir_mem_free(old_data - (old_hash_size * sizeof(uint32_t)));
1335+
1336+
i = tab->count;
1337+
pos = 0;
1338+
p = (ir_addrtab_bucket*)tab->data;
1339+
do {
1340+
uint32_t key = (uint32_t)p->key | tab->mask;
1341+
p->next = ((uint32_t*)tab->data)[(int32_t)key];
1342+
((uint32_t*)tab->data)[(int32_t)key] = pos;
1343+
pos += sizeof(ir_addrtab_bucket);
1344+
p++;
1345+
} while (--i);
1346+
}
1347+
1348+
void ir_addrtab_init(ir_hashtab *tab, uint32_t size)
1349+
{
1350+
IR_ASSERT(size > 0);
1351+
uint32_t hash_size = ir_hashtab_hash_size(size);
1352+
char *data = ir_mem_malloc(hash_size * sizeof(uint32_t) + size * sizeof(ir_addrtab_bucket));
1353+
memset(data, -1, hash_size * sizeof(uint32_t));
1354+
tab->data = (data + (hash_size * sizeof(uint32_t)));
1355+
tab->mask = (uint32_t)(-(int32_t)hash_size);
1356+
tab->size = size;
1357+
tab->count = 0;
1358+
tab->pos = 0;
1359+
}
1360+
1361+
void ir_addrtab_free(ir_hashtab *tab)
1362+
{
1363+
uint32_t hash_size = (uint32_t)(-(int32_t)tab->mask);
1364+
char *data = (char*)tab->data - (hash_size * sizeof(uint32_t));
1365+
ir_mem_free(data);
1366+
tab->data = NULL;
1367+
}
1368+
1369+
ir_ref ir_addrtab_find(const ir_hashtab *tab, uint64_t key)
1370+
{
1371+
const char *data = (const char*)tab->data;
1372+
uint32_t pos = ((uint32_t*)data)[(int32_t)(key | tab->mask)];
1373+
ir_addrtab_bucket *p;
1374+
1375+
while (pos != IR_INVALID_IDX) {
1376+
p = (ir_addrtab_bucket*)(data + pos);
1377+
if (p->key == key) {
1378+
return p->val;
1379+
}
1380+
pos = p->next;
1381+
}
1382+
return IR_INVALID_VAL;
1383+
}
1384+
1385+
bool ir_addrtab_add(ir_hashtab *tab, uint64_t key, ir_ref val)
1386+
{
1387+
char *data = (char*)tab->data;
1388+
uint32_t pos = ((uint32_t*)data)[(int32_t)(key | tab->mask)];
1389+
ir_addrtab_bucket *p;
1390+
1391+
while (pos != IR_INVALID_IDX) {
1392+
p = (ir_addrtab_bucket*)(data + pos);
1393+
if (p->key == key) {
1394+
return p->val == val;
1395+
}
1396+
pos = p->next;
1397+
}
1398+
1399+
if (UNEXPECTED(tab->count >= tab->size)) {
1400+
ir_addrtab_resize(tab);
1401+
data = tab->data;
1402+
}
1403+
1404+
pos = tab->pos;
1405+
tab->pos += sizeof(ir_addrtab_bucket);
1406+
tab->count++;
1407+
p = (ir_addrtab_bucket*)(data + pos);
1408+
p->key = key;
1409+
p->val = val;
1410+
key |= tab->mask;
1411+
p->next = ((uint32_t*)data)[(int32_t)key];
1412+
((uint32_t*)data)[(int32_t)key] = pos;
1413+
return 1;
1414+
}
1415+
13101416
/* Memory API */
13111417
#ifdef _WIN32
13121418
void *ir_mem_mmap(size_t size)
@@ -1537,24 +1643,32 @@ ir_ref _ir_PARAM(ir_ctx *ctx, ir_type type, const char* name, ir_ref num)
15371643

15381644
ir_ref _ir_VAR(ir_ctx *ctx, ir_type type, const char* name)
15391645
{
1540-
IR_ASSERT(ctx->control);
1541-
IR_ASSERT(IR_IS_BB_START(ctx->ir_base[ctx->control].op));
1542-
return ir_var(ctx, type, ctx->control, name);
1646+
// IR_ASSERT(ctx->control);
1647+
// IR_ASSERT(IR_IS_BB_START(ctx->ir_base[ctx->control].op));
1648+
// TODO: VAR may be insterted after some "memory" instruction
1649+
ir_ref ref = ctx->control;
1650+
1651+
while (1) {
1652+
IR_ASSERT(ctx->control);
1653+
if (IR_IS_BB_START(ctx->ir_base[ref].op)) {
1654+
break;
1655+
}
1656+
ref = ctx->ir_base[ref].op1;
1657+
}
1658+
return ir_var(ctx, type, ref, name);
15431659
}
15441660

1545-
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_ref src1, ir_ref src2)
1661+
ir_ref _ir_PHI_2(ir_ctx *ctx, ir_type type, ir_ref src1, ir_ref src2)
15461662
{
1547-
ir_type type = ctx->ir_base[src1].type;
1548-
15491663
IR_ASSERT(ctx->control);
15501664
IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
1551-
if (src1 == src2) {
1665+
if (src1 == src2 && src1 != IR_UNUSED) {
15521666
return src1;
15531667
}
15541668
return ir_emit3(ctx, IR_OPTX(IR_PHI, type, 3), ctx->control, src1, src2);
15551669
}
15561670

1557-
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
1671+
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_type type, ir_ref n, ir_ref *inputs)
15581672
{
15591673
IR_ASSERT(ctx->control);
15601674
IR_ASSERT(n > 0);
@@ -1565,17 +1679,19 @@ ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
15651679
ir_ref ref = inputs[0];
15661680

15671681
IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
1568-
for (i = 1; i < n; i++) {
1569-
if (inputs[i] != ref) {
1570-
break;
1682+
if (ref != IR_UNUSED) {
1683+
for (i = 1; i < n; i++) {
1684+
if (inputs[i] != ref) {
1685+
break;
1686+
}
1687+
}
1688+
if (i == n) {
1689+
/* all the same */
1690+
return ref;
15711691
}
1572-
}
1573-
if (i == n) {
1574-
/* all the same */
1575-
return ref;
15761692
}
15771693

1578-
ref = ir_emit_N(ctx, IR_OPT(IR_PHI, ctx->ir_base[inputs[0]].type), n + 1);
1694+
ref = ir_emit_N(ctx, IR_OPT(IR_PHI, type), n + 1);
15791695
ir_set_op(ctx, ref, 1, ctx->control);
15801696
for (i = 0; i < n; i++) {
15811697
ir_set_op(ctx, ref, i + 2, inputs[i]);
@@ -1857,6 +1973,22 @@ ir_ref _ir_CALL_5(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref ar
18571973
return call;
18581974
}
18591975

1976+
ir_ref _ir_CALL_N(ir_ctx *ctx, ir_type type, ir_ref func, uint32_t count, ir_ref *args)
1977+
{
1978+
ir_ref call;
1979+
uint32_t i;
1980+
1981+
IR_ASSERT(ctx->control);
1982+
call = ir_emit_N(ctx, IR_OPT(IR_CALL, type), count + 2);
1983+
ir_set_op(ctx, call, 1, ctx->control);
1984+
ir_set_op(ctx, call, 2, func);
1985+
for (i = 0; i < count; i++) {
1986+
ir_set_op(ctx, call, i + 3, args[i]);
1987+
}
1988+
ctx->control = call;
1989+
return call;
1990+
}
1991+
18601992
void _ir_UNREACHABLE(ir_ctx *ctx)
18611993
{
18621994
IR_ASSERT(ctx->control);
@@ -1941,6 +2073,22 @@ void _ir_TAILCALL_5(ir_ctx *ctx, ir_ref func, ir_ref arg1, ir_ref arg2, ir_ref a
19412073
_ir_UNREACHABLE(ctx);
19422074
}
19432075

2076+
void _ir_TAILCALL_N(ir_ctx *ctx, ir_ref func, uint32_t count, ir_ref *args)
2077+
{
2078+
ir_ref call;
2079+
uint32_t i;
2080+
2081+
IR_ASSERT(ctx->control);
2082+
call = ir_emit_N(ctx, IR_TAILCALL, count + 2);
2083+
ir_set_op(ctx, call, 1, ctx->control);
2084+
ir_set_op(ctx, call, 2, func);
2085+
for (i = 0; i < count; i++) {
2086+
ir_set_op(ctx, call, i + 3, args[i]);
2087+
}
2088+
ctx->control = call;
2089+
_ir_UNREACHABLE(ctx);
2090+
}
2091+
19442092
ir_ref _ir_SWITCH(ir_ctx *ctx, ir_ref val)
19452093
{
19462094
ir_ref ref;
@@ -2197,20 +2345,23 @@ ir_type ir_get_return_type(ir_ctx *ctx)
21972345
ir_ref ref;
21982346
ir_insn *insn;
21992347
uint8_t ret_type = 255;
2348+
ir_type type;
22002349

22012350
/* Check all RETURN nodes */
22022351
ref = ctx->ir_base[1].op1;
22032352
while (ref) {
22042353
insn = &ctx->ir_base[ref];
22052354
if (insn->op == IR_RETURN) {
2355+
type = ctx->ir_base[insn->op2].type;
2356+
check_type:
22062357
if (ret_type == 255) {
22072358
if (insn->op2) {
2208-
ret_type = ctx->ir_base[insn->op2].type;
2359+
ret_type = type;
22092360
} else {
22102361
ret_type = IR_VOID;
22112362
}
22122363
} else if (insn->op2) {
2213-
if (ret_type != ctx->ir_base[insn->op2].type) {
2364+
if (ret_type != type) {
22142365
IR_ASSERT(0 && "conflicting return types");
22152366
return IR_VOID;
22162367
}
@@ -2220,6 +2371,12 @@ ir_type ir_get_return_type(ir_ctx *ctx)
22202371
return IR_VOID;
22212372
}
22222373
}
2374+
} else if (insn->op == IR_UNREACHABLE) {
2375+
insn = &ctx->ir_base[insn->op1];
2376+
if (insn->op == IR_TAILCALL) {
2377+
type = insn->type;
2378+
goto check_type;
2379+
}
22232380
}
22242381
ref = ctx->ir_base[ref].op3;
22252382
}

ext/opcache/jit/ir/ir.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ typedef enum _ir_type {
166166
* def - reference to a definition op (data-flow use-def dependency edge)
167167
* ref - memory reference (data-flow use-def dependency edge)
168168
* var - variable reference (data-flow use-def dependency edge)
169-
* arg - argument referene CALL/TAILCALL/CARG->CARG
169+
* arg - argument reference CALL/TAILCALL/CARG->CARG
170170
* src - reference to a previous control region (IF, IF_TRUE, IF_FALSE, MERGE, LOOP_BEGIN, LOOP_END, RETURN)
171171
* reg - data-control dependency on region (PHI, VAR, PARAM)
172172
* ret - reference to a previous RETURN instruction (RETURN)
@@ -180,7 +180,7 @@ typedef enum _ir_type {
180180
* - NOP is never used (code 0 is used as ANY pattern)
181181
* - CONST is the most often used instruction (encode with 1 bit)
182182
* - equality inversion: EQ <-> NE => op =^ 1
183-
* - comparison inversio: [U]LT <-> [U]GT, [U]LE <-> [U]GE => op =^ 3
183+
* - comparison inversion: [U]LT <-> [U]GT, [U]LE <-> [U]GE => op =^ 3
184184
*/
185185

186186
#define IR_OPS(_) \
@@ -484,7 +484,7 @@ void ir_strtab_free(ir_strtab *strtab);
484484
#define IR_OPT_IN_SCCP (1<<19)
485485
#define IR_LINEAR (1<<20)
486486
#define IR_GEN_NATIVE (1<<21)
487-
#define IR_GEN_C (1<<22)
487+
#define IR_GEN_CODE (1<<22) /* C or LLVM */
488488

489489
/* Temporary: SCCP -> CFG */
490490
#define IR_SCCP_DONE (1<<25)
@@ -499,7 +499,7 @@ void ir_strtab_free(ir_strtab *strtab);
499499
#define IR_RA_HAVE_SPLITS (1<<25)
500500
#define IR_RA_HAVE_SPILLS (1<<26)
501501

502-
/* debug relted */
502+
/* debug related */
503503
#ifdef IR_DEBUG
504504
# define IR_DEBUG_SCCP (1<<27)
505505
# define IR_DEBUG_GCM (1<<28)
@@ -525,7 +525,7 @@ typedef bool (*ir_set_veneer_t)(ir_ctx *ctx, const void *addr, const void *venee
525525

526526
struct _ir_ctx {
527527
ir_insn *ir_base; /* two directional array - instructions grow down, constants grow up */
528-
ir_ref insns_count; /* number of instructins stored in instructions buffer */
528+
ir_ref insns_count; /* number of instructions stored in instructions buffer */
529529
ir_ref insns_limit; /* size of allocated instructions buffer (it's extended when overflow) */
530530
ir_ref consts_count; /* number of constants stored in constants buffer */
531531
ir_ref consts_limit; /* size of allocated constants buffer (it's extended when overflow) */
@@ -551,7 +551,7 @@ struct _ir_ctx {
551551
int32_t fixed_stack_red_zone; /* reusable stack allocated by caller (default 0) */
552552
int32_t fixed_stack_frame_size; /* fixed stack allocated by generated code for spills and registers save/restore */
553553
int32_t fixed_call_stack_size; /* fixed preallocated stack for parameter passing (default 0) */
554-
uint64_t fixed_save_regset; /* registers that always saved/restored in prologue/epilugue */
554+
uint64_t fixed_save_regset; /* registers that always saved/restored in prologue/epilogue */
555555
ir_live_interval **live_intervals;
556556
ir_arena *arena;
557557
ir_live_range *unused_ranges;
@@ -711,7 +711,7 @@ bool ir_reg_is_int(int32_t reg);
711711
const char *ir_reg_name(int8_t reg, ir_type type);
712712
int32_t ir_get_spill_slot_offset(ir_ctx *ctx, ir_ref ref);
713713

714-
/* Target CPU instruction selection and code geneartion (see ir_x86.c) */
714+
/* Target CPU instruction selection and code generation (see ir_x86.c) */
715715
int ir_match(ir_ctx *ctx);
716716
void *ir_emit_code(ir_ctx *ctx, size_t *size);
717717

@@ -750,6 +750,10 @@ void ir_loader_init(void);
750750
void ir_loader_free(void);
751751
int ir_load(ir_ctx *ctx, FILE *f);
752752

753+
/* IR LLVM load API (implementation in ir_load_llvm.c) */
754+
int ir_load_llvm_bitcode(const char *filename, uint32_t flags);
755+
int ir_load_llvm_asm(const char *filename, uint32_t flags);
756+
753757
/* IR save API (implementation in ir_save.c) */
754758
void ir_save(const ir_ctx *ctx, FILE *f);
755759

@@ -763,7 +767,10 @@ void ir_dump_live_ranges(const ir_ctx *ctx, FILE *f);
763767
void ir_dump_codegen(const ir_ctx *ctx, FILE *f);
764768

765769
/* IR to C conversion (implementation in ir_emit_c.c) */
766-
int ir_emit_c(ir_ctx *ctx, FILE *f);
770+
int ir_emit_c(ir_ctx *ctx, const char *name, FILE *f);
771+
772+
/* IR to LLVM conversion (implementation in ir_emit_llvm.c) */
773+
int ir_emit_llvm(ir_ctx *ctx, const char *name, FILE *f);
767774

768775
/* IR verification API (implementation in ir_check.c) */
769776
bool ir_check(const ir_ctx *ctx);

0 commit comments

Comments
 (0)