{
/* live_in[s] = GEN[s] + (live_out[s] - KILL[s]) */
- pan_liveness_kill(live, bi_get_node(ins->dest[0]), max, bi_writemask(ins));
+ bi_foreach_dest(ins, d) {
+ pan_liveness_kill(live, bi_get_node(ins->dest[d]), max,
+ bi_writemask(ins, d));
+ }
bi_foreach_src(ins, src) {
unsigned count = bi_count_read_registers(ins, src);
uint16_t *live = mem_dup(block->base.live_out, temp_count * sizeof(uint16_t));
bi_foreach_instr_in_block_safe_rev(block, ins) {
- unsigned index = bi_get_node(ins->dest[0]);
+ bool all_null = true;
- if (index < temp_count && !(live[index] & bi_writemask(ins))) {
- if (soft || bi_side_effects(ins->op))
- ins->dest[0] = bi_null();
- else
- bi_remove_instruction(ins);
+ bi_foreach_dest(ins, d) {
+ unsigned index = bi_get_node(ins->dest[d]);
- progress |= true;
+ if (index < temp_count && !(live[index] & bi_writemask(ins, d))) {
+ ins->dest[d] = bi_null();
+ progress = true;
+ }
+
+ all_null &= bi_is_null(ins->dest[d]);
+ }
+
+ if (all_null && !soft && !bi_side_effects(ins->op)) {
+ bi_remove_instruction(ins);
+ progress = true;
}
bi_liveness_ins_update(live, ins, temp_count);
bi_foreach_instr_in_clause(block, clause, ins) {
if (!bi_opcode_props[ins->op].sr_write) continue;
- bi_foreach_dest(ins, d) {
- unsigned node = bi_get_node(ins->dest[d]);
- if (node < node_count)
- live[node] = bi_writemask(ins);
- }
+ /* Set liveness for dest 0 which is the staging register */
+ unsigned node = bi_get_node(ins->dest[0]);
+ if (node < node_count)
+ live[node] = bi_writemask(ins, 0);
break;
}
for (unsigned i = 0; i < node_count; ++i) {
if (live[i]) {
lcra_add_node_interference(l, bi_get_node(ins->dest[d]),
- bi_writemask(ins), i, live[i]);
+ bi_writemask(ins, d), i, live[i]);
}
}
}
}
}
-static void
-bi_rewrite_index_dst_single(bi_instr *ins, bi_index old, bi_index new)
-{
- bi_foreach_dest(ins, i) {
- if (bi_is_equiv(ins->dest[i], old)) {
- ins->dest[i].type = new.type;
- ins->dest[i].reg = new.reg;
- ins->dest[i].value = new.value;
- }
- }
-}
-
/* If register allocation fails, find the best spill node */
static signed
unsigned channels = 0;
bi_foreach_instr_in_clause(block, clause, ins) {
- if (!bi_is_equiv(ins->dest[0], index)) continue;
- if (bi_is_null(*temp)) *temp = bi_temp_reg(ctx);
- ins->no_spill = true;
- bi_rewrite_index_dst_single(ins, index, *temp);
- unsigned newc = util_last_bit(bi_writemask(ins)) >> 2;
- channels = MAX2(channels, newc);
+ bi_foreach_dest(ins, d) {
+ if (!bi_is_equiv(ins->dest[d], index)) continue;
+ if (bi_is_null(*temp)) *temp = bi_temp_reg(ctx);
+ ins->no_spill = true;
+
+ unsigned offset = ins->dest[d].offset;
+ ins->dest[d] = bi_replace_index(ins->dest[d], *temp);
+ ins->dest[d].offset = offset;
+
+ unsigned newc = util_last_bit(bi_writemask(ins, d)) >> 2;
+ channels = MAX2(channels, newc);
+ }
}
return channels;
}
unsigned
-bi_writemask(bi_instr *ins)
+bi_writemask(bi_instr *ins, unsigned d)
{
/* Assume we write a scalar */
unsigned mask = 0xF;
- if (bi_opcode_props[ins->op].sr_write) {
+ if (d == 0 && bi_opcode_props[ins->op].sr_write) {
unsigned count = bi_count_staging_registers(ins);
/* TODO: this special case is even more special, TEXC has a
mask = (1 << (count * 4)) - 1;
}
- unsigned shift = ins->dest[0].offset * 4; /* 32-bit words */
+ unsigned shift = ins->dest[d].offset * 4; /* 32-bit words */
return (mask << shift);
}