From acf24df2017598eb23c57599e39738e0ec059438 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Sun, 13 Mar 2016 16:33:39 -0700 Subject: [PATCH] intel/compiler/vec4: Switch liveness analysis to IR analysis framework This involves wrapping vec4_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 vec4_visitor invalidate_ and calculate_live_intervals() methods are no longer necessary after this change. Reviewed-by: Matt Turner Part-of: --- src/intel/compiler/brw_vec4.cpp | 7 ++-- src/intel/compiler/brw_vec4.h | 6 ++-- src/intel/compiler/brw_vec4_cse.cpp | 10 +++--- .../compiler/brw_vec4_dead_code_eliminate.cpp | 9 +++-- .../compiler/brw_vec4_live_variables.cpp | 35 ++----------------- src/intel/compiler/brw_vec4_live_variables.h | 11 ++++-- src/intel/compiler/brw_vec4_reg_allocate.cpp | 5 ++- src/intel/compiler/brw_vec4_visitor.cpp | 3 +- 8 files changed, 29 insertions(+), 57 deletions(-) diff --git a/src/intel/compiler/brw_vec4.cpp b/src/intel/compiler/brw_vec4.cpp index 514fab10820..dad53edc56c 100644 --- a/src/intel/compiler/brw_vec4.cpp +++ b/src/intel/compiler/brw_vec4.cpp @@ -1253,8 +1253,7 @@ vec4_visitor::opt_register_coalesce() { bool progress = false; int next_ip = 0; - - calculate_live_intervals(); + const vec4_live_variables &live = live_analysis.require(); foreach_block_and_inst_safe (block, vec4_instruction, inst, cfg) { int ip = next_ip; @@ -1296,8 +1295,7 @@ vec4_visitor::opt_register_coalesce() /* Can't coalesce this GRF if someone else was going to * read it later. */ - if (live_intervals->var_range_end( - var_from_reg(alloc, dst_reg(inst->src[0])), 8) > ip) + if (live.var_range_end(var_from_reg(alloc, dst_reg(inst->src[0])), 8) > ip) continue; /* We need to check interference with the final destination between this @@ -2672,6 +2670,7 @@ void vec4_visitor::invalidate_analysis(brw::analysis_dependency_class c) { backend_shader::invalidate_analysis(c); + live_analysis.invalidate(c); } bool diff --git a/src/intel/compiler/brw_vec4.h b/src/intel/compiler/brw_vec4.h index b5d3fb1b0cd..c0ea912a634 100644 --- a/src/intel/compiler/brw_vec4.h +++ b/src/intel/compiler/brw_vec4.h @@ -105,7 +105,8 @@ public: int first_non_payload_grf; unsigned int max_grf; - brw::vec4_live_variables *live_intervals; + BRW_ANALYSIS(live_analysis, brw::vec4_live_variables, + backend_shader *) live_analysis; bool need_all_constants_in_pull_buffer; @@ -134,7 +135,6 @@ public: void move_push_constants_to_pull_constants(); void split_uniform_registers(); void pack_uniform_registers(); - void calculate_live_intervals(); void invalidate_live_intervals(); virtual void invalidate_analysis(brw::analysis_dependency_class c); void split_virtual_grfs(); @@ -143,7 +143,7 @@ public: bool dead_code_eliminate(); bool opt_cmod_propagation(); bool opt_copy_propagation(bool do_constant_prop = true); - bool opt_cse_local(bblock_t *block); + bool opt_cse_local(bblock_t *block, const vec4_live_variables &live); bool opt_cse(); bool opt_algebraic(); bool opt_register_coalesce(); diff --git a/src/intel/compiler/brw_vec4_cse.cpp b/src/intel/compiler/brw_vec4_cse.cpp index c7d55788f00..585676a9042 100644 --- a/src/intel/compiler/brw_vec4_cse.cpp +++ b/src/intel/compiler/brw_vec4_cse.cpp @@ -163,7 +163,7 @@ instructions_match(vec4_instruction *a, vec4_instruction *b) } bool -vec4_visitor::opt_cse_local(bblock_t *block) +vec4_visitor::opt_cse_local(bblock_t *block, const vec4_live_variables &live) { bool progress = false; exec_list aeb; @@ -288,8 +288,7 @@ vec4_visitor::opt_cse_local(bblock_t *block) * more -- a sure sign they'll fail operands_match(). */ if (src->file == VGRF) { - if (live_intervals->var_range_end( - var_from_reg(alloc, *src), 8) < ip) { + if (live.var_range_end(var_from_reg(alloc, *src), 8) < ip) { entry->remove(); ralloc_free(entry); break; @@ -310,11 +309,10 @@ bool vec4_visitor::opt_cse() { bool progress = false; - - calculate_live_intervals(); + const vec4_live_variables &live = live_analysis.require(); foreach_block (block, cfg) { - progress = opt_cse_local(block) || progress; + progress = opt_cse_local(block, live) || progress; } if (progress) diff --git a/src/intel/compiler/brw_vec4_dead_code_eliminate.cpp b/src/intel/compiler/brw_vec4_dead_code_eliminate.cpp index 5975f1f6437..39fd3f513ff 100644 --- a/src/intel/compiler/brw_vec4_dead_code_eliminate.cpp +++ b/src/intel/compiler/brw_vec4_dead_code_eliminate.cpp @@ -41,16 +41,15 @@ vec4_visitor::dead_code_eliminate() { bool progress = false; - calculate_live_intervals(); - - int num_vars = live_intervals->num_vars; + const vec4_live_variables &live_vars = live_analysis.require(); + int num_vars = live_vars.num_vars; BITSET_WORD *live = rzalloc_array(NULL, BITSET_WORD, BITSET_WORDS(num_vars)); BITSET_WORD *flag_live = rzalloc_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(vec4_instruction, inst, block) { diff --git a/src/intel/compiler/brw_vec4_live_variables.cpp b/src/intel/compiler/brw_vec4_live_variables.cpp index 107f4d5ae5c..8457706024f 100644 --- a/src/intel/compiler/brw_vec4_live_variables.cpp +++ b/src/intel/compiler/brw_vec4_live_variables.cpp @@ -254,41 +254,12 @@ vec4_live_variables::~vec4_live_variables() ralloc_free(mem_ctx); } -/** - * Computes a conservative start/end of the live intervals for each virtual GRF. - * - * We could expose per-channel live intervals to the consumer based on the - * information we computed in vec4_live_variables, except that our only - * current user is virtual_grf_interferes(). So we instead union the - * per-channel ranges into a per-vgrf range for vgrf_start[] and vgrf_end[]. - * - * We could potentially have virtual_grf_interferes() do the test per-channel, - * which would let some interesting register allocation occur (particularly on - * code-generated GLSL sequences from the Cg compiler which does register - * allocation at the GLSL level and thus reuses components of the variable - * with distinct lifetimes). But right now the complexity of doing so doesn't - * seem worth it, since having virtual_grf_interferes() be cheap is important - * for register allocation performance. - */ -void -vec4_visitor::calculate_live_intervals() -{ - if (this->live_intervals) - return; - - /* Now, extend those intervals using our analysis of control flow. - * - * The control flow-aware analysis was done at a channel level, while at - * this point we're distilling it down to vgrfs. - */ - this->live_intervals = new(mem_ctx) vec4_live_variables(this); -} - void vec4_visitor::invalidate_live_intervals() { - ralloc_free(live_intervals); - live_intervals = NULL; + /* XXX -- Leave this around for the moment to keep the vec4_vistor object + * concrete. + */ } static bool diff --git a/src/intel/compiler/brw_vec4_live_variables.h b/src/intel/compiler/brw_vec4_live_variables.h index b5023fa0dc7..06281432955 100644 --- a/src/intel/compiler/brw_vec4_live_variables.h +++ b/src/intel/compiler/brw_vec4_live_variables.h @@ -29,6 +29,7 @@ #define BRW_VEC4_LIVE_VARIABLES_H #include "brw_ir_vec4.h" +#include "brw_ir_analysis.h" #include "util/bitset.h" struct backend_shader; @@ -63,14 +64,20 @@ public: BITSET_WORD flag_liveout[1]; }; - DECLARE_RALLOC_CXX_OPERATORS(vec4_live_variables) - vec4_live_variables(const backend_shader *s); ~vec4_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); + } + int num_vars; int bitset_words; diff --git a/src/intel/compiler/brw_vec4_reg_allocate.cpp b/src/intel/compiler/brw_vec4_reg_allocate.cpp index bb1cf371329..a7bbd478825 100644 --- a/src/intel/compiler/brw_vec4_reg_allocate.cpp +++ b/src/intel/compiler/brw_vec4_reg_allocate.cpp @@ -201,8 +201,7 @@ vec4_visitor::reg_allocate() if (0) return reg_allocate_trivial(); - calculate_live_intervals(); - + const vec4_live_variables &live = live_analysis.require(); int node_count = alloc.count; int first_payload_node = node_count; node_count += payload_reg_count; @@ -215,7 +214,7 @@ vec4_visitor::reg_allocate() ra_set_node_class(g, i, compiler->vec4_reg_set.classes[size - 1]); 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); } } diff --git a/src/intel/compiler/brw_vec4_visitor.cpp b/src/intel/compiler/brw_vec4_visitor.cpp index 29a558d07d9..da8af709600 100644 --- a/src/intel/compiler/brw_vec4_visitor.cpp +++ b/src/intel/compiler/brw_vec4_visitor.cpp @@ -1841,6 +1841,7 @@ vec4_visitor::vec4_visitor(const struct brw_compiler *compiler, prog_data(prog_data), fail_msg(NULL), first_non_payload_grf(0), + live_analysis(this), need_all_constants_in_pull_buffer(false), no_spills(no_spills), shader_time_index(shader_time_index), @@ -1854,8 +1855,6 @@ vec4_visitor::vec4_visitor(const struct brw_compiler *compiler, memset(this->output_num_components, 0, sizeof(this->output_num_components)); - this->live_intervals = NULL; - this->max_grf = devinfo->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF; this->uniforms = 0; -- 2.30.2