lower_vec_index_to_swizzle.cpp revision b145e903694fa932ab1e0d955e889555193ab604
1/*
2 * Copyright © 2010 Intel Corporation
3 *
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:
10 *
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.
14 *
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.
22 */
23
24/**
25 * \file ir_vec_index_to_swizzle.cpp
26 *
27 * Turns constant indexing into vector types to swizzles.  This will
28 * let other swizzle-aware optimization passes catch these constructs,
29 * and codegen backends not have to worry about this case.
30 */
31
32#include <stdio.h>
33#include "ir.h"
34#include "ir_visitor.h"
35#include "ir_optimization.h"
36#include "ir_print_visitor.h"
37#include "glsl_types.h"
38
39/**
40 * Visitor class for replacing expressions with ir_constant values.
41 */
42
43class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor {
44public:
45   ir_vec_index_to_swizzle_visitor()
46   {
47      progress = false;
48   }
49
50   ir_rvalue *convert_vec_index_to_swizzle(ir_rvalue *val);
51
52   virtual ir_visitor_status visit_enter(ir_expression *);
53   virtual ir_visitor_status visit_enter(ir_swizzle *);
54   virtual ir_visitor_status visit_enter(ir_assignment *);
55   virtual ir_visitor_status visit_enter(ir_return *);
56   virtual ir_visitor_status visit_enter(ir_call *);
57   virtual ir_visitor_status visit_enter(ir_if *);
58
59   bool progress;
60};
61
62ir_rvalue *
63ir_vec_index_to_swizzle_visitor::convert_vec_index_to_swizzle(ir_rvalue *ir)
64{
65   ir_dereference_array *deref = ir->as_dereference_array();
66   ir_constant *ir_constant;
67   ir_rvalue *deref_var;
68
69   if (!deref)
70      return ir;
71
72   if (deref->array->type->is_matrix() || deref->array->type->is_array())
73      return ir;
74
75   deref_var = deref->array->as_rvalue();
76   if (!deref_var) {
77      ir_variable *var = deref->array->as_variable();
78      assert(var);
79      deref_var = new ir_dereference_variable(var);
80   }
81
82   assert(deref->array_index->type->base_type == GLSL_TYPE_INT);
83   ir_constant = deref->array_index->constant_expression_value();
84   if (!ir_constant)
85      return ir;
86
87   this->progress = true;
88   return new ir_swizzle(deref_var, ir_constant->value.i[0], 0, 0, 0, 1);
89}
90
91ir_visitor_status
92ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir)
93{
94   unsigned int i;
95
96   for (i = 0; i < ir->get_num_operands(); i++) {
97      ir->operands[i] = convert_vec_index_to_swizzle(ir->operands[i]);
98   }
99
100   return visit_continue;
101}
102
103ir_visitor_status
104ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir)
105{
106   /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
107    * the result of indexing a vector is.  But maybe at some point we'll end up
108    * using swizzling of scalars for vector construction.
109    */
110   ir->val = convert_vec_index_to_swizzle(ir->val);
111
112   return visit_continue;
113}
114
115ir_visitor_status
116ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir)
117{
118   ir->lhs = convert_vec_index_to_swizzle(ir->lhs);
119   ir->rhs = convert_vec_index_to_swizzle(ir->rhs);
120
121   return visit_continue;
122}
123
124ir_visitor_status
125ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir)
126{
127   foreach_iter(exec_list_iterator, iter, *ir) {
128      ir_rvalue *param = (ir_rvalue *)iter.get();
129      ir_rvalue *new_param = convert_vec_index_to_swizzle(param);
130
131      if (new_param != param) {
132	 param->insert_before(new_param);
133	 param->remove();
134      }
135   }
136
137   return visit_continue;
138}
139
140ir_visitor_status
141ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir)
142{
143   if (ir->value) {
144      ir->value = convert_vec_index_to_swizzle(ir->value);
145   }
146
147   return visit_continue;
148}
149
150ir_visitor_status
151ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir)
152{
153   ir->condition = convert_vec_index_to_swizzle(ir->condition);
154
155   return visit_continue;
156}
157
158bool
159do_vec_index_to_swizzle(exec_list *instructions)
160{
161   ir_vec_index_to_swizzle_visitor v;
162
163   v.run(instructions);
164
165   return false;
166}
167