basic constant folding

This commit is contained in:
dzaima 2021-06-16 03:03:31 +03:00
parent 1afe46b393
commit 4322fb8232
4 changed files with 85 additions and 21 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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));

View File

@ -81,6 +81,7 @@ struct Body {
u16 maxPSC;
u16 varAm;
NSDesc* nsDesc;
B nvmRefs;
i32 varIDs[];
};