mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 08:50:13 +01:00
nir/range_analysis: add helpers for limiting stack usage
Signed-off-by: Rhys Perry <pendingchaos02@gmail.com> Reviewed-by: Georg Lehmann <dadschoorse@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21381>
This commit is contained in:
parent
2145cf3dd1
commit
29a38b09cf
1 changed files with 82 additions and 0 deletions
|
|
@ -26,12 +26,94 @@
|
|||
#include "nir_range_analysis.h"
|
||||
#include "util/hash_table.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_dynarray.h"
|
||||
|
||||
/**
|
||||
* Analyzes a sequence of operations to determine some aspects of the range of
|
||||
* the result.
|
||||
*/
|
||||
|
||||
struct analysis_query {
|
||||
uint32_t pushed_queries;
|
||||
uint32_t result_index;
|
||||
};
|
||||
|
||||
struct analysis_state {
|
||||
nir_shader *shader;
|
||||
const nir_unsigned_upper_bound_config *config;
|
||||
struct hash_table *range_ht;
|
||||
|
||||
struct util_dynarray query_stack;
|
||||
struct util_dynarray result_stack;
|
||||
|
||||
size_t query_size;
|
||||
uintptr_t (*get_key)(struct analysis_query *q);
|
||||
void (*process_query)(struct analysis_state *state, struct analysis_query *q,
|
||||
uint32_t *result, const uint32_t *src);
|
||||
};
|
||||
|
||||
static void *
|
||||
push_analysis_query(struct analysis_state *state, size_t size)
|
||||
{
|
||||
struct analysis_query *q = util_dynarray_grow_bytes(&state->query_stack, 1, size);
|
||||
q->pushed_queries = 0;
|
||||
q->result_index = util_dynarray_num_elements(&state->result_stack, uint32_t);
|
||||
|
||||
util_dynarray_append(&state->result_stack, uint32_t, 0);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
/* Helper for performing range analysis without recursion. */
|
||||
static uint32_t
|
||||
perform_analysis(struct analysis_state *state)
|
||||
{
|
||||
while (state->query_stack.size) {
|
||||
struct analysis_query *cur =
|
||||
(struct analysis_query *)((char*)util_dynarray_end(&state->query_stack) - state->query_size);
|
||||
uint32_t *result = util_dynarray_element(&state->result_stack, uint32_t, cur->result_index);
|
||||
|
||||
uintptr_t key = state->get_key(cur);
|
||||
struct hash_entry *he = NULL;
|
||||
/* There might be a cycle-resolving entry for loop header phis. Ignore this when finishing
|
||||
* them by testing pushed_queries.
|
||||
*/
|
||||
if (cur->pushed_queries == 0 && key &&
|
||||
(he = _mesa_hash_table_search(state->range_ht, (void*)key))) {
|
||||
*result = (uintptr_t)he->data;
|
||||
state->query_stack.size -= state->query_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t *src = (uint32_t*)util_dynarray_end(&state->result_stack) - cur->pushed_queries;
|
||||
state->result_stack.size -= sizeof(uint32_t) * cur->pushed_queries;
|
||||
|
||||
uint32_t prev_num_queries = state->query_stack.size;
|
||||
state->process_query(state, cur, result, src);
|
||||
|
||||
uint32_t num_queries = state->query_stack.size;
|
||||
if (num_queries > prev_num_queries) {
|
||||
cur = (struct analysis_query *)util_dynarray_element(&state->query_stack, char,
|
||||
prev_num_queries - state->query_size);
|
||||
cur->pushed_queries = (num_queries - prev_num_queries) / state->query_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key)
|
||||
_mesa_hash_table_insert(state->range_ht, (void*)key, (void*)(uintptr_t)*result);
|
||||
|
||||
state->query_stack.size -= state->query_size;
|
||||
}
|
||||
|
||||
assert(state->result_stack.size == sizeof(uint32_t));
|
||||
|
||||
uint32_t res = util_dynarray_top(&state->result_stack, uint32_t);
|
||||
util_dynarray_fini(&state->query_stack);
|
||||
util_dynarray_fini(&state->result_stack);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_not_negative(enum ssa_ranges r)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue