android: generate files by $(call es-gen)
[mesa.git] / src / glsl / opt_cse.cpp
index c0fdb23e64c15132a98b545ce290f0c3ac13181c..4b8e9a07ba5bffeb482a59250303c573d519da74 100644 (file)
@@ -63,6 +63,17 @@ public:
       var = NULL;
    }
 
+   void init(ir_instruction *base_ir, ir_rvalue **val)
+   {
+      this->val = val;
+      this->base_ir = base_ir;
+      this->var = NULL;
+
+      assert(val);
+      assert(*val);
+      assert(base_ir);
+   }
+
    /**
     * The pointer to the expression that we might be able to reuse
     *
@@ -116,6 +127,18 @@ private:
    ir_rvalue *try_cse(ir_rvalue *rvalue);
    void add_to_ae(ir_rvalue **rvalue);
 
+   /**
+    * Move all nodes from the ae list to the free list
+    */
+   void empty_ae_list();
+
+   /**
+    * Get and initialize a new ae_entry
+    *
+    * This will either come from the free list or be freshly allocated.
+    */
+   ae_entry *get_ae_entry(ir_rvalue **rvalue);
+
    /** List of ae_entry: The available expressions to reuse */
    exec_list *ae;
 
@@ -126,6 +149,11 @@ private:
     * right.
     */
    exec_list *validate_instructions;
+
+   /**
+    * List of available-for-use ae_entry objects.
+    */
+   exec_list free_ae_entries;
 };
 
 /**
@@ -173,9 +201,7 @@ dump_ae(exec_list *ae)
    int i = 0;
 
    printf("CSE: AE contents:\n");
-   foreach_list(node, ae) {
-      ae_entry *entry = (ae_entry *)node;
-
+   foreach_in_list(ae_entry, entry, ae) {
       printf("CSE:   AE %2d (%p): ", i, entry);
       (*entry->val)->print();
       printf("\n");
@@ -193,9 +219,11 @@ is_cse_candidate_visitor::visit(ir_dereference_variable *ir)
    /* Currently, since we don't handle kills of the ae based on variables
     * getting assigned, we can only handle constant variables.
     */
