nir: Add support for 16-bit types (half float, int16 and uint16)
[mesa.git] / src / compiler / glsl / tests / lower_int64_test.cpp
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 <gtest/gtest.h>
24 #include "main/compiler.h"
25 #include "main/mtypes.h"
26 #include "main/macros.h"
27 #include "ir.h"
28 #include "ir_builder.h"
29
30 using namespace ir_builder;
31
32 namespace lower_64bit {
33 void expand_source(ir_factory &body,
34 ir_rvalue *val,
35 ir_variable **expanded_src);
36
37 ir_dereference_variable *compact_destination(ir_factory &body,
38 const glsl_type *type,
39 ir_variable *result[4]);
40
41 ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir,
42 ir_expression *ir,
43 ir_function_signature *callee);
44 };
45
46 class expand_source : public ::testing::Test {
47 public:
48 virtual void SetUp();
49 virtual void TearDown();
50
51 exec_list instructions;
52 ir_factory *body;
53 ir_variable *expanded_src[4];
54 void *mem_ctx;
55 };
56
57 void
58 expand_source::SetUp()
59 {
60 mem_ctx = ralloc_context(NULL);
61
62 memset(expanded_src, 0, sizeof(expanded_src));
63 instructions.make_empty();
64 body = new ir_factory(&instructions, mem_ctx);
65 }
66
67 void
68 expand_source::TearDown()
69 {
70 delete body;
71 body = NULL;
72
73 ralloc_free(mem_ctx);
74 mem_ctx = NULL;
75 }
76
77 static ir_dereference_variable *
78 create_variable(void *mem_ctx, const glsl_type *type)
79 {
80 ir_variable *var = new(mem_ctx) ir_variable(type,
81 "variable",
82 ir_var_temporary);
83
84 return new(mem_ctx) ir_dereference_variable(var);
85 }
86
87 static ir_expression *
88 create_expression(void *mem_ctx, const glsl_type *type)
89 {
90 return new(mem_ctx) ir_expression(ir_unop_neg,
91 create_variable(mem_ctx, type));
92 }
93
94 static void
95 check_expanded_source(const glsl_type *type,
96 ir_variable *expanded_src[4])
97 {
98 const glsl_type *const expanded_type =
99 type->base_type == GLSL_TYPE_UINT64
100 ? glsl_type::uvec2_type :glsl_type::ivec2_type;
101
102 for (int i = 0; i < type->vector_elements; i++) {
103 EXPECT_EQ(expanded_type, expanded_src[i]->type);
104
105 /* All elements that are part of the vector must be unique. */
106 for (int j = i - 1; j >= 0; j--) {
107 EXPECT_NE(expanded_src[i], expanded_src[j])
108 << " Element " << i << " is the same as element " << j;
109 }
110 }
111
112 /* All elements that are not part of the vector must be the same as element
113 * 0. This is primarily for scalars (where every element is the same).
114 */
115 for (int i = type->vector_elements; i < 4; i++) {
116 EXPECT_EQ(expanded_src[0], expanded_src[i])
117 << " Element " << i << " should be the same as element 0";
118 }
119 }
120
121 static void
122 check_instructions(exec_list *instructions,
123 const glsl_type *type,
124 const ir_instruction *source)
125 {
126 const glsl_type *const expanded_type =
127 type->base_type == GLSL_TYPE_UINT64
128 ? glsl_type::uvec2_type : glsl_type::ivec2_type;
129
130 const ir_expression_operation unpack_opcode =
131 type->base_type == GLSL_TYPE_UINT64
132 ? ir_unop_unpack_uint_2x32 : ir_unop_unpack_int_2x32;
133
134 ir_instruction *ir;
135
136 /* The instruction list should contain IR to represent:
137 *
138 * type tmp1;
139 * tmp1 = source;
140 * uvec2 tmp2;
141 * tmp2 = unpackUint2x32(tmp1.x);
142 * uvec2 tmp3;
143 * tmp3 = unpackUint2x32(tmp1.y);
144 * uvec2 tmp4;
145 * tmp4 = unpackUint2x32(tmp1.z);
146 * uvec2 tmp5;
147 * tmp5 = unpackUint2x32(tmp1.w);
148 */
149 ASSERT_FALSE(instructions->is_empty());
150 ir = (ir_instruction *) instructions->pop_head();
151 ir_variable *const tmp1 = ir->as_variable();
152 EXPECT_EQ(ir_type_variable, ir->ir_type);
153 EXPECT_EQ(type, tmp1->type) <<
154 " Got " <<
155 tmp1->type->name <<
156 ", expected " <<
157 type->name;
158
159 ASSERT_FALSE(instructions->is_empty());
160 ir = (ir_instruction *) instructions->pop_head();
161 ir_assignment *const assign1 = ir->as_assignment();
162 EXPECT_EQ(ir_type_assignment, ir->ir_type);
163 ASSERT_NE((void *)0, assign1);
164 EXPECT_EQ(tmp1, assign1->lhs->variable_referenced());
165 EXPECT_EQ(source, assign1->rhs);
166
167 for (unsigned i = 0; i < type->vector_elements; i++) {
168 ASSERT_FALSE(instructions->is_empty());
169 ir = (ir_instruction *) instructions->pop_head();
170 ir_variable *const tmp2 = ir->as_variable();
171 EXPECT_EQ(ir_type_variable, ir->ir_type);
172 EXPECT_EQ(expanded_type, tmp2->type);
173
174 ASSERT_FALSE(instructions->is_empty());
175 ir = (ir_instruction *) instructions->pop_head();
176 ir_assignment *const assign2 = ir->as_assignment();
177 EXPECT_EQ(ir_type_assignment, ir->ir_type);
178 ASSERT_NE((void *)0, assign2);
179 EXPECT_EQ(tmp2, assign2->lhs->variable_referenced());
180 ir_expression *unpack = assign2->rhs->as_expression();
181 ASSERT_NE((void *)0, unpack);
182 EXPECT_EQ(unpack_opcode, unpack->operation);
183 EXPECT_EQ(tmp1, unpack->operands[0]->variable_referenced());
184 }
185
186 EXPECT_TRUE(instructions->is_empty());
187 }
188
189 TEST_F(expand_source, uint64_variable)
190 {
191 const glsl_type *const type = glsl_type::uint64_t_type;
192 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
193
194 lower_64bit::expand_source(*body, deref, expanded_src);
195
196 check_expanded_source(type, expanded_src);
197 check_instructions(&instructions, type, deref);
198 }
199
200 TEST_F(expand_source, u64vec2_variable)
201 {
202 const glsl_type *const type = glsl_type::u64vec2_type;
203 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
204
205 lower_64bit::expand_source(*body, deref, expanded_src);
206
207 check_expanded_source(type, expanded_src);
208 check_instructions(&instructions, type, deref);
209 }
210
211 TEST_F(expand_source, u64vec3_variable)
212 {
213 const glsl_type *const type = glsl_type::u64vec3_type;
214
215 /* Generate an operand that is a scalar variable dereference. */
216 ir_variable *const var = new(mem_ctx) ir_variable(type,
217 "variable",
218 ir_var_temporary);
219
220 ir_dereference_variable *const deref =
221 new(mem_ctx) ir_dereference_variable(var);
222
223 lower_64bit::expand_source(*body, deref, expanded_src);
224
225 check_expanded_source(type, expanded_src);
226 check_instructions(&instructions, type, deref);
227 }
228
229 TEST_F(expand_source, u64vec4_variable)
230 {
231 const glsl_type *const type = glsl_type::u64vec4_type;
232 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
233
234 lower_64bit::expand_source(*body, deref, expanded_src);
235
236 check_expanded_source(type, expanded_src);
237 check_instructions(&instructions, type, deref);
238 }
239
240 TEST_F(expand_source, int64_variable)
241 {
242 const glsl_type *const type = glsl_type::int64_t_type;
243 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
244
245 lower_64bit::expand_source(*body, deref, expanded_src);
246
247 check_expanded_source(type, expanded_src);
248 check_instructions(&instructions, type, deref);
249 }
250
251 TEST_F(expand_source, i64vec2_variable)
252 {
253 const glsl_type *const type = glsl_type::i64vec2_type;
254 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
255
256 lower_64bit::expand_source(*body, deref, expanded_src);
257
258 check_expanded_source(type, expanded_src);
259 check_instructions(&instructions, type, deref);
260 }
261
262 TEST_F(expand_source, i64vec3_variable)
263 {
264 const glsl_type *const type = glsl_type::i64vec3_type;
265 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
266
267 lower_64bit::expand_source(*body, deref, expanded_src);
268
269 check_expanded_source(type, expanded_src);
270 check_instructions(&instructions, type, deref);
271 }
272
273 TEST_F(expand_source, i64vec4_variable)
274 {
275 const glsl_type *const type = glsl_type::i64vec4_type;
276 ir_dereference_variable *const deref = create_variable(mem_ctx, type);
277
278 lower_64bit::expand_source(*body, deref, expanded_src);
279
280 check_expanded_source(type, expanded_src);
281 check_instructions(&instructions, type, deref);
282 }
283
284 TEST_F(expand_source, uint64_expression)
285 {
286 const glsl_type *const type = glsl_type::uint64_t_type;
287 ir_expression *const expr = create_expression(mem_ctx, type);
288
289 lower_64bit::expand_source(*body, expr, expanded_src);
290
291 check_expanded_source(type, expanded_src);
292 check_instructions(&instructions, type, expr);
293 }
294
295 TEST_F(expand_source, u64vec2_expression)
296 {
297 const glsl_type *const type = glsl_type::u64vec2_type;
298 ir_expression *const expr = create_expression(mem_ctx, type);
299
300 lower_64bit::expand_source(*body, expr, expanded_src);
301
302 check_expanded_source(type, expanded_src);
303 check_instructions(&instructions, type, expr);
304 }
305
306 TEST_F(expand_source, u64vec3_expression)
307 {
308 const glsl_type *const type = glsl_type::u64vec3_type;
309 ir_expression *const expr = create_expression(mem_ctx, type);
310
311 lower_64bit::expand_source(*body, expr, expanded_src);
312
313 check_expanded_source(type, expanded_src);
314 check_instructions(&instructions, type, expr);
315 }
316
317 TEST_F(expand_source, u64vec4_expression)
318 {
319 const glsl_type *const type = glsl_type::u64vec4_type;
320 ir_expression *const expr = create_expression(mem_ctx, type);
321
322 lower_64bit::expand_source(*body, expr, expanded_src);
323
324 check_expanded_source(type, expanded_src);
325 check_instructions(&instructions, type, expr);
326 }
327
328 TEST_F(expand_source, int64_expression)
329 {
330 const glsl_type *const type = glsl_type::int64_t_type;
331 ir_expression *const expr = create_expression(mem_ctx, type);
332
333 lower_64bit::expand_source(*body, expr, expanded_src);
334
335 check_expanded_source(type, expanded_src);
336 check_instructions(&instructions, type, expr);
337 }
338
339 TEST_F(expand_source, i64vec2_expression)
340 {
341 const glsl_type *const type = glsl_type::i64vec2_type;
342 ir_expression *const expr = create_expression(mem_ctx, type);
343
344 lower_64bit::expand_source(*body, expr, expanded_src);
345
346 check_expanded_source(type, expanded_src);
347 check_instructions(&instructions, type, expr);
348 }
349
350 TEST_F(expand_source, i64vec3_expression)
351 {
352 const glsl_type *const type = glsl_type::i64vec3_type;
353 ir_expression *const expr = create_expression(mem_ctx, type);
354
355 lower_64bit::expand_source(*body, expr, expanded_src);
356
357 check_expanded_source(type, expanded_src);
358 check_instructions(&instructions, type, expr);
359 }
360
361 TEST_F(expand_source, i64vec4_expression)
362 {
363 const glsl_type *const type = glsl_type::i64vec4_type;
364 ir_expression *const expr = create_expression(mem_ctx, type);
365
366 lower_64bit::expand_source(*body, expr, expanded_src);
367
368 check_expanded_source(type, expanded_src);
369 check_instructions(&instructions, type, expr);
370 }
371
372 class compact_destination : public ::testing::Test {
373 public:
374 virtual void SetUp();
375 virtual void TearDown();
376
377 exec_list instructions;
378 ir_factory *body;
379 ir_variable *expanded_src[4];
380 void *mem_ctx;
381 };
382
383 void
384 compact_destination::SetUp()
385 {
386 mem_ctx = ralloc_context(NULL);
387
388 memset(expanded_src, 0, sizeof(expanded_src));
389 instructions.make_empty();
390 body = new ir_factory(&instructions, mem_ctx);
391 }
392
393 void
394 compact_destination::TearDown()
395 {
396 delete body;
397 body = NULL;
398
399 ralloc_free(mem_ctx);
400 mem_ctx = NULL;
401 }
402
403 TEST_F(compact_destination, uint64)
404 {
405 const glsl_type *const type = glsl_type::uint64_t_type;
406
407 for (unsigned i = 0; i < type->vector_elements; i++) {
408 expanded_src[i] = new(mem_ctx) ir_variable(glsl_type::uvec2_type,
409 "result",
410 ir_var_temporary);
411 }
412
413 ir_dereference_variable *deref =
414 lower_64bit::compact_destination(*body,
415 type,
416 expanded_src);
417
418 ASSERT_EQ(ir_type_dereference_variable, deref->ir_type);
419 EXPECT_EQ(type, deref->var->type) <<
420 " Got " <<
421 deref->var->type->name <<
422 ", expected " <<
423 type->name;
424
425 ir_instruction *ir;
426
427 ASSERT_FALSE(instructions.is_empty());
428 ir = (ir_instruction *) instructions.pop_head();
429 ir_variable *const var = ir->as_variable();
430 ASSERT_NE((void *)0, var);
431 EXPECT_EQ(deref->var, var);
432
433 for (unsigned i = 0; i < type->vector_elements; i++) {
434 ASSERT_FALSE(instructions.is_empty());
435 ir = (ir_instruction *) instructions.pop_head();
436 ir_assignment *const assign = ir->as_assignment();
437 ASSERT_NE((void *)0, assign);
438 EXPECT_EQ(deref->var, assign->lhs->variable_referenced());
439 }
440 }