Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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 lower_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 "ir.h"
33
#include "ir_visitor.h"
34
#include "ir_optimization.h"
35
#include "glsl_types.h"
36
#include "main/macros.h"
37
 
38
/**
39
 * Visitor class for replacing expressions with ir_constant values.
40
 */
41
 
42
namespace {
43
 
44
class ir_vec_index_to_swizzle_visitor : public ir_hierarchical_visitor {
45
public:
46
   ir_vec_index_to_swizzle_visitor()
47
   {
48
      progress = false;
49
   }
50
 
51
   ir_rvalue *convert_vector_extract_to_swizzle(ir_rvalue *val);
52
 
53
   virtual ir_visitor_status visit_enter(ir_expression *);
54
   virtual ir_visitor_status visit_enter(ir_swizzle *);
55
   virtual ir_visitor_status visit_enter(ir_assignment *);
56
   virtual ir_visitor_status visit_enter(ir_return *);
57
   virtual ir_visitor_status visit_enter(ir_call *);
58
   virtual ir_visitor_status visit_enter(ir_if *);
59
 
60
   bool progress;
61
};
62
 
63
} /* anonymous namespace */
64
 
65
ir_rvalue *
66
ir_vec_index_to_swizzle_visitor::convert_vector_extract_to_swizzle(ir_rvalue *ir)
67
{
68
   ir_expression *const expr = ir->as_expression();
69
   if (expr == NULL || expr->operation != ir_binop_vector_extract)
70
      return ir;
71
 
72
   ir_constant *const idx = expr->operands[1]->constant_expression_value();
73
   if (idx == NULL)
74
      return ir;
75
 
76
   void *ctx = ralloc_parent(ir);
77
   this->progress = true;
78
 
79
   /* Page 40 of the GLSL 1.20 spec says:
80
    *
81
    *     "When indexing with non-constant expressions, behavior is undefined
82
    *     if the index is negative, or greater than or equal to the size of
83
    *     the vector."
84
    *
85
    * The quoted spec text mentions non-constant expressions, but this code
86
    * operates on constants.  These constants are the result of non-constant
87
    * expressions that have been optimized to constants.  The common case here
88
    * is a loop counter from an unrolled loop that is used to index a vector.
89
    *
90
    * The ir_swizzle constructor gets angry if the index is negative or too
91
    * large.  For simplicity sake, just clamp the index to [0, size-1].
92
    */
93
   const int i = CLAMP(idx->value.i[0], 0,
94
                       (int) expr->operands[0]->type->vector_elements - 1);
95
 
96
   return new(ctx) ir_swizzle(expr->operands[0], i, 0, 0, 0, 1);
97
}
98
 
99
ir_visitor_status
100
ir_vec_index_to_swizzle_visitor::visit_enter(ir_expression *ir)
101
{
102
   unsigned int i;
103
 
104
   for (i = 0; i < ir->get_num_operands(); i++) {
105
      ir->operands[i] = convert_vector_extract_to_swizzle(ir->operands[i]);
106
   }
107
 
108
   return visit_continue;
109
}
110
 
111
ir_visitor_status
112
ir_vec_index_to_swizzle_visitor::visit_enter(ir_swizzle *ir)
113
{
114
   /* Can't be hit from normal GLSL, since you can't swizzle a scalar (which
115
    * the result of indexing a vector is.  But maybe at some point we'll end up
116
    * using swizzling of scalars for vector construction.
117
    */
118
   ir->val = convert_vector_extract_to_swizzle(ir->val);
119
 
120
   return visit_continue;
121
}
122
 
123
ir_visitor_status
124
ir_vec_index_to_swizzle_visitor::visit_enter(ir_assignment *ir)
125
{
126
   ir->rhs = convert_vector_extract_to_swizzle(ir->rhs);
127
 
128
   return visit_continue;
129
}
130
 
131
ir_visitor_status
132
ir_vec_index_to_swizzle_visitor::visit_enter(ir_call *ir)
133
{
134
   foreach_in_list_safe(ir_rvalue, param, &ir->actual_parameters) {
135
      ir_rvalue *new_param = convert_vector_extract_to_swizzle(param);
136
 
137
      if (new_param != param) {
138
	 param->replace_with(new_param);
139
      }
140
   }
141
 
142
   return visit_continue;
143
}
144
 
145
ir_visitor_status
146
ir_vec_index_to_swizzle_visitor::visit_enter(ir_return *ir)
147
{
148
   if (ir->value) {
149
      ir->value = convert_vector_extract_to_swizzle(ir->value);
150
   }
151
 
152
   return visit_continue;
153
}
154
 
155
ir_visitor_status
156
ir_vec_index_to_swizzle_visitor::visit_enter(ir_if *ir)
157
{
158
   ir->condition = convert_vector_extract_to_swizzle(ir->condition);
159
 
160
   return visit_continue;
161
}
162
 
163
bool
164
do_vec_index_to_swizzle(exec_list *instructions)
165
{
166
   ir_vec_index_to_swizzle_visitor v;
167
 
168
   v.run(instructions);
169
 
170
   return v.progress;
171
}