X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Floop_analysis.cpp;h=6a0e4da51004cd1c67547f631f3e770c7204bbc5;hb=9a204bb9f611e34396ea838b44517dd6eeb99bcc;hp=91e34da0ee49247ab62ddca076ab45cd5b12eab5;hpb=695cc370a280a637f411f5ff3877b3fd1c05e424;p=mesa.git diff --git a/src/glsl/loop_analysis.cpp b/src/glsl/loop_analysis.cpp index 91e34da0ee4..6a0e4da5100 100644 --- a/src/glsl/loop_analysis.cpp +++ b/src/glsl/loop_analysis.cpp @@ -37,13 +37,15 @@ loop_state::loop_state() { this->ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); - this->mem_ctx = talloc_init("loop state"); + this->mem_ctx = ralloc_context(NULL); + this->loop_found = false; } loop_state::~loop_state() { hash_table_dtor(this->ht); + ralloc_free(this->mem_ctx); } @@ -51,7 +53,9 @@ loop_variable_state * loop_state::insert(ir_loop *ir) { loop_variable_state *ls = new(this->mem_ctx) loop_variable_state; + hash_table_insert(this->ht, ls, ir); + this->loop_found = true; return ls; } @@ -74,8 +78,8 @@ loop_variable_state::get(const ir_variable *ir) loop_variable * loop_variable_state::insert(ir_variable *var) { - void *mem_ctx = talloc_parent(this); - loop_variable *lv = talloc_zero(mem_ctx, loop_variable); + void *mem_ctx = ralloc_parent(this); + loop_variable *lv = rzalloc(mem_ctx, loop_variable); lv->var = var; @@ -89,8 +93,8 @@ loop_variable_state::insert(ir_variable *var) loop_terminator * loop_variable_state::insert(ir_if *if_stmt) { - void *mem_ctx = talloc_parent(this); - loop_terminator *t = talloc_zero(mem_ctx, loop_terminator); + void *mem_ctx = ralloc_parent(this); + loop_terminator *t = rzalloc(mem_ctx, loop_terminator); t->ir = if_stmt; this->terminators.push_tail(t); @@ -106,6 +110,8 @@ public: virtual ir_visitor_status visit(ir_loop_jump *); virtual ir_visitor_status visit(ir_dereference_variable *); + virtual ir_visitor_status visit_enter(ir_call *); + virtual ir_visitor_status visit_enter(ir_loop *); virtual ir_visitor_status visit_leave(ir_loop *); virtual ir_visitor_status visit_enter(ir_assignment *); @@ -148,6 +154,21 @@ loop_analysis::visit(ir_loop_jump *ir) } +ir_visitor_status +loop_analysis::visit_enter(ir_call *ir) +{ + /* If we're not somewhere inside a loop, there's nothing to do. */ + if (this->state.is_empty()) + return visit_continue; + + loop_variable_state *const ls = + (loop_variable_state *) this->state.get_head(); + + ls->contains_calls = true; + return visit_continue_with_parent; +} + + ir_visitor_status loop_analysis::visit(ir_dereference_variable *ir) { @@ -205,6 +226,17 @@ loop_analysis::visit_leave(ir_loop *ir) loop_variable_state *const ls = (loop_variable_state *) this->state.pop_head(); + /* Function calls may contain side effects. These could alter any of our + * variables in ways that cannot be known, and may even terminate shader + * execution (say, calling discard in the fragment shader). So we can't + * rely on any of our analysis about assignments to variables. + * + * We could perform some conservative analysis (prove there's no statically + * possible assignment, etc.) but it isn't worth it for now; function + * inlining will allow us to unroll loops anyway. + */ + if (ls->contains_calls) + return visit_continue; foreach_list(node, &ir->body_instructions) { /* Skip over declarations at the start of a loop. @@ -446,7 +478,7 @@ get_basic_induction_increment(ir_assignment *ir, hash_table *var_hash) } if ((inc != NULL) && (rhs->operation == ir_binop_sub)) { - void *mem_ctx = talloc_parent(ir); + void *mem_ctx = ralloc_parent(ir); inc = new(mem_ctx) ir_expression(ir_unop_neg, inc->type,