ilo: add the driver to the build system
[mesa.git] / src / glsl / loop_analysis.cpp
index 32e8b8c85b3ba333256ef9950b35b2efcb192cf9..191e92de7c48f7689837f5c769a2784702bf16f2 100644 (file)
@@ -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);
@@ -101,11 +105,13 @@ loop_variable_state::insert(ir_if *if_stmt)
 
 class loop_analysis : public ir_hierarchical_visitor {
 public:
-   loop_analysis();
+   loop_analysis(loop_state *loops);
 
    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 *);
@@ -123,12 +129,10 @@ public:
 };
 
 
-loop_analysis::loop_analysis()
+loop_analysis::loop_analysis(loop_state *loops)
+   : loops(loops), if_statement_depth(0), current_assignment(NULL)
 {
-   this->loops = new loop_state;
-
-   this->if_statement_depth = 0;
-   this->current_assignment = NULL;
+   /* empty */
 }
 
 
@@ -148,13 +152,28 @@ 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)
 {
    /* If we're not somewhere inside a loop, there's nothing to do.
     */
    if (this->state.is_empty())
-      return visit_continue_with_parent;
+      return visit_continue;
 
    loop_variable_state *const ls =
       (loop_variable_state *) this->state.get_head();
@@ -205,6 +224,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 +476,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,
@@ -489,7 +519,8 @@ is_loop_terminator(ir_if *ir)
 loop_state *
 analyze_loop_variables(exec_list *instructions)
 {
-   loop_analysis v;
+   loop_state *loops = new loop_state;
+   loop_analysis v(loops);
 
    v.run(instructions);
    return v.loops;