diff options
author | Gert Wollny <[email protected]> | 2018-06-05 22:26:45 +0200 |
---|---|---|
committer | Gert Wollny <[email protected]> | 2018-08-11 12:32:42 +0200 |
commit | 5e58eb37f1380876fbb58280727fcdc16d32e293 (patch) | |
tree | 06f729d5608fde7a57210773c67109944704c542 /src | |
parent | 7d55d01b539ac298edf95c2fd006a53dc7df6ee6 (diff) |
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 <[email protected]>
Acked-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
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; |