summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2018-05-24 11:37:51 -0700
committerIan Romanick <ian.d.romanick@intel.com>2019-03-28 15:35:52 -0700
commitbe1cc3552bc8af23612e37521bc90d106610e62e (patch)
tree063b6bb10d4173d96865eb4f83816d8fd3690c72
parentae21b52e1dc5db5f7678ce9817364384dc0cbc87 (diff)
nir: Add nir_const_value_negative_equal
v2: Rebase on 1-bit Boolean changes. Reviewed-by: Thomas Helland <thomashelland90@gmail.com> [v1] Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
-rw-r--r--src/compiler/nir/meson.build12
-rw-r--r--src/compiler/nir/nir.h6
-rw-r--r--src/compiler/nir/nir_instr_set.c102
-rw-r--r--src/compiler/nir/tests/negative_equal_tests.cpp278
4 files changed, 398 insertions, 0 deletions
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index eecc19e7a6e..0900f56648e 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -282,4 +282,16 @@ if with_tests
],
suite : ['compiler', 'nir'],
)
+
+ test(
+ 'negative_equal',
+ executable(
+ 'negative_equal',
+ files('tests/negative_equal_tests.cpp'),
+ c_args : [c_vis_args, c_msvc_compat_args, no_override_init_args],
+ include_directories : [inc_common],
+ dependencies : [dep_thread, idep_gtest, idep_nir],
+ link_with : libmesa_util,
+ )
+ )
endif
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 4285458cdf2..e123a59cca8 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -988,6 +988,12 @@ nir_ssa_alu_instr_src_components(const nir_alu_instr *instr, unsigned src)
return instr->dest.dest.ssa.num_components;
}
+bool nir_const_value_negative_equal(const nir_const_value *c1,
+ const nir_const_value *c2,
+ unsigned components,
+ nir_alu_type base_type,
+ unsigned bits);
+
bool nir_alu_srcs_equal(const nir_alu_instr *alu1, const nir_alu_instr *alu2,
unsigned src1, unsigned src2);
diff --git a/src/compiler/nir/nir_instr_set.c b/src/compiler/nir/nir_instr_set.c
index d106e9ebcae..1307fe2f3c9 100644
--- a/src/compiler/nir/nir_instr_set.c
+++ b/src/compiler/nir/nir_instr_set.c
@@ -23,6 +23,7 @@
#include "nir_instr_set.h"
#include "nir_vla.h"
+#include "util/half_float.h"
#define HASH(hash, data) _mesa_fnv32_1a_accumulate((hash), (data))
@@ -276,6 +277,107 @@ nir_srcs_equal(nir_src src1, nir_src src2)
}
bool
+nir_const_value_negative_equal(const nir_const_value *c1,
+ const nir_const_value *c2,
+ unsigned components,
+ nir_alu_type base_type,
+ unsigned bits)
+{
+ assert(base_type == nir_alu_type_get_base_type(base_type));
+ assert(base_type != nir_type_invalid);
+
+ /* This can occur for 1-bit Boolean values. */
+ if (bits == 1)
+ return false;
+
+ switch (base_type) {
+ case nir_type_float:
+ switch (bits) {
+ case 16:
+ for (unsigned i = 0; i < components; i++) {
+ if (_mesa_half_to_float(c1->u16[i]) !=
+ -_mesa_half_to_float(c2->u16[i])) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case 32:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->f32[i] != -c2->f32[i])
+ return false;
+ }
+
+ return true;
+
+ case 64:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->f64[i] != -c2->f64[i])
+ return false;
+ }
+
+ return true;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_int:
+ case nir_type_uint:
+ switch (bits) {
+ case 8:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->i8[i] != -c2->i8[i])
+ return false;
+ }
+
+ return true;
+
+ case 16:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->i16[i] != -c2->i16[i])
+ return false;
+ }
+
+ return true;
+ break;
+
+ case 32:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->i32[i] != -c2->i32[i])
+ return false;
+ }
+
+ return true;
+
+ case 64:
+ for (unsigned i = 0; i < components; i++) {
+ if (c1->i64[i] != -c2->i64[i])
+ return false;
+ }
+
+ return true;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_bool:
+ return false;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool
nir_alu_srcs_equal(const nir_alu_instr *alu1, const nir_alu_instr *alu2,
unsigned src1, unsigned src2)
{
diff --git a/src/compiler/nir/tests/negative_equal_tests.cpp b/src/compiler/nir/tests/negative_equal_tests.cpp
new file mode 100644
index 00000000000..e450a8172db
--- /dev/null
+++ b/src/compiler/nir/tests/negative_equal_tests.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright © 2018 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 "nir.h"
+#include "util/half_float.h"
+
+static nir_const_value count_sequence(nir_alu_type base_type, unsigned bits,
+ int first);
+static nir_const_value negate(const nir_const_value &src,
+ nir_alu_type base_type, unsigned bits,
+ unsigned components);
+
+class const_value_negative_equal_test : public ::testing::Test {
+protected:
+ const_value_negative_equal_test()
+ {
+ memset(&c1, 0, sizeof(c1));
+ memset(&c2, 0, sizeof(c2));
+ }
+
+ ~const_value_negative_equal_test()
+ {
+ /* empty */
+ }
+
+ nir_const_value c1;
+ nir_const_value c2;
+};
+
+
+TEST_F(const_value_negative_equal_test, float32_zero)
+{
+ /* Verify that 0.0 negative-equals 0.0. */
+ EXPECT_TRUE(nir_const_value_negative_equal(&c1, &c1,
+ 4, nir_type_float, 32));
+}
+
+TEST_F(const_value_negative_equal_test, float64_zero)
+{
+ /* Verify that 0.0 negative-equals 0.0. */
+ EXPECT_TRUE(nir_const_value_negative_equal(&c1, &c1,
+ 4, nir_type_float, 64));
+}
+
+/* Compare an object with non-zero values to itself. This should always be
+ * false.
+ */
+#define compare_with_self(base_type, bits) \
+TEST_F(const_value_negative_equal_test, base_type ## bits ## _self) \
+{ \
+ c1 = count_sequence(base_type, bits, 1); \
+ EXPECT_FALSE(nir_const_value_negative_equal(&c1, &c1, 4, base_type, bits)); \
+}
+
+compare_with_self(nir_type_float, 16)
+compare_with_self(nir_type_float, 32)
+compare_with_self(nir_type_float, 64)
+compare_with_self(nir_type_int, 8)
+compare_with_self(nir_type_uint, 8)
+compare_with_self(nir_type_int, 16)
+compare_with_self(nir_type_uint, 16)
+compare_with_self(nir_type_int, 32)
+compare_with_self(nir_type_uint, 32)
+compare_with_self(nir_type_int, 64)
+compare_with_self(nir_type_uint, 64)
+
+/* Compare an object with the negation of itself. This should always be true.
+ */
+#define compare_with_negation(base_type, bits) \
+TEST_F(const_value_negative_equal_test, base_type ## bits ## _trivially_true) \
+{ \
+ c1 = count_sequence(base_type, bits, 1); \
+ c2 = negate(c1, base_type, bits, 4); \
+ EXPECT_TRUE(nir_const_value_negative_equal(&c1, &c2, 4, base_type, bits)); \
+}
+
+compare_with_negation(nir_type_float, 16)
+compare_with_negation(nir_type_float, 32)
+compare_with_negation(nir_type_float, 64)
+compare_with_negation(nir_type_int, 8)
+compare_with_negation(nir_type_uint, 8)
+compare_with_negation(nir_type_int, 16)
+compare_with_negation(nir_type_uint, 16)
+compare_with_negation(nir_type_int, 32)
+compare_with_negation(nir_type_uint, 32)
+compare_with_negation(nir_type_int, 64)
+compare_with_negation(nir_type_uint, 64)
+
+/* Compare fewer than the maximum possible components. All of the components
+ * that are compared a negative-equal, but the extra components are not.
+ */
+#define compare_fewer_components(base_type, bits) \
+TEST_F(const_value_negative_equal_test, base_type ## bits ## _fewer_components) \
+{ \
+ c1 = count_sequence(base_type, bits, 1); \
+ c2 = negate(c1, base_type, bits, 3); \
+ EXPECT_TRUE(nir_const_value_negative_equal(&c1, &c2, 3, base_type, bits)); \
+ EXPECT_FALSE(nir_const_value_negative_equal(&c1, &c2, 4, base_type, bits)); \
+}
+
+compare_fewer_components(nir_type_float, 16)
+compare_fewer_components(nir_type_float, 32)
+compare_fewer_components(nir_type_float, 64)
+compare_fewer_components(nir_type_int, 8)
+compare_fewer_components(nir_type_uint, 8)
+compare_fewer_components(nir_type_int, 16)
+compare_fewer_components(nir_type_uint, 16)
+compare_fewer_components(nir_type_int, 32)
+compare_fewer_components(nir_type_uint, 32)
+compare_fewer_components(nir_type_int, 64)
+compare_fewer_components(nir_type_uint, 64)
+
+static nir_const_value
+count_sequence(nir_alu_type base_type, unsigned bits, int first)
+{
+ nir_const_value c;
+
+ switch (base_type) {
+ case nir_type_float:
+ switch (bits) {
+ case 16:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.u16); i++)
+ c.u16[i] = _mesa_float_to_half(float(i + first));
+
+ break;
+
+ case 32:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.f32); i++)
+ c.f32[i] = float(i + first);
+
+ break;
+
+ case 64:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.f64); i++)
+ c.f64[i] = double(i + first);
+
+ break;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_int:
+ case nir_type_uint:
+ switch (bits) {
+ case 8:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.i8); i++)
+ c.i8[i] = i + first;
+
+ break;
+
+ case 16:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.i16); i++)
+ c.i16[i] = i + first;
+
+ break;
+
+ case 32:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.i32); i++)
+ c.i32[i] = i + first;
+
+ break;
+
+ case 64:
+ for (unsigned i = 0; i < ARRAY_SIZE(c.i64); i++)
+ c.i64[i] = i + first;
+
+ break;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_bool:
+ default:
+ unreachable("invalid base type");
+ }
+
+ return c;
+}
+
+static nir_const_value
+negate(const nir_const_value &src, nir_alu_type base_type, unsigned bits,
+ unsigned components)
+{
+ nir_const_value c = src;
+
+ switch (base_type) {
+ case nir_type_float:
+ switch (bits) {
+ case 16:
+ for (unsigned i = 0; i < components; i++)
+ c.u16[i] = _mesa_float_to_half(-_mesa_half_to_float(c.u16[i]));
+
+ break;
+
+ case 32:
+ for (unsigned i = 0; i < components; i++)
+ c.f32[i] = -c.f32[i];
+
+ break;
+
+ case 64:
+ for (unsigned i = 0; i < components; i++)
+ c.f64[i] = -c.f64[i];
+
+ break;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_int:
+ case nir_type_uint:
+ switch (bits) {
+ case 8:
+ for (unsigned i = 0; i < components; i++)
+ c.i8[i] = -c.i8[i];
+
+ break;
+
+ case 16:
+ for (unsigned i = 0; i < components; i++)
+ c.i16[i] = -c.i16[i];
+
+ break;
+
+ case 32:
+ for (unsigned i = 0; i < components; i++)
+ c.i32[i] = -c.i32[i];
+
+ break;
+
+ case 64:
+ for (unsigned i = 0; i < components; i++)
+ c.i64[i] = -c.i64[i];
+
+ break;
+
+ default:
+ unreachable("unknown bit size");
+ }
+
+ break;
+
+ case nir_type_bool:
+ default:
+ unreachable("invalid base type");
+ }
+
+ return c;
+}