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