aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl/tests
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2016-10-14 18:17:16 -0700
committerIan Romanick <[email protected]>2017-01-20 15:41:23 -0800
commit6c3af043633997633d03e5409939263162076e81 (patch)
treef9131a40077f0e3315cf473f2bdda5e86fd256b5 /src/compiler/glsl/tests
parent330fc2413c61f0bd9c7bb9f3a0ecd91b09de267a (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.cpp440
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());
+ }
+}