diff options
author | Ian Romanick <[email protected]> | 2016-10-14 18:17:16 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2017-01-20 15:41:23 -0800 |
commit | 6c3af043633997633d03e5409939263162076e81 (patch) | |
tree | f9131a40077f0e3315cf473f2bdda5e86fd256b5 /src/compiler/glsl/tests | |
parent | 330fc2413c61f0bd9c7bb9f3a0ecd91b09de267a (diff) |
glsl: Add a lowering pass for 64-bit integer multiplication
v2: Rename lower_64bit.cpp and lower_64bit_test.cpp to lower_int64.
Suggested by Matt.
Signed-off-by: Ian Romanick <[email protected]>
Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src/compiler/glsl/tests')
-rw-r--r-- | src/compiler/glsl/tests/lower_int64_test.cpp | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/src/compiler/glsl/tests/lower_int64_test.cpp b/src/compiler/glsl/tests/lower_int64_test.cpp new file mode 100644 index 00000000000..4ddc433582e --- /dev/null +++ b/src/compiler/glsl/tests/lower_int64_test.cpp @@ -0,0 +1,440 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include <gtest/gtest.h> +#include "main/compiler.h" +#include "main/mtypes.h" +#include "main/macros.h" +#include "ir.h" +#include "ir_builder.h" + +using namespace ir_builder; + +namespace lower_64bit { +void expand_source(ir_factory &body, + ir_rvalue *val, + ir_variable **expanded_src); + +ir_dereference_variable *compact_destination(ir_factory &body, + const glsl_type *type, + ir_variable *result[4]); + +ir_rvalue *lower_op_to_function_call(ir_instruction *base_ir, + ir_expression *ir, + ir_function_signature *callee); +}; + +class expand_source : public ::testing::Test { +public: + virtual void SetUp(); + virtual void TearDown(); + + exec_list instructions; + ir_factory *body; + ir_variable *expanded_src[4]; + void *mem_ctx; +}; + +void +expand_source::SetUp() +{ + mem_ctx = ralloc_context(NULL); + + memset(expanded_src, 0, sizeof(expanded_src)); + instructions.make_empty(); + body = new ir_factory(&instructions, mem_ctx); +} + +void +expand_source::TearDown() +{ + delete body; + body = NULL; + + ralloc_free(mem_ctx); + mem_ctx = NULL; +} + +static ir_dereference_variable * +create_variable(void *mem_ctx, const glsl_type *type) +{ + ir_variable *var = new(mem_ctx) ir_variable(type, + "variable", + ir_var_temporary); + + return new(mem_ctx) ir_dereference_variable(var); +} + +static ir_expression * +create_expression(void *mem_ctx, const glsl_type *type) +{ + return new(mem_ctx) ir_expression(ir_unop_neg, + create_variable(mem_ctx, type)); +} + +static void +check_expanded_source(const glsl_type *type, + ir_variable *expanded_src[4]) +{ + const glsl_type *const expanded_type = + type->base_type == GLSL_TYPE_UINT64 + ? glsl_type::uvec2_type :glsl_type::ivec2_type; + + for (int i = 0; i < type->vector_elements; i++) { + EXPECT_EQ(expanded_type, expanded_src[i]->type); + + /* All elements that are part of the vector must be unique. */ + for (int j = i - 1; j >= 0; j--) { + EXPECT_NE(expanded_src[i], expanded_src[j]) + << " Element " << i << " is the same as element " << j; + } + } + + /* All elements that are not part of the vector must be the same as element + * 0. This is primarily for scalars (where every element is the same). + */ + for (int i = type->vector_elements; i < 4; i++) { + EXPECT_EQ(expanded_src[0], expanded_src[i]) + << " Element " << i << " should be the same as element 0"; + } +} + +static void +check_instructions(exec_list *instructions, + const glsl_type *type, + const ir_instruction *source) +{ + const glsl_type *const expanded_type = + type->base_type == GLSL_TYPE_UINT64 + ? glsl_type::uvec2_type : glsl_type::ivec2_type; + + const ir_expression_operation unpack_opcode = + type->base_type == GLSL_TYPE_UINT64 + ? ir_unop_unpack_uint_2x32 : ir_unop_unpack_int_2x32; + + ir_instruction *ir; + + /* The instruction list should contain IR to represent: + * + * type tmp1; + * tmp1 = source; + * uvec2 tmp2; + * tmp2 = unpackUint2x32(tmp1.x); + * uvec2 tmp3; + * tmp3 = unpackUint2x32(tmp1.y); + * uvec2 tmp4; + * tmp4 = unpackUint2x32(tmp1.z); + * uvec2 tmp5; + * tmp5 = unpackUint2x32(tmp1.w); + */ + ASSERT_FALSE(instructions->is_empty()); + ir = (ir_instruction *) instructions->pop_head(); + ir_variable *const tmp1 = ir->as_variable(); + EXPECT_EQ(ir_type_variable, ir->ir_type); + EXPECT_EQ(type, tmp1->type) << + " Got " << + tmp1->type->name << + ", expected " << + type->name; + + ASSERT_FALSE(instructions->is_empty()); + ir = (ir_instruction *) instructions->pop_head(); + ir_assignment *const assign1 = ir->as_assignment(); + EXPECT_EQ(ir_type_assignment, ir->ir_type); + ASSERT_NE((void *)0, assign1); + EXPECT_EQ(tmp1, assign1->lhs->variable_referenced()); + EXPECT_EQ(source, assign1->rhs); + + for (unsigned i = 0; i < type->vector_elements; i++) { + ASSERT_FALSE(instructions->is_empty()); + ir = (ir_instruction *) instructions->pop_head(); + ir_variable *const tmp2 = ir->as_variable(); + EXPECT_EQ(ir_type_variable, ir->ir_type); + EXPECT_EQ(expanded_type, tmp2->type); + + ASSERT_FALSE(instructions->is_empty()); + ir = (ir_instruction *) instructions->pop_head(); + ir_assignment *const assign2 = ir->as_assignment(); + EXPECT_EQ(ir_type_assignment, ir->ir_type); + ASSERT_NE((void *)0, assign2); + EXPECT_EQ(tmp2, assign2->lhs->variable_referenced()); + ir_expression *unpack = assign2->rhs->as_expression(); + ASSERT_NE((void *)0, unpack); + EXPECT_EQ(unpack_opcode, unpack->operation); + EXPECT_EQ(tmp1, unpack->operands[0]->variable_referenced()); + } + + EXPECT_TRUE(instructions->is_empty()); +} + +TEST_F(expand_source, uint64_variable) +{ + const glsl_type *const type = glsl_type::uint64_t_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, u64vec2_variable) +{ + const glsl_type *const type = glsl_type::u64vec2_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, u64vec3_variable) +{ + const glsl_type *const type = glsl_type::u64vec3_type; + + /* Generate an operand that is a scalar variable dereference. */ + ir_variable *const var = new(mem_ctx) ir_variable(type, + "variable", + ir_var_temporary); + + ir_dereference_variable *const deref = + new(mem_ctx) ir_dereference_variable(var); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, u64vec4_variable) +{ + const glsl_type *const type = glsl_type::u64vec4_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, int64_variable) +{ + const glsl_type *const type = glsl_type::int64_t_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, i64vec2_variable) +{ + const glsl_type *const type = glsl_type::i64vec2_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, i64vec3_variable) +{ + const glsl_type *const type = glsl_type::i64vec3_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, i64vec4_variable) +{ + const glsl_type *const type = glsl_type::i64vec4_type; + ir_dereference_variable *const deref = create_variable(mem_ctx, type); + + lower_64bit::expand_source(*body, deref, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, deref); +} + +TEST_F(expand_source, uint64_expression) +{ + const glsl_type *const type = glsl_type::uint64_t_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, u64vec2_expression) +{ + const glsl_type *const type = glsl_type::u64vec2_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, u64vec3_expression) +{ + const glsl_type *const type = glsl_type::u64vec3_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, u64vec4_expression) +{ + const glsl_type *const type = glsl_type::u64vec4_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, int64_expression) +{ + const glsl_type *const type = glsl_type::int64_t_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, i64vec2_expression) +{ + const glsl_type *const type = glsl_type::i64vec2_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, i64vec3_expression) +{ + const glsl_type *const type = glsl_type::i64vec3_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +TEST_F(expand_source, i64vec4_expression) +{ + const glsl_type *const type = glsl_type::i64vec4_type; + ir_expression *const expr = create_expression(mem_ctx, type); + + lower_64bit::expand_source(*body, expr, expanded_src); + + check_expanded_source(type, expanded_src); + check_instructions(&instructions, type, expr); +} + +class compact_destination : public ::testing::Test { +public: + virtual void SetUp(); + virtual void TearDown(); + + exec_list instructions; + ir_factory *body; + ir_variable *expanded_src[4]; + void *mem_ctx; +}; + +void +compact_destination::SetUp() +{ + mem_ctx = ralloc_context(NULL); + + memset(expanded_src, 0, sizeof(expanded_src)); + instructions.make_empty(); + body = new ir_factory(&instructions, mem_ctx); +} + +void +compact_destination::TearDown() +{ + delete body; + body = NULL; + + ralloc_free(mem_ctx); + mem_ctx = NULL; +} + +TEST_F(compact_destination, uint64) +{ + const glsl_type *const type = glsl_type::uint64_t_type; + + for (unsigned i = 0; i < type->vector_elements; i++) { + expanded_src[i] = new(mem_ctx) ir_variable(glsl_type::uvec2_type, + "result", + ir_var_temporary); + } + + ir_dereference_variable *deref = + lower_64bit::compact_destination(*body, + type, + expanded_src); + + ASSERT_EQ(ir_type_dereference_variable, deref->ir_type); + EXPECT_EQ(type, deref->var->type) << + " Got " << + deref->var->type->name << + ", expected " << + type->name; + + ir_instruction *ir; + + ASSERT_FALSE(instructions.is_empty()); + ir = (ir_instruction *) instructions.pop_head(); + ir_variable *const var = ir->as_variable(); + ASSERT_NE((void *)0, var); + EXPECT_EQ(deref->var, var); + + for (unsigned i = 0; i < type->vector_elements; i++) { + ASSERT_FALSE(instructions.is_empty()); + ir = (ir_instruction *) instructions.pop_head(); + ir_assignment *const assign = ir->as_assignment(); + ASSERT_NE((void *)0, assign); + EXPECT_EQ(deref->var, assign->lhs->variable_referenced()); + } +} |