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);
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();
int rsi;
ra_graph *g;
+ bool have_spill_costs;
int payload_node_count;
int *payload_last_use_ip;
*/
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
}
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;
* 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;
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);
}