[Mesa-dev] [PATCH 5/8] nir: Add nir_const_value_negative_equal

Ian Romanick idr at freedesktop.org
Wed Jun 6 21:33:20 UTC 2018


From: Ian Romanick <ian.d.romanick at intel.com>

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/compiler/nir/meson.build                    |  12 +
 src/compiler/nir/nir.h                          |   6 +
 src/compiler/nir/nir_instr_set.c                |  98 +++++++++
 src/compiler/nir/tests/negative_equal_tests.cpp | 278 ++++++++++++++++++++++++
 4 files changed, 394 insertions(+)
 create mode 100644 src/compiler/nir/tests/negative_equal_tests.cpp

diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index 3fec363691d..18dea5eeb2b 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -236,4 +236,16 @@ if with_tests
       link_with : libmesa_util,
     )
   )
+
+  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 1ce7bcb9df1..fee2c1c150b 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -887,6 +887,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 9cb9ed43e8b..a8e47ff874a 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))
 
@@ -228,6 +229,103 @@ 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);
+
+   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;
+}
-- 
2.14.4



More information about the mesa-dev mailing list