]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Now this should deal with vector life ranges more correctly.
authorWolfgang Bumiller <blub@speed.at>
Mon, 24 Dec 2012 11:43:05 +0000 (12:43 +0100)
committerWolfgang Bumiller <blub@speed.at>
Mon, 24 Dec 2012 11:43:05 +0000 (12:43 +0100)
ir.c

diff --git a/ir.c b/ir.c
index fda38e9faaf3026bf604a3851b7bef37dc5e8baa..d57837017da16c47c0118f48f3a4ee5286a3d9f6 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -2018,7 +2018,7 @@ void ir_function_enumerate(ir_function *self)
 static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
 bool ir_function_calculate_liferanges(ir_function *self)
 {
 static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
 bool ir_function_calculate_liferanges(ir_function *self)
 {
-    size_t i;
+    size_t i, s;
     bool changed;
 
     /* parameters live at 0 */
     bool changed;
 
     /* parameters live at 0 */
@@ -2044,23 +2044,45 @@ bool ir_function_calculate_liferanges(ir_function *self)
             ir_value *v = block->living[i];
             if (v->store != store_local)
                 continue;
             ir_value *v = block->living[i];
             if (v->store != store_local)
                 continue;
-            if ((v->members[0] && v->members[1] && v->members[2])) {
-                /* all vector members have been accessed - only treat this as uninitialized
-                 * if any of them is also uninitialized.
-                 */
-                if (!vec_ir_value_find(block->living, v->members[0], NULL) &&
-                    !vec_ir_value_find(block->living, v->members[1], NULL) &&
-                    !vec_ir_value_find(block->living, v->members[2], NULL))
+            if (v->vtype == TYPE_VECTOR)
+                continue;
+            self->flags |= IR_FLAG_HAS_UNINITIALIZED;
+            /* find the instruction reading from it */
+            for (s = 0; s < vec_size(v->reads); ++s) {
+                if (v->reads[s]->eid == v->life[0].end)
+                    break;
+            }
+            if (s < vec_size(v->reads)) {
+                if (irwarning(v->context, WARN_USED_UNINITIALIZED,
+                              "variable `%s` may be used uninitialized in this function\n"
+                              " -> %s:%i",
+                              v->name,
+                              v->reads[s]->context.file, v->reads[s]->context.line)
+                   )
                 {
                 {
-                    continue;
+                    return false;
                 }
                 }
+                continue;
             }
             if (v->memberof) {
             }
             if (v->memberof) {
-                /* A member is only uninitialized if the whole vector is also uninitialized */
-                if (!vec_ir_value_find(block->living, v->memberof, NULL))
+                ir_value *vec = v->memberof;
+                for (s = 0; s < vec_size(vec->reads); ++s) {
+                    if (vec->reads[s]->eid == v->life[0].end)
+                        break;
+                }
+                if (s < vec_size(vec->reads)) {
+                    if (irwarning(v->context, WARN_USED_UNINITIALIZED,
+                                  "variable `%s` may be used uninitialized in this function\n"
+                                  " -> %s:%i",
+                                  v->name,
+                                  vec->reads[s]->context.file, vec->reads[s]->context.line)
+                       )
+                    {
+                        return false;
+                    }
                     continue;
                     continue;
+                }
             }
             }
-            self->flags |= IR_FLAG_HAS_UNINITIALIZED;
             if (irwarning(v->context, WARN_USED_UNINITIALIZED,
                           "variable `%s` may be used uninitialized in this function", v->name))
             {
             if (irwarning(v->context, WARN_USED_UNINITIALIZED,
                           "variable `%s` may be used uninitialized in this function", v->name))
             {
@@ -2316,7 +2338,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
     ir_instr *instr;
     ir_value *value;
     bool  tempbool;
     ir_instr *instr;
     ir_value *value;
     bool  tempbool;
-    size_t i, o, p;
+    size_t i, o, p, mem;
     /* bitmasks which operands are read from or written to */
     size_t read, write;
     char dbg_ind[16] = { '#', '0' };
     /* bitmasks which operands are read from or written to */
     size_t read, write;
     char dbg_ind[16] = { '#', '0' };
@@ -2385,14 +2407,9 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
                      * and make sure it's only printed once
                      * since this function is run multiple times.
                      */
                      * and make sure it's only printed once
                      * since this function is run multiple times.
                      */
-                    /* For now: debug info: */
                     /* con_err( "Value only written %s\n", value->name); */
                     tempbool = ir_value_life_merge(value, instr->eid);
                     *changed = *changed || tempbool;
                     /* con_err( "Value only written %s\n", value->name); */
                     tempbool = ir_value_life_merge(value, instr->eid);
                     *changed = *changed || tempbool;
-                    /*
-                    ir_instr_dump(instr, dbg_ind, printf);
-                    abort();
-                    */
                 } else {
                     /* since 'living' won't contain it
                      * anymore, merge the value, since
                 } else {
                     /* since 'living' won't contain it
                      * anymore, merge the value, since
@@ -2403,6 +2420,27 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
                     /* Then remove */
                     vec_remove(self->living, idx, 1);
                 }
                     /* Then remove */
                     vec_remove(self->living, idx, 1);
                 }
+                /* Removing a vector removes all members */
+                for (mem = 0; mem < 3; ++mem) {
+                    if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], &idx)) {
+                        tempbool = ir_value_life_merge(value->members[mem], instr->eid);
+                        *changed = *changed || tempbool;
+                        vec_remove(self->living, idx, 1);
+                    }
+                }
+                /* Removing the last member removes the vector */
+                if (value->memberof) {
+                    value = value->memberof;
+                    for (mem = 0; mem < 3; ++mem) {
+                        if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], NULL))
+                            break;
+                    }
+                    if (mem == 3 && vec_ir_value_find(self->living, value, &idx)) {
+                        tempbool = ir_value_life_merge(value, instr->eid);
+                        *changed = *changed || tempbool;
+                        vec_remove(self->living, idx, 1);
+                    }
+                }
             }
         }
 
             }
         }
 
