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 * constant 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, constant, 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 constantright 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 CONSTANTRIGHT 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 opt_constant_propagation.cpp
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Tracks assignments of constants to channels of variables, and
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * usage of those constant channels with direct usage of the constants.
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This can lead to constant folding and algebraic optimizations in
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * those later expressions, while causing no increase in instruction
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * count (due to constants being generally free to load from a
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * constant push buffer or as instruction immediate values) and
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * possibly reducing register pressure.
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_visitor.h"
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_rvalue_visitor.h"
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_basic_block.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_optimization.h"
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_types.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace {
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass acp_entry : public exec_node
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   acp_entry(ir_variable *var, unsigned write_mask, ir_constant *constant)
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(var);
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(constant);
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->var = var;
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->write_mask = write_mask;
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->constant = constant;
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->initial_values = write_mask;
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   acp_entry(const acp_entry *src)
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->var = src->var;
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->write_mask = src->write_mask;
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->constant = src->constant;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->initial_values = src->initial_values;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_variable *var;
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant *constant;
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned write_mask;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /** Mask of values initially available in the constant. */
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned initial_values;
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass kill_entry : public exec_node
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   kill_entry(ir_variable *var, unsigned write_mask)
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(var);
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->var = var;
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->write_mask = write_mask;
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_variable *var;
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned write_mask;
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_constant_propagation_visitor : public ir_rvalue_visitor {
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant_propagation_visitor()
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      progress = false;
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      killed_all = false;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      mem_ctx = ralloc_context(0);
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->acp = new(mem_ctx) exec_list;
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->kills = new(mem_ctx) exec_list;
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ~ir_constant_propagation_visitor()
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ralloc_free(mem_ctx);
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_loop *);
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_function_signature *);
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_function *);
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_leave(class ir_assignment *);
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_call *);
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(class ir_if *);
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void add_constant(ir_assignment *ir);
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void kill(ir_variable *ir, unsigned write_mask);
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void handle_if_block(exec_list *instructions);
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void handle_rvalue(ir_rvalue **rvalue);
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /** List of acp_entry: The available constants to propagate */
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *acp;
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * List of kill_entry: The masks of variables whose values were
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * killed in this block.
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *kills;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool progress;
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool killed_all;
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *mem_ctx;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::handle_rvalue(ir_rvalue **rvalue)
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->in_assignee || !*rvalue)
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const glsl_type *type = (*rvalue)->type;
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!type->is_scalar() && !type->is_vector())
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_swizzle *swiz = NULL;
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!deref) {
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      swiz = (*rvalue)->as_swizzle();
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!swiz)
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      deref = swiz->val->as_dereference_variable();
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!deref)
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant_data data;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&data, 0, sizeof(data));
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned int i = 0; i < type->components(); i++) {
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int channel;
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      acp_entry *found = NULL;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (swiz) {
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 switch (i) {
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case 0: channel = swiz->mask.x; break;
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case 1: channel = swiz->mask.y; break;
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case 2: channel = swiz->mask.z; break;
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 case 3: channel = swiz->mask.w; break;
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 default: assert(!"shouldn't be reached"); channel = 0; break;
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 channel = i;
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_iter(exec_list_iterator, iter, *this->acp) {
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 acp_entry *entry = (acp_entry *)iter.get();
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (entry->var == deref->var && entry->write_mask & (1 << channel)) {
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    found = entry;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!found)
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int rhs_channel = 0;
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (int j = 0; j < 4; j++) {
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (j == channel)
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (found->initial_values & (1 << j))
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    rhs_channel++;
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (type->base_type) {
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GLSL_TYPE_FLOAT:
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 data.f[i] = found->constant->value.f[rhs_channel];
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GLSL_TYPE_INT:
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 data.i[i] = found->constant->value.i[rhs_channel];
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GLSL_TYPE_UINT:
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 data.u[i] = found->constant->value.u[rhs_channel];
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GLSL_TYPE_BOOL:
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 data.b[i] = found->constant->value.b[rhs_channel];
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 assert(!"not reached");
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *rvalue = new(ralloc_parent(deref)) ir_constant(type, &data);
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->progress = true;
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_enter(ir_function_signature *ir)
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Treat entry into a function signature as a completely separate
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * block.  Any instructions at global scope will be shuffled into
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * main() at link time, so they're irrelevant to us.
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_acp = this->acp;
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_kills = this->kills;
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool orig_killed_all = this->killed_all;
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = new(mem_ctx) exec_list;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = new(mem_ctx) exec_list;
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = false;
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_list_elements(this, &ir->body);
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = orig_kills;
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = orig_acp;
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = orig_killed_all;
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue_with_parent;
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_leave(ir_assignment *ir)
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->in_assignee)
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue;
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned kill_mask = ir->write_mask;
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ir->lhs->as_dereference_array()) {
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* The LHS of the assignment uses an array indexing operator (e.g. v[i]
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * = ...;).  Since we only try to constant propagate vectors and
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * scalars, this means that either (a) array indexing is being used to
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * select a vector component, or (b) the variable in question is neither
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * a scalar or a vector, so we don't care about it.  In the former case,
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * we want to kill the whole vector, since in general we can't predict
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * which vector component will be selected by array indexing.  In the
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * latter case, it doesn't matter what we do, so go ahead and kill the
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * whole variable anyway.
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * Note that if the array index is constant (e.g. v[2] = ...;), we could
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * in principle be smarter, but we don't need to, because a future
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * optimization pass will convert it to a simple assignment with the
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * correct mask.
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill_mask = ~0;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   kill(ir->lhs->variable_referenced(), kill_mask);
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   add_constant(ir);
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue;
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_enter(ir_function *ir)
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   (void) ir;
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue;
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_enter(ir_call *ir)
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Do constant propagation on call parameters, but skip any out params */
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list_iterator sig_param_iter = ir->callee->parameters.iterator();
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, ir->actual_parameters) {
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *sig_param = (ir_variable *)sig_param_iter.get();
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_rvalue *param = (ir_rvalue *)iter.get();
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sig_param->mode != ir_var_out && sig_param->mode != ir_var_inout) {
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_rvalue *new_param = param;
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 handle_rvalue(&new_param);
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (new_param != param)
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    param->replace_with(new_param);
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 else
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    param->accept(this);
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      sig_param_iter.next();
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Since we're unlinked, we don't (necssarily) know the side effects of
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * this call.  So kill all copies.
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   acp->make_empty();
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = true;
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue_with_parent;
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::handle_if_block(exec_list *instructions)
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_acp = this->acp;
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_kills = this->kills;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool orig_killed_all = this->killed_all;
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = new(mem_ctx) exec_list;
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = new(mem_ctx) exec_list;
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = false;
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Populate the initial acp with a constant of the original */
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, *orig_acp) {
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      acp_entry *a = (acp_entry *)iter.get();
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->acp->push_tail(new(this->mem_ctx) acp_entry(a));
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_list_elements(this, instructions);
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->killed_all) {
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      orig_acp->make_empty();
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *new_kills = this->kills;
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = orig_kills;
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = orig_acp;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = this->killed_all || orig_killed_all;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, *new_kills) {
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill_entry *k = (kill_entry *)iter.get();
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill(k->var, k->write_mask);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_enter(ir_if *ir)
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir->condition->accept(this);
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   handle_rvalue(&ir->condition);
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   handle_if_block(&ir->then_instructions);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   handle_if_block(&ir->else_instructions);
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* handle_if_block() already descended into the children. */
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue_with_parent;
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::visit_enter(ir_loop *ir)
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_acp = this->acp;
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *orig_kills = this->kills;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool orig_killed_all = this->killed_all;
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: For now, the initial acp for loops is totally empty.
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * We could go through once, then go through again with the acp
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * cloned minus the killed entries after the first run through.
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = new(mem_ctx) exec_list;
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = new(mem_ctx) exec_list;
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = false;
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_list_elements(this, &ir->body_instructions);
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->killed_all) {
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      orig_acp->make_empty();
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_list *new_kills = this->kills;
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills = orig_kills;
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp = orig_acp;
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->killed_all = this->killed_all || orig_killed_all;
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, *new_kills) {
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill_entry *k = (kill_entry *)iter.get();
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill(k->var, k->write_mask);
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* already descended into the children. */
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return visit_continue_with_parent;
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::kill(ir_variable *var, unsigned write_mask)
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(var != NULL);
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* We don't track non-vectors. */
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!var->type->is_vector() && !var->type->is_scalar())
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Remove any entries currently in the ACP for this kill. */
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, *this->acp) {
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      acp_entry *entry = (acp_entry *)iter.get();
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (entry->var == var) {
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 entry->write_mask &= ~write_mask;
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (entry->write_mask == 0)
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    entry->remove();
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Add this writemask of the variable to the list of killed
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * variables in this block.
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_iter(exec_list_iterator, iter, *this->kills) {
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      kill_entry *entry = (kill_entry *)iter.get();
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (entry->var == var) {
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 entry->write_mask |= write_mask;
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return;
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Not already in the list.  Make new entry. */
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->kills->push_tail(new(this->mem_ctx) kill_entry(var, write_mask));
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Adds an entry to the available constant list if it's a plain assignment
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of a variable to a variable.
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_constant_propagation_visitor::add_constant(ir_assignment *ir)
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   acp_entry *entry;
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ir->condition)
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!ir->write_mask)
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_dereference_variable *deref = ir->lhs->as_dereference_variable();
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant *constant = ir->rhs->as_constant();
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!deref || !constant)
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Only do constant propagation on vectors.  Constant matrices,
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * arrays, or structures would require more work elsewhere.
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!deref->var->type->is_vector() && !deref->var->type->is_scalar())
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   entry = new(this->mem_ctx) acp_entry(deref->var, ir->write_mask, constant);
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->acp->push_tail(entry);
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} /* unnamed namespace */
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Does a constant propagation pass on the code present in the instruction stream.
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo_constant_propagation(exec_list *instructions)
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_constant_propagation_visitor v;
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   visit_list_elements(&v, instructions);
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return v.progress;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
470