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 } 441