glsl: Use a new foreach_two_lists macro for walking two lists at once.
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 11 Jan 2014 00:39:17 +0000 (16:39 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Mon, 13 Jan 2014 19:49:42 +0000 (11:49 -0800)
When handling function calls, we often want to walk through the list of
formal parameters and list of actual parameters at the same time.
(Both are guaranteed to be the same length.)

Previously, we used a pattern of:

   exec_list_iterator 1st_iter = <1st list>.iterator();
   foreach_iter(exec_list_iterator, 2nd_iter, <2nd list>) {
      ...
      1st_iter.next();
   }

This was awkward, since you had to manually iterate through one of
the two lists.

This patch introduces a foreach_two_lists macro which safely walks
through two lists at the same time, so you can simply do:

   foreach_two_lists(1st_node, <1st list>, 2nd_node, <2nd list>) {
      ...
   }

v2: Rename macro from foreach_list2 to foreach_two_lists, as suggested
    by Ian Romanick.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
12 files changed:
src/glsl/ast_function.cpp
src/glsl/ir.cpp
src/glsl/linker.cpp
src/glsl/list.h
src/glsl/opt_constant_folding.cpp
src/glsl/opt_constant_propagation.cpp
src/glsl/opt_constant_variable.cpp
src/glsl/opt_copy_propagation.cpp
src/glsl/opt_copy_propagation_elements.cpp
src/glsl/opt_function_inlining.cpp
src/glsl/opt_tree_grafting.cpp
src/mesa/state_tracker/st_glsl_to_tgsi.cpp

index e4c0fd1c4769eb54e4ede253aeff685efc0625de..2d05d0723411e0ddf4f285829829370ff6cc3446 100644 (file)
@@ -293,15 +293,10 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
     * call takes place.  Since we haven't emitted the call yet, we'll place
     * the post-call conversions in a temporary exec_list, and emit them later.
     */
-   exec_list_iterator actual_iter = actual_parameters->iterator();
-   exec_list_iterator formal_iter = sig->parameters.iterator();
-
-   while (actual_iter.has_next()) {
-      ir_rvalue *actual = (ir_rvalue *) actual_iter.get();
-      ir_variable *formal = (ir_variable *) formal_iter.get();
-
-      assert(actual != NULL);
-      assert(formal != NULL);
+   foreach_two_lists(formal_node, &sig->parameters,
+                     actual_node, actual_parameters) {
+      ir_rvalue *actual = (ir_rvalue *) actual_node;
+      ir_variable *formal = (ir_variable *) formal_node;
 
       if (formal->type->is_numeric() || formal->type->is_boolean()) {
         switch (formal->data.mode) {
@@ -323,9 +318,6 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
            break;
         }
       }
-
-      actual_iter.next();
-      formal_iter.next();
    }
 
    /* If the function call is a constant expression, don't generate any
index 6ffa987f6d20dbd821c424d41aacfb71b3d82582..1a36bd631c18fe16f0a3f3ad6f61768cdb388be4 100644 (file)
@@ -1649,13 +1649,10 @@ modes_match(unsigned a, unsigned b)
 const char *
 ir_function_signature::qualifiers_match(exec_list *params)
 {
-   exec_list_iterator iter_a = parameters.iterator();
-   exec_list_iterator iter_b = params->iterator();
-
    /* check that the qualifiers match. */
-   while (iter_a.has_next()) {
-      ir_variable *a = (ir_variable *)iter_a.get();
-      ir_variable *b = (ir_variable *)iter_b.get();
+   foreach_two_lists(a_node, &this->parameters, b_node, params) {
+      ir_variable *a = (ir_variable *) a_node;
+      ir_variable *b = (ir_variable *) b_node;
 
       if (a->data.read_only != b->data.read_only ||
          !modes_match(a->data.mode, b->data.mode) ||
@@ -1666,9 +1663,6 @@ ir_function_signature::qualifiers_match(exec_list *params)
         /* parameter a's qualifiers don't match */
         return a->name;
       }
-
-      iter_a.next();
-      iter_b.next();
    }
    return NULL;
 }
index 14e2ff61062a9e00e850e32fbf535e094ed5e322..85a4d388326f28d6ee31d94a9e05b80aa0362956 100644 (file)
@@ -109,10 +109,10 @@ public:
 
    virtual ir_visitor_status visit_enter(ir_call *ir)
    {
-      exec_list_iterator sig_iter = ir->callee->parameters.iterator();
-      foreach_iter(exec_list_iterator, iter, *ir) {
-        ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-        ir_variable *sig_param = (ir_variable *)sig_iter.get();
+      foreach_two_lists(formal_node, &ir->callee->parameters,
+                        actual_node, &ir->actual_parameters) {
+        ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+        ir_variable *sig_param = (ir_variable *) formal_node;
 
         if (sig_param->data.mode == ir_var_function_out ||
             sig_param->data.mode == ir_var_function_inout) {
@@ -122,7 +122,6 @@ public:
               return visit_stop;
            }
         }
-        sig_iter.next();
       }
 
       if (ir->return_deref != NULL) {
index 5ac17cb37a47d4568fc7d82ea358886f46a5cf76..f9eb60ec7c4f07d6dbe428341d759252172cd5be 100644 (file)
@@ -447,6 +447,22 @@ inline void exec_node::insert_before(exec_list *before)
        ; (__node)->next != NULL                        \
        ; (__node) = (__node)->next)
 
+/**
+ * Iterate through two lists at once.  Stops at the end of the shorter list.
+ *
+ * This is safe against either current node being removed or replaced.
+ */
+#define foreach_two_lists(__node1, __list1, __node2, __list2) \
+   for (exec_node * __node1 = (__list1)->head,                \
+                  * __node2 = (__list2)->head,                \
+                  * __next1 = __node1->next,                  \
+                  * __next2 = __node2->next                   \
+       ; __next1 != NULL && __next2 != NULL                  \
+       ; __node1 = __next1,                                  \
+          __node2 = __next2,                                  \
+          __next1 = __next1->next,                            \
+          __next2 = __next2->next)
+
 #define foreach_list_const(__node, __list)             \
    for (const exec_node * __node = (__list)->head      \
        ; (__node)->next != NULL                        \
index 08a47b96bf752cadc4b1a852b39eae68b4304237..d0e575460bdb5b0e4c7451b0e77e1cea97c067ef 100644 (file)
@@ -122,10 +122,10 @@ ir_visitor_status
 ir_constant_folding_visitor::visit_enter(ir_call *ir)
 {
    /* Attempt to constant fold parameters */
-   exec_list_iterator sig_iter = ir->callee->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-      ir_variable *sig_param = (ir_variable *)sig_iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+      ir_variable *sig_param = (ir_variable *) formal_node;
 
       if (sig_param->data.mode == ir_var_function_in
           || sig_param->data.mode == ir_var_const_in) {
@@ -136,7 +136,6 @@ ir_constant_folding_visitor::visit_enter(ir_call *ir)
            param_rval->replace_with(new_param);
         }
       }
-      sig_iter.next();
    }
 
    /* Next, see if the call can be replaced with an assignment of a constant */
index a2d1b0f7582ada3163ae6135be716f67c3aba0b8..18f5da689071b801809792bae0b2ab3c5142fa59 100644 (file)
@@ -281,10 +281,10 @@ ir_visitor_status
 ir_constant_propagation_visitor::visit_enter(ir_call *ir)
 {
    /* Do constant propagation on call parameters, but skip any out params */
-   exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
-      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
-      ir_rvalue *param = (ir_rvalue *)iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *) formal_node;
+      ir_rvalue *param = (ir_rvalue *) actual_node;
       if (sig_param->data.mode != ir_var_function_out
           && sig_param->data.mode != ir_var_function_inout) {
         ir_rvalue *new_param = param;
@@ -294,7 +294,6 @@ ir_constant_propagation_visitor::visit_enter(ir_call *ir)
         else
            param->accept(this);
       }
-      sig_param_iter.next();
    }
 
    /* Since we're unlinked, we don't (necssarily) know the side effects of
index 22a0fe1d107a4c12dc8611d08a558f2f30aeee01..961b8aa0660ed4c6adfdb5f281a768177978e5bd 100644 (file)
@@ -132,10 +132,10 @@ ir_visitor_status
 ir_constant_variable_visitor::visit_enter(ir_call *ir)
 {
    /* Mark any out parameters as assigned to */
-   exec_list_iterator sig_iter = ir->callee->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-      ir_variable *param = (ir_variable *)sig_iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+      ir_variable *param = (ir_variable *) formal_node;
 
       if (param->data.mode == ir_var_function_out ||
          param->data.mode == ir_var_function_inout) {
@@ -146,7 +146,6 @@ ir_constant_variable_visitor::visit_enter(ir_call *ir)
         entry = get_assignment_entry(var, &this->list);
         entry->assignment_count++;
       }
-      sig_iter.next();
    }
 
    /* Mark the return storage as having been assigned to */
index 44c6f2fd3e94e01fd49082f516192cf86ad12c90..195cc8baae69ae85f3dbed5f25919fc87200fab9 100644 (file)
@@ -185,15 +185,14 @@ ir_visitor_status
 ir_copy_propagation_visitor::visit_enter(ir_call *ir)
 {
    /* Do copy propagation on call parameters, but skip any out params */
-   exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
-      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
-      ir_rvalue *ir = (ir_rvalue *) iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *) formal_node;
+      ir_rvalue *ir = (ir_rvalue *) actual_node;
       if (sig_param->data.mode != ir_var_function_out
           && sig_param->data.mode != ir_var_function_inout) {
          ir->accept(this);
       }
-      sig_param_iter.next();
    }
 
    /* Since we're unlinked, we don't (necessarily) know the side effects of
index a64a9ce274fbeceb36b0a5a25f47bbd71835620b..cc53e0dd00e1ef4c61b9edf1995915ea0fb950c0 100644 (file)
@@ -293,15 +293,14 @@ ir_visitor_status
 ir_copy_propagation_elements_visitor::visit_enter(ir_call *ir)
 {
    /* Do copy propagation on call parameters, but skip any out params */
