intel/nir: Take nir_shader*s in brw_nir_link_shaders
[mesa.git] / src / intel / compiler / brw_fs_reg_allocate.cpp
index b2bd514dc3be46291d96e35155b9d51b8f087a7d..6a594a4f520e7afe3ba1c031adb6cc9590c264e3 100644 (file)
@@ -396,7 +396,8 @@ void fs_visitor::calculate_payload_ranges(int payload_node_count,
 class fs_reg_alloc {
 public:
    fs_reg_alloc(fs_visitor *fs):
-      fs(fs), devinfo(fs->devinfo), compiler(fs->compiler), g(NULL)
+      fs(fs), devinfo(fs->devinfo), compiler(fs->compiler), g(NULL),
+      have_spill_costs(false)
    {
       mem_ctx = ralloc_context(NULL);
 
@@ -431,6 +432,7 @@ private:
    void setup_inst_interference(fs_inst *inst);
 
    void build_interference_graph(bool allow_spilling);
+   void discard_interference_graph();
 
    void set_spill_costs();
    int choose_spill_reg();
@@ -446,6 +448,7 @@ private:
    int rsi;
 
    ra_graph *g;
+   bool have_spill_costs;
 
    int payload_node_count;
    int *payload_last_use_ip;
@@ -795,9 +798,14 @@ fs_reg_alloc::build_interference_graph(bool allow_spilling)
     */
    foreach_block_and_inst(block, fs_inst, inst, fs->cfg)
       setup_inst_interference(inst);
+}
 
-   if (allow_spilling)
-      set_spill_costs();
+void
+fs_reg_alloc::discard_interference_graph()
+{
+   ralloc_free(g);
+   g = NULL;
+   have_spill_costs = false;
 }
 
 static void
@@ -914,6 +922,15 @@ fs_reg_alloc::set_spill_costs()
    }
 
    for (unsigned i = 0; i < fs->alloc.count; i++) {
+      /* Do the no_spill check first.  Registers that are used as spill
+       * temporaries may have been allocated after we calculated liveness so
+       * we shouldn't look their liveness up.  Fortunately, they're always
+       * used in SCRATCH_READ/WRITE instructions so they'll always be flagged
+       * no_spill.
+       */
+      if (no_spill[i])
+         continue;
+
       int live_length = fs->virtual_grf_end[i] - fs->virtual_grf_start[i];
       if (live_length <= 0)
          continue;
@@ -926,14 +943,18 @@ fs_reg_alloc::set_spill_costs()
        * to spill medium length registers with more uses.
        */
       float adjusted_cost = spill_costs[i] / logf(live_length);
-      if (!no_spill[i])
-        ra_set_node_spill_cost(g, first_vgrf_node + i, adjusted_cost);
+      ra_set_node_spill_cost(g, first_vgrf_node + i, adjusted_cost);
    }
+
+   have_spill_costs = true;
 }
 
 int
 fs_reg_alloc::choose_spill_reg()
 {
+   if (!have_spill_costs)
+      set_spill_costs();
+
    int node = ra_get_best_spill_node(g);
    if (node < 0)
       return -1;
@@ -1144,24 +1165,23 @@ fs_reg_alloc::assign_regs(bool allow_spilling, bool spill_all)
       if (!allow_spilling)
          return false;
 
+      /* Failed to allocate registers.  Spill a reg, and the caller will
+       * loop back into here to try again.
+       */
+      int reg = choose_spill_reg();
+      if (reg == -1)
+         return false;
+
       /* If we're going to spill but we've never spilled before, we need to
        * re-build the interference graph with MRFs enabled to allow spilling.
        */
       if (!fs->spilled_any_registers) {
-         ralloc_free(g);
-         g = NULL;
+         discard_interference_graph();
          build_interference_graph(true);
       }
 
       spilled = true;
 
-      /* Failed to allocate registers.  Spill a reg, and the caller will
-       * loop back into here to try again.
-       */
-      int reg = choose_spill_reg();
-      if (reg == -1)
-         return false;
-
       spill_reg(reg);
    }