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 30using namespace ir_builder; 31 32namespace lower_64bit { 33void expand_source(ir_factory &body, 34 ir_rvalue *val, 35 ir_variable **expanded_src); 36 37ir_dereference_variable *compact_destination(ir_factory &body, 38 const glsl_type *type, 39 ir_variable *result[4]); 40 41ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir, 42 ir_expression *ir, 43 ir_function_signature *callee); 44}; 45 46class expand_source : public ::testing::Test { 47public: 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 57void 58expand_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 67void 68expand_source::TearDown() 69{ 70 delete body; 71 body = NULL; 72 73 ralloc_free(mem_ctx); 74 mem_ctx = NULL; 75} 76 77static ir_dereference_variable * 78create_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 87static ir_expression * 88create_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 94static void 95check_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 121static void 122check_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 189TEST_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 200TEST_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 211TEST_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 229TEST_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 240TEST_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 251TEST_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 262TEST_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 273TEST_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 284TEST_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 295TEST_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 306TEST_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 317TEST_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 328TEST_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 339TEST_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 350TEST_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 361TEST_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 372class compact_destination : public ::testing::Test { 373public: 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 383void 384compact_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 393void 394compact_destination::TearDown() 395{ 396 delete body; 397 body = NULL; 398 399 ralloc_free(mem_ctx); 400 mem_ctx = NULL; 401} 402 403TEST_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} 441