From: David Given Date: Fri, 13 Jan 2017 21:05:42 +0000 (+0100) Subject: Change the value in/out info from a bunch of ARRAYOFs to a single hashtable of X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=2d71b6a1d4cc8319694b045db85e91e2e6721fd7;p=ack.git Change the value in/out info from a bunch of ARRAYOFs to a single hashtable of per-hop value metadata. --- diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 85c859520..31a205f8e 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -26,6 +26,26 @@ struct hop* new_move_hop(struct basicblock* bb) return hop; } +struct valueusage* hop_get_value_usage(struct hop* hop, struct value* value) +{ + struct valueusage* usage; + + if (!hop->valueusage) + { + hop->valueusage = heap_alloc(&proc_heap, 1, sizeof(struct hashtable)); + *hop->valueusage = empty_hashtable_of_values; + } + + usage = hashtable_get(hop->valueusage, value); + if (!usage) + { + usage = heap_alloc(&proc_heap, 1, sizeof(struct hashtable)); + hashtable_put(hop->valueusage, value, usage); + } + + return usage; +} + static struct insel* new_insel(enum insel_type type) { struct insel* insel = heap_alloc(&proc_heap, 1, sizeof(*insel)); @@ -232,25 +252,24 @@ static void appendheader(struct hop* hop) appendf(" from $%d", hop->ir->id); appendf(":"); - for (i=0; iinputs.count; i++) { - struct value* value = hop->inputs.item[i]; - appendf(" r"); - appendvalue(hop, value); - } - - for (i=0; ioutputs.count; i++) - { - struct value* value = hop->outputs.item[i]; - appendf(" w"); - appendvalue(hop, value); - } + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; - for (i=0; ithroughs.count; i++) - { - struct value* value = hop->throughs.item[i]; - appendf(" ="); - appendvalue(hop, value); + appendf(" "); + if (usage->input) + appendf("r"); + if (usage->output) + appendf("w"); + if (usage->through) + appendf("="); + if (usage->corrupted) + appendf("!"); + appendvalue(hop, value); + } } appendf(" "); diff --git a/mach/proto/mcg/hop.h b/mach/proto/mcg/hop.h index 0c56984fd..920bd77ea 100644 --- a/mach/proto/mcg/hop.h +++ b/mach/proto/mcg/hop.h @@ -28,6 +28,15 @@ struct insel u; }; +struct valueusage +{ + struct vreg* vreg; + bool input : 1; + bool output : 1; + bool through : 1; + bool corrupted : 1; +}; + struct hop { int id; @@ -40,18 +49,17 @@ struct hop const char* pseudo; PMAPOF(struct value, struct value) equals_constraint; - ARRAYOF(struct value) inputs; - ARRAYOF(struct value) outputs; - ARRAYOF(struct value) throughs; - ARRAYOF(struct value) corrupted; + struct hashtable* valueusage; - struct hashtable* vregmapping; + struct hashtable* vregmapping; /* value -> vreg */ PMAPOF(struct vreg, struct vreg) copies; }; 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_string_insel(struct hop* hop, const char* string); extern void hop_add_hreg_insel(struct hop* hop, struct hreg* hreg, int index); extern void hop_add_vreg_insel(struct hop* hop, struct value* value, int index); diff --git a/mach/proto/mcg/ir.c b/mach/proto/mcg/ir.c index 0e0459d86..e6e5d6b69 100644 --- a/mach/proto/mcg/ir.c +++ b/mach/proto/mcg/ir.c @@ -2,6 +2,8 @@ static int next_id = 0; +const struct hashtable empty_hashtable_of_values = HASHTABLE_OF_VALUES; + uint32_t value_hash_function(void* key) { struct value* value = key; diff --git a/mach/proto/mcg/ir.h b/mach/proto/mcg/ir.h index ec27b42ef..dd85edfc3 100644 --- a/mach/proto/mcg/ir.h +++ b/mach/proto/mcg/ir.h @@ -14,6 +14,7 @@ extern uint32_t value_hash_function(void* key); extern bool value_comparison_function(void* key1, void* key2); #define HASHTABLE_OF_VALUES \ { value_hash_function, value_comparison_function } +extern const struct hashtable empty_hashtable_of_values; struct ir { diff --git a/mach/proto/mcg/pass_assignvregs.c b/mach/proto/mcg/pass_assignvregs.c index e58a52814..8f1c72a18 100644 --- a/mach/proto/mcg/pass_assignvregs.c +++ b/mach/proto/mcg/pass_assignvregs.c @@ -1,7 +1,5 @@ #include "mcg.h" -static const struct hashtable empty_hashtable_of_values = HASHTABLE_OF_VALUES; - static struct basicblock* current_bb; static int vregcount = 0; @@ -43,17 +41,8 @@ static struct hop* create_move(struct hashtable* previous_mapping) static bool hop_reads_value(struct hop* hop, struct value* value) { - int i; - - for (i=0; iinputs.count; i++) - if (value_comparison_function(hop->inputs.item[i], value)) - return true; - - for (i=0; ithroughs.count; i++) - if (value_comparison_function(hop->throughs.item[i], value)) - return true; - - return false; + struct valueusage* usage = hop_get_value_usage(hop, value); + return usage->input || usage->through; } static void assign_vregs(void) @@ -70,10 +59,18 @@ static void assign_vregs(void) current_bb->inputmapping = heap_alloc(&proc_heap, 1, sizeof(struct hashtable)); *current_bb->inputmapping = empty_hashtable_of_values; hashtable_empty(current_bb->inputmapping); - for (i=0; iinputs.count; i++) - create_and_map_vreg(current_bb->inputmapping, hop->inputs.item[i]); - for (i=0; ithroughs.count; i++) - create_and_map_vreg(current_bb->inputmapping, hop->throughs.item[i]); + + { + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; + + if (usage->input || usage->through) + create_and_map_vreg(current_bb->inputmapping, value); + } + } previous_mapping = current_bb->inputmapping; for (i=0; ihops.count; i++) @@ -102,8 +99,17 @@ static void assign_vregs(void) /* Create vregs for any new outputs. */ - for (j=0; joutputs.count; j++) - create_and_map_vreg(current_mapping, hop->outputs.item[j]); + { + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; + + if (usage->output) + create_and_map_vreg(current_mapping, value); + } + } /* And move on to the next one. */ diff --git a/mach/proto/mcg/pass_instructionselection.c b/mach/proto/mcg/pass_instructionselection.c index dfb1497c1..8a2277f0d 100644 --- a/mach/proto/mcg/pass_instructionselection.c +++ b/mach/proto/mcg/pass_instructionselection.c @@ -85,7 +85,7 @@ static void constrain_input_reg(int child, uint32_t attr) struct value* value = find_value_of_child(child); struct constraint* c; - array_appendu(¤t_hop->inputs, value); + hop_get_value_usage(current_hop, value)->input = true; value->attrs = attr; } @@ -94,7 +94,7 @@ static void constrain_input_reg_corrupted(int child) struct value* value = find_value_of_child(child); struct constraint* c; - array_appendu(¤t_hop->corrupted, value); + hop_get_value_usage(current_hop, value)->corrupted = true; } static uint32_t find_type_from_constraint(uint32_t attr) @@ -129,7 +129,7 @@ static void constrain_output_reg(uint32_t attr) { struct value* value = ¤t_insn->value; - array_appendu(¤t_hop->outputs, value); + hop_get_value_usage(current_hop, value)->output = true; value->attrs = find_type_from_constraint(attr); } @@ -221,8 +221,8 @@ static struct insn* walk_instructions(struct burm_node* node, int goal) case ir_to_esn(IR_NOP, 'F'): case ir_to_esn(IR_NOP, 'L'): case ir_to_esn(IR_NOP, 'D'): - array_appendu(¤t_hop->inputs, &insn->children[0]->value); - array_appendu(¤t_hop->outputs, current_hop->value); + hop_get_value_usage(current_hop, &insn->children[0]->value)->input = true; + hop_get_value_usage(current_hop, current_hop->value)->output = true; hop_add_insel(current_hop, "@copy %V %V", &insn->children[0]->value, current_hop->value); break; } diff --git a/mach/proto/mcg/pass_livevalueanalysis.c b/mach/proto/mcg/pass_livevalueanalysis.c index 9ecc23b39..4e83880fd 100644 --- a/mach/proto/mcg/pass_livevalueanalysis.c +++ b/mach/proto/mcg/pass_livevalueanalysis.c @@ -19,10 +19,16 @@ static void propagate_liveness(struct basicblock* bb) /* Values are only ever written once, so if we see a write then we * know the value was not live before this. */ - for (j=0; joutputs.count; j++) { - struct value* value = hop->outputs.item[j]; - set_remove(&known_live, value); + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; + + if (usage->output) + set_remove(&known_live, value); + } } /* Propagate the set of live values across this hop. */ @@ -32,17 +38,23 @@ static void propagate_liveness(struct basicblock* bb) while (set_next(&known_live, &si)) { struct value* value = si.item; - array_appendu(&hop->throughs, value); + hop_get_value_usage(hop, value)->through = true; } } /* Values which are read from must have come from somewhere, and so * become live. */ - for (j=0; jinputs.count; j++) { - struct value* value = hop->inputs.item[j]; - set_add(&known_live, value); + struct hashtable_iterator hit = {}; + while (hashtable_next(hop->valueusage, &hit)) + { + struct value* value = hit.key; + struct valueusage* usage = hit.value; + + if (usage->input) + set_remove(&known_live, value); + } } } }