Change the value in/out info from a bunch of ARRAYOFs to a single hashtable of
authorDavid Given <dg@cowlark.com>
Fri, 13 Jan 2017 21:05:42 +0000 (22:05 +0100)
committerDavid Given <dg@cowlark.com>
Fri, 13 Jan 2017 21:05:42 +0000 (22:05 +0100)
per-hop value metadata.

mach/proto/mcg/hop.c
mach/proto/mcg/hop.h
mach/proto/mcg/ir.c
mach/proto/mcg/ir.h
mach/proto/mcg/pass_assignvregs.c
mach/proto/mcg/pass_instructionselection.c
mach/proto/mcg/pass_livevalueanalysis.c

index 85c8595..31a205f 100644 (file)
@@ -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; i<hop->inputs.count; i++)
     {
-        struct value* value = hop->inputs.item[i];
-        appendf(" r");
-        appendvalue(hop, value);
-    }
-
-    for (i=0; i<hop->outputs.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; i<hop->throughs.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(" ");
index 0c56984..920bd77 100644 (file)
@@ -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);
index 0e0459d..e6e5d6b 100644 (file)
@@ -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;
index ec27b42..dd85edf 100644 (file)
@@ -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
 {
index e58a528..8f1c72a 100644 (file)
@@ -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; i<hop->inputs.count; i++)
-        if (value_comparison_function(hop->inputs.item[i], value))
-            return true;
-
-    for (i=0; i<hop->throughs.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; i<hop->inputs.count; i++)
-        create_and_map_vreg(current_bb->inputmapping, hop->inputs.item[i]);
-    for (i=0; i<hop->throughs.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; i<current_bb->hops.count; i++)
@@ -102,8 +99,17 @@ static void assign_vregs(void)
 
         /* Create vregs for any new outputs. */
 
-        for (j=0; j<hop->outputs.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. */
 
index dfb1497..8a2277f 100644 (file)
@@ -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(&current_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(&current_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 = &current_insn->value;
 
-    array_appendu(&current_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(&current_hop->inputs, &insn->children[0]->value);
-                    array_appendu(&current_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;
             }
index 9ecc23b..4e83880 100644 (file)
@@ -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; j<hop->outputs.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; j<hop->inputs.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);
+            }
         }
        }
 }