]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
ir_value_life_merge_into, to merge the liferange of one value into the range of anoth...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Mon, 25 Jun 2012 12:51:31 +0000 (14:51 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Mon, 25 Jun 2012 12:51:31 +0000 (14:51 +0200)
ir.c
ir.h
test/ir-test.c

diff --git a/ir.c b/ir.c
index 4c03899a539316618132bc1b517df0b7c00513ec..398744ed512f376d82874ed764236795284c5e5c 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -584,6 +584,83 @@ bool ir_value_life_merge(ir_value *self, size_t s)
     return ir_value_life_insert(self, i, new_entry);
 }
 
+bool ir_value_life_merge_into(ir_value *self, const ir_value *other)
+{
+    size_t i, myi;
+
+    if (!other->life_count)
+        return true;
+
+    if (!self->life_count) {
+        for (i = 0; i < other->life_count; ++i) {
+            if (!ir_value_life_add(self, other->life[i]))
+                return false;
+        }
+        return true;
+    }
+
+    myi = 0;
+    for (i = 0; i < other->life_count; ++i)
+    {
+        const ir_life_entry_t *life = &other->life[i];
+        while (true)
+        {
+            ir_life_entry_t *entry = &self->life[myi];
+
+            if (life->end+1 < entry->start)
+            {
+                /* adding an interval before entry */
+                if (!ir_value_life_insert(self, myi, *life))
+                    return false;
+                ++myi;
+                break;
+            }
+
+            if (life->start <  entry->start &&
+                life->end   >= entry->start)
+            {
+                /* starts earlier and overlaps */
+                entry->start = life->start;
+            }
+
+            if (life->end     >  entry->end &&
+                life->start-1 <= entry->end)
+            {
+                /* ends later and overlaps */
+                entry->end = life->end;
+            }
+
+            /* see if our change combines it with the next ranges */
+            while (myi+1 < self->life_count &&
+                   entry->end+1 >= self->life[1+myi].start)
+            {
+                /* overlaps with (myi+1) */
+                if (entry->end < self->life[1+myi].end)
+                    entry->end = self->life[1+myi].end;
+                if (!ir_value_life_remove(self, myi+1))
+                    return false;
+                entry = &self->life[myi];
+            }
+
+            /* see if we're after the entry */
+            if (life->start > entry->end)
+            {
+                ++myi;
+                /* append if we're at the end */
+                if (myi >= self->life_count) {
+                    if (!ir_value_life_add(self, *life))
+                        return false;
+                    break;
+                }
+                /* otherweise check the next range */
+                continue;
+            }
+            break;
+        }
+    }
+    return true;
+}
+
 bool ir_values_overlap(ir_value *a, ir_value *b)
 {
     /* For any life entry in A see if it overlaps with
@@ -1425,7 +1502,7 @@ bool ir_function_calculate_liferanges(ir_function *self)
  */
 bool ir_function_allocate_locals(ir_function *self)
 {
-    return false;
+    return true;
 }
 
 /* Get information about which operand
diff --git a/ir.h b/ir.h
index 3881c30fb618ab0e1c64a294221a0b94a054d617..a7f0076ccaf6ada0d6cbc85850d5b9af8377839e 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -89,6 +89,7 @@ MEM_VECTOR_PROTO(ir_value, ir_life_entry_t, life);
 /* merge an instruction into the life-range */
 /* returns false if the lifepoint was already known */
 bool ir_value_life_merge(ir_value*, size_t);
+bool ir_value_life_merge_into(ir_value*, const ir_value*);
 /* check if a value lives at a specific point */
 bool ir_value_lives(ir_value*, size_t);
 /* check if the life-range of 2 values overlaps */
index f21ce4517dabdaef76327554bf966e6f9b3bcc3a..38fa764cb7c5bf122b1795aca97323af08ba3458 100644 (file)
@@ -9,6 +9,8 @@
 
 int main()
 {
+    int lf;
+
        ir_builder *b  = ir_builder_new("test");
        ir_value   *va = ir_builder_create_global(b, "a", TYPE_FLOAT);
        ir_value   *v3 = ir_builder_create_global(b, "const_f_3", TYPE_FLOAT);
@@ -16,6 +18,10 @@ int main()
        ir_value   *vc = ir_builder_create_global(b, "c", TYPE_FLOAT);
        ir_value   *vd = ir_builder_create_global(b, "d", TYPE_FLOAT);
 
+       ir_value   *life1  = ir_builder_create_global(b, "life1", TYPE_FLOAT);
+       ir_value   *life2  = ir_builder_create_global(b, "life2", TYPE_FLOAT);
+       ir_value   *life3  = ir_builder_create_global(b, "life3", TYPE_FLOAT);
+
        ir_function *fmain  = NULL;
        ir_value    *la     = NULL;
        ir_block    *bmain  = NULL;
@@ -110,6 +116,35 @@ int main()
        ir_value_dump_life(vig, printf);
        ir_value_dump_life(la, printf);
 
+       ir_value_life_merge_into(retval, vig);
+       ir_value_dump_life(retval, printf);
+       ir_value_life_merge(x1, 12);
+       ir_value_life_merge(x1, 13);
+       ir_value_life_merge(x1, 14);
+       ir_value_life_merge_into(retval, x1);
+       ir_value_dump_life(retval, printf);
+       ir_value_life_merge(x1, 20);
+       ir_value_life_merge(x1, 21);
+       ir_value_life_merge(x1, 22);
+       ir_value_life_merge_into(retval, x1);
+       ir_value_dump_life(retval, printf);
+       ir_value_life_merge(x2, 1);
+       ir_value_life_merge(x2, 2);
+       ir_value_life_merge_into(retval, x2);
+       ir_value_dump_life(retval, printf);
+       for (lf = 4; lf <= 15; ++lf)
+           ir_value_life_merge(life1, lf);
+       ir_value_life_merge_into(retval, life1);
+       ir_value_dump_life(retval, printf);
+       for (lf = 17; lf <= 18; ++lf)
+           ir_value_life_merge(life2, lf);
+       ir_value_life_merge_into(retval, life2);
+       ir_value_dump_life(retval, printf);
+       for (lf = 2; lf <= 29; ++lf)
+           ir_value_life_merge(life3, lf);
+       ir_value_life_merge_into(retval, life3);
+       ir_value_dump_life(retval, printf);
+
        ir_builder_delete(b);
        return 0;
 }