Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright © 2013 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
#include "ir.h"
24
#include "ir_builder.h"
25
#include "ir_rvalue_visitor.h"
26
#include "ir_optimization.h"
27
 
28
using namespace ir_builder;
29
 
30
class vector_insert_visitor : public ir_rvalue_visitor {
31
public:
32
   vector_insert_visitor(bool lower_nonconstant_index)
33
      : progress(false), lower_nonconstant_index(lower_nonconstant_index)
34
   {
35
      factory.instructions = &factory_instructions;
36
   }
37
 
38
   virtual ~vector_insert_visitor()
39
   {
40
      assert(factory_instructions.is_empty());
41
   }
42
 
43
   virtual void handle_rvalue(ir_rvalue **rv);
44
 
45
   ir_factory factory;
46
   exec_list factory_instructions;
47
   bool progress;
48
   bool lower_nonconstant_index;
49
};
50
 
51
 
52
void
53
vector_insert_visitor::handle_rvalue(ir_rvalue **rv)
54
{
55
   if (*rv == NULL || (*rv)->ir_type != ir_type_expression)
56
      return;
57
 
58
   ir_expression *const expr = (ir_expression *) *rv;
59
 
60
   if (likely(expr->operation != ir_triop_vector_insert))
61
      return;
62
 
63
   factory.mem_ctx = ralloc_parent(expr);
64
 
65
   ir_constant *const idx = expr->operands[2]->constant_expression_value();
66
   if (idx != NULL) {
67
      /* Replace (vector_insert (vec) (scalar) (index)) with a dereference of
68
       * a new temporary.  The new temporary gets assigned as
69
       *
70
       *     t = vec
71
       *     t.mask = scalar
72
       *
73
       * where mask is the component selected by index.
74
       */
75
      ir_variable *const temp =
76
         factory.make_temp(expr->operands[0]->type, "vec_tmp");
77
 
78
      const int mask = 1 << idx->value.i[0];
79
 
80
      factory.emit(assign(temp, expr->operands[0]));
81
      factory.emit(assign(temp, expr->operands[1], mask));
82
 
83
      this->progress = true;
84
      *rv = new(factory.mem_ctx) ir_dereference_variable(temp);
85
   } else if (this->lower_nonconstant_index) {
86
      /* Replace (vector_insert (vec) (scalar) (index)) with a dereference of
87
       * a new temporary.  The new temporary gets assigned as
88
       *
89
       *     t = vec
90
       *     if (index == 0)
91
       *         t.x = scalar
92
       *     if (index == 1)
93
       *         t.y = scalar
94
       *     if (index == 2)
95
       *         t.z = scalar
96
       *     if (index == 3)
97
       *         t.w = scalar
98
       */
99
      ir_variable *const temp =
100
         factory.make_temp(expr->operands[0]->type, "vec_tmp");
101
 
102
      ir_variable *const src_temp =
103
         factory.make_temp(expr->operands[1]->type, "src_temp");
104
 
105
      factory.emit(assign(temp, expr->operands[0]));
106
      factory.emit(assign(src_temp, expr->operands[1]));
107
 
108
      for (unsigned i = 0; i < expr->type->vector_elements; i++) {
109
         ir_constant *const cmp_index =
110
            new(factory.mem_ctx) ir_constant(int(i));
111
 
112
         ir_variable *const cmp_result =
113
            factory.make_temp(glsl_type::bool_type, "index_condition");
114
 
115
         factory.emit(assign(cmp_result,
116
                             equal(expr->operands[2]->clone(factory.mem_ctx,
117
                                                            NULL),
118
                                   cmp_index)));
119
 
120
         factory.emit(if_tree(cmp_result,
121
                              assign(temp, src_temp, WRITEMASK_X << i)));
122
      }
123
 
124
      this->progress = true;
125
      *rv = new(factory.mem_ctx) ir_dereference_variable(temp);
126
   }
127
 
128
   base_ir->insert_before(factory.instructions);
129
}
130
 
131
bool
132
lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index)
133
{
134
   vector_insert_visitor v(lower_nonconstant_index);
135
 
136
   visit_list_elements(&v, instructions);
137
 
138
   return v.progress;
139
}