]> Nishi Git Mirror - gwion.git/commitdiff
:art: string and branch optimizations
authorJérémie Astor <fennecdjay@gmail.com>
Mon, 15 Feb 2021 11:06:58 +0000 (12:06 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Mon, 15 Feb 2021 11:06:58 +0000 (12:06 +0100)
src/emit/emit.c
src/lib/string.c

index c015c73f1a1b14277f5c416ba5eb0d5f1dd37d57..fe45053dff3c1e0c8b9b386d440127f0ac6e85c9 100644 (file)
@@ -1501,7 +1501,15 @@ ANN2(1) /*static */m_bool emit_exp(const Emitter emit, /* const */Exp e) {
   return GW_OK;
 }
 
+ANN static m_bool emit_if_const(const Emitter emit, const Stmt_If stmt) {
+  if(stmt->cond->d.prim.d.num)
+    return emit_stmt(emit, stmt->if_body, 1);
+  return stmt->else_body ? emit_stmt(emit, stmt->else_body, 1) : GW_OK;
+}
+
 ANN static m_bool emit_if(const Emitter emit, const Stmt_If stmt) {
+  if(stmt->cond->exp_type == ae_exp_primary && stmt->cond->d.prim.prim_type == ae_prim_num)
+    return emit_if_const(emit, stmt);
   DECL_OB(const Instr, op, = emit_flow(emit, stmt->cond))
   CHECK_BB(scoped_stmt(emit, stmt->if_body, 1))
   const Instr op2 = emit_add_instr(emit, Goto);
@@ -1609,16 +1617,30 @@ ANN static void emit_pop_stack(const Emitter emit, const m_uint index) {
 
 ANN static m_bool _emit_stmt_flow(const Emitter emit, const Stmt_Flow stmt, const m_uint index) {
   Instr op = NULL;
-  if(!stmt->is_do)
-    op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type == ae_stmt_while);
+  const ae_stmt_t is_while = stmt_self(stmt)->stmt_type == ae_stmt_while;
+  const uint is_const = stmt->cond->exp_type == ae_exp_primary && stmt->cond->d.prim.prim_type == ae_prim_num;
+  if(!stmt->is_do) {
+    if(!is_const)
+      op = _flow(emit, stmt->cond, is_while);
+    else if((!is_while && stmt->cond->d.prim.d.num) ||
+        (is_while && !stmt->cond->d.prim.d.num))
+      return GW_OK;
+  }
   CHECK_BB(scoped_stmt(emit, stmt->body, 1))
   if(stmt->is_do) {
-    CHECK_OB((op = _flow(emit, stmt->cond, stmt_self(stmt)->stmt_type != ae_stmt_while)))
-    op->m_val = index;
+    if(!is_const) {
+      CHECK_OB((op = _flow(emit, stmt->cond, !is_while)))
+      op->m_val = index;
+    } else if((is_while && stmt->cond->d.prim.d.num) ||
+        (!is_while && !stmt->cond->d.prim.d.num)) {
+      const Instr goto_ = emit_add_instr(emit, Goto);
+      goto_->m_val = index;
+    }
   } else {
     const Instr goto_ = emit_add_instr(emit, Goto);
     goto_->m_val = index;
-    op->m_val = emit_code_size(emit);
+    if(op)
+      op->m_val = emit_code_size(emit);
   }
   return GW_OK;
 }
index 560694dee94dc7af05ed9d662d3e088a557010bd..25b80dfc4af79e7eaa4e628afbf4cae98567fc39 100644 (file)
@@ -25,6 +25,29 @@ static INSTR(String_##name) {                    \
 describe_string_logical(eq, (!strcmp(STRING(lhs), STRING(rhs))))
 describe_string_logical(neq, (strcmp(STRING(lhs), STRING(rhs))))
 
+static inline uint is_const_str(const Exp exp) {
+  return exp->exp_type == ae_exp_primary &&
+         exp->d.prim.prim_type == ae_prim_str;
+}
+
+#define opck_str(name, __exp__)                          \
+OP_CHECK(opck_string_##name) {                           \
+  Exp_Binary *bin = (Exp_Binary*)data;                   \
+  if(!is_const_str(bin->lhs) || !is_const_str(bin->rhs)) \
+    return env->gwion->type[et_bool];                    \
+  const int ret = __exp__;                               \
+  free_exp(env->gwion->mp, bin->lhs);                    \
+  free_exp(env->gwion->mp, bin->rhs);                    \
+  const Exp e = exp_self(bin);                           \
+  e->exp_type = ae_exp_primary;                          \
+  e->d.prim.prim_type = ae_prim_num;                     \
+  e->d.prim.d.num = ret;                                 \
+  return env->gwion->type[et_bool];                      \
+}
+
+opck_str(eq, !strcmp(bin->lhs->d.prim.d.str, bin->rhs->d.prim.d.str))
+opck_str(neq, strcmp(bin->lhs->d.prim.d.str, bin->rhs->d.prim.d.str))
+
 static CTOR(string_ctor) {
   STRING(o) = _mp_calloc(shred->info->vm->gwion->mp, 1);
 }
@@ -457,7 +480,9 @@ GWION_IMPORT(string) {
   GWI_BB(gwi_class_end(gwi))
 
   GWI_BB(gwi_oper_ini(gwi, "string",  "string", "bool"))
+  GWI_BB(gwi_oper_add(gwi, opck_string_eq))
   GWI_BB(gwi_oper_end(gwi, "==",       String_eq))
+  GWI_BB(gwi_oper_add(gwi, opck_string_neq))
   GWI_BB(gwi_oper_end(gwi, "!=",       String_neq))
 
   GWI_BB(gwi_oper_ini(gwi, "int", "string", "string"))