1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file lower_if_to_cond_assign.cpp
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This attempts to flatten if-statements to conditional assignments for
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GPUs with limited or no flow control support.
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * It can't handle other control flow being inside of its block, such
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * as calls or loops.  Hopefully loop unrolling and inlining will take
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * care of those.
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Drivers for GPUs with no control flow support should simply call
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    lower_if_to_cond_assign(instructions)
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to attempt to flatten all if-statements.
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Some GPUs (such as i965 prior to gen6) do support control flow, but have a
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * maximum nesting depth N.  Drivers for such hardware can call
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    lower_if_to_cond_assign(instructions, N)
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to attempt to flatten any if-statements appearing at depth > N.
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_types.h"
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h"
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program/hash_table.h"
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_if_to_cond_assign_visitor : public ir_hierarchical_visitor {
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_if_to_cond_assign_visitor(unsigned max_depth)
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->progress = false;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->max_depth = max_depth;
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->depth = 0;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->condition_variables = hash_table_ctor(0, hash_table_pointer_hash,
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						  hash_table_pointer_compare);
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ~ir_if_to_cond_assign_visitor()
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hash_table_dtor(this->condition_variables);
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_visitor_status visit_enter(ir_if *);
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_visitor_status visit_leave(ir_if *);
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool progress;
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned max_depth;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned depth;
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct hash_table *condition_variables;
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglower_if_to_cond_assign(exec_list *instructions, unsigned max_depth)
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (max_depth == UINT_MAX)
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_if_to_cond_assign_visitor v(max_depth);
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_list_elements(&v, instructions);
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return v.progress;
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcheck_control_flow(ir_instruction *ir, void *data)
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool *found_control_flow = (bool *)data;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (ir->ir_type) {
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_type_call:
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_type_discard:
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_type_loop:
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_type_loop_jump:
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_type_return:
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *found_control_flow = true;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmove_block_to_cond_assign(void *mem_ctx,
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  ir_if *if_ir, ir_rvalue *cond_expr,
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  exec_list *instructions,
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			  struct hash_table *ht)
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list_safe(node, instructions) {
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *ir = (ir_instruction *) node;
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ir->ir_type == ir_type_assignment) {
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_assignment *assign = (ir_assignment *)ir;
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (hash_table_find(ht, assign) == NULL) {
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    hash_table_insert(ht, assign, assign);
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* If the LHS of the assignment is a condition variable that was
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * previously added, insert an additional assignment of false to
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * the variable.
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    const bool assign_to_cv =
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       hash_table_find(ht, assign->lhs->variable_referenced()) != NULL;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (!assign->condition) {
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (assign_to_cv) {
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  assign->rhs =
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     new(mem_ctx) ir_expression(ir_binop_logic_and,
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						glsl_type::bool_type,
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						cond_expr->clone(mem_ctx, NULL),
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						assign->rhs);
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       } else {
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  assign->condition = cond_expr->clone(mem_ctx, NULL);
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    } else {
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       assign->condition =
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  new(mem_ctx) ir_expression(ir_binop_logic_and,
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					     glsl_type::bool_type,
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					     cond_expr->clone(mem_ctx, NULL),
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					     assign->condition);
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Now, move from the if block to the block surrounding it. */
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir->remove();
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if_ir->insert_before(ir);
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_if_to_cond_assign_visitor::visit_enter(ir_if *ir)
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   (void) ir;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->depth++;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Only flatten when beyond the GPU's maximum supported nesting depth. */
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->depth-- <= this->max_depth)
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue;
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool found_control_flow = false;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_assignment *assign;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Check that both blocks don't contain anything we can't support. */
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, then_iter, ir->then_instructions) {
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *then_ir = (ir_instruction *)then_iter.get();
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      visit_tree(then_ir, check_control_flow, &found_control_flow);
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, else_iter, ir->else_instructions) {
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *else_ir = (ir_instruction *)else_iter.get();
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      visit_tree(else_ir, check_control_flow, &found_control_flow);
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (found_control_flow)
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *mem_ctx = ralloc_parent(ir);
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Store the condition to a variable.  Move all of the instructions from
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * the then-clause of the if-statement.  Use the condition variable as a
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * condition for all assignments.
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_variable *const then_var =
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      new(mem_ctx) ir_variable(glsl_type::bool_type,
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "if_to_cond_assign_then",
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       ir_var_temporary);
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir->insert_before(then_var);
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *then_cond =
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      new(mem_ctx) ir_dereference_variable(then_var);
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assign = new(mem_ctx) ir_assignment(then_cond, ir->condition);
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir->insert_before(assign);
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   move_block_to_cond_assign(mem_ctx, ir, then_cond,
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     &ir->then_instructions,
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     this->condition_variables);
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Add the new condition variable to the hash table.  This allows us to
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * find this variable when lowering other (enclosing) if-statements.
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   hash_table_insert(this->condition_variables, then_var, then_var);
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* If there are instructions in the else-clause, store the inverse of the
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * condition to a variable.  Move all of the instructions from the
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * else-clause if the if-statement.  Use the (inverse) condition variable
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * as a condition for all assignments.
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!ir->else_instructions.is_empty()) {
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const else_var =
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 new(mem_ctx) ir_variable(glsl_type::bool_type,
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  "if_to_cond_assign_else",
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  ir_var_temporary);
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir->insert_before(else_var);
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_dereference_variable *else_cond =
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 new(mem_ctx) ir_dereference_variable(else_var);
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *inverse =
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 new(mem_ctx) ir_expression(ir_unop_logic_not,
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    then_cond->clone(mem_ctx, NULL));
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assign = new(mem_ctx) ir_assignment(else_cond, inverse);
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir->insert_before(assign);
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      move_block_to_cond_assign(mem_ctx, ir, else_cond,
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				&ir->else_instructions,
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				this->condition_variables);
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Add the new condition variable to the hash table.  This allows us to
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * find this variable when lowering other (enclosing) if-statements.
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hash_table_insert(this->condition_variables, else_var, else_var);
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir->remove();
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->progress = true;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
253