ir_to_mesa: Support texture rectangle targets
[mesa/nouveau-pmpeg.git] / src / glsl / ir_constant_folding.cpp
blob11260423d90b81ccb0dc7669f7332b502509b6a4
1 /*
2 * Copyright © 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /**
25 * \file ir_constant_folding.cpp
26 * Replace constant-valued expressions with references to constant values.
29 #include "ir.h"
30 #include "ir_visitor.h"
31 #include "ir_optimization.h"
32 #include "glsl_types.h"
34 /**
35 * Visitor class for replacing expressions with ir_constant values.
38 class ir_constant_folding_visitor : public ir_visitor {
39 public:
40 ir_constant_folding_visitor()
42 this->progress = false;
45 virtual ~ir_constant_folding_visitor()
47 /* empty */
50 /**
51 * \name Visit methods
53 * As typical for the visitor pattern, there must be one \c visit method for
54 * each concrete subclass of \c ir_instruction. Virtual base classes within
55 * the hierarchy should not have \c visit methods.
57 /*@{*/
58 virtual void visit(ir_variable *);
59 virtual void visit(ir_function_signature *);
60 virtual void visit(ir_function *);
61 virtual void visit(ir_expression *);
62 virtual void visit(ir_texture *);
63 virtual void visit(ir_swizzle *);
64 virtual void visit(ir_dereference_variable *);
65 virtual void visit(ir_dereference_array *);
66 virtual void visit(ir_dereference_record *);
67 virtual void visit(ir_assignment *);
68 virtual void visit(ir_constant *);
69 virtual void visit(ir_call *);
70 virtual void visit(ir_return *);
71 virtual void visit(ir_discard *);
72 virtual void visit(ir_if *);
73 virtual void visit(ir_loop *);
74 virtual void visit(ir_loop_jump *);
75 /*@}*/
77 void fold_constant(ir_rvalue **rvalue);
79 bool progress;
82 void
83 ir_constant_folding_visitor::fold_constant(ir_rvalue **rvalue)
85 if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
86 return;
88 ir_constant *constant = (*rvalue)->constant_expression_value();
89 if (constant) {
90 *rvalue = constant;
91 this->progress = true;
92 } else {
93 (*rvalue)->accept(this);
97 void
98 ir_constant_folding_visitor::visit(ir_variable *ir)
100 (void) ir;
104 void
105 ir_constant_folding_visitor::visit(ir_function_signature *ir)
107 visit_exec_list(&ir->body, this);
111 void
112 ir_constant_folding_visitor::visit(ir_function *ir)
114 foreach_iter(exec_list_iterator, iter, *ir) {
115 ir_function_signature *const sig = (ir_function_signature *) iter.get();
116 sig->accept(this);
120 void
121 ir_constant_folding_visitor::visit(ir_expression *ir)
123 unsigned int operand;
125 for (operand = 0; operand < ir->get_num_operands(); operand++) {
126 fold_constant(&ir->operands[operand]);
131 void
132 ir_constant_folding_visitor::visit(ir_texture *ir)
134 fold_constant(&ir->coordinate);
135 fold_constant(&ir->projector);
136 fold_constant(&ir->shadow_comparitor);
138 switch (ir->op) {
139 case ir_tex:
140 break;
141 case ir_txb:
142 fold_constant(&ir->lod_info.bias);
143 break;
144 case ir_txf:
145 case ir_txl:
146 fold_constant(&ir->lod_info.lod);
147 break;
148 case ir_txd:
149 fold_constant(&ir->lod_info.grad.dPdx);
150 fold_constant(&ir->lod_info.grad.dPdy);
151 break;
156 void
157 ir_constant_folding_visitor::visit(ir_swizzle *ir)
159 fold_constant(&ir->val);
163 void
164 ir_constant_folding_visitor::visit(ir_dereference_variable *ir)
166 (void) ir;
170 void
171 ir_constant_folding_visitor::visit(ir_dereference_array *ir)
173 fold_constant(&ir->array_index);
174 ir->array->accept(this);
178 void
179 ir_constant_folding_visitor::visit(ir_dereference_record *ir)
181 ir->record->accept(this);
185 void
186 ir_constant_folding_visitor::visit(ir_assignment *ir)
188 fold_constant(&ir->rhs);
190 if (ir->condition) {
191 /* If the condition is constant, either remove the condition or
192 * remove the never-executed assignment.
194 ir_constant *const_val = ir->condition->constant_expression_value();
195 if (const_val) {
196 if (const_val->value.b[0])
197 ir->condition = NULL;
198 else
199 ir->remove();
200 this->progress = true;
206 void
207 ir_constant_folding_visitor::visit(ir_constant *ir)
209 (void) ir;
213 void
214 ir_constant_folding_visitor::visit(ir_call *ir)
216 foreach_iter(exec_list_iterator, iter, *ir) {
217 ir_rvalue *param = (ir_rvalue *)iter.get();
218 ir_rvalue *new_param = param;
219 fold_constant(&new_param);
221 if (new_param != param) {
222 param->replace_with(new_param);
228 void
229 ir_constant_folding_visitor::visit(ir_return *ir)
231 fold_constant(&ir->value);
235 void
236 ir_constant_folding_visitor::visit(ir_discard *ir)
238 (void) ir;
242 void
243 ir_constant_folding_visitor::visit(ir_if *ir)
245 fold_constant(&ir->condition);
247 visit_exec_list(&ir->then_instructions, this);
248 visit_exec_list(&ir->else_instructions, this);
252 void
253 ir_constant_folding_visitor::visit(ir_loop *ir)
255 (void) ir;
259 void
260 ir_constant_folding_visitor::visit(ir_loop_jump *ir)
262 (void) ir;
265 bool
266 do_constant_folding(exec_list *instructions)
268 ir_constant_folding_visitor constant_folding;
270 visit_exec_list(instructions, &constant_folding);
272 return constant_folding.progress;