util: rename list_empty() to list_is_empty()
[mesa.git] / src / gallium / drivers / lima / ir / pp / regalloc.c
index 70a178deff85a870e42010cfae84062c397c61ce..d0fe5f9d68e2ce59c48a92021e10e7e3c802713e 100644 (file)
@@ -324,10 +324,10 @@ static bool ppir_update_spilled_src(ppir_compiler *comp, ppir_block *block,
    ppir_node_foreach_pred_safe(node, dep) {
       ppir_node *pred = dep->pred;
       ppir_node_remove_dep(dep);
-      ppir_node_add_dep(load_node, pred);
+      ppir_node_add_dep(load_node, pred, ppir_dep_src);
    }
-   ppir_node_add_dep(node, move_node);
-   ppir_node_add_dep(move_node, load_node);
+   ppir_node_add_dep(node, move_node, ppir_dep_src);
+   ppir_node_add_dep(move_node, load_node, ppir_dep_src);
 
    *fill_node = move_node;
 
@@ -392,10 +392,10 @@ static bool ppir_update_spilled_dest_load(ppir_compiler *comp, ppir_block *block
    ppir_node_foreach_pred_safe(node, dep) {
       ppir_node *pred = dep->pred;
       ppir_node_remove_dep(dep);
-      ppir_node_add_dep(load_node, pred);
+      ppir_node_add_dep(load_node, pred, ppir_dep_src);
    }
-   ppir_node_add_dep(node, move_node);
-   ppir_node_add_dep(move_node, load_node);
+   ppir_node_add_dep(node, move_node, ppir_dep_src);
+   ppir_node_add_dep(move_node, load_node, ppir_dep_src);
 
    return true;
 }
@@ -426,9 +426,9 @@ static bool ppir_update_spilled_dest(ppir_compiler *comp, ppir_block *block,
    ppir_node_foreach_succ_safe(node, dep) {
       ppir_node *succ = dep->succ;
       ppir_node_remove_dep(dep);
-      ppir_node_add_dep(succ, store_node);
+      ppir_node_add_dep(succ, store_node, ppir_dep_src);
    }
-   ppir_node_add_dep(store_node, node);
+   ppir_node_add_dep(store_node, node, ppir_dep_src);
 
    /* If the store temp slot is empty, we can insert the store_temp
     * there and use it directly. Exceptionally, if the node is in the
@@ -479,27 +479,71 @@ static bool ppir_regalloc_spill_reg(ppir_compiler *comp, ppir_reg *chosen)
 static ppir_reg *ppir_regalloc_choose_spill_node(ppir_compiler *comp,
                                                  struct ra_graph *g)
 {
-   int i = 0;
-   ppir_reg *chosen = NULL;
+   float spill_costs[list_length(&comp->reg_list)];
+   /* experimentally determined, it seems to be worth scaling cost of
+    * regs in instructions that have used uniform/store_temp slots,
+    * but not too much as to offset the num_components base cost. */
+   const float slot_scale = 1.1f;
 
    list_for_each_entry(ppir_reg, reg, &comp->reg_list, list) {
       if (reg->spilled || reg->live_out == INT_MAX) {
          /* not considered for spilling */
-         ra_set_node_spill_cost(g, i++, 0.0f);
+         spill_costs[reg->regalloc_index] = 0.0f;
          continue;
       }
 
       /* It is beneficial to spill registers with higher component number,
        * so increase the cost of spilling registers with few components */
       float spill_cost = 4.0f / (float)reg->num_components;
-      ra_set_node_spill_cost(g, i++, spill_cost);
+      spill_costs[reg->regalloc_index] = spill_cost;
+   }
+
+   list_for_each_entry(ppir_block, block, &comp->block_list, list) {
+      list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
+         if (instr->slots[PPIR_INSTR_SLOT_UNIFORM]) {
+            for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
+               ppir_node *node = instr->slots[i];
+               if (!node)
+                  continue;
+               for (int j = 0; j < ppir_node_get_src_num(node); j++) {
+                  ppir_src *src = ppir_node_get_src(node, j);
+                  if (!src)
+                     continue;
+                  ppir_reg *reg = ppir_src_get_reg(src);
+                  if (!reg)
+                     continue;
+
+                  spill_costs[reg->regalloc_index] *= slot_scale;
+               }
+            }
+         }
+         if (instr->slots[PPIR_INSTR_SLOT_STORE_TEMP]) {
+            for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
+               ppir_node *node = instr->slots[i];
+               if (!node)
+                  continue;
+               ppir_dest *dest = ppir_node_get_dest(node);
+               if (!dest)
+                  continue;
+               ppir_reg *reg = ppir_dest_get_reg(dest);
+               if (!reg)
+                  continue;
+
+               spill_costs[reg->regalloc_index] *= slot_scale;
+            }
+         }
+      }
    }
 
+   for (int i = 0; i < list_length(&comp->reg_list); i++)
+      ra_set_node_spill_cost(g, i, spill_costs[i]);
+
    int r = ra_get_best_spill_node(g);
    if (r == -1)
       return NULL;
 
-   i = 0;
+   ppir_reg *chosen = NULL;
+   int i = 0;
    list_for_each_entry(ppir_reg, reg, &comp->reg_list, list) {
       if (i++ == r) {
          chosen = reg;
@@ -568,7 +612,10 @@ static bool ppir_regalloc_prog_try(ppir_compiler *comp, bool *spilled)
       list_for_each_entry_from(ppir_reg, reg2, reg1->list.next,
                                &comp->reg_list, list) {
          bool interference = false;
-         if (reg1->live_in < reg2->live_in) {
+
+         if (reg1->undef || reg2->undef)
+            interference = false;
+         else if (reg1->live_in < reg2->live_in) {
             if (reg1->live_out > reg2->live_in)
                interference = true;
          }
@@ -641,7 +688,7 @@ bool ppir_regalloc_prog(ppir_compiler *comp)
    ppir_regalloc_update_reglist_ssa(comp);
 
    /* No registers? Probably shader consists of discard instruction */
-   if (list_empty(&comp->reg_list))
+   if (list_is_empty(&comp->reg_list))
       return true;
 
    /* this will most likely succeed in the first