intel/compiler/vec4: Switch liveness analysis to IR analysis framework
authorFrancisco Jerez <currojerez@riseup.net>
Sun, 13 Mar 2016 23:33:39 +0000 (16:33 -0700)
committerMatt Turner <mattst88@gmail.com>
Fri, 6 Mar 2020 18:20:59 +0000 (10:20 -0800)
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 <mattst88@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4012>

src/intel/compiler/brw_vec4.cpp
src/intel/compiler/brw_vec4.h
src/intel/compiler/brw_vec4_cse.cpp
src/intel/compiler/brw_vec4_dead_code_eliminate.cpp
src/intel/compiler/brw_vec4_live_variables.cpp
src/intel/compiler/brw_vec4_live_variables.h
src/intel/compiler/brw_vec4_reg_allocate.cpp
src/intel/compiler/brw_vec4_visitor.cpp

index 514fab10820af7bff86c00aaf43aab4d6e81d3f3..dad53edc56c1145aa762bc20052170dc25226548 100644 (file)
@@ -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
index b5d3fb1b0cdd226cafb50d2dfd483bf71758ff01..c0ea912a634d9e05ce9f5831638ed1a5fe9e0bf1 100644 (file)
@@ -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();
index c7d55788f00eb7f0ebff0c4be379732f71fc073f..585676a904280230f1ae0312f081170fc9d4d91a 100644 (file)
@@ -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)
index 5975f1f64378a726f83c42961fcd3879154a91a3..39fd3f513ffa2019d0dc5a31c11f8cf2868eb29c 100644 (file)
@@ -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) {
index 107f4d5ae5c84833c80759a07dbcc954e5dba462..8457706024faebd73e3ac6093f9fec004e28271c 100644 (file)
@@ -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
index b5023fa0dc71cbfc19d4199eb2d5ed36ad8becce..062814329559fe8e2464ad3724eb1d126f914fe8 100644 (file)
@@ -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;
 
index bb1cf37132949ff6a99eedf69d674833f5d6d9ff..a7bbd478825583b7b6c05fefec265d4561061ca1 100644 (file)
@@ -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);
         }
       }
index 29a558d07d9c16d45659921c959fe2ef741a896d..da8af709600b87d4da14da174a12a076f1b91e4e 100644 (file)
@@ -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;