@@ -2426,6 +2464,13 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
             {
                 if (!vec_ir_value_find(self->living, value, NULL))
                     vec_push(self->living, value);
             {
                 if (!vec_ir_value_find(self->living, value, NULL))
                     vec_push(self->living, value);
+                /* reading adds the full vector */
+                if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+                    vec_push(self->living, value->memberof);
+                for (mem = 0; mem < 3; ++mem) {
+                    if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+                        vec_push(self->living, value->members[mem]);
+                }
             }
         }
         /* PHI operands are always read operands */
             }
         }
         /* PHI operands are always read operands */
@@ -2434,6 +2479,13 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
             value = instr->phi[p].value;
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
             value = instr->phi[p].value;
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
+            /* reading adds the full vector */
+            if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+                vec_push(self->living, value->memberof);
+            for (mem = 0; mem < 3; ++mem) {
+                if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+                    vec_push(self->living, value->members[mem]);
+            }
         }
 
         /* call params are read operands too */
         }
 
         /* call params are read operands too */
@@ -2442,6 +2494,13 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
             value = instr->params[p];
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
             value = instr->params[p];
             if (!vec_ir_value_find(self->living, value, NULL))
                 vec_push(self->living, value);
+            /* reading adds the full vector */
+            if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+                vec_push(self->living, value->memberof);
+            for (mem = 0; mem < 3; ++mem) {
+                if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+                    vec_push(self->living, value->members[mem]);
+            }
         }
 
         /* (A) */
         }
 
         /* (A) */
@@ -3516,13 +3575,23 @@ void ir_function_dump(ir_function *f, char *ind,
     }
     oprintf("%sliferanges:\n", ind);
     for (i = 0; i < vec_size(f->locals); ++i) {
     }
     oprintf("%sliferanges:\n", ind);
     for (i = 0; i < vec_size(f->locals); ++i) {
-        size_t l;
+        size_t l, m;
         ir_value *v = f->locals[i];
         oprintf("%s\t%s: %s@%i ", ind, v->name, (v->unique_life ? "unique " : ""), (int)v->code.local);
         for (l = 0; l < vec_size(v->life); ++l) {
             oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
         }
         oprintf("\n");
         ir_value *v = f->locals[i];
         oprintf("%s\t%s: %s@%i ", ind, v->name, (v->unique_life ? "unique " : ""), (int)v->code.local);
         for (l = 0; l < vec_size(v->life); ++l) {
             oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
         }
         oprintf("\n");
+        for (m = 0; m < 3; ++m) {
+            ir_value *vm = v->members[m];
+            if (!vm)
+                continue;
+            oprintf("%s\t%s: %s@%i ", ind, vm->name, (vm->unique_life ? "unique " : ""), (int)vm->code.local);
+            for (l = 0; l < vec_size(vm->life); ++l) {
+                oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end);
+            }
+            oprintf("\n");
+        }
     }
     for (i = 0; i < vec_size(f->values); ++i) {
         size_t l;
     }
     for (i = 0; i < vec_size(f->values); ++i) {
         size_t l;