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/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 glsl_type_singleton_init_or_ref(); 61 62 mem_ctx = ralloc_context(NULL); 63 64 memset(expanded_src, 0, sizeof(expanded_src)); 65 instructions.make_empty(); 66 body = new ir_factory(&instructions, mem_ctx); 67} 68 69void 70expand_source::TearDown() 71{ 72 delete body; 73 body = NULL; 74 75 ralloc_free(mem_ctx); 76 mem_ctx = NULL; 77 78 glsl_type_singleton_decref(); 79} 80 81static ir_dereference_variable * 82create_variable(void *mem_ctx, const glsl_type *type) 83{ 84 ir_variable *var = new(mem_ctx) ir_variable(type, 85 "variable", 86 ir_var_temporary); 87 88 return new(mem_ctx) ir_dereference_variable(var); 89} 90 91static ir_expression * 92create_expression(void *mem_ctx, const glsl_type *type) 93{ 94 return new(mem_ctx) ir_expression(ir_unop_neg, 95 create_variable(mem_ctx, type)); 96} 97 98static void 99check_expanded_source(const glsl_type *type, 100 ir_variable *expanded_src[4]) 101{ 102 const glsl_type *const expanded_type = 103 type->base_type == GLSL_TYPE_UINT64 104 ? glsl_type::uvec2_type :glsl_type::ivec2_type; 105 106 for (int i = 0; i < type->vector_elements; i++) { 107 EXPECT_EQ(expanded_type, expanded_src[i]->type); 108 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; 113 } 114 } 115 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). 118 */ 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"; 122 } 123} 124 125static void 126check_instructions(exec_list *instructions, 127 const glsl_type *type, 128 const ir_instruction *source) 129{ 130 const glsl_type *const expanded_type = 131 type->base_type == GLSL_TYPE_UINT64 132 ? glsl_type::uvec2_type : glsl_type::ivec2_type; 133 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; 137 138 ir_instruction *ir; 139 140 /* The instruction list should contain IR to represent: 141 * 142 * type tmp1; 143 * tmp1 = source; 144 * uvec2 tmp2; 145 * tmp2 = unpackUint2x32(tmp1.x); 146 * uvec2 tmp3; 147 * tmp3 = unpackUint2x32(tmp1.y); 148 * uvec2 tmp4; 149 * tmp4 = unpackUint2x32(tmp1.z); 150 * uvec2 tmp5; 151 * tmp5 = unpackUint2x32(tmp1.w); 152 */ 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) << 158 " Got " << 159 tmp1->type->name << 160 ", expected " << 161 type->name; 162 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); 170 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); 177 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()); 188 } 189 190 EXPECT_TRUE(instructions->is_empty()); 191} 192 193TEST_F(expand_source, uint64_variable) 194{ 195 const glsl_type *const type = glsl_type::uint64_t_type; 196 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 197 198 lower_64bit::expand_source(*body, deref, expanded_src); 199 200 check_expanded_source(type, expanded_src); 201 check_instructions(&instructions, type, deref); 202} 203 204TEST_F(expand_source, u64vec2_variable) 205{ 206 const glsl_type *const type = glsl_type::u64vec2_type; 207 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 208 209 lower_64bit::expand_source(*body, deref, expanded_src); 210 211 check_expanded_source(type, expanded_src); 212 check_instructions(&instructions, type, deref); 213} 214 215TEST_F(expand_source, u64vec3_variable) 216{ 217 const glsl_type *const type = glsl_type::u64vec3_type; 218 219 /* Generate an operand that is a scalar variable dereference. */ 220 ir_variable *const var = new(mem_ctx) ir_variable(type, 221 "variable", 222 ir_var_temporary); 223 224 ir_dereference_variable *const deref = 225 new(mem_ctx) ir_dereference_variable(var); 226 227 lower_64bit::expand_source(*body, deref, expanded_src); 228 229 check_expanded_source(type, expanded_src); 230 check_instructions(&instructions, type, deref); 231} 232 233TEST_F(expand_source, u64vec4_variable) 234{ 235 const glsl_type *const type = glsl_type::u64vec4_type; 236 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 237 238 lower_64bit::expand_source(*body, deref, expanded_src); 239 240 check_expanded_source(type, expanded_src); 241 check_instructions(&instructions, type, deref); 242} 243 244TEST_F(expand_source, int64_variable) 245{ 246 const glsl_type *const type = glsl_type::int64_t_type; 247 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 248 249 lower_64bit::expand_source(*body, deref, expanded_src); 250 251 check_expanded_source(type, expanded_src); 252 check_instructions(&instructions, type, deref); 253} 254 255TEST_F(expand_source, i64vec2_variable) 256{ 257 const glsl_type *const type = glsl_type::i64vec2_type; 258 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 259 260 lower_64bit::expand_source(*body, deref, expanded_src); 261 262 check_expanded_source(type, expanded_src); 263 check_instructions(&instructions, type, deref); 264} 265 266TEST_F(expand_source, i64vec3_variable) 267{ 268 const glsl_type *const type = glsl_type::i64vec3_type; 269 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 270 271 lower_64bit::expand_source(*body, deref, expanded_src); 272 273 check_expanded_source(type, expanded_src); 274 check_instructions(&instructions, type, deref); 275} 276 277TEST_F(expand_source, i64vec4_variable) 278{ 279 const glsl_type *const type = glsl_type::i64vec4_type; 280 ir_dereference_variable *const deref = create_variable(mem_ctx, type); 281 282 lower_64bit::expand_source(*body, deref, expanded_src); 283 284 check_expanded_source(type, expanded_src); 285 check_instructions(&instructions, type, deref); 286} 287 288TEST_F(expand_source, uint64_expression) 289{ 290 const glsl_type *const type = glsl_type::uint64_t_type; 291 ir_expression *const expr = create_expression(mem_ctx, type); 292 293 lower_64bit::expand_source(*body, expr, expanded_src); 294 295 check_expanded_source(type, expanded_src); 296 check_instructions(&instructions, type, expr); 297} 298 299TEST_F(expand_source, u64vec2_expression) 300{ 301 const glsl_type *const type = glsl_type::u64vec2_type; 302 ir_expression *const expr = create_expression(mem_ctx, type); 303 304 lower_64bit::expand_source(*body, expr, expanded_src); 305 306 check_expanded_source(type, expanded_src); 307 check_instructions(&instructions, type, expr); 308} 309 310TEST_F(expand_source, u64vec3_expression) 311{ 312 const glsl_type *const type = glsl_type::u64vec3_type; 313 ir_expression *const expr = create_expression(mem_ctx, type); 314 315 lower_64bit::expand_source(*body, expr, expanded_src); 316 317 check_expanded_source(type, expanded_src); 318 check_instructions(&instructions, type, expr); 319} 320 321TEST_F(expand_source, u64vec4_expression) 322{ 323 const glsl_type *const type = glsl_type::u64vec4_type; 324 ir_expression *const expr = create_expression(mem_ctx, type); 325 326 lower_64bit::expand_source(*body, expr, expanded_src); 327 328 check_expanded_source(type, expanded_src); 329 check_instructions(&instructions, type, expr); 330} 331 332TEST_F(expand_source, int64_expression) 333{ 334 const glsl_type *const type = glsl_type::int64_t_type; 335 ir_expression *const expr = create_expression(mem_ctx, type); 336 337 lower_64bit::expand_source(*body, expr, expanded_src); 338 339 check_expanded_source(type, expanded_src); 340 check_instructions(&instructions, type, expr); 341} 342 343TEST_F(expand_source, i64vec2_expression) 344{ 345 const glsl_type *const type = glsl_type::i64vec2_type; 346 ir_expression *const expr = create_expression(mem_ctx, type); 347 348 lower_64bit::expand_source(*body, expr, expanded_src); 349 350 check_expanded_source(type, expanded_src); 351 check_instructions(&instructions, type, expr); 352} 353 354TEST_F(expand_source, i64vec3_expression) 355{ 356 const glsl_type *const type = glsl_type::i64vec3_type; 357 ir_expression *const expr = create_expression(mem_ctx, type); 358 359 lower_64bit::expand_source(*body, expr, expanded_src); 360 361 check_expanded_source(type, expanded_src); 362 check_instructions(&instructions, type, expr); 363} 364 365TEST_F(expand_source, i64vec4_expression) 366{ 367 const glsl_type *const type = glsl_type::i64vec4_type; 368 ir_expression *const expr = create_expression(mem_ctx, type); 369 370 lower_64bit::expand_source(*body, expr, expanded_src); 371 372 check_expanded_source(type, expanded_src); 373 check_instructions(&instructions, type, expr); 374} 375 376class compact_destination : public ::testing::Test { 377public: 378 virtual void SetUp(); 379 virtual void TearDown(); 380 381 exec_list instructions; 382 ir_factory *body; 383 ir_variable *expanded_src[4]; 384 void *mem_ctx; 385}; 386 387void 388compact_destination::SetUp() 389{ 390 mem_ctx = ralloc_context(NULL); 391 392 memset(expanded_src, 0, sizeof(expanded_src)); 393 instructions.make_empty(); 394 body = new ir_factory(&instructions, mem_ctx); 395} 396 397void 398compact_destination::TearDown() 399{ 400 delete body; 401 body = NULL; 402 403 ralloc_free(mem_ctx); 404 mem_ctx = NULL; 405} 406 407TEST_F(compact_destination, uint64) 408{ 409 const glsl_type *const type = glsl_type::uint64_t_type; 410 411 for (unsigned i = 0; i < type->vector_elements; i++) { 412 expanded_src[i] = new(mem_ctx) ir_variable(glsl_type::uvec2_type, 413 "result", 414 ir_var_temporary); 415 } 416 417 ir_dereference_variable *deref = 418 lower_64bit::compact_destination(*body, 419 type, 420 expanded_src); 421 422 ASSERT_EQ(ir_type_dereference_variable, deref->ir_type); 423 EXPECT_EQ(type, deref->var->type) << 424 " Got " << 425 deref->var->type->name << 426 ", expected " << 427 type->name; 428 429 ir_instruction *ir; 430 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); 436 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()); 443 } 444} 445