From: David Given Date: Sat, 14 Jan 2017 11:26:23 +0000 (+0100) Subject: vregmapping has gone; the input and output vregs are now part of the valueusage X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=32176226fddeaaee0cf2eca2cc8b76a967d79f60;p=ack.git vregmapping has gone; the input and output vregs are now part of the valueusage structure. This allows them to be different, which vastly simplifies parallel copies. --- diff --git a/mach/proto/mcg/basicblock.h b/mach/proto/mcg/basicblock.h index 6edafad5e..c95a16a85 100644 --- a/mach/proto/mcg/basicblock.h +++ b/mach/proto/mcg/basicblock.h @@ -21,8 +21,8 @@ struct basicblock PMAPOF(struct ir, struct ir) imports; PMAPOF(struct ir, struct ir) exports; - struct hashtable* inputmapping; - struct hashtable* outputmapping; + struct hashtable inputmapping; + struct hashtable outputmapping; bool is_fake : 1; bool is_root : 1; diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 31a205f8e..f259bad7e 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -235,9 +235,26 @@ static char* appendf(const char* fmt, ...) void appendvalue(struct hop* hop, struct value* value) { - struct vreg* vreg; + struct valueusage* usage = hop_get_value_usage(hop, value); + struct vreg* vreg = NULL; - if (hop->vregmapping && ((vreg = hashtable_get(hop->vregmapping, value)))) + 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) appendf("%%%d", vreg->id); else appendf("$%d:%d", value->ir->id, value->subid); @@ -259,16 +276,19 @@ static void appendheader(struct hop* hop) struct value* value = hit.key; struct valueusage* usage = hit.value; - appendf(" "); - if (usage->input) - appendf("r"); - if (usage->output) - appendf("w"); - if (usage->through) - appendf("="); - if (usage->corrupted) - appendf("!"); - appendvalue(hop, value); + if (usage->input || usage->output || usage->through || usage->corrupted) + { + appendf(" "); + if (usage->input) + appendf("r"); + if (usage->output) + appendf("w"); + if (usage->through) + appendf("="); + if (usage->corrupted) + appendf("!"); + appendvalue(hop, value); + } } } @@ -388,6 +408,9 @@ void hop_print(char k, struct hop* hop) char* p; char* header; + if (!tracing(k)) + return; + appendf(""); /* ensure the buffer has been allocated */ bufferlen = 0; buffer[0] = '\0'; diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index e70d6d21a..5c80c5f6c 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -30,6 +30,8 @@ struct insel struct valueusage { + struct vreg* invreg; + struct vreg* outvreg; bool input : 1; bool output : 1; bool through : 1; @@ -49,7 +51,6 @@ struct hop PMAPOF(struct value, struct value) equals_constraint; struct hashtable* valueusage; - struct hashtable* vregmapping; /* value -> vreg */ PMAPOF(struct vreg, struct vreg) copies; }; diff --git a/mach/proto/mcg/pass_assignvregs.c b/mach/proto/mcg/pass_assignvregs.c index 8f1c72a18..dbcd4e41d 100644 --- a/mach/proto/mcg/pass_assignvregs.c +++ b/mach/proto/mcg/pass_assignvregs.c @@ -3,6 +3,7 @@ static struct basicblock* current_bb; static int vregcount = 0; +static struct hashtable mapping = HASHTABLE_OF_VALUES; static struct vreg* create_vreg(struct value* value) { @@ -12,28 +13,32 @@ static struct vreg* create_vreg(struct value* value) return vreg; } -static void create_and_map_vreg(struct hashtable* mapping, struct value* value) +static struct vreg* create_and_map_vreg(struct value* value) { struct vreg* vreg = create_vreg(value); - assert(!hashtable_get(mapping, value)); - hashtable_put(mapping, value, vreg); + assert(!hashtable_get(&mapping, value)); + hashtable_put(&mapping, value, vreg); + return vreg; } -static struct hop* create_move(struct hashtable* previous_mapping) +static struct hop* clone_vregs(void) { struct hop* hop = new_hop(current_bb, NULL); - hop->vregmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable));; - *hop->vregmapping = empty_hashtable_of_values; hop->is_move = true; struct hashtable_iterator hit = {}; - while (hashtable_next(previous_mapping, &hit)) + while (hashtable_next(&mapping, &hit)) { struct value* value = hit.key; struct vreg* oldvreg = hit.value; struct vreg* newvreg = create_vreg(value); - hashtable_put(hop->vregmapping, value, newvreg); - pmap_add(&hop->copies, oldvreg, newvreg); + 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; } return hop; @@ -48,17 +53,16 @@ static bool hop_reads_value(struct hop* hop, struct value* value) static void assign_vregs(void) { int i, j; - struct hashtable* previous_mapping; - struct hashtable* current_mapping; struct hop* hop; /* Preload the mapping from the first hop. It might be a move, but that * does no harm. */ hop = current_bb->hops.item[0]; - current_bb->inputmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable)); - *current_bb->inputmapping = empty_hashtable_of_values; - hashtable_empty(current_bb->inputmapping); + assert(current_bb->inputmapping.size == 0); + assert(current_bb->outputmapping.size == 0); + assert(mapping.size == 0); + current_bb->outputmapping = empty_hashtable_of_values; { struct hashtable_iterator hit = {}; @@ -68,36 +72,35 @@ static void assign_vregs(void) struct valueusage* usage = hit.value; if (usage->input || usage->through) - create_and_map_vreg(current_bb->inputmapping, value); + { + struct vreg* vreg = create_and_map_vreg(value); + hashtable_put(¤t_bb->inputmapping, value, vreg); + } } } - previous_mapping = current_bb->inputmapping; for (i=0; ihops.count; i++) { /* Insert a parallel-move hop to copy all the vregs. */ - struct hop* move = create_move(previous_mapping); + struct hop* move = clone_vregs(); array_insert(¤t_bb->hops, move, i); i++; - previous_mapping = move->vregmapping; - /* Copy the previous mapping to this hop, pruning out any unused values. */ + /* Copy the previous mapping to this hop. */ hop = current_bb->hops.item[i]; - current_mapping = hop->vregmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable));; - *current_mapping = empty_hashtable_of_values; { struct hashtable_iterator hit = {}; - while (hashtable_next(previous_mapping, &hit)) + while (hashtable_next(&mapping, &hit)) { struct value* value = hit.key; - if (hop_reads_value(hop, value)) - hashtable_put(current_mapping, value, hit.value); + struct vreg* vreg = hit.value; + hop_get_value_usage(hop, value)->invreg = vreg; } } - /* Create vregs for any new outputs. */ + /* Prune any unused values from the mapping. */ { struct hashtable_iterator hit = {}; @@ -105,22 +108,35 @@ static void assign_vregs(void) { struct value* value = hit.key; struct valueusage* usage = hit.value; - - if (usage->output) - create_and_map_vreg(current_mapping, value); + if (!usage->through) + hashtable_remove(&mapping, value); } } - /* And move on to the next one. */ + /* Handle new output vregs, and propagated through vregs. */ - previous_mapping = current_mapping; + { + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; + + assert(!(usage->through && usage->output)); + if (usage->through) + usage->outvreg = usage->invreg; + if (usage->output) + usage->outvreg = create_and_map_vreg(value); + } + } } /* Insert one final move at the end of the block. */ - hop = create_move(previous_mapping); + hop = clone_vregs(); array_append(¤t_bb->hops, hop); - current_bb->outputmapping = hop->vregmapping; + + hashtable_copy_all(&mapping, ¤t_bb->outputmapping); } void pass_assign_vregs(void) @@ -133,8 +149,10 @@ void pass_assign_vregs(void) { current_bb = dominance.preorder.item[i]; assign_vregs(); + hashtable_empty(&mapping); } + hashtable_reset(&mapping); tracef('V', "V: finished vreg assignment with %d vregs\n", vregcount); }