]> Nishi Git Mirror - gwion.git/commitdiff
:art: Optimized loop instructions
authorJérémie Astor <fennecdjay@gmail.com>
Wed, 19 May 2021 11:16:48 +0000 (13:16 +0200)
committerJérémie Astor <fennecdjay@gmail.com>
Wed, 19 May 2021 11:16:48 +0000 (13:16 +0200)
include/env/value.h
include/opcode.h
opcode.txt
src/emit/emit.c
src/parse/check.c
src/parse/scan1.c
src/vm/vm.c
src/vm/vm_code.c
util

index 5796979a31f9d5cbc5d6f73d224c4a8970dca7c1..ec3ebf05871e58fe53da517fc11d67973dcd3615 100644 (file)
@@ -44,4 +44,8 @@ FLAG_FUNC(Value, v)
 
 ANEW ANN Value new_value(MemPool p, const Type type, const m_str name);
 ANN void valuefrom(const Env, struct ValueFrom_*, const loc_t loc);
+
+ANN static inline void defined_here(const Value v) {
+  gwerr_secondary(_("defined here"), v->from->filename, v->from->loc);
+}
 #endif
index d0e695d1ecfb340247d9d21f96c6b677ed3a49d7..f734353354720dbb9e2d2d98eb6674ec0cfecaca 100644 (file)
@@ -25,6 +25,9 @@ enum {
   eStructMemberOther,
   eStructMemberAddr,
   eMemSetImm,
+  eMemAddImm,
+  eRepeatIdx,
+  eRepeat,
   eRegPushMe,
   eRegPushMaybe,
   eFuncReturn,
@@ -222,6 +225,9 @@ enum {
 #define  StructMemberOther    (f_instr)eStructMemberOther
 #define  StructMemberAddr     (f_instr)eStructMemberAddr
 #define  MemSetImm            (f_instr)eMemSetImm
+#define  MemAddImm            (f_instr)eMemAddImm
+#define  RepeatIdx            (f_instr)eRepeatIdx
+#define  Repeat               (f_instr)eRepeat
 #define  RegPushMe            (f_instr)eRegPushMe
 #define  RegPushMaybe         (f_instr)eRegPushMaybe
 #define  FuncReturn           (f_instr)eFuncReturn
index 73536e3af2323664fad5fee0c77a2902b93441d7..efce167a6b23a035585d36de9dd45f7e5b5cae6b 100644 (file)
@@ -22,6 +22,9 @@ StructMemberFloat
 StructMemberOther
 StructMemberAddr
 MemSetImm
+MemAddImm
+RepeatIdx
+Repeat
 RegPushMe
 RegPushMaybe
 FuncReturn
index 6f23c45f82dc1da3251e891eb5fda19b0716f506..1b3f5825fe4e2dc6f0b9c8e4a295b2dc6b170589 100644 (file)
@@ -1751,28 +1751,27 @@ ANN static m_bool emit_stmt_for(const Emitter emit, const Stmt_For stmt) {
 
 
 struct Looper;
+typedef Instr (*f_looper_init)(const Emitter, const struct Looper *);
 typedef void (*f_looper)(const Emitter, const struct Looper *);
 struct Looper {
   const Stmt stmt;
   /*const */m_uint offset;
   const m_uint n;
-  const f_looper roll;
+  const f_looper_init roll;
   const f_looper unroll;
 };
 
 ANN static inline m_bool roll(const Emitter emit, const struct Looper *loop) {
-  if(loop->roll)
-    loop->roll(emit, loop);
-  const Instr instr = emit_add_instr(emit, BranchEqInt);
+  const Instr instr = loop->roll(emit, loop);
   CHECK_BB(scoped_stmt(emit, loop->stmt, 1));
   instr->m_val = emit_code_size(emit) + 1; // pass after goto
   return GW_OK;
 }
 
-ANN static void stmt_each_roll(const Emitter emit, const struct Looper *loop) {
+ANN static Instr stmt_each_roll(const Emitter emit, const struct Looper *loop) {
   const Instr instr = emit_add_instr(emit, AutoLoop);
-  instr->m_val = loop->offset + SZ_INT;
-  regpush(emit, SZ_INT);
+  instr->m_val2 = loop->offset + SZ_INT;
+  return instr;
 }
 
 ANN static inline void unroll_init(const Emitter emit, const m_uint n) {
@@ -1860,28 +1859,28 @@ ANN static m_bool emit_stmt_each(const Emitter emit, const Stmt_Each stmt) {
   return ret;
 }
 
-ANN static void stmt_loop_roll(const Emitter emit, const struct Looper *loop) {
-  const Instr counter = emit_add_instr(emit, RegPushMem4);
-  counter->m_val = loop->offset;
-  emit_add_instr(emit, int_post_dec);
+ANN static Instr stmt_loop_roll(const Emitter emit, const struct Looper *loop) {
+  const Instr eq = emit_add_instr(emit, Repeat);
+  eq->m_val2 = loop->offset;
+  return eq;
 }
 
-ANN static void stmt_loop_roll_idx(const Emitter emit, const struct Looper *loop) {
-  const Instr target = emit_add_instr(emit, RegPushMem);
-  target->m_val = loop->offset + SZ_INT;
-  const Instr counter = emit_add_instr(emit, RegPushMem4);
-  counter->m_val = loop->offset;
-  emit_add_instr(emit, int_post_inc);
-  emit_add_instr(emit, int_minus);
+ANN static Instr stmt_loop_roll_idx(const Emitter emit, const struct Looper *loop) {
+  const Instr instr = emit_add_instr(emit, RepeatIdx);
+  instr->m_val2 = loop->offset;
+  return instr;
 }
 
-ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt, m_uint *index) {
+ANN static m_bool _emit_stmt_loop(const Emitter emit, const Stmt_Loop stmt,
+          m_uint *index) {
   const uint n = emit->info->unroll;
   if(n)
     unroll_init(emit, n);
   const m_uint offset = emit_local(emit, emit->gwion->type[et_int]);
-  if(stmt->idx)
-    emit_local(emit, emit->gwion->type[et_int]);
+  if(stmt->idx) {
+    const Instr instr = emit_add_instr(emit, MemSetImm);
+    instr->m_val = stmt->idx->v->from->offset = emit_local(emit, emit->gwion->type[et_int]);
+  }
   CHECK_BB(emit_exp_pop_next(emit, stmt->cond));
   regpop(emit, SZ_INT);
   const Instr tomem = emit_add_instr(emit, Reg2Mem);
index 68100dec3becb71df63b67138abecc14787a381e..27e4ead57774409dd6604c806e3e776758daf79c 100644 (file)
@@ -50,7 +50,7 @@ ANN static inline m_bool check_exp_decl_parent(const Env env, const Var_Decl var
   if(value) {
     env_err(env, var->pos,
           _("Value defined in parent class"));
-    gwerr_secondary(_("defined here"), value->from->filename, value->from->loc);
+    defined_here(value);
     return GW_ERROR;
   }
   return GW_OK;
index 1df28fda0d67c21859ccaaf89b06efa70d3e5e50..34d05424a0d5ed6e8fdf7dd981b5e4d815d68840 100644 (file)
@@ -305,7 +305,7 @@ ANN static inline m_bool stmt_each_defined(const restrict Env env, const Stmt_Ea
 
 ANN static inline m_bool shadow_err(const Env env, const Value v, const loc_t loc) {
   gwerr_basic(_("shadowing a previously defined variable"), NULL, NULL, env->name, loc, 0);
-  gwerr_secondary(_("defined here"), v->from->filename, v->from->loc);
+  defined_here(v);
   env->context->error = true;
   return GW_ERROR;
 }
index 902013ace73ed414e4e8990eb876954741e8f430..bc7118eb7ff42b4b0b83add0428a518d0f32975f 100644 (file)
@@ -372,7 +372,7 @@ ANN void vm_run(const VM* vm) { // lgtm [cpp/use-of-goto]
     &&baseint, &&basefloat, &&baseother, &&baseaddr,
     &&regtoreg, &&regtoregother, &&regtoregaddr, &&regtoregderef,
     &&structmember, &&structmemberfloat, &&structmemberother, &&structmemberaddr,
-    &&memsetimm,
+    &&memsetimm, &&memaddimm, &&repeatidx, &&repeat,
     &&regpushme, &&regpushmaybe,
     &&funcreturn,
     &&_goto,
@@ -529,6 +529,14 @@ structmemberaddr:
 memsetimm:
   *(m_uint*)(mem+VAL) = VAL2;
   DISPATCH();
+memaddimm:
+  *(m_int*)(mem+VAL) += (m_int)VAL2;
+//  (*(m_int*)(mem+VAL))--;
+  DISPATCH();
+repeatidx:
+  BRANCH_DISPATCH(*(m_int*)(mem+VAL2+SZ_INT) == ++(*(m_int*)(mem+VAL2)));
+repeat:
+  BRANCH_DISPATCH(!--*(m_uint*)(mem+VAL2));
 regpushme:
   *(M_Object*)reg = shred->info->me;
   reg += SZ_INT;
@@ -817,9 +825,8 @@ autounrollinit:
   *(m_uint*)(mem + VAL) = m_vector_size(ARRAY(*(M_Object*)(mem+VAL+SZ_INT)));
   DISPATCH()
 autoloop:
-  *(m_bit**)(mem + VAL + SZ_INT) = m_vector_addr(ARRAY(*(M_Object*)(mem+VAL-SZ_INT)), *(m_uint*)(mem + VAL) + 1);
-  *(m_uint*)reg = m_vector_size(ARRAY(*(M_Object*)(mem+VAL-SZ_INT))) - (*(m_uint*)(mem + VAL))++ -1;
-  DISPATCH()
+  *(m_bit**)(mem + VAL2 + SZ_INT) = m_vector_addr(ARRAY(*(M_Object*)(mem+VAL2-SZ_INT)), *(m_uint*)(mem + VAL2) + 1);
+  BRANCH_DISPATCH(m_vector_size(ARRAY(*(M_Object*)(mem+VAL2-SZ_INT))) == ++*(m_uint*)(mem + VAL2));
 arraytop:
   if(*(m_uint*)(reg - SZ_INT * 2) < *(m_uint*)(reg-SZ_INT))
     goto newobj;
index 453bc29534610dac46a537abbcf9e2b5a0c4ee82..77418999b1a412e799e15fbe8e07e4f82b059abf 100644 (file)
@@ -42,10 +42,11 @@ ANN void free_vmcode(VM_Code a, Gwion gwion) {
 }
 
 static inline uint isgoto(const unsigned opcode) {
-  return opcode == eGoto || opcode == eArrayTop ||
-      opcode == eBranchEqInt || opcode == eBranchNeqInt ||
+  return opcode == eGoto       || opcode == eArrayTop       ||
+      opcode == eBranchEqInt   || opcode == eBranchNeqInt   ||
       opcode == eBranchEqFloat || opcode == eBranchNeqFloat ||
-      opcode == eHandleEffect;
+      opcode == eHandleEffect  || opcode == eRepeat         ||
+      opcode == eRepeatIdx     || opcode == eAutoLoop;
 }
 
 ANN static inline void setpc(const m_bit *data, const m_uint i) {
diff --git a/util b/util
index 7f657c4d12c8a4362d26b1976ddca5de2324d60a..4e08843bd4c85578e1965ffd81c41fc36f42358d 160000 (submodule)
--- a/util
+++ b/util
@@ -1 +1 @@
-Subproject commit 7f657c4d12c8a4362d26b1976ddca5de2324d60a
+Subproject commit 4e08843bd4c85578e1965ffd81c41fc36f42358d