[Mesa-dev] [PATCH 23/30] i965/fs: Switch liveness analysis to IR analysis framework.
Francisco Jerez
currojerez at riseup.net
Mon Mar 14 03:47:27 UTC 2016
This involves wrapping fs_live_variables in a BRW_ANALYSIS object and
hooking it up to invalidate_analysis() so it's properly invalidated.
Seems like a lot of churn but it's fairly straightforward. The
fs_visitor invalidate_ and calculate_live_intervals() methods are no
longer necessary after this change.
---
src/mesa/drivers/dri/i965/brw_fs.cpp | 12 ++++----
src/mesa/drivers/dri/i965/brw_fs.h | 10 ++++---
src/mesa/drivers/dri/i965/brw_fs_cse.cpp | 10 +++----
.../dri/i965/brw_fs_dead_code_eliminate.cpp | 18 ++++++------
.../drivers/dri/i965/brw_fs_live_variables.cpp | 20 ++-----------
src/mesa/drivers/dri/i965/brw_fs_live_variables.h | 11 ++++++--
src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp | 10 +++----
.../drivers/dri/i965/brw_fs_register_coalesce.cpp | 33 +++++++++-------------
.../dri/i965/brw_fs_saturate_propagation.cpp | 13 +++++----
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 3 +-
.../drivers/dri/i965/brw_schedule_instructions.cpp | 19 ++++++-------
11 files changed, 72 insertions(+), 87 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index afa1db9..030e66f 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -2596,7 +2596,7 @@ fs_visitor::compute_to_mrf()
if (devinfo->gen >= 7)
return false;
- calculate_live_intervals();
+ const fs_live_variables &live = live_analysis.require();
foreach_block_and_inst_safe(block, fs_inst, inst, cfg) {
int ip = next_ip;
@@ -2627,7 +2627,7 @@ fs_visitor::compute_to_mrf()
/* Can't compute-to-MRF this GRF if someone else was going to
* read it later.
*/
- if (live_intervals->vgrf_end[inst->src[0].nr] > ip)
+ if (live.vgrf_end[inst->src[0].nr] > ip)
continue;
/* Found a move of a GRF to a MRF. Let's see if we can go
@@ -5064,9 +5064,7 @@ fs_visitor::setup_cs_payload()
void
fs_visitor::calculate_register_pressure()
{
- invalidate_live_intervals();
- calculate_live_intervals();
-
+ const fs_live_variables &live = live_analysis.require();
unsigned num_instructions = 0;
foreach_block(block, cfg)
num_instructions += block->instructions.length();
@@ -5074,8 +5072,7 @@ fs_visitor::calculate_register_pressure()
regs_live_at_ip = rzalloc_array(mem_ctx, int, num_instructions);
for (unsigned reg = 0; reg < alloc.count; reg++) {
- for (int ip = live_intervals->vgrf_start[reg];
- ip <= live_intervals->vgrf_end[reg]; ip++)
+ for (int ip = live.vgrf_start[reg]; ip <= live.vgrf_end[reg]; ip++)
regs_live_at_ip[ip] += alloc.sizes[reg];
}
}
@@ -5084,6 +5081,7 @@ void
fs_visitor::invalidate_analysis(brw::analysis_dependency_class c)
{
backend_shader::invalidate_analysis(c);
+ live_analysis.invalidate(c);
}
void
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 82d5d63..ac5e8cf 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -132,7 +132,9 @@ public:
void assign_regs_trivial();
void calculate_payload_ranges(int payload_node_count,
int *payload_last_use_ip);
- void setup_payload_interference(struct ra_graph *g, int payload_reg_count,
+ void setup_payload_interference(struct ra_graph *g,
+ const brw::fs_live_variables &live,
+ int payload_reg_count,
int first_payload_node);
int choose_spill_reg(struct ra_graph *g);
void spill_reg(int spill_reg);
@@ -142,13 +144,12 @@ public:
void demote_pull_constants();
void invalidate_live_intervals();
virtual void invalidate_analysis(brw::analysis_dependency_class c);
- void calculate_live_intervals();
void calculate_register_pressure();
void validate();
bool opt_algebraic();
bool opt_redundant_discard_jumps();
bool opt_cse();
- bool opt_cse_local(bblock_t *block);
+ bool opt_cse_local(const brw::fs_live_variables &live, bblock_t *block);
bool opt_copy_propagate();
bool try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry);
bool try_constant_propagate(fs_inst *inst, acp_entry *entry);
@@ -328,7 +329,8 @@ public:
int *param_size;
- brw::fs_live_variables *live_intervals;
+ BRW_ANALYSIS(live_analysis, brw::fs_live_variables,
+ backend_shader *) live_analysis;
int *regs_live_at_ip;
diff --git a/src/mesa/drivers/dri/i965/brw_fs_cse.cpp b/src/mesa/drivers/dri/i965/brw_fs_cse.cpp
index d112378..f2c257e 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_cse.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_cse.cpp
@@ -222,7 +222,7 @@ create_copy_instr(const fs_builder &bld, fs_inst *inst, fs_reg src, bool negate)
}
bool
-fs_visitor::opt_cse_local(bblock_t *block)
+fs_visitor::opt_cse_local(const fs_live_variables &live, bblock_t *block)
{
bool progress = false;
exec_list aeb;
@@ -328,8 +328,7 @@ fs_visitor::opt_cse_local(bblock_t *block)
/* Kill any AEB entries using registers that don't get reused any
* more -- a sure sign they'll fail operands_match().
*/
- if (src_reg->file == VGRF &&
- live_intervals->vgrf_end[src_reg->nr] < ip) {
+ if (src_reg->file == VGRF && live.vgrf_end[src_reg->nr] < ip) {
entry->remove();
ralloc_free(entry);
break;
@@ -348,12 +347,11 @@ fs_visitor::opt_cse_local(bblock_t *block)
bool
fs_visitor::opt_cse()
{
+ const fs_live_variables &live = live_analysis.require();
bool progress = false;
- calculate_live_intervals();
-
foreach_block (block, cfg) {
- progress = opt_cse_local(block) || progress;
+ progress = opt_cse_local(live, block) || progress;
}
if (progress)
diff --git a/src/mesa/drivers/dri/i965/brw_fs_dead_code_eliminate.cpp b/src/mesa/drivers/dri/i965/brw_fs_dead_code_eliminate.cpp
index 540230c..2a4c67a 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_dead_code_eliminate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_dead_code_eliminate.cpp
@@ -40,17 +40,15 @@ bool
fs_visitor::dead_code_eliminate()
{
bool progress = false;
-
- calculate_live_intervals();
-
- int num_vars = live_intervals->num_vars;
+ const fs_live_variables &live_vars = live_analysis.require();
+ int num_vars = live_vars.num_vars;
BITSET_WORD *live = ralloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars));
BITSET_WORD *flag_live = ralloc_array(NULL, BITSET_WORD, 1);
foreach_block_reverse_safe(block, cfg) {
- memcpy(live, live_intervals->block_data[block->num].liveout,
+ memcpy(live, live_vars.block_data[block->num].liveout,
sizeof(BITSET_WORD) * BITSET_WORDS(num_vars));
- memcpy(flag_live, live_intervals->block_data[block->num].flag_liveout,
+ memcpy(flag_live, live_vars.block_data[block->num].flag_liveout,
sizeof(BITSET_WORD));
foreach_inst_in_block_reverse_safe(fs_inst, inst, block) {
@@ -58,10 +56,10 @@ fs_visitor::dead_code_eliminate()
bool result_live = false;
if (inst->regs_written == 1) {
- int var = live_intervals->var_from_reg(inst->dst);
+ int var = live_vars.var_from_reg(inst->dst);
result_live = BITSET_TEST(live, var);
} else {
- int var = live_intervals->var_from_reg(inst->dst);
+ int var = live_vars.var_from_reg(inst->dst);
for (int i = 0; i < inst->regs_written; i++) {
result_live = result_live || BITSET_TEST(live, var + i);
}
@@ -97,7 +95,7 @@ fs_visitor::dead_code_eliminate()
if (inst->dst.file == VGRF) {
if (!inst->is_partial_write()) {
- int var = live_intervals->var_from_reg(inst->dst);
+ int var = live_vars.var_from_reg(inst->dst);
for (int i = 0; i < inst->regs_written; i++) {
BITSET_CLEAR(live, var + i);
}
@@ -115,7 +113,7 @@ fs_visitor::dead_code_eliminate()
for (int i = 0; i < inst->sources; i++) {
if (inst->src[i].file == VGRF) {
- int var = live_intervals->var_from_reg(inst->src[i]);
+ int var = live_vars.var_from_reg(inst->src[i]);
for (int j = 0; j < inst->regs_read(i); j++) {
BITSET_SET(live, var + j);
diff --git a/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp b/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
index 215349a..0d5bef2 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
@@ -348,23 +348,9 @@ fs_live_variables::validate(const backend_shader *s) const
void
fs_visitor::invalidate_live_intervals()
{
- ralloc_free(live_intervals);
- live_intervals = NULL;
-}
-
-/**
- * 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()
-{
- if (this->live_intervals)
- return;
-
- this->live_intervals = new(mem_ctx) fs_live_variables(this);
+ /* XXX -- Leave this around for the moment to keep the fs_vistor object
+ * concrete.
+ */
}
bool
diff --git a/src/mesa/drivers/dri/i965/brw_fs_live_variables.h b/src/mesa/drivers/dri/i965/brw_fs_live_variables.h
index c2a3c63..fa462fc 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_live_variables.h
+++ b/src/mesa/drivers/dri/i965/brw_fs_live_variables.h
@@ -28,6 +28,7 @@
#ifndef BRW_FS_LIVE_VARIABLES_H
#define BRW_FS_LIVE_VARIABLES_H
+#include "brw_ir_analysis.h"
#include "brw_ir_fs.h"
#include "util/bitset.h"
@@ -64,14 +65,20 @@ public:
BITSET_WORD flag_liveout[1];
};
- DECLARE_RALLOC_CXX_OPERATORS(fs_live_variables)
-
fs_live_variables(const backend_shader *s);
~fs_live_variables();
bool
validate(const backend_shader *s) const;
+ analysis_dependency_class
+ dependency_class() const
+ {
+ return (DEPENDENCY_INSTRUCTION_IDENTITY |
+ DEPENDENCY_INSTRUCTION_DATA_FLOW |
+ DEPENDENCY_VARIABLES);
+ }
+
bool vars_interfere(int a, int b) const;
bool vgrfs_interfere(int a, int b) const;
int var_from_reg(const fs_reg ®) const
diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
index efb5d6f..f770239 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp
@@ -427,6 +427,7 @@ void fs_visitor::calculate_payload_ranges(int payload_node_count,
*/
void
fs_visitor::setup_payload_interference(struct ra_graph *g,
+ const fs_live_variables &live,
int payload_node_count,
int first_payload_node)
{
@@ -446,7 +447,7 @@ fs_visitor::setup_payload_interference(struct ra_graph *g,
* in order to not have to worry about the uniform issue described in
* calculate_live_intervals().
*/
- if (live_intervals->vgrf_start[j] <= payload_last_use_ip[i]) {
+ if (live.vgrf_start[j] <= payload_last_use_ip[i]) {
ra_add_node_interference(g, first_payload_node + i, j);
}
}
@@ -544,6 +545,7 @@ setup_mrf_hack_interference(fs_visitor *v, struct ra_graph *g,
bool
fs_visitor::assign_regs(bool allow_spilling)
{
+ const fs_live_variables &live = live_analysis.require();
/* Most of this allocation was written for a reg_width of 1
* (dispatch_width == 8). In extending to SIMD16, the code was
* left in place and it was converted to have the hardware
@@ -554,8 +556,6 @@ fs_visitor::assign_regs(bool allow_spilling)
unsigned hw_reg_mapping[this->alloc.count];
int payload_node_count = ALIGN(this->first_non_payload_grf, reg_width);
int rsi = reg_width - 1; /* Which compiler->fs_reg_sets[] to use */
- calculate_live_intervals();
-
int node_count = this->alloc.count;
int first_payload_node = node_count;
node_count += payload_node_count;
@@ -591,7 +591,7 @@ fs_visitor::assign_regs(bool allow_spilling)
ra_set_node_class(g, i, c);
for (unsigned j = 0; j < i; j++) {
- if (live_intervals->vgrfs_interfere(i, j)) {
+ if (live.vgrfs_interfere(i, j)) {
ra_add_node_interference(g, i, j);
}
}
@@ -610,7 +610,7 @@ fs_visitor::assign_regs(bool allow_spilling)
}
}
- setup_payload_interference(g, payload_node_count, first_payload_node);
+ setup_payload_interference(g, live, payload_node_count, first_payload_node);
if (devinfo->gen >= 7) {
int first_used_mrf = BRW_MAX_MRF(devinfo->gen);
setup_mrf_hack_interference(this, g, first_mrf_hack_node,
diff --git a/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp b/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
index 4a9a502..3f13aed 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
@@ -95,17 +95,17 @@ is_coalesce_candidate(const fs_visitor *v, const fs_inst *inst)
}
static bool
-can_coalesce_vars(brw::fs_live_variables *live_intervals,
+can_coalesce_vars(const fs_live_variables &live,
const cfg_t *cfg, const fs_inst *inst,
int dst_var, int src_var)
{
- if (!live_intervals->vars_interfere(src_var, dst_var))
+ if (!live.vars_interfere(src_var, dst_var))
return true;
- int dst_start = live_intervals->start[dst_var];
- int dst_end = live_intervals->end[dst_var];
- int src_start = live_intervals->start[src_var];
- int src_end = live_intervals->end[src_var];
+ int dst_start = live.start[dst_var];
+ int dst_end = live.end[dst_var];
+ int src_start = live.start[src_var];
+ int src_end = live.end[src_var];
/* Variables interfere and one line range isn't a subset of the other. */
if ((dst_end > src_end && src_start < dst_start) ||
@@ -151,9 +151,7 @@ bool
fs_visitor::register_coalesce()
{
bool progress = false;
-
- calculate_live_intervals();
-
+ fs_live_variables &live = live_analysis.require();
int src_size = 0;
int channels_remaining = 0;
int src_reg = -1, dst_reg = -1;
@@ -224,11 +222,10 @@ fs_visitor::register_coalesce()
break;
}
- dst_var[i] = live_intervals->var_from_vgrf[dst_reg] + dst_reg_offset[i];
- src_var[i] = live_intervals->var_from_vgrf[src_reg] + i;
+ dst_var[i] = live.var_from_vgrf[dst_reg] + dst_reg_offset[i];
+ src_var[i] = live.var_from_vgrf[src_reg] + i;
- if (!can_coalesce_vars(live_intervals, cfg, inst,
- dst_var[i], src_var[i])) {
+ if (!can_coalesce_vars(live, cfg, inst, dst_var[i], src_var[i])) {
can_coalesce = false;
src_reg = -1;
break;
@@ -270,12 +267,10 @@ fs_visitor::register_coalesce()
}
for (int i = 0; i < src_size; i++) {
- live_intervals->start[dst_var[i]] =
- MIN2(live_intervals->start[dst_var[i]],
- live_intervals->start[src_var[i]]);
- live_intervals->end[dst_var[i]] =
- MAX2(live_intervals->end[dst_var[i]],
- live_intervals->end[src_var[i]]);
+ live.start[dst_var[i]] = MIN2(live.start[dst_var[i]],
+ live.start[src_var[i]]);
+ live.end[dst_var[i]] = MAX2(live.end[dst_var[i]],
+ live.end[src_var[i]]);
}
src_reg = -1;
}
diff --git a/src/mesa/drivers/dri/i965/brw_fs_saturate_propagation.cpp b/src/mesa/drivers/dri/i965/brw_fs_saturate_propagation.cpp
index f59fdbd..eb69070 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_saturate_propagation.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_saturate_propagation.cpp
@@ -25,6 +25,8 @@
#include "brw_fs_live_variables.h"
#include "brw_cfg.h"
+using namespace brw;
+
/** @file brw_fs_saturate_propagation.cpp
*
* Implements a pass that propagates the SAT modifier from a MOV.SAT into the
@@ -43,7 +45,7 @@
*/
static bool
-opt_saturate_propagation_local(fs_visitor *v, bblock_t *block)
+opt_saturate_propagation_local(const fs_live_variables &live, bblock_t *block)
{
bool progress = false;
int ip = block->end_ip + 1;
@@ -59,8 +61,8 @@ opt_saturate_propagation_local(fs_visitor *v, bblock_t *block)
inst->src[0].abs)
continue;
- int src_var = v->live_intervals->var_from_reg(inst->src[0]);
- int src_end_ip = v->live_intervals->end[src_var];
+ int src_var = live.var_from_reg(inst->src[0]);
+ int src_end_ip = live.end[src_var];
bool interfered = false;
foreach_inst_in_block_reverse_starting_from(fs_inst, scan_inst, inst) {
@@ -140,12 +142,11 @@ opt_saturate_propagation_local(fs_visitor *v, bblock_t *block)
bool
fs_visitor::opt_saturate_propagation()
{
+ const fs_live_variables &live = live_analysis.require();
bool progress = false;
- calculate_live_intervals();
-
foreach_block (block, cfg) {
- progress = opt_saturate_propagation_local(this, block) || progress;
+ progress = opt_saturate_propagation_local(live, block) || progress;
}
/* Live intervals are still valid. */
diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index b9fde5d..ede39df 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -973,6 +973,7 @@ fs_visitor::fs_visitor(const struct brw_compiler *compiler, void *log_data,
: backend_shader(compiler, log_data, mem_ctx, shader, prog_data),
key(key), gs_compile(NULL), prog_data(prog_data), prog(prog),
input_vue_map(input_vue_map),
+ live_analysis(this),
dispatch_width(dispatch_width),
shader_time_index(shader_time_index),
bld(fs_builder(this, dispatch_width).at_end())
@@ -990,6 +991,7 @@ fs_visitor::fs_visitor(const struct brw_compiler *compiler, void *log_data,
&prog_data->base.base),
key(&c->key), gs_compile(c),
prog_data(&prog_data->base.base), prog(NULL),
+ live_analysis(this),
dispatch_width(8),
shader_time_index(shader_time_index),
bld(fs_builder(this, dispatch_width).at_end())
@@ -1049,7 +1051,6 @@ fs_visitor::init()
this->first_non_payload_grf = 0;
this->max_grf = devinfo->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF;
- this->live_intervals = NULL;
this->regs_live_at_ip = NULL;
this->uniforms = 0;
diff --git a/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp b/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp
index 4bcefe5..756cda5 100644
--- a/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp
+++ b/src/mesa/drivers/dri/i965/brw_schedule_instructions.cpp
@@ -596,21 +596,23 @@ fs_instruction_scheduler::count_reads_remaining(backend_instruction *be)
void
fs_instruction_scheduler::setup_liveness(cfg_t *cfg)
{
+ const fs_live_variables &live = v->live_analysis.require();
+
/* First, compute liveness on a per-GRF level using the in/out sets from
* liveness calculation.
*/
for (int block = 0; block < cfg->num_blocks; block++) {
- for (int i = 0; i < v->live_intervals->num_vars; i++) {
- if (BITSET_TEST(v->live_intervals->block_data[block].livein, i)) {
- int vgrf = v->live_intervals->vgrf_from_var[i];
+ for (int i = 0; i < live.num_vars; i++) {
+ if (BITSET_TEST(live.block_data[block].livein, i)) {
+ int vgrf = live.vgrf_from_var[i];
if (!BITSET_TEST(livein[block], vgrf)) {
reg_pressure_in[block] += v->alloc.sizes[vgrf];
BITSET_SET(livein[block], vgrf);
}
}
- if (BITSET_TEST(v->live_intervals->block_data[block].liveout, i))
- BITSET_SET(liveout[block], v->live_intervals->vgrf_from_var[i]);
+ if (BITSET_TEST(live.block_data[block].liveout, i))
+ BITSET_SET(liveout[block], live.vgrf_from_var[i]);
}
}
@@ -620,8 +622,8 @@ fs_instruction_scheduler::setup_liveness(cfg_t *cfg)
*/
for (int block = 0; block < cfg->num_blocks - 1; block++) {
for (int i = 0; i < grf_count; i++) {
- if (v->live_intervals->vgrf_start[i] <= cfg->blocks[block]->end_ip &&
- v->live_intervals->vgrf_end[i] >= cfg->blocks[block + 1]->start_ip) {
+ if (live.vgrf_start[i] <= cfg->blocks[block]->end_ip &&
+ live.vgrf_end[i] >= cfg->blocks[block + 1]->start_ip) {
if (!BITSET_TEST(livein[block + 1], i)) {
reg_pressure_in[block + 1] += v->alloc.sizes[i];
BITSET_SET(livein[block + 1], i);
@@ -1661,9 +1663,6 @@ instruction_scheduler::run(cfg_t *cfg)
void
fs_visitor::schedule_instructions(instruction_scheduler_mode mode)
{
- if (mode != SCHEDULE_POST)
- calculate_live_intervals();
-
int grf_count;
if (mode == SCHEDULE_POST)
grf_count = grf_used;
--
2.7.0
More information about the mesa-dev
mailing list