diff --git a/src/intel/compiler/brw_fs.cpp b/src/intel/compiler/brw_fs.cpp index 2afe59900e5..dbe35026006 100644 --- a/src/intel/compiler/brw_fs.cpp +++ b/src/intel/compiler/brw_fs.cpp @@ -3099,7 +3099,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; @@ -3117,7 +3117,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 rewrite the @@ -7362,8 +7362,7 @@ fs_visitor::setup_cs_payload() void fs_visitor::calculate_register_pressure() { - invalidate_analysis(DEPENDENCY_EVERYTHING); - calculate_live_intervals(); + const fs_live_variables &live = live_analysis.require(); unsigned num_instructions = 0; foreach_block(block, cfg) @@ -7372,8 +7371,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]; } } @@ -7382,6 +7380,7 @@ void fs_visitor::invalidate_analysis(brw::analysis_dependency_class c) { backend_shader::invalidate_analysis(c); + live_analysis.invalidate(c); } void @@ -7668,15 +7667,15 @@ fs_visitor::fixup_nomask_control_flow() unsigned depth = 0; bool progress = false; - calculate_live_intervals(); + const fs_live_variables &live_vars = live_analysis.require(); /* Scan the program backwards in order to be able to easily determine * whether the flag register is live at any point. */ foreach_block_reverse_safe(block, cfg) { - BITSET_WORD flag_liveout = live_intervals->block_data[block->num] + BITSET_WORD flag_liveout = live_vars.block_data[block->num] .flag_liveout[0]; - STATIC_ASSERT(ARRAY_SIZE(live_intervals->block_data[0].flag_liveout) == 1); + STATIC_ASSERT(ARRAY_SIZE(live_vars.block_data[0].flag_liveout) == 1); foreach_inst_in_block_reverse_safe(fs_inst, inst, block) { if (!inst->predicate && inst->exec_size >= 8) diff --git a/src/intel/compiler/brw_fs.h b/src/intel/compiler/brw_fs.h index 17b87134d3c..265a1106a15 100644 --- a/src/intel/compiler/brw_fs.h +++ b/src/intel/compiler/brw_fs.h @@ -127,13 +127,13 @@ public: void lower_constant_loads(); 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, int &ip); + bool opt_cse_local(const brw::fs_live_variables &live, bblock_t *block, int &ip); + bool opt_copy_propagation(); bool try_copy_propagate(fs_inst *inst, int arg, acp_entry *entry); bool try_constant_propagate(fs_inst *inst, acp_entry *entry); @@ -321,7 +321,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/intel/compiler/brw_fs_copy_propagation.cpp b/src/intel/compiler/brw_fs_copy_propagation.cpp index 8e04dde4a78..bc5af9732b3 100644 --- a/src/intel/compiler/brw_fs_copy_propagation.cpp +++ b/src/intel/compiler/brw_fs_copy_propagation.cpp @@ -94,7 +94,7 @@ class fs_copy_prop_dataflow { public: fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg, - const fs_live_variables *live, + const fs_live_variables &live, exec_list *out_acp[ACP_HASH_SIZE]); void setup_initial_values(); @@ -104,7 +104,7 @@ public: void *mem_ctx; cfg_t *cfg; - const fs_live_variables *live; + const fs_live_variables &live; acp_entry **acp; int num_acp; @@ -115,7 +115,7 @@ public: } /* anonymous namespace */ fs_copy_prop_dataflow::fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg, - const fs_live_variables *live, + const fs_live_variables &live, exec_list *out_acp[ACP_HASH_SIZE]) : mem_ctx(mem_ctx), cfg(cfg), live(live) { @@ -265,8 +265,8 @@ fs_copy_prop_dataflow::setup_initial_values() for (int i = 0; i < num_acp; i++) { BITSET_SET(bd[block->num].undef, i); for (unsigned off = 0; off < acp[i]->size_written; off += REG_SIZE) { - if (BITSET_TEST(live->block_data[block->num].defout, - live->var_from_reg(byte_offset(acp[i]->dst, off)))) + if (BITSET_TEST(live.block_data[block->num].defout, + live.var_from_reg(byte_offset(acp[i]->dst, off)))) BITSET_CLEAR(bd[block->num].undef, i); } } @@ -1013,7 +1013,7 @@ fs_visitor::opt_copy_propagation() for (int i = 0; i < cfg->num_blocks; i++) out_acp[i] = new exec_list [ACP_HASH_SIZE]; - calculate_live_intervals(); + const fs_live_variables &live = live_analysis.require(); /* First, walk through each block doing local copy propagation and getting * the set of copies available at the end of the block. @@ -1035,15 +1035,15 @@ fs_visitor::opt_copy_propagation() for (unsigned a = 0; a < ACP_HASH_SIZE; a++) { foreach_in_list_safe(acp_entry, entry, &out_acp[block->num][a]) { assert(entry->dst.file == VGRF); - if (block->start_ip <= live_intervals->vgrf_start[entry->dst.nr] && - live_intervals->vgrf_end[entry->dst.nr] <= block->end_ip) + if (block->start_ip <= live.vgrf_start[entry->dst.nr] && + live.vgrf_end[entry->dst.nr] <= block->end_ip) entry->remove(); } } } /* Do dataflow analysis for those available copies. */ - fs_copy_prop_dataflow dataflow(copy_prop_ctx, cfg, live_intervals, out_acp); + fs_copy_prop_dataflow dataflow(copy_prop_ctx, cfg, live, out_acp); /* Next, re-run local copy propagation, this time with the set of copies * provided by the dataflow analysis available at the start of a block. diff --git a/src/intel/compiler/brw_fs_cse.cpp b/src/intel/compiler/brw_fs_cse.cpp index d80b70a1458..198bb5c4c5e 100644 --- a/src/intel/compiler/brw_fs_cse.cpp +++ b/src/intel/compiler/brw_fs_cse.cpp @@ -243,7 +243,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, int &ip) +fs_visitor::opt_cse_local(const fs_live_variables &live, bblock_t *block, int &ip) { bool progress = false; exec_list aeb; @@ -360,8 +360,7 @@ fs_visitor::opt_cse_local(bblock_t *block, int &ip) /* 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; @@ -380,13 +379,12 @@ fs_visitor::opt_cse_local(bblock_t *block, int &ip) bool fs_visitor::opt_cse() { + const fs_live_variables &live = live_analysis.require(); bool progress = false; int ip = 0; - calculate_live_intervals(); - foreach_block (block, cfg) { - progress = opt_cse_local(block, ip) || progress; + progress = opt_cse_local(live, block, ip) || progress; } if (progress) diff --git a/src/intel/compiler/brw_fs_dead_code_eliminate.cpp b/src/intel/compiler/brw_fs_dead_code_eliminate.cpp index 8e30e6de6ce..272b6c41b2d 100644 --- a/src/intel/compiler/brw_fs_dead_code_eliminate.cpp +++ b/src/intel/compiler/brw_fs_dead_code_eliminate.cpp @@ -76,21 +76,20 @@ 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 = 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(fs_inst, inst, block) { if (inst->dst.file == VGRF) { - const unsigned var = live_intervals->var_from_reg(inst->dst); + const unsigned var = live_vars.var_from_reg(inst->dst); bool result_live = false; for (unsigned i = 0; i < regs_written(inst); i++) @@ -111,7 +110,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); + const unsigned var = live_vars.var_from_reg(inst->dst); for (unsigned i = 0; i < regs_written(inst); i++) { BITSET_CLEAR(live, var + i); } @@ -128,7 +127,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 (unsigned j = 0; j < regs_read(inst, i); j++) { BITSET_SET(live, var + j); diff --git a/src/intel/compiler/brw_fs_live_variables.cpp b/src/intel/compiler/brw_fs_live_variables.cpp index 6debf50be8f..f7f6de1fe76 100644 --- a/src/intel/compiler/brw_fs_live_variables.cpp +++ b/src/intel/compiler/brw_fs_live_variables.cpp @@ -367,23 +367,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/intel/compiler/brw_fs_live_variables.h b/src/intel/compiler/brw_fs_live_variables.h index ba2e841f1cc..5827fe0fd7d 100644 --- a/src/intel/compiler/brw_fs_live_variables.h +++ b/src/intel/compiler/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" @@ -76,13 +77,19 @@ 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/intel/compiler/brw_fs_reg_allocate.cpp b/src/intel/compiler/brw_fs_reg_allocate.cpp index 9e6e414d104..8c16d117bc0 100644 --- a/src/intel/compiler/brw_fs_reg_allocate.cpp +++ b/src/intel/compiler/brw_fs_reg_allocate.cpp @@ -410,7 +410,8 @@ void fs_visitor::calculate_payload_ranges(int payload_node_count, class fs_reg_alloc { public: fs_reg_alloc(fs_visitor *fs): - fs(fs), devinfo(fs->devinfo), compiler(fs->compiler), g(NULL), + fs(fs), devinfo(fs->devinfo), compiler(fs->compiler), + live(fs->live_analysis.require()), g(NULL), have_spill_costs(false) { mem_ctx = ralloc_context(NULL); @@ -457,6 +458,7 @@ private: fs_visitor *fs; const gen_device_info *devinfo; const brw_compiler *compiler; + const fs_live_variables &live; /* Which compiler->fs_reg_sets[] to use */ int rsi; @@ -590,8 +592,8 @@ fs_reg_alloc::setup_live_interference(unsigned node, for (unsigned n2 = first_vgrf_node; n2 < (unsigned)first_spill_node && n2 < node; n2++) { unsigned vgrf = n2 - first_vgrf_node; - if (!(node_end_ip <= fs->live_intervals->vgrf_start[vgrf] || - fs->live_intervals->vgrf_end[vgrf] <= node_start_ip)) + if (!(node_end_ip <= live.vgrf_start[vgrf] || + live.vgrf_end[vgrf] <= node_start_ip)) ra_add_node_interference(g, node, n2); } } @@ -740,7 +742,6 @@ fs_reg_alloc::build_interference_graph(bool allow_spilling) node_count += fs->alloc.count; first_spill_node = node_count; - fs->calculate_live_intervals(); fs->calculate_payload_ranges(payload_node_count, payload_last_use_ip); @@ -812,8 +813,8 @@ fs_reg_alloc::build_interference_graph(bool allow_spilling) /* Add interference based on the live range of the register */ for (unsigned i = 0; i < fs->alloc.count; i++) { setup_live_interference(first_vgrf_node + i, - fs->live_intervals->vgrf_start[i], - fs->live_intervals->vgrf_end[i]); + live.vgrf_start[i], + live.vgrf_end[i]); } /* Add interference based on the instructions in which a register is used. @@ -953,7 +954,7 @@ fs_reg_alloc::set_spill_costs() if (no_spill[i]) continue; - int live_length = fs->live_intervals->vgrf_end[i] - fs->live_intervals->vgrf_start[i]; + int live_length = live.vgrf_end[i] - live.vgrf_start[i]; if (live_length <= 0) continue; diff --git a/src/intel/compiler/brw_fs_register_coalesce.cpp b/src/intel/compiler/brw_fs_register_coalesce.cpp index 15699658bc7..44ad3e624c3 100644 --- a/src/intel/compiler/brw_fs_register_coalesce.cpp +++ b/src/intel/compiler/brw_fs_register_coalesce.cpp @@ -97,17 +97,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) || @@ -155,9 +155,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; unsigned src_reg = ~0u, dst_reg = ~0u; @@ -227,11 +225,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 = ~0u; break; @@ -273,12 +270,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 = ~0u; } diff --git a/src/intel/compiler/brw_fs_saturate_propagation.cpp b/src/intel/compiler/brw_fs_saturate_propagation.cpp index 8140de69749..50c3fc19f3b 100644 --- a/src/intel/compiler/brw_fs_saturate_propagation.cpp +++ b/src/intel/compiler/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) { @@ -149,12 +151,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/intel/compiler/brw_fs_visitor.cpp b/src/intel/compiler/brw_fs_visitor.cpp index 92332eb8337..f7f58b02259 100644 --- a/src/intel/compiler/brw_fs_visitor.cpp +++ b/src/intel/compiler/brw_fs_visitor.cpp @@ -886,6 +886,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), 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()) @@ -903,6 +904,7 @@ fs_visitor::fs_visitor(const struct brw_compiler *compiler, void *log_data, &prog_data->base.base), key(&c->key.base), gs_compile(c), prog_data(&prog_data->base.base), + live_analysis(this), dispatch_width(8), shader_time_index(shader_time_index), bld(fs_builder(this, dispatch_width).at_end()) @@ -933,7 +935,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/intel/compiler/brw_schedule_instructions.cpp b/src/intel/compiler/brw_schedule_instructions.cpp index 596b99ecd90..709237fab57 100644 --- a/src/intel/compiler/brw_schedule_instructions.cpp +++ b/src/intel/compiler/brw_schedule_instructions.cpp @@ -730,21 +730,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]); } } @@ -754,8 +756,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); @@ -1826,9 +1828,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;