-   if (ir->var->read_only) {
+   if (ir->var->data.read_only) {
       return visit_continue;
    } else {
+      if (debug)
+         printf("CSE: non-candidate: var %s is not read only\n", ir->var->name);
       ok = false;
       return visit_stop;
    }
@@ -222,8 +250,11 @@ is_cse_candidate(ir_rvalue *ir)
    /* Our temporary variable assignment generation isn't ready to handle
     * anything bigger than a vector.
     */
-   if (!ir->type->is_vector() && !ir->type->is_scalar())
+   if (!ir->type->is_vector() && !ir->type->is_scalar()) {
+      if (debug)
+         printf("CSE: non-candidate: not a vector/scalar\n");
       return false;
+   }
 
    /* Only handle expressions and textures currently.  We may want to extend
     * to variable-index array dereferences at some point.
@@ -233,6 +264,8 @@ is_cse_candidate(ir_rvalue *ir)
    case ir_type_texture:
       break;
    default:
+      if (debug)
+         printf("CSE: non-candidate: not an expression/texture\n");
       return false;
    }
 
@@ -243,182 +276,6 @@ is_cse_candidate(ir_rvalue *ir)
    return v.ok;
 }
 
-static bool
-equals(ir_rvalue *a, ir_rvalue *b);
-
-static bool
-equals(ir_constant *a, ir_constant *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   for (unsigned i = 0; i < a->type->components(); i++) {
-      if (a->value.u[i] != b->value.u[i])
-         return false;
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_dereference_variable *a, ir_dereference_variable *b)
-{
-   if (!a || !b)
-      return false;
-
-   return a->var == b->var;
-}
-
-static bool
-equals(ir_dereference_array *a, ir_dereference_array *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (!equals(a->array, b->array))
-      return false;
-
-   if (!equals(a->array_index, b->array_index))
-      return false;
-
-   return true;
-}
-
-static bool
-equals(ir_swizzle *a, ir_swizzle *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->mask.x != b->mask.x ||
-       a->mask.y != b->mask.y ||
-       a->mask.z != b->mask.z ||
-       a->mask.w != b->mask.w) {
-      return false;
-   }
-
-   return equals(a->val, b->val);
-}
-
-static bool
-equals(ir_texture *a, ir_texture *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->op != b->op)
-      return false;
-
-   if (!equals(a->coordinate, b->coordinate))
-      return false;
-
-   if (!equals(a->projector, b->projector))
-      return false;
-
-   if (!equals(a->shadow_comparitor, b->shadow_comparitor))
-      return false;
-
-   if (!equals(a->offset, b->offset))
-      return false;
-
-   if (!equals(a->sampler, b->sampler))
-      return false;
-
-   switch (a->op) {
-   case ir_tex:
-   case ir_lod:
-   case ir_query_levels:
-      break;
-   case ir_txb:
-      if (!equals(a->lod_info.bias, b->lod_info.bias))
-         return false;
-      break;
-   case ir_txl:
-   case ir_txf:
-   case ir_txs:
-      if (!equals(a->lod_info.lod, b->lod_info.lod))
-         return false;
-      break;
-   case ir_txd:
-      if (!equals(a->lod_info.grad.dPdx, b->lod_info.grad.dPdx) ||
-          !equals(a->lod_info.grad.dPdy, b->lod_info.grad.dPdy))
-         return false;
-   case ir_txf_ms:
-      if (!equals(a->lod_info.sample_index, b->lod_info.sample_index))
-         return false;
-      break;
-   case ir_tg4:
-      if (!equals(a->lod_info.component, b->lod_info.component))
-         return false;
-   default:
-      assert(!"Unrecognized texture op");
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_expression *a, ir_expression *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->operation != b->operation)
-      return false;
-
-   for (unsigned i = 0; i < a->get_num_operands(); i++) {
-      if (!equals(a->operands[i], b->operands[i]))
-         return false;
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_rvalue *a, ir_rvalue *b)
-{
-   if (!a || !b)
-      return !a && !b;
-
-   if (a->type != b->type)
-      return false;
-
-   switch (a->ir_type) {
-   case ir_type_texture:
-      return equals(a->as_texture(), b->as_texture());
-
-   case ir_type_constant:
-      return equals(a->as_constant(), b->as_constant());
-
-   case ir_type_expression:
-      return equals(a->as_expression(), b->as_expression());
-
-   case ir_type_dereference_variable:
-      return equals(a->as_dereference_variable(), b->as_dereference_variable());
-
-   case ir_type_dereference_array:
-      return equals(a->as_dereference_array(), b->as_dereference_array());
-
-   case ir_type_swizzle:
-      return equals(a->as_swizzle(), b->as_swizzle());
-
-   default:
-      return false;
-   }
-}
-
 /**
  * Tries to find and return a reference to a previous computation of a given
  * expression.
@@ -430,16 +287,14 @@ equals(ir_rvalue *a, ir_rvalue *b)
 ir_rvalue *
 cse_visitor::try_cse(ir_rvalue *rvalue)
 {
-   foreach_list(node, ae) {
-      ae_entry *entry = (ae_entry *)node;
-
+   foreach_in_list(ae_entry, entry, ae) {
       if (debug) {
          printf("Comparing to AE %p: ", entry);
          (*entry->val)->print();
          printf("\n");
       }
 
-      if (!equals(rvalue, *entry->val))
+      if (!rvalue->equals(*entry->val))
          continue;
 
       if (debug) {
@@ -456,7 +311,7 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
 
          ir_variable *var = new(rvalue) ir_variable(rvalue->type,
                                                     "cse",
-                                                    ir_var_auto);
+                                                    ir_var_temporary);
 
          /* Write the previous expression result into a new variable. */
          base_ir->insert_before(var);
@@ -479,8 +334,7 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
           * updated so that any further elimination from inside gets its new
           * assignments put before our new assignment.
           */
-         foreach_list(fixup_node, ae) {
-            ae_entry *fixup_entry = (ae_entry *)fixup_node;
+         foreach_in_list(ae_entry, fixup_entry, ae) {
             if (contains_rvalue(assignment->rhs, *fixup_entry->val))
                fixup_entry->base_ir = assignment;
          }
@@ -496,6 +350,25 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
    return NULL;
 }
 
+void
+cse_visitor::empty_ae_list()
+{
+   free_ae_entries.append_list(ae);
+}
+
+ae_entry *
+cse_visitor::get_ae_entry(ir_rvalue **rvalue)
+{
+   ae_entry *entry = (ae_entry *) free_ae_entries.pop_head();
+   if (entry) {
+      entry->init(base_ir, rvalue);
+   } else {
+      entry = new(mem_ctx) ae_entry(base_ir, rvalue);
+   }
+
+   return entry;
+}
+
 /** Add the rvalue to the list of available expressions for CSE. */
 void
 cse_visitor::add_to_ae(ir_rvalue **rvalue)
@@ -506,7 +379,7 @@ cse_visitor::add_to_ae(ir_rvalue **rvalue)
       printf("\n");
    }
 
-   ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue));
+   ae->push_tail(get_ae_entry(rvalue));
 
    if (debug)
       dump_ae(ae);
@@ -544,38 +417,38 @@ cse_visitor::visit_enter(ir_if *ir)
 {
    handle_rvalue(&ir->condition);
 
-   ae->make_empty();
+   empty_ae_list();
    visit_list_elements(this, &ir->then_instructions);
 
-   ae->make_empty();
+   empty_ae_list();
    visit_list_elements(this, &ir->else_instructions);
 
-   ae->make_empty();
+   empty_ae_list();
    return visit_continue_with_parent;
 }
 
 ir_visitor_status
 cse_visitor::visit_enter(ir_function_signature *ir)
 {
-   ae->make_empty();
+   empty_ae_list();
    visit_list_elements(this, &ir->body);
 
-   ae->make_empty();
+   empty_ae_list();
    return visit_continue_with_parent;
 }
 
 ir_visitor_status
 cse_visitor::visit_enter(ir_loop *ir)
 {
-   ae->make_empty();
+   empty_ae_list();
    visit_list_elements(this, &ir->body_instructions);
 
-   ae->make_empty();
+   empty_ae_list();
    return visit_continue_with_parent;
 }
 
 ir_visitor_status
-cse_visitor::visit_enter(ir_call *ir)
+cse_visitor::visit_enter(ir_call *)
 {
    /* Because call is an exec_list of ir_rvalues, handle_rvalue gets passed a
     * pointer to the (ir_rvalue *) on the stack.  Since we save those pointers