basic constant folding
This commit is contained in:
parent
1afe46b393
commit
4322fb8232
@ -3,6 +3,8 @@
|
||||
#include "../ns.h"
|
||||
#include "../utils/file.h"
|
||||
#include "../utils/talloc.h"
|
||||
#include "../utils/mut.h"
|
||||
#include "nvm.h"
|
||||
|
||||
#ifndef USE_PERF
|
||||
#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;
|
||||
#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) {
|
||||
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
|
||||
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;
|
||||
while (true) {
|
||||
u32* sbc = bc;
|
||||
#define L64 ({ u64 r = bc[0] | ((u64)bc[1])<<32; bc+= 2; r; })
|
||||
bool ret = false;
|
||||
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__");
|
||||
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;
|
||||
actions[f.p] = 2; cact = 3;
|
||||
RM(f.p); cact = 3;
|
||||
TSADD(data, (u64) c(Fun, f.v)->c1);
|
||||
goto defStk;
|
||||
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;
|
||||
actions[f.p] = 2; cact = 3;
|
||||
cact = 3; RM(f.p);
|
||||
TSADD(data, (u64) c(Fun, f.v)->c2);
|
||||
goto defStk;
|
||||
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;
|
||||
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)->c2);
|
||||
goto defStk;
|
||||
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:
|
||||
ret = true;
|
||||
cact = 1;
|
||||
@ -260,8 +302,10 @@ static OptRes opt(u32* bc0) {
|
||||
i32 added = stackAdded(sbc);
|
||||
for (i32 i = 0; i < added; i++) TSADD(stk, SREF(bi_optOut, -1))
|
||||
}
|
||||
#undef S
|
||||
TSADD(actions, cact);
|
||||
#undef L64
|
||||
#undef RM
|
||||
if (ret) break;
|
||||
bc = nextBC(sbc);
|
||||
pos++;
|
||||
@ -270,6 +314,7 @@ static OptRes opt(u32* bc0) {
|
||||
|
||||
TSALLOC(u32, rbc, TSSIZE(actions));
|
||||
TSALLOC(u32, roff, TSSIZE(actions));
|
||||
B refs = inc(bi_emptyHVec);
|
||||
bc = bc0;
|
||||
u64 tpos = 0, dpos = 0;
|
||||
while (true) {
|
||||
@ -291,11 +336,20 @@ static OptRes opt(u32* bc0) {
|
||||
A64(data[dpos++]);
|
||||
A64(data[dpos++]);
|
||||
break;
|
||||
|
||||
case 2: break; // remove
|
||||
|
||||
case 5:
|
||||
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 0: def2:; // do nothing
|
||||
TSADDA(rbc, sbc, ebc-sbc);
|
||||
}
|
||||
@ -306,10 +360,10 @@ static OptRes opt(u32* bc0) {
|
||||
bc = ebc;
|
||||
}
|
||||
bc = bc0; pos = 0;
|
||||
|
||||
TSFREE(data);
|
||||
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
|
||||
void freeOpt(OptRes o) {
|
||||
@ -323,7 +377,7 @@ static u32 readBytes4(u8* d) {
|
||||
|
||||
typedef B JITFn(B* cStack, Scope** pscs);
|
||||
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);
|
||||
TSALLOC(u32, rel, 64);
|
||||
#define r_TMP 3
|
||||
@ -454,7 +508,7 @@ u8* m_nvm(Body* body) {
|
||||
// write_asm(binEx, sz);
|
||||
FREE_ASM();
|
||||
TSFREE(rel);
|
||||
return binEx;
|
||||
return (Nvm_res){.p = binEx, .refs = optRes.refs};
|
||||
}
|
||||
B evalJIT(Body* b, Scope* sc, u8* ptr) { // doesn't consume
|
||||
u32* bc = b->bc;
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
#include "../vm.h"
|
||||
|
||||
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);
|
||||
|
||||
16
src/vm.c
16
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->bc = (u32*)nbc;
|
||||
body->nvm = NULL;
|
||||
body->nvmRefs = m_f64(0);
|
||||
body->map = map;
|
||||
body->blocks = nBl;
|
||||
body->maxStack = hM;
|
||||
@ -558,6 +559,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume
|
||||
#undef P
|
||||
#undef ADD
|
||||
#undef POP
|
||||
#undef POS_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⋄`
|
||||
B r;
|
||||
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);
|
||||
} else {
|
||||
r = evalBC(body, sc);
|
||||
@ -650,9 +656,10 @@ void scope_free(Value* x) {
|
||||
}
|
||||
void body_free(Value* x) {
|
||||
Body* c = (Body*) x;
|
||||
if(c->nsDesc) ptr_decR(c->nsDesc);
|
||||
if(c->blocks) ptr_decR(c->blocks);
|
||||
if(c->nvm ) nvm_free(c->nvm);
|
||||
if(c->nsDesc ) ptr_decR(c->nsDesc);
|
||||
if(c->blocks ) ptr_decR(c->blocks);
|
||||
if(c->nvm ) nvm_free(c->nvm);
|
||||
dec(c->nvmRefs);
|
||||
ptr_decR(c->comp);
|
||||
ptr_decR(RFLD(c->bc, I32Arr,a));
|
||||
ptr_decR(RFLD(c->map,I32Arr,a));
|
||||
@ -678,6 +685,7 @@ void body_visit(Value* x) {
|
||||
Body* c = (Body*) x;
|
||||
if(c->nsDesc) mm_visitP(c->nsDesc);
|
||||
if(c->blocks) mm_visitP(c->blocks);
|
||||
mm_visit(c->nvmRefs);
|
||||
mm_visitP(c->comp);
|
||||
mm_visitP(RFLD(c->bc, I32Arr,a));
|
||||
mm_visitP(RFLD(c->map,I32Arr,a));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user