return usage;
}
+void hop_add_input_vreg(struct hop* hop, struct vreg* vreg)
+{
+ if (!pmap_findleft(&hop->vregusage, vreg))
+ pmap_add(&hop->vregusage, vreg, NULL);
+}
+
+void hop_add_output_vreg(struct hop* hop, struct vreg* vreg)
+{
+ assert(!pmap_findright(&hop->vregusage, vreg));
+ pmap_add(&hop->vregusage, NULL, vreg);
+}
+
+void hop_add_through_vreg(struct hop* hop, struct vreg* src, struct vreg* dest)
+{
+ int i;
+
+ for (i=0; i<hop->vregusage.count; i++)
+ {
+ struct vreg* candidatesrc = hop->vregusage.item[i].left;
+ struct vreg* candidatedest = hop->vregusage.item[i].right;
+ if ((candidatesrc == src) && !candidatedest)
+ {
+ hop->vregusage.item[i].right = dest;
+ return;
+ }
+ if (!candidatesrc && (candidatedest == dest))
+ {
+ hop->vregusage.item[i].left = src;
+ return;
+ }
+ }
+
+ pmap_add(&hop->vregusage, src, dest);
+}
+
+struct vreg* hop_find_input_vreg(struct hop* hop, struct value* value)
+{
+ int i;
+
+ for (i=0; i<hop->vregusage.count; i++)
+ {
+ struct vreg* vreg = hop->vregusage.item[i].left;
+ if (vreg && value_comparison_function(vreg->value, value))
+ return vreg;
+ }
+
+ return NULL;
+}
+
+struct vreg* hop_find_output_vreg(struct hop* hop, struct value* value)
+{
+ int i;
+
+ for (i=0; i<hop->vregusage.count; i++)
+ {
+ struct vreg* vreg = hop->vregusage.item[i].right;
+ if (vreg && value_comparison_function(vreg->value, value))
+ return vreg;
+ }
+
+ return NULL;
+}
+
void hop_add_move(struct hop* hop, struct value* src, struct value* dest)
{
struct valueusage* usage;
void appendvreg(struct vreg* vreg)
{
- appendf("%%%d", vreg->id);
+ appendf("($%d:%d=%%%d", vreg->value->ir->id, vreg->value->subid, vreg->id);
if (vreg->hreg != -1)
- appendf("=%d", vreg->hreg);
+ appendf("=R%d", vreg->hreg);
if (vreg->is_spilt)
appendf("S");
-}
-
-void appendvalue(struct hop* hop, struct value* value)
-{
- struct valueusage* usage = hop_get_value_usage(hop, value);
- struct vreg* vreg = NULL;
-
- if (usage->input && usage->output && usage->invreg && usage->outvreg)
- {
- appendf("%%%d->%%%d", usage->invreg->id, usage->outvreg->id);
- return;
- }
-
- if (usage->input)
- vreg = usage->invreg;
- if (usage->output)
- vreg = usage->outvreg;
- if (usage->through)
- {
- assert(usage->invreg == usage->outvreg);
- vreg = usage->invreg;
- }
-
- if (vreg)
- appendvreg(actual(vreg));
- else
- appendf("$%d:%d", value->ir->id, value->subid);
+ appendf(")");
}
static void appendheader(struct hop* hop)
appendf(" from $%d", hop->ir->id);
appendf(":");
+ appendf(" VALUES:");
{
struct hashtable_iterator hit = {};
while (hashtable_next(hop->valueusage, &hit))
appendf("=");
if (usage->corrupted)
appendf("!");
- appendvalue(hop, value);
+ appendf("$%d:%d", value->ir->id, value->subid);
}
}
}
- appendf(" ");
+ appendf(" VREGS:");
+ for (i=0; i<hop->vregusage.count; i++)
+ {
+ struct vreg* src = hop->vregusage.item[i].left;
+ struct vreg* dest = hop->vregusage.item[i].right;
+
+ appendf(" ");
+ if (src)
+ appendvreg(src);
+ appendf("->");
+ if (dest)
+ appendvreg(dest);
+ }
+
+ appendf(" INSN: ");
}
char* hop_render(struct hop* hop)
if (hop->is_move)
{
- struct hashtable_iterator hit = {};
appendf("@move:");
- while (hashtable_next(hop->valueusage, &hit))
+
+ for (i=0; i<hop->vregusage.count; i++)
{
- struct valueusage* usage = hit.value;
- struct vreg* invreg = actual(usage->invreg);
- struct vreg* outvreg = actual(usage->outvreg);
- if (usage->input && usage->output && (invreg == outvreg))
+ struct vreg* invreg = actual(hop->vregusage.item[i].left);
+ struct vreg* outvreg = actual(hop->vregusage.item[i].right);
+ if ((invreg == outvreg) || !invreg || !outvreg)
continue;
appendf(" ");
- if (usage->input && invreg)
+ if (invreg)
appendvreg(invreg);
appendf("->");
- if (usage->output && outvreg)
+ if (outvreg)
appendvreg(outvreg);
}
appendf("\n");
case INSEL_VREG:
{
- appendvalue(hop, insel->u.value);
- if (insel->index)
- appendf(".%d", insel->index);
+ struct value* value = insel->u.value;
+ struct valueusage* usage = hop_get_value_usage(hop, value);
+ struct vreg* vreg = NULL;
+ if (usage->input)
+ vreg = hop_find_input_vreg(hop, value);
+ else if (usage->output)
+ vreg = hop_find_output_vreg(hop, value);
+
+ if (vreg)
+ appendvreg(actual(vreg));
+ else
+ {
+ appendf("$%d:%d", value->ir->id, value->subid);
+ if (insel->index)
+ appendf(".%d", insel->index);
+ }
break;
}
struct valueusage
{
- struct vreg* invreg;
- struct vreg* outvreg;
bool input : 1;
bool output : 1;
bool through : 1;
PMAPOF(struct value, struct value) equals_constraint;
struct hashtable* valueusage;
+ PMAPOF(struct vreg, struct vreg) vregusage;
};
extern struct hop* new_hop(struct basicblock* bb, struct ir* ir);
extern struct hop* new_move_hop(struct basicblock* bb);
extern struct valueusage* hop_get_value_usage(struct hop* hop, struct value* value);
+extern void hop_add_input_vreg(struct hop* hop, struct vreg* vreg);
+extern void hop_add_output_vreg(struct hop* hop, struct vreg* vreg);
+extern void hop_add_through_vreg(struct hop* hop, struct vreg* src, struct vreg* dest);
+extern struct vreg* hop_find_input_vreg(struct hop* hop, struct value* value);
+extern struct vreg* hop_find_output_vreg(struct hop* hop, struct value* value);
extern void hop_add_move(struct hop* hop, struct value* src, struct value* dest);
extern void hop_add_string_insel(struct hop* hop, const char* string);
struct valueusage* usage = hop_get_value_usage(hop, value);
hashtable_put(&mapping, value, newvreg);
- usage->input = true;
- usage->invreg = oldvreg;
- usage->output = true;
- usage->outvreg = newvreg;
+ usage->input = usage->output = true;
+ hop_add_through_vreg(hop, oldvreg, newvreg);
}
return hop;
for (i=0; i<current_bb->hops.count; i++)
{
+ /* Remove completely unused vregs from the mapping. */
+
+ hop = current_bb->hops.item[i];
+ {
+ struct hashtable_iterator hit = {};
+ while (hashtable_next(&mapping, &hit))
+ {
+ struct value* value = hit.key;
+ struct valueusage* usage = hop_get_value_usage(hop, value);
+ if (!usage->input && !usage->output && !usage->through)
+ hashtable_delete_current(&mapping, &hit);
+ }
+ }
+
/* Insert a parallel-move hop to copy all the vregs. */
- struct hop* move = clone_vregs();
- array_insert(¤t_bb->hops, move, i);
- i++;
+ {
+ struct hop* move = clone_vregs();
+ array_insert(¤t_bb->hops, move, i);
+ i++;
+ }
/* Copy the previous mapping to this hop. */
{
struct value* value = hit.key;
struct vreg* vreg = hit.value;
- hop_get_value_usage(hop, value)->invreg = vreg;
+ hop_add_input_vreg(hop, vreg);
}
}
assert(!(usage->through && usage->output));
if (usage->through)
- usage->outvreg = usage->invreg;
+ {
+ struct vreg* invreg = hop_find_input_vreg(hop, value);
+ hop_add_through_vreg(hop, invreg, invreg);
+ }
if (usage->output)
- usage->outvreg = create_and_map_vreg(value);
+ {
+ struct vreg* outvreg = create_and_map_vreg(value);
+ hop_add_output_vreg(hop, outvreg);
+ }
}
}
}
void pass_convert_copies_to_moves(void)
{
- int i, j;
+ int i, j, k;
for (i=0; i<cfg.preorder.count; i++)
{
struct hop* hop = bb->hops.item[j];
if (hop->is_move)
{
- struct valueusage* usage;
- struct hashtable_iterator hit = {};
struct vreg* invreg = NULL;
struct vreg* outvreg = NULL;
- while (hashtable_next(hop->valueusage, &hit))
+
+ for (k=0; k<hop->vregusage.count; k++)
{
- usage = hit.value;
- if (usage->input && !usage->output)
+ struct vreg* in = hop->vregusage.item[k].left;
+ struct vreg* out = hop->vregusage.item[k].right;
+
+ if (in && !out)
{
assert(!invreg);
- invreg = usage->invreg;
+ invreg = in;
}
- if (!usage->input && usage->output)
+ if (!in && out)
{
assert(!outvreg);
- outvreg = usage->outvreg;
+ outvreg = out;
}
}
if (invreg && outvreg)
{
- usage = hop_get_value_usage(hop, outvreg->value);
+ struct valueusage* usage = hop_get_value_usage(hop, outvreg->value);
assert(!usage->input);
usage->input = true;
- usage->invreg = invreg;
+ hop_add_through_vreg(hop, invreg, outvreg);
}
}
}
static struct vreg* actual(struct vreg* vreg)
{
+ if (!vreg)
+ return NULL;
while (vreg->coalesced_with)
vreg = vreg->coalesced_with;
return vreg;
static void generate_graph(void)
{
- int i, j, k;
+ int i, j, k, m;
for (i=0; i<cfg.preorder.count; i++)
{
for (j=0; j<bb->hops.count; j++)
{
struct hop* hop = bb->hops.item[j];
- struct hashtable_iterator hit1 = {};
- while (hashtable_next(hop->valueusage, &hit1))
+ for (k=0; k<hop->vregusage.count; k++)
{
- struct valueusage* usage1 = hit1.value;
- struct hashtable_iterator hit2 = {};
- while (hashtable_next(hop->valueusage, &hit2))
+ struct vreg* invreg1 = actual(hop->vregusage.item[k].left);
+ struct vreg* outvreg1 = actual(hop->vregusage.item[k].right);
+
+ for (m=k; m<hop->vregusage.count; m++)
{
- struct valueusage* usage2 = hit2.value;
-
- if (usage1->invreg)
- graph_add_vertex(&interference, actual(usage1->invreg));
- if (usage2->invreg)
- graph_add_vertex(&interference, actual(usage2->invreg));
- if (usage1->invreg && usage2->invreg)
- graph_add_edge(&interference, actual(usage1->invreg), actual(usage2->invreg));
- if (usage1->outvreg && usage2->outvreg)
- graph_add_edge(&interference, actual(usage1->outvreg), actual(usage2->outvreg));
-
- if (usage1->corrupted && usage1->invreg && usage2->outvreg)
- graph_add_edge(&interference, actual(usage1->invreg), actual(usage2->outvreg));
+ struct vreg* invreg2 = actual(hop->vregusage.item[m].left);
+ struct vreg* outvreg2 = actual(hop->vregusage.item[m].right);
+
+ if (invreg1)
+ graph_add_vertex(&interference, invreg1);
+ if (invreg2)
+ graph_add_vertex(&interference, invreg2);
+ if (outvreg1)
+ graph_add_vertex(&interference, outvreg1);
+ if (outvreg2)
+ graph_add_vertex(&interference, outvreg2);
+
+ if (invreg1 && invreg2)
+ graph_add_edge(&interference, invreg1, invreg2);
+ if (outvreg1 && outvreg2)
+ graph_add_edge(&interference, outvreg1, outvreg2);
}
- if (hop->is_move && usage1->invreg && usage1->outvreg)
- graph_add_edge(&affinity, actual(usage1->invreg), actual(usage1->outvreg));
+ if (hop->is_move && invreg1 && outvreg1)
+ graph_add_edge(&affinity, invreg1, outvreg1);
}
}
}
{
struct vreg* vreg = array_pop(&simplified);
int neighbours = vreg->neighbours;
- unsigned int bitmap = 0;
+ burm_register_bitmap_t bitmap = {};
while (neighbours > 0)
{
struct vreg* neighbour = actual(array_pop(&simplified));
if (neighbour->hreg != -1)
- bitmap_set(&bitmap, 32, neighbour->hreg);
+ bitmap_set(bitmap, burm_register_count, neighbour->hreg);
neighbours--;
}
- vreg->hreg = bitmap_find_unset_bit(&bitmap, 32);
+ vreg->hreg = bitmap_find_unset_bit(bitmap, burm_register_count);
}
}
static void calculate_spillibility(void)
{
- int i;
+ int i, j;
for (i=0; i<current_bb->hops.count; i++)
{
struct hop* hop = current_bb->hops.item[i];
if (!hop->is_move)
{
- struct hashtable_iterator hit = {};
- while (hashtable_next(hop->valueusage, &hit))
+ for (j=0; j<hop->vregusage.count; j++)
{
- struct value* value = hit.key;
- struct valueusage* usage = hit.value;
+ struct vreg* invreg = hop->vregusage.item[j].left;
+ struct vreg* outvreg = hop->vregusage.item[j].right;
+ struct valueusage* usage = invreg ? hop_get_value_usage(hop, invreg->value) : NULL;
- if (!usage->through)
- {
- if (usage->invreg)
- usage->invreg->needs_register = true;
- if (usage->outvreg)
- usage->outvreg->needs_register = true;
- }
+ if (invreg && !outvreg)
+ invreg->needs_register = true;
+ if (!invreg && outvreg)
+ outvreg->needs_register = true;
+ if (invreg && outvreg && !usage->through)
+ invreg->needs_register = outvreg->needs_register = true;
}
}
}