]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.c
Merge pull request #74 from matthiaskrgr/PKGBUILD
[xonotic/gmqcc.git] / ir.c
diff --git a/ir.c b/ir.c
index 0189c2e50ad259ec737086a41d1454faa0300a68..9a19a596988b8fe58e65525d8ec443c9ffb6be61 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -736,6 +736,8 @@ bool ir_function_pass_tailrecursion(ir_function *self)
 
 bool ir_function_finalize(ir_function *self)
 {
+    size_t i;
+
     if (self->builtin)
         return true;
 
@@ -756,6 +758,27 @@ bool ir_function_finalize(ir_function *self)
     if (!ir_function_naive_phi(self))
         return false;
 
+    for (i = 0; i < vec_size(self->locals); ++i) {
+        ir_value *v = self->locals[i];
+        if (v->vtype == TYPE_VECTOR ||
+            (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
+        {
+            ir_value_vector_member(v, 0);
+            ir_value_vector_member(v, 1);
+            ir_value_vector_member(v, 2);
+        }
+    }
+    for (i = 0; i < vec_size(self->values); ++i) {
+        ir_value *v = self->values[i];
+        if (v->vtype == TYPE_VECTOR ||
+            (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
+        {
+            ir_value_vector_member(v, 0);
+            ir_value_vector_member(v, 1);
+            ir_value_vector_member(v, 2);
+        }
+    }
+
     ir_function_enumerate(self);
 
     if (!ir_function_calculate_liferanges(self))
@@ -2172,8 +2195,8 @@ bool ir_function_allocate_locals(ir_function *self)
          * If the value is a parameter-temp: 1 write, 1 read from a CALL
          * and it's not "locked", write it to the OFS_PARM directly.
          */
-        if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES)) {
-            if (!v->locked && vec_size(v->reads) == 1 && vec_size(v->writes) == 1 &&
+        if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked) {
+            if (vec_size(v->reads) == 1 && vec_size(v->writes) == 1 &&
                 (v->reads[0]->opcode == VINSTR_NRCALL ||
                  (v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8)
                 )
@@ -2186,6 +2209,7 @@ bool ir_function_allocate_locals(ir_function *self)
                     goto error;
                 }
 
+                ++opts_optimizationcount[OPTIM_CALL_STORES];
                 v->callparam = true;
                 if (param < 8)
                     ir_value_code_setaddr(v, OFS_PARM0 + 3*param);
@@ -2201,6 +2225,12 @@ bool ir_function_allocate_locals(ir_function *self)
                 }
                 continue;
             }
+            if (vec_size(v->writes) == 1 && v->writes[0]->opcode == INSTR_CALL0)
+            {
+                v->store = store_return;
+                ++opts_optimizationcount[OPTIM_CALL_STORES];
+                continue;
+            }
         }
 
         for (a = 0; a < vec_size(alloc.locals); ++a)
@@ -2593,7 +2623,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
  *
  * Breaking conventions is annoying...
  */
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal, bool defs_only);
+static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal);
 
 static bool gen_global_field(ir_value *global)
 {
@@ -2933,7 +2963,7 @@ tailcall:
 static bool gen_function_code(ir_function *self)
 {
     ir_block *block;
-    prog_section_statement stmt;
+    prog_section_statement stmt, *retst;
 
     /* Starting from entry point, we generate blocks "as they come"
      * for now. Dead blocks will not be translated obviously.
@@ -2953,11 +2983,21 @@ static bool gen_function_code(ir_function *self)
     }
 
     /* code_write and qcvm -disasm need to know that the function ends here */
-    stmt.opcode = INSTR_DONE;
-    stmt.o1.u1 = 0;
-    stmt.o2.u1 = 0;
-    stmt.o3.u1 = 0;
-    code_push_statement(&stmt, vec_last(code_linenums));
+    retst = &vec_last(code_statements);
+    if (OPTS_OPTIMIZATION(OPTIM_VOID_RETURN) &&
+        self->outtype == TYPE_VOID &&
+        retst->opcode == INSTR_RETURN &&
+        !retst->o1.u1 && !retst->o2.u1 && !retst->o3.u1)
+    {
+        retst->opcode = INSTR_DONE;
+        ++opts_optimizationcount[OPTIM_VOID_RETURN];
+    } else {
+        stmt.opcode = INSTR_DONE;
+        stmt.o1.u1 = 0;
+        stmt.o2.u1 = 0;
+        stmt.o3.u1 = 0;
+        code_push_statement(&stmt, vec_last(code_linenums));
+    }
     return true;
 }
 
@@ -3114,7 +3154,7 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global)
         vec_push(code_globals, 0);
     for (i = 0; i < vec_size(irfun->locals); ++i) {
         ir_value_code_setaddr(irfun->locals[i], firstlocal + irfun->locals[i]->code.local);
-        if (!ir_builder_gen_global(ir, irfun->locals[i], true, true)) {
+        if (!ir_builder_gen_global(ir, irfun->locals[i], true)) {
             irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name);
             return false;
         }
@@ -3227,18 +3267,19 @@ static void gen_vector_fields(prog_section_field fld, const char *name)
     }
 }
 
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal, bool defs_only)
+static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal)
 {
     size_t           i;
     int32_t         *iptr;
     prog_section_def def;
     bool             pushdef = false;
 
+    def.type   = global->vtype;
+    def.offset = vec_size(code_globals);
+    def.name   = 0;
     if (opts.g || !islocal)
     {
         pushdef = true;
-        def.type   = global->vtype;
-        def.offset = vec_size(code_globals);
 
         if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
             (global->name[0] == '#' || global->cvq == CV_CONST))
@@ -3257,7 +3298,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
         }
         else
             def.name   = 0;
-        if (defs_only) {
+        if (islocal) {
             def.offset = ir_value_code_addr(global);
             vec_push(code_defs, def);
             if (global->vtype == TYPE_VECTOR)
@@ -3267,7 +3308,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
             return true;
         }
     }
-    if (defs_only)
+    if (islocal)
         return true;
 
     switch (global->vtype)
@@ -3301,12 +3342,8 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
     case TYPE_FIELD:
         if (pushdef) {
             vec_push(code_defs, def);
-            if (global->fieldtype == TYPE_VECTOR) {
+            if (global->fieldtype == TYPE_VECTOR)
                 gen_vector_defs(def, global->name);
-                ir_value_vector_member(global, 0);
-                ir_value_vector_member(global, 1);
-                ir_value_vector_member(global, 2);
-            }
         }
         return gen_global_field(global);
     case TYPE_ENTITY:
@@ -3342,9 +3379,6 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
     case TYPE_VECTOR:
     {
         size_t d;
-        ir_value_vector_member(global, 0);
-        ir_value_vector_member(global, 1);
-        ir_value_vector_member(global, 2);
         ir_value_code_setaddr(global, vec_size(code_globals));
         if (global->hasvalue) {
             iptr = (int32_t*)&global->constval.ivec[0];
@@ -3492,7 +3526,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename)
 
     for (i = 0; i < vec_size(self->globals); ++i)
     {
-        if (!ir_builder_gen_global(self, self->globals[i], false, false)) {
+        if (!ir_builder_gen_global(self, self->globals[i], false)) {
             return false;
         }
         if (self->globals[i]->vtype == TYPE_FUNCTION) {