2 * Copyright © 2013 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
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.
23 #include <gtest/gtest.h>
24 #include "util/compiler.h"
25 #include "main/mtypes.h"
26 #include "main/macros.h"
28 #include "ir_builder.h"
30 using namespace ir_builder
;
32 namespace lower_64bit
{
33 void expand_source(ir_factory
&body
,
35 ir_variable
**expanded_src
);
37 ir_dereference_variable
*compact_destination(ir_factory
&body
,
38 const glsl_type
*type
,
39 ir_variable
*result
[4]);
41 ir_rvalue
*lower_op_to_function_call(ir_instruction
*base_ir
,
43 ir_function_signature
*callee
);
46 class expand_source
: public ::testing::Test
{
49 virtual void TearDown();
51 exec_list instructions
;
53 ir_variable
*expanded_src
[4];
58 expand_source::SetUp()
60 glsl_type_singleton_init_or_ref();
62 mem_ctx
= ralloc_context(NULL
);
64 memset(expanded_src
, 0, sizeof(expanded_src
));
65 instructions
.make_empty();
66 body
= new ir_factory(&instructions
, mem_ctx
);
70 expand_source::TearDown()
78 glsl_type_singleton_decref();
81 static ir_dereference_variable
*
82 create_variable(void *mem_ctx
, const glsl_type
*type
)
84 ir_variable
*var
= new(mem_ctx
) ir_variable(type
,
88 return new(mem_ctx
) ir_dereference_variable(var
);
91 static ir_expression
*
92 create_expression(void *mem_ctx
, const glsl_type
*type
)
94 return new(mem_ctx
) ir_expression(ir_unop_neg
,
95 create_variable(mem_ctx
, type
));
99 check_expanded_source(const glsl_type
*type
,
100 ir_variable
*expanded_src
[4])
102 const glsl_type
*const expanded_type
=
103 type
->base_type
== GLSL_TYPE_UINT64
104 ? glsl_type::uvec2_type
:glsl_type::ivec2_type
;
106 for (int i
= 0; i
< type
->vector_elements
; i
++) {
107 EXPECT_EQ(expanded_type
, expanded_src
[i
]->type
);
109 /* All elements that are part of the vector must be unique. */
110 for (int j
= i
- 1; j
>= 0; j
--) {
111 EXPECT_NE(expanded_src
[i
], expanded_src
[j
])
112 << " Element " << i
<< " is the same as element " << j
;
116 /* All elements that are not part of the vector must be the same as element
117 * 0. This is primarily for scalars (where every element is the same).
119 for (int i
= type
->vector_elements
; i
< 4; i
++) {
120 EXPECT_EQ(expanded_src
[0], expanded_src
[i
])
121 << " Element " << i
<< " should be the same as element 0";
126 check_instructions(exec_list
*instructions
,
127 const glsl_type
*type
,
128 const ir_instruction
*source
)
130 const glsl_type
*const expanded_type
=
131 type
->base_type
== GLSL_TYPE_UINT64
132 ? glsl_type::uvec2_type
: glsl_type::ivec2_type
;
134 const ir_expression_operation unpack_opcode
=
135 type
->base_type
== GLSL_TYPE_UINT64
136 ? ir_unop_unpack_uint_2x32
: ir_unop_unpack_int_2x32
;
140 /* The instruction list should contain IR to represent:
145 * tmp2 = unpackUint2x32(tmp1.x);
147 * tmp3 = unpackUint2x32(tmp1.y);
149 * tmp4 = unpackUint2x32(tmp1.z);
151 * tmp5 = unpackUint2x32(tmp1.w);
153 ASSERT_FALSE(instructions
->is_empty());
154 ir
= (ir_instruction
*) instructions
->pop_head();
155 ir_variable
*const tmp1
= ir
->as_variable();
156 EXPECT_EQ(ir_type_variable
, ir
->ir_type
);
157 EXPECT_EQ(type
, tmp1
->type
) <<
163 ASSERT_FALSE(instructions
->is_empty());
164 ir
= (ir_instruction
*) instructions
->pop_head();
165 ir_assignment
*const assign1
= ir
->as_assignment();
166 EXPECT_EQ(ir_type_assignment
, ir
->ir_type
);
167 ASSERT_NE((void *)0, assign1
);
168 EXPECT_EQ(tmp1
, assign1
->lhs
->variable_referenced());
169 EXPECT_EQ(source
, assign1
->rhs
);
171 for (unsigned i
= 0; i
< type
->vector_elements
; i
++) {
172 ASSERT_FALSE(instructions
->is_empty());
173 ir
= (ir_instruction
*) instructions
->pop_head();
174 ir_variable
*const tmp2
= ir
->as_variable();
175 EXPECT_EQ(ir_type_variable
, ir
->ir_type
);
176 EXPECT_EQ(expanded_type
, tmp2
->type
);
178 ASSERT_FALSE(instructions
->is_empty());
179 ir
= (ir_instruction
*) instructions
->pop_head();
180 ir_assignment
*const assign2
= ir
->as_assignment();
181 EXPECT_EQ(ir_type_assignment
, ir
->ir_type
);
182 ASSERT_NE((void *)0, assign2
);
183 EXPECT_EQ(tmp2
, assign2
->lhs
->variable_referenced());
184 ir_expression
*unpack
= assign2
->rhs
->as_expression();
185 ASSERT_NE((void *)0, unpack
);
186 EXPECT_EQ(unpack_opcode
, unpack
->operation
);
187 EXPECT_EQ(tmp1
, unpack
->operands
[0]->variable_referenced());
190 EXPECT_TRUE(instructions
->is_empty());
193 TEST_F(expand_source
, uint64_variable
)
195 const glsl_type
*const type
= glsl_type::uint64_t_type
;
196 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
198 lower_64bit::expand_source(*body
, deref
, expanded_src
);
200 check_expanded_source(type
, expanded_src
);
201 check_instructions(&instructions
, type
, deref
);
204 TEST_F(expand_source
, u64vec2_variable
)
206 const glsl_type
*const type
= glsl_type::u64vec2_type
;
207 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
209 lower_64bit::expand_source(*body
, deref
, expanded_src
);
211 check_expanded_source(type
, expanded_src
);
212 check_instructions(&instructions
, type
, deref
);
215 TEST_F(expand_source
, u64vec3_variable
)
217 const glsl_type
*const type
= glsl_type::u64vec3_type
;
219 /* Generate an operand that is a scalar variable dereference. */
220 ir_variable
*const var
= new(mem_ctx
) ir_variable(type
,
224 ir_dereference_variable
*const deref
=
225 new(mem_ctx
) ir_dereference_variable(var
);
227 lower_64bit::expand_source(*body
, deref
, expanded_src
);
229 check_expanded_source(type
, expanded_src
);
230 check_instructions(&instructions
, type
, deref
);
233 TEST_F(expand_source
, u64vec4_variable
)
235 const glsl_type
*const type
= glsl_type::u64vec4_type
;
236 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
238 lower_64bit::expand_source(*body
, deref
, expanded_src
);
240 check_expanded_source(type
, expanded_src
);
241 check_instructions(&instructions
, type
, deref
);
244 TEST_F(expand_source
, int64_variable
)
246 const glsl_type
*const type
= glsl_type::int64_t_type
;
247 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
249 lower_64bit::expand_source(*body
, deref
, expanded_src
);
251 check_expanded_source(type
, expanded_src
);
252 check_instructions(&instructions
, type
, deref
);
255 TEST_F(expand_source
, i64vec2_variable
)
257 const glsl_type
*const type
= glsl_type::i64vec2_type
;
258 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
260 lower_64bit::expand_source(*body
, deref
, expanded_src
);
262 check_expanded_source(type
, expanded_src
);
263 check_instructions(&instructions
, type
, deref
);
266 TEST_F(expand_source
, i64vec3_variable
)
268 const glsl_type
*const type
= glsl_type::i64vec3_type
;
269 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
271 lower_64bit::expand_source(*body
, deref
, expanded_src
);
273 check_expanded_source(type
, expanded_src
);
274 check_instructions(&instructions
, type
, deref
);
277 TEST_F(expand_source
, i64vec4_variable
)
279 const glsl_type
*const type
= glsl_type::i64vec4_type
;
280 ir_dereference_variable
*const deref
= create_variable(mem_ctx
, type
);
282 lower_64bit::expand_source(*body
, deref
, expanded_src
);
284 check_expanded_source(type
, expanded_src
);
285 check_instructions(&instructions
, type
, deref
);
288 TEST_F(expand_source
, uint64_expression
)
290 const glsl_type
*const type
= glsl_type::uint64_t_type
;
291 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
293 lower_64bit::expand_source(*body
, expr
, expanded_src
);
295 check_expanded_source(type
, expanded_src
);
296 check_instructions(&instructions
, type
, expr
);
299 TEST_F(expand_source
, u64vec2_expression
)
301 const glsl_type
*const type
= glsl_type::u64vec2_type
;
302 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
304 lower_64bit::expand_source(*body
, expr
, expanded_src
);
306 check_expanded_source(type
, expanded_src
);
307 check_instructions(&instructions
, type
, expr
);
310 TEST_F(expand_source
, u64vec3_expression
)
312 const glsl_type
*const type
= glsl_type::u64vec3_type
;
313 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
315 lower_64bit::expand_source(*body
, expr
, expanded_src
);
317 check_expanded_source(type
, expanded_src
);
318 check_instructions(&instructions
, type
, expr
);
321 TEST_F(expand_source
, u64vec4_expression
)
323 const glsl_type
*const type
= glsl_type::u64vec4_type
;
324 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
326 lower_64bit::expand_source(*body
, expr
, expanded_src
);
328 check_expanded_source(type
, expanded_src
);
329 check_instructions(&instructions
, type
, expr
);
332 TEST_F(expand_source
, int64_expression
)
334 const glsl_type
*const type
= glsl_type::int64_t_type
;
335 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
337 lower_64bit::expand_source(*body
, expr
, expanded_src
);
339 check_expanded_source(type
, expanded_src
);
340 check_instructions(&instructions
, type
, expr
);
343 TEST_F(expand_source
, i64vec2_expression
)
345 const glsl_type
*const type
= glsl_type::i64vec2_type
;
346 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
348 lower_64bit::expand_source(*body
, expr
, expanded_src
);
350 check_expanded_source(type
, expanded_src
);
351 check_instructions(&instructions
, type
, expr
);
354 TEST_F(expand_source
, i64vec3_expression
)
356 const glsl_type
*const type
= glsl_type::i64vec3_type
;
357 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
359 lower_64bit::expand_source(*body
, expr
, expanded_src
);
361 check_expanded_source(type
, expanded_src
);
362 check_instructions(&instructions
, type
, expr
);
365 TEST_F(expand_source
, i64vec4_expression
)
367 const glsl_type
*const type
= glsl_type::i64vec4_type
;
368 ir_expression
*const expr
= create_expression(mem_ctx
, type
);
370 lower_64bit::expand_source(*body
, expr
, expanded_src
);
372 check_expanded_source(type
, expanded_src
);
373 check_instructions(&instructions
, type
, expr
);
376 class compact_destination
: public ::testing::Test
{
378 virtual void SetUp();
379 virtual void TearDown();
381 exec_list instructions
;
383 ir_variable
*expanded_src
[4];
388 compact_destination::SetUp()
390 mem_ctx
= ralloc_context(NULL
);
392 memset(expanded_src
, 0, sizeof(expanded_src
));
393 instructions
.make_empty();
394 body
= new ir_factory(&instructions
, mem_ctx
);
398 compact_destination::TearDown()
403 ralloc_free(mem_ctx
);
407 TEST_F(compact_destination
, uint64
)
409 const glsl_type
*const type
= glsl_type::uint64_t_type
;
411 for (unsigned i
= 0; i
< type
->vector_elements
; i
++) {
412 expanded_src
[i
] = new(mem_ctx
) ir_variable(glsl_type::uvec2_type
,
417 ir_dereference_variable
*deref
=
418 lower_64bit::compact_destination(*body
,
422 ASSERT_EQ(ir_type_dereference_variable
, deref
->ir_type
);
423 EXPECT_EQ(type
, deref
->var
->type
) <<
425 deref
->var
->type
->name
<<
431 ASSERT_FALSE(instructions
.is_empty());
432 ir
= (ir_instruction
*) instructions
.pop_head();
433 ir_variable
*const var
= ir
->as_variable();
434 ASSERT_NE((void *)0, var
);
435 EXPECT_EQ(deref
->var
, var
);
437 for (unsigned i
= 0; i
< type
->vector_elements
; i
++) {
438 ASSERT_FALSE(instructions
.is_empty());
439 ir
= (ir_instruction
*) instructions
.pop_head();
440 ir_assignment
*const assign
= ir
->as_assignment();
441 ASSERT_NE((void *)0, assign
);
442 EXPECT_EQ(deref
->var
, assign
->lhs
->variable_referenced());