-   exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
-      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
-      ir_rvalue *ir = (ir_rvalue *) iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *) formal_node;
+      ir_rvalue *ir = (ir_rvalue *) actual_node;
       if (sig_param->data.mode != ir_var_function_out
           && sig_param->data.mode != ir_var_function_inout) {
          ir->accept(this);
       }
-      sig_param_iter.next();
    }
 
    /* Since we're unlinked, we don't (necessarily) know the side effects of
index a140ed335e029b294c8043a3dfdcc013d9613137..9649598dd2befc06ec36e1c85f899d9d26c9ef93 100644 (file)
@@ -116,11 +116,10 @@ ir_call::generate_inline(ir_instruction *next_ir)
     * and set up the mapping of real function body variables to ours.
     */
    i = 0;
-   exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
-   exec_list_iterator param_iter = this->actual_parameters.iterator();
-   for (i = 0; i < num_parameters; i++) {
-      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
-      ir_rvalue *param = (ir_rvalue *) param_iter.get();
+   foreach_two_lists(formal_node, &this->callee->parameters,
+                     actual_node, &this->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *) formal_node;
+      ir_rvalue *param = (ir_rvalue *) actual_node;
 
       /* Generate a new variable for the parameter. */
       if (sig_param->type->contains_opaque()) {
@@ -154,8 +153,7 @@ ir_call::generate_inline(ir_instruction *next_ir)
         next_ir->insert_before(assign);
       }
 
-      sig_param_iter.next();
-      param_iter.next();
+      ++i;
    }
 
    exec_list new_instructions;
