basic constant folding
This commit is contained in:
parent
1afe46b393
commit
4322fb8232
@ -3,6 +3,8 @@
|
|||||||
#include "../ns.h"
|
#include "../ns.h"
|
||||||
#include "../utils/file.h"
|
#include "../utils/file.h"
|
||||||
#include "../utils/talloc.h"
|
#include "../utils/talloc.h"
|
||||||
|
#include "../utils/mut.h"
|
||||||
|
#include "nvm.h"
|
||||||
|
|
||||||
#ifndef USE_PERF
|
#ifndef USE_PERF
|
||||||
#define USE_PERF 0 // enable writing symbols to /tmp/perf-<pid>.map
|
#define USE_PERF 0 // enable writing symbols to /tmp/perf-<pid>.map
|
||||||
@ -215,41 +217,81 @@ static void write_asm(u8* p, u64 sz) { // for debugging; view with objdump -b bi
|
|||||||
|
|
||||||
typedef struct SRef { B v; i32 p; } SRef;
|
typedef struct SRef { B v; i32 p; } SRef;
|
||||||
#define SREF(V,P) ((SRef){.v=V, .p=P})
|
#define SREF(V,P) ((SRef){.v=V, .p=P})
|
||||||
typedef struct OptRes { u32* bc; u32* offset; } OptRes;
|
typedef struct OptRes { u32* bc; u32* offset; B refs; } OptRes;
|
||||||
static OptRes opt(u32* bc0) {
|
static OptRes opt(u32* bc0) {
|
||||||
TSALLOC(SRef, stk, 8);
|
TSALLOC(SRef, stk, 8);
|
||||||
TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 2: remove; 3: FN1_/FN2C; 4: FN2O
|
TSALLOC(u8, actions, 64); // 1 per instruction; 0: nothing; 1: indicates return; 3: FN1_/FN2C; 4: FN2O; 5: replace with PUSH; 6: decrement 1 data; 10+N: ignore N data
|
||||||
TSALLOC(u64, data, 64); // variable length; whatever things are needed for the specific action
|
TSALLOC(u64, data, 64); // variable length; whatever things are needed for the specific action
|
||||||
|
u8 rm_map[] = {10,10,10,11,12,6,6,99,99,99,11,12,13,14,15,16,17,18,19};
|
||||||
|
#define RM(N) actions[N] = rm_map[actions[N]]
|
||||||
u32* bc = bc0; usz pos = 0;
|
u32* bc = bc0; usz pos = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
u32* sbc = bc;
|
u32* sbc = bc;
|
||||||
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
|
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
u8 cact = 0;
|
u8 cact = 0;
|
||||||
|
#define S(N,I) SRef N = stk[TSSIZE(stk)-1-(I)];
|
||||||
switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("JIT optimization: didn't already expect immediate FN__");
|
switch (*bc++) { case FN1Ci: case FN1Oi: case FN2Ci: case FN2Oi: thrM("JIT optimization: didn't already expect immediate FN__");
|
||||||
case ADDU: case ADDI: cact = 0; TSADD(stk,SREF(b(L64), pos)); break;
|
case ADDU: case ADDI: cact = 0; TSADD(stk,SREF(b(L64), pos)); break;
|
||||||
case FN1C: case FN1O: { SRef f = stk[TSSIZE(stk)-1];
|
case FN1C: case FN1O: { S(f,0)
|
||||||
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
||||||
actions[f.p] = 2; cact = 3;
|
RM(f.p); cact = 3;
|
||||||
TSADD(data, (u64) c(Fun, f.v)->c1);
|
TSADD(data, (u64) c(Fun, f.v)->c1);
|
||||||
goto defStk;
|
goto defStk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FN2C: { SRef f = stk[TSSIZE(stk)-2];
|
case FN2C: { S(f,1)
|
||||||
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
||||||
actions[f.p] = 2; cact = 3;
|
cact = 3; RM(f.p);
|
||||||
TSADD(data, (u64) c(Fun, f.v)->c2);
|
TSADD(data, (u64) c(Fun, f.v)->c2);
|
||||||
goto defStk;
|
goto defStk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FN2O: { SRef f = stk[TSSIZE(stk)-2];
|
case FN2O: { S(f,1)
|
||||||
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
if (!isFun(f.v) || v(f.v)->type!=t_funBI) goto defIns;
|
||||||
actions[f.p] = 2; cact = 4;
|
cact = 4; RM(f.p);
|
||||||
TSADD(data, (u64) c(Fun, f.v)->c1);
|
TSADD(data, (u64) c(Fun, f.v)->c1);
|
||||||
TSADD(data, (u64) c(Fun, f.v)->c2);
|
TSADD(data, (u64) c(Fun, f.v)->c2);
|
||||||
goto defStk;
|
goto defStk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP1D: { S(f,0) S(m,1)
|
||||||
|
if (f.p==-1 | m.p==-1) goto defIns;
|
||||||
|
B d = m1_d(inc(m.v), inc(f.v));
|
||||||
|
cact = 5; RM(f.p); RM(m.p);
|
||||||
|
TSADD(data, d.u);
|
||||||
|
TSSIZE(stk)--;
|
||||||
|
stk[TSSIZE(stk)-1] = SREF(d, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OP2D: { S(f,0) S(m,1) S(g,2)
|
||||||
|
if (f.p==-1 | m.p==-1 | g.p==-1) goto defIns;
|
||||||
|
B d = m2_d(inc(m.v), inc(f.v), inc(g.v));
|
||||||
|
cact = 5; RM(f.p); RM(m.p); RM(g.p);
|
||||||
|
TSADD(data, d.u);
|
||||||
|
TSSIZE(stk)-= 2;
|
||||||
|
stk[TSSIZE(stk)-1] = SREF(d, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TR2D: { S(g,0) S(h,1)
|
||||||
|
if (g.p==-1 | h.p==-1) goto defIns;
|
||||||
|
B d = m_atop(inc(g.v), inc(h.v));
|
||||||
|
cact = 5; RM(g.p); RM(h.p);
|
||||||
|
TSADD(data, d.u);
|
||||||
|
TSSIZE(stk)--;
|
||||||
|
stk[TSSIZE(stk)-1] = SREF(d, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TR3D: case TR3O: { S(f,0) S(g,1) S(h,2)
|
||||||
|
if (f.p==-1 | g.p==-1 | h.p==-1) goto defIns;
|
||||||
|
if (isNothing(f.v)) thrM("JIT optimization: didn't expect constant ·");
|
||||||
|
B d = m_fork(inc(f.v), inc(g.v), inc(h.v));
|
||||||
|
cact = 5; RM(f.p); RM(g.p); RM(h.p);
|
||||||
|
TSADD(data, d.u);
|
||||||
|
TSSIZE(stk)-= 2;
|
||||||
|
stk[TSSIZE(stk)-1] = SREF(d, pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RETN: case RETD:
|
case RETN: case RETD:
|
||||||
ret = true;
|
ret = true;
|
||||||
cact = 1;
|
cact = 1;
|
||||||
@ -260,8 +302,10 @@ static OptRes opt(u32* bc0) {
|
|||||||
i32 added = stackAdded(sbc);
|
i32 added = stackAdded(sbc);
|
||||||
for (i32 i = 0; i < added; i++) TSADD(stk, SREF(bi_optOut, -1))
|
for (i32 i = 0; i < added; i++) TSADD(stk, SREF(bi_optOut, -1))
|
||||||
}
|
}
|
||||||
|
#undef S
|
||||||
TSADD(actions, cact);
|
TSADD(actions, cact);
|
||||||
#undef L64
|
#undef L64
|
||||||
|
#undef RM
|
||||||
if (ret) break;
|
if (ret) break;
|
||||||
bc = nextBC(sbc);
|
bc = nextBC(sbc);
|
||||||
pos++;
|
pos++;
|
||||||
@ -270,6 +314,7 @@ static OptRes opt(u32* bc0) {
|
|||||||
|
|
||||||
TSALLOC(u32, rbc, TSSIZE(actions));
|
TSALLOC(u32, rbc, TSSIZE(actions));
|
||||||
TSALLOC(u32, roff, TSSIZE(actions));
|
TSALLOC(u32, roff, TSSIZE(actions));
|
||||||
|
B refs = inc(bi_emptyHVec);
|
||||||
bc = bc0;
|
bc = bc0;
|
||||||
u64 tpos = 0, dpos = 0;
|
u64 tpos = 0, dpos = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -291,11 +336,20 @@ static OptRes opt(u32* bc0) {
|
|||||||
A64(data[dpos++]);
|
A64(data[dpos++]);
|
||||||
A64(data[dpos++]);
|
A64(data[dpos++]);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
case 2: break; // remove
|
u64 on = data[dpos++]; B ob = b(on);
|
||||||
|
TSADD(rbc, isVal(ob)? ADDI : ADDU);
|
||||||
|
A64(on);
|
||||||
|
if (isVal(ob)) refs = vec_add(refs, ob);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
dec(b(data[dpos++]));
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:
|
||||||
|
dpos+= ctype-10;
|
||||||
|
break;
|
||||||
case 1: ret = true; goto def2; // return
|
case 1: ret = true; goto def2; // return
|
||||||
|
|
||||||
case 0: def2:; // do nothing
|
case 0: def2:; // do nothing
|
||||||
TSADDA(rbc, sbc, ebc-sbc);
|
TSADDA(rbc, sbc, ebc-sbc);
|
||||||
}
|
}
|
||||||
@ -306,10 +360,10 @@ static OptRes opt(u32* bc0) {
|
|||||||
bc = ebc;
|
bc = ebc;
|
||||||
}
|
}
|
||||||
bc = bc0; pos = 0;
|
bc = bc0; pos = 0;
|
||||||
|
|
||||||
TSFREE(data);
|
TSFREE(data);
|
||||||
TSFREE(actions);
|
TSFREE(actions);
|
||||||
return (OptRes){.bc = rbc, .offset = roff};
|
if (a(refs)->ia==0) { dec(refs); refs=m_f64(0); }
|
||||||
|
return (OptRes){.bc = rbc, .offset = roff, .refs = refs};
|
||||||
}
|
}
|
||||||
#undef SREF
|
#undef SREF
|
||||||
void freeOpt(OptRes o) {
|
void freeOpt(OptRes o) {
|
||||||
@ -323,7 +377,7 @@ static u32 readBytes4(u8* d) {
|
|||||||
|
|
||||||
typedef B JITFn(B* cStack, Scope** pscs);
|
typedef B JITFn(B* cStack, Scope** pscs);
|
||||||
static inline i32 maxi32(i32 a, i32 b) { return a>b?a:b; }
|
static inline i32 maxi32(i32 a, i32 b) { return a>b?a:b; }
|
||||||
u8* m_nvm(Body* body) {
|
Nvm_res m_nvm(Body* body) {
|
||||||
ALLOC_ASM(64);
|
ALLOC_ASM(64);
|
||||||
TSALLOC(u32, rel, 64);
|
TSALLOC(u32, rel, 64);
|
||||||
#define r_TMP 3
|
#define r_TMP 3
|
||||||
@ -454,7 +508,7 @@ u8* m_nvm(Body* body) {
|
|||||||
// write_asm(binEx, sz);
|
// write_asm(binEx, sz);
|
||||||
FREE_ASM();
|
FREE_ASM();
|
||||||
TSFREE(rel);
|
TSFREE(rel);
|
||||||
return binEx;
|
return (Nvm_res){.p = binEx, .refs = optRes.refs};
|
||||||
}
|
}
|
||||||
B evalJIT(Body* b, Scope* sc, u8* ptr) { // doesn't consume
|
B evalJIT(Body* b, Scope* sc, u8* ptr) { // doesn't consume
|
||||||
u32* bc = b->bc;
|
u32* bc = b->bc;
|
||||||
|
|||||||
@ -2,5 +2,6 @@
|
|||||||
#include "../vm.h"
|
#include "../vm.h"
|
||||||
|
|
||||||
B evalJIT(Body* b, Scope* sc, u8* ptr);
|
B evalJIT(Body* b, Scope* sc, u8* ptr);
|
||||||
u8* m_nvm(Body* b);
|
typedef struct Nvm_res { u8* p; B refs; } Nvm_res;
|
||||||
|
Nvm_res m_nvm(Body* b);
|
||||||
void nvm_free(u8* ptr);
|
void nvm_free(u8* ptr);
|
||||||
|
|||||||
10
src/vm.c
10
src/vm.c
@ -228,6 +228,7 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B block
|
|||||||
body->comp = comp; ptr_inc(comp);
|
body->comp = comp; ptr_inc(comp);
|
||||||
body->bc = (u32*)nbc;
|
body->bc = (u32*)nbc;
|
||||||
body->nvm = NULL;
|
body->nvm = NULL;
|
||||||
|
body->nvmRefs = m_f64(0);
|
||||||
body->map = map;
|
body->map = map;
|
||||||
body->blocks = nBl;
|
body->blocks = nBl;
|
||||||
body->maxStack = hM;
|
body->maxStack = hM;
|
||||||
@ -558,6 +559,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume
|
|||||||
#undef P
|
#undef P
|
||||||
#undef ADD
|
#undef ADD
|
||||||
#undef POP
|
#undef POP
|
||||||
|
#undef POS_UPD
|
||||||
#undef GS_UPD
|
#undef GS_UPD
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +584,11 @@ B actualExec(Block* bl, Scope* psc, i32 ga, B* svar) { // consumes svar contents
|
|||||||
// jit = body->bc[2]==m_f64(123456).u>>32; // enable JIT just for blocks starting with `123456⋄`
|
// jit = body->bc[2]==m_f64(123456).u>>32; // enable JIT just for blocks starting with `123456⋄`
|
||||||
B r;
|
B r;
|
||||||
if (jit) {
|
if (jit) {
|
||||||
if (!body->nvm) body->nvm = m_nvm(body);
|
if (!body->nvm) {
|
||||||
|
Nvm_res r = m_nvm(body);
|
||||||
|
body->nvm = r.p;
|
||||||
|
body->nvmRefs = r.refs;
|
||||||
|
}
|
||||||
r = evalJIT(body, sc, body->nvm);
|
r = evalJIT(body, sc, body->nvm);
|
||||||
} else {
|
} else {
|
||||||
r = evalBC(body, sc);
|
r = evalBC(body, sc);
|
||||||
@ -653,6 +659,7 @@ void body_free(Value* x) {
|
|||||||
if(c->nsDesc ) ptr_decR(c->nsDesc);
|
if(c->nsDesc ) ptr_decR(c->nsDesc);
|
||||||
if(c->blocks ) ptr_decR(c->blocks);
|
if(c->blocks ) ptr_decR(c->blocks);
|
||||||
if(c->nvm ) nvm_free(c->nvm);
|
if(c->nvm ) nvm_free(c->nvm);
|
||||||
|
dec(c->nvmRefs);
|
||||||
ptr_decR(c->comp);
|
ptr_decR(c->comp);
|
||||||
ptr_decR(RFLD(c->bc, I32Arr,a));
|
ptr_decR(RFLD(c->bc, I32Arr,a));
|
||||||
ptr_decR(RFLD(c->map,I32Arr,a));
|
ptr_decR(RFLD(c->map,I32Arr,a));
|
||||||
@ -678,6 +685,7 @@ void body_visit(Value* x) {
|
|||||||
Body* c = (Body*) x;
|
Body* c = (Body*) x;
|
||||||
if(c->nsDesc) mm_visitP(c->nsDesc);
|
if(c->nsDesc) mm_visitP(c->nsDesc);
|
||||||
if(c->blocks) mm_visitP(c->blocks);
|
if(c->blocks) mm_visitP(c->blocks);
|
||||||
|
mm_visit(c->nvmRefs);
|
||||||
mm_visitP(c->comp);
|
mm_visitP(c->comp);
|
||||||
mm_visitP(RFLD(c->bc, I32Arr,a));
|
mm_visitP(RFLD(c->bc, I32Arr,a));
|
||||||
mm_visitP(RFLD(c->map,I32Arr,a));
|
mm_visitP(RFLD(c->map,I32Arr,a));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user