*
*/
-#include "brw_cfg.h"
+#include "brw_fs.h"
#include "brw_fs_live_variables.h"
using namespace brw;
*/
void
-fs_live_variables::setup_one_read(struct block_data *bd, fs_inst *inst,
+fs_live_variables::setup_one_read(struct block_data *bd,
int ip, const fs_reg ®)
{
int var = var_from_reg(reg);
continue;
for (unsigned j = 0; j < regs_read(inst, i); j++) {
- setup_one_read(bd, inst, ip, reg);
+ setup_one_read(bd, ip, reg);
reg.offset += REG_SIZE;
}
}
- bd->flag_use[0] |= inst->flags_read(v->devinfo) & ~bd->flag_def[0];
+ bd->flag_use[0] |= inst->flags_read(devinfo) & ~bd->flag_def[0];
/* Set def[] for this instruction */
if (inst->dst.file == VGRF) {
/* Update liveout */
foreach_list_typed(bblock_link, child_link, link, &block->children) {
- struct block_data *child_bd = &block_data[child_link->block->num];
+ struct block_data *child_bd = &block_data[child_link->block->num];
for (int i = 0; i < bitset_words; i++) {
BITSET_WORD new_liveout = (child_bd->livein[i] &
const struct block_data *bd = &block_data[block->num];
foreach_list_typed(bblock_link, child_link, link, &block->children) {
- struct block_data *child_bd = &block_data[child_link->block->num];
+ struct block_data *child_bd = &block_data[child_link->block->num];
for (int i = 0; i < bitset_words; i++) {
const BITSET_WORD new_def = bd->defout[i] & ~child_bd->defin[i];
foreach_block (block, cfg) {
struct block_data *bd = &block_data[block->num];
- for (int i = 0; i < num_vars; i++) {
- if (BITSET_TEST(bd->livein, i) && BITSET_TEST(bd->defin, i)) {
- start[i] = MIN2(start[i], block->start_ip);
- end[i] = MAX2(end[i], block->start_ip);
- }
-
- if (BITSET_TEST(bd->liveout, i) && BITSET_TEST(bd->defout, i)) {
- start[i] = MIN2(start[i], block->end_ip);
- end[i] = MAX2(end[i], block->end_ip);
+ for (int w = 0; w < bitset_words; w++) {
+ BITSET_WORD livedefin = bd->livein[w] & bd->defin[w];
+ BITSET_WORD livedefout = bd->liveout[w] & bd->defout[w];
+ BITSET_WORD livedefinout = livedefin | livedefout;
+ while (livedefinout) {
+ unsigned b = u_bit_scan(&livedefinout);
+ unsigned i = w * BITSET_WORDBITS + b;
+ if (livedefin & (1u << b)) {
+ start[i] = MIN2(start[i], block->start_ip);
+ end[i] = MAX2(end[i], block->start_ip);
+ }
+ if (livedefout & (1u << b)) {
+ start[i] = MIN2(start[i], block->end_ip);
+ end[i] = MAX2(end[i], block->end_ip);
+ }
}
}
}
}
-fs_live_variables::fs_live_variables(fs_visitor *v, const cfg_t *cfg)
- : v(v), cfg(cfg)
+fs_live_variables::fs_live_variables(const backend_shader *s)
+ : devinfo(s->devinfo), cfg(s->cfg)
{
mem_ctx = ralloc_context(NULL);
- num_vgrfs = v->alloc.count;
+ num_vgrfs = s->alloc.count;
num_vars = 0;
var_from_vgrf = rzalloc_array(mem_ctx, int, num_vgrfs);
for (int i = 0; i < num_vgrfs; i++) {
var_from_vgrf[i] = num_vars;
- num_vars += v->alloc.sizes[i];
+ num_vars += s->alloc.sizes[i];
}
vgrf_from_var = rzalloc_array(mem_ctx, int, num_vars);
for (int i = 0; i < num_vgrfs; i++) {
- for (unsigned j = 0; j < v->alloc.sizes[i]; j++) {
+ for (unsigned j = 0; j < s->alloc.sizes[i]; j++) {
vgrf_from_var[var_from_vgrf[i] + j] = i;
}
}
end[i] = -1;
}
- block_data= rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks);
+ vgrf_start = ralloc_array(mem_ctx, int, num_vgrfs);
+ vgrf_end = ralloc_array(mem_ctx, int, num_vgrfs);
+ for (int i = 0; i < num_vgrfs; i++) {
+ vgrf_start[i] = MAX_INSTRUCTION;
+ vgrf_end[i] = -1;
+ }
+
+ block_data = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks);
bitset_words = BITSET_WORDS(num_vars);
for (int i = 0; i < cfg->num_blocks; i++) {
setup_def_use();
compute_live_variables();
compute_start_end();
+
+ /* Merge the per-component live ranges to whole VGRF live ranges. */
+ for (int i = 0; i < num_vars; i++) {
+ const unsigned vgrf = vgrf_from_var[i];
+ vgrf_start[vgrf] = MIN2(vgrf_start[vgrf], start[i]);
+ vgrf_end[vgrf] = MAX2(vgrf_end[vgrf], end[i]);
+ }
}
fs_live_variables::~fs_live_variables()
ralloc_free(mem_ctx);
}
-void
-fs_visitor::invalidate_live_intervals()
+static bool
+check_register_live_range(const fs_live_variables *live, int ip,
+ const fs_reg ®, unsigned n)
{
- ralloc_free(live_intervals);
- live_intervals = NULL;
+ const unsigned var = live->var_from_reg(reg);
+
+ if (var + n > unsigned(live->num_vars) ||
+ live->vgrf_start[reg.nr] > ip || live->vgrf_end[reg.nr] < ip)
+ return false;
+
+ for (unsigned j = 0; j < n; j++) {
+ if (live->start[var + j] > ip || live->end[var + j] < ip)
+ return false;
+ }
+
+ return true;
}
-/**
- * Compute the live intervals for each virtual GRF.
- *
- * This uses the per-component use/def data, but combines it to produce
- * information about whole VGRFs.
- */
-void
-fs_visitor::calculate_live_intervals()
+bool
+fs_live_variables::validate(const backend_shader *s) const
{
- if (this->live_intervals)
- return;
-
- int num_vgrfs = this->alloc.count;
- ralloc_free(this->virtual_grf_start);
- ralloc_free(this->virtual_grf_end);
- virtual_grf_start = ralloc_array(mem_ctx, int, num_vgrfs);
- virtual_grf_end = ralloc_array(mem_ctx, int, num_vgrfs);
+ int ip = 0;
- for (int i = 0; i < num_vgrfs; i++) {
- virtual_grf_start[i] = MAX_INSTRUCTION;
- virtual_grf_end[i] = -1;
- }
+ foreach_block_and_inst(block, fs_inst, inst, s->cfg) {
+ for (unsigned i = 0; i < inst->sources; i++) {
+ if (inst->src[i].file == VGRF &&
+ !check_register_live_range(this, ip,
+ inst->src[i], regs_read(inst, i)))
+ return false;
+ }
- this->live_intervals = new(mem_ctx) fs_live_variables(this, cfg);
+ if (inst->dst.file == VGRF &&
+ !check_register_live_range(this, ip, inst->dst, regs_written(inst)))
+ return false;
- /* Merge the per-component live ranges to whole VGRF live ranges. */
- for (int i = 0; i < live_intervals->num_vars; i++) {
- int vgrf = live_intervals->vgrf_from_var[i];
- virtual_grf_start[vgrf] = MIN2(virtual_grf_start[vgrf],
- live_intervals->start[i]);
- virtual_grf_end[vgrf] = MAX2(virtual_grf_end[vgrf],
- live_intervals->end[i]);
+ ip++;
}
+
+ return true;
}
bool
-fs_live_variables::vars_interfere(int a, int b)
+fs_live_variables::vars_interfere(int a, int b) const
{
return !(end[b] <= start[a] ||
end[a] <= start[b]);
}
bool
-fs_visitor::virtual_grf_interferes(int a, int b)
+fs_live_variables::vgrfs_interfere(int a, int b) const
{
- return !(virtual_grf_end[a] <= virtual_grf_start[b] ||
- virtual_grf_end[b] <= virtual_grf_start[a]);
+ return !(vgrf_end[a] <= vgrf_start[b] ||
+ vgrf_end[b] <= vgrf_start[a]);
}