@@ -172,11 +170,10 @@ ir_call::generate_inline(ir_instruction *next_ir)
    /* If any opaque types were passed in, replace any deref of the
     * opaque variable with a deref of the argument.
     */
-   param_iter = this->actual_parameters.iterator();
-   sig_param_iter = this->callee->parameters.iterator();
-   for (i = 0; i < num_parameters; i++) {
-      ir_rvalue *const param = (ir_rvalue *) param_iter.get();
-      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
+   foreach_two_lists(formal_node, &this->callee->parameters,
+                     actual_node, &this->actual_parameters) {
+      ir_rvalue *const param = (ir_rvalue *) actual_node;
+      ir_variable *sig_param = (ir_variable *) formal_node;
 
       if (sig_param->type->contains_opaque()) {
         ir_dereference *deref = param->as_dereference();
@@ -184,8 +181,6 @@ ir_call::generate_inline(ir_instruction *next_ir)
         assert(deref);
         do_variable_replacement(&new_instructions, sig_param, deref);
       }
-      param_iter.next();
-      sig_param_iter.next();
    }
 
    /* Now push those new instructions in. */
@@ -195,11 +190,10 @@ ir_call::generate_inline(ir_instruction *next_ir)
     * variables to our own.
     */
    i = 0;
-   param_iter = this->actual_parameters.iterator();
-   sig_param_iter = this->callee->parameters.iterator();
-   for (i = 0; i < num_parameters; i++) {
-      ir_rvalue *const param = (ir_rvalue *) param_iter.get();
-      const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
+   foreach_two_lists(formal_node, &this->callee->parameters,
+                     actual_node, &this->actual_parameters) {
+      ir_rvalue *const param = (ir_rvalue *) actual_node;
+      const ir_variable *const sig_param = (ir_variable *) formal_node;
 
       /* Move our param variable into the actual param if it's an 'out' type. */
       if (parameters[i] && (sig_param->data.mode == ir_var_function_out ||
@@ -212,8 +206,7 @@ ir_call::generate_inline(ir_instruction *next_ir)
         next_ir->insert_before(assign);
       }
 
-      param_iter.next();
-      sig_param_iter.next();
+      ++i;
    }
 
    delete [] parameters;
index 6d75a157383d934a5dd87d29c45252f488a451ba..f3bd580af19d64495ddc982eb4ceba6c30bc750c 100644 (file)
@@ -204,11 +204,10 @@ ir_tree_grafting_visitor::visit_enter(ir_function_signature *ir)
 ir_visitor_status
 ir_tree_grafting_visitor::visit_enter(ir_call *ir)
 {
-   exec_list_iterator sig_iter = ir->callee->parameters.iterator();
-   /* Reminder: iterating ir_call iterates its parameters. */
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_variable *sig_param = (ir_variable *)sig_iter.get();
-      ir_rvalue *ir = (ir_rvalue *)iter.get();
+   foreach_two_lists(formal_node, &ir->callee->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_variable *sig_param = (ir_variable *) formal_node;
+      ir_rvalue *ir = (ir_rvalue *) actual_node;
       ir_rvalue *new_ir = ir;
 
       if (sig_param->data.mode != ir_var_function_in
@@ -222,7 +221,6 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir)
         ir->replace_with(new_ir);
         return visit_stop;
       }
-      sig_iter.next();
    }
 
    if (ir->return_deref && check_graft(ir, ir->return_deref->var) == visit_stop)
index ed3715fc16ef11ae3329d7adf04f5929f7c44a8d..f1b35442969e9ce801133dd28755039cebd46be9 100644 (file)
@@ -2617,10 +2617,10 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
    int i;
 
    /* Process in parameters. */
-   exec_list_iterator sig_iter = sig->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-      ir_variable *param = (ir_variable *)sig_iter.get();
+   foreach_two_lists(formal_node, &sig->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+      ir_variable *param = (ir_variable *) formal_node;
 
       if (param->data.mode == ir_var_function_in ||
           param->data.mode == ir_var_function_inout) {
@@ -2643,20 +2643,17 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
             r.index++;
          }
       }
-
-      sig_iter.next();
    }
-   assert(!sig_iter.has_next());
 
    /* Emit call instruction */
    call_inst = emit(ir, TGSI_OPCODE_CAL);
    call_inst->function = entry;
 
    /* Process out parameters. */
-   sig_iter = sig->parameters.iterator();
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
-      ir_variable *param = (ir_variable *)sig_iter.get();
+   foreach_two_lists(formal_node, &sig->parameters,
+                     actual_node, &ir->actual_parameters) {
+      ir_rvalue *param_rval = (ir_rvalue *) actual_node;
+      ir_variable *param = (ir_variable *) formal_node;
 
       if (param->data.mode == ir_var_function_out ||
           param->data.mode == ir_var_function_inout) {
@@ -2679,10 +2676,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
             r.index++;
          }
       }
-
-      sig_iter.next();
    }
-   assert(!sig_iter.has_next());
 
    /* Process return value. */
    this->result = entry->return_reg;