From 5e58eb37f1380876fbb58280727fcdc16d32e293 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 5 Jun 2018 22:26:45 +0200 Subject: [PATCH] mesa/st/glsl_to_tgsi: add class for array access tracking Because of the indirect access it is impossible to obtain an accurate per component and array element tracking. Therefore, the tracking is simplified to only track whether any element was accessed, whether this happend conditionally in a loop. In addition, while tracking of temporaries requires a per-componet tracking that is later fused, for arrays only the components access mask is neede. The resulting tracking code and evaluation of the array live range is sufficiently different from the evaluation of the live range of temporaries to justify implementing this in a different class instead of adding more complexity to the already existing code for temporary life range evaluation. v4: Update commit message to make it clearer why this class is seperate from the tracking of temporaries. Signed-off-by: Gert Wollny Acked-by: Dave Airlie --- .../st_glsl_to_tgsi_temprename.cpp | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp index 24c3fbe2ae3..cc02ca5c1c0 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp @@ -22,6 +22,7 @@ */ #include "st_glsl_to_tgsi_temprename.h" +#include "st_glsl_to_tgsi_array_merge.h" #include "tgsi/tgsi_info.h" #include "tgsi/tgsi_strings.h" #include "program/prog_instruction.h" @@ -239,6 +240,27 @@ private: bool needs_component_tracking; }; +/* Class to track array access. + * Compared to the temporary tracking this is very simplified, mainly because + * with the likely indirect access one can not really establish access + * patterns for individual elements. Instead the life range evaluation is + * always for the whole array, handles only loops and the fact whether a + * value was accessed conditionally in a loop. + */ +class array_access { +public: + array_access(); + void record_access(int line, prog_scope *scope, int swizzle); + void get_required_live_range(array_live_range &lr); +private: + int first_access; + int last_access; + prog_scope *first_access_scope; + prog_scope *last_access_scope; + unsigned accumulated_swizzle:4; + int conditional_access_in_loop:1; +}; + prog_scope_storage::prog_scope_storage(void *mc, int n): mem_ctx(mc), current_slot(0) @@ -508,6 +530,86 @@ void temp_access::record_read(int line, prog_scope *scope, int readmask) comp[3].record_read(line, scope); } +array_access::array_access(): + first_access(-1), + last_access(-1), + first_access_scope(nullptr), + last_access_scope(nullptr), + accumulated_swizzle(0), + conditional_access_in_loop(false) +{ +} + +void array_access::record_access(int line, prog_scope *scope, int swizzle) +{ + if (!first_access_scope) { + first_access = line; + first_access_scope = scope; + } + last_access_scope = scope; + last_access = line; + accumulated_swizzle |= swizzle; + if (scope->in_ifelse_scope() && scope->innermost_loop()) + conditional_access_in_loop = true; +} + +void array_access::get_required_live_range(array_live_range& lr) +{ + RENAME_DEBUG(debug_log << "first_access_scope=" << first_access_scope << "\n"); + RENAME_DEBUG(debug_log << "last_access_scope=" << last_access_scope << "\n"); + + if (first_access_scope == last_access_scope) { + lr.set_live_range(first_access, last_access); + lr.set_access_mask(accumulated_swizzle); + return; + } + + const prog_scope *shared_scope = first_access_scope; + const prog_scope *other_scope = last_access_scope; + + assert(shared_scope); + RENAME_DEBUG(debug_log << "shared_scope=" << shared_scope << "\n"); + + if (conditional_access_in_loop) { + const prog_scope *help = shared_scope->outermost_loop(); + if (help) { + shared_scope = help; + } else { + help = other_scope->outermost_loop(); + if (help) + other_scope = help; + } + if (first_access > shared_scope->begin()) + first_access = shared_scope->begin(); + if (last_access < shared_scope->end()) + last_access = shared_scope->end(); + } + + /* See if any of the two is the parent of the other. */ + if (other_scope->contains_range_of(*shared_scope)) { + shared_scope = other_scope; + } else while (!shared_scope->contains_range_of(*other_scope)) { + assert(shared_scope->parent()); + if (shared_scope->type() == loop_body) { + if (last_access < shared_scope->end()) + last_access = shared_scope->end(); + } + shared_scope = shared_scope->parent(); + } + + while (shared_scope != other_scope) { + if (other_scope->type() == loop_body) { + if (last_access < other_scope->end()) + last_access = other_scope->end(); + } + other_scope = other_scope->parent(); + } + + lr.set_live_range(first_access, last_access); + lr.set_access_mask(accumulated_swizzle); +} + + inline static register_live_range make_live_range(int b, int e) { register_live_range lt; -- 2.30.2