diff --git a/ir.c b/ir.c index 4c03899..398744e 100644 --- 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 3881c30..a7f0076 100644 --- 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 */ diff --git a/test/ir-test.c b/test/ir-test.c index f21ce45..38fa764 100644 --- a/test/ir-test.c +++ b/test/ir-test.c @@ -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; }