glsl: Move the CSE equality functions to the ir class.
authorEric Anholt <eric@anholt.net>
Thu, 31 Oct 2013 06:56:18 +0000 (23:56 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 15 Nov 2013 19:33:07 +0000 (11:33 -0800)
I want to reuse them in opt_algebraic.

v2: Merge in Chris Forbes's break fix.

Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/glsl/Makefile.sources
src/glsl/ir.h
src/glsl/ir_equals.cpp [new file with mode: 0644]
src/glsl/opt_cse.cpp

index 744b0adcf5a901b837deb06eff10a5096ed99423..2e81deddabb9c79ee4a6a0ff78f38c14cdacab38 100644 (file)
@@ -33,6 +33,7 @@ LIBGLSL_FILES = \
        $(GLSL_SRCDIR)/ir_clone.cpp \
        $(GLSL_SRCDIR)/ir_constant_expression.cpp \
        $(GLSL_SRCDIR)/ir.cpp \
+       $(GLSL_SRCDIR)/ir_equals.cpp \
        $(GLSL_SRCDIR)/ir_expression_flattening.cpp \
        $(GLSL_SRCDIR)/ir_function_can_inline.cpp \
        $(GLSL_SRCDIR)/ir_function_detect_recursion.cpp \
index 2f06fb9eaa8023406c7927cdefa0c660504c2cf1..7859702ed015c7d2d2464048da2500d0f36030bb 100644 (file)
@@ -139,6 +139,16 @@ public:
    virtual class ir_jump *              as_jump()             { return NULL; }
    /*@}*/
 
+   /**
+    * IR equality method: Return true if the referenced instruction would
+    * return the same value as this one.
+    *
+    * This intended to be used for CSE and algebraic optimizations, on rvalues
+    * in particular.  No support for other instruction types (assignments,
+    * jumps, calls, etc.) is planned.
+    */
+   virtual bool equals(ir_instruction *ir);
+
 protected:
    ir_instruction()
    {
@@ -1405,6 +1415,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
    /**
@@ -1739,6 +1751,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Return a string representing the ir_texture_opcode.
     */
@@ -1843,6 +1857,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    bool is_lvalue() const
    {
       return val->is_lvalue() && !mask.has_duplicates;
@@ -1907,6 +1923,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -1965,6 +1983,8 @@ public:
       return this;
    }
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -2099,6 +2119,8 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
+   virtual bool equals(ir_instruction *ir);
+
    /**
     * Get a particular component of a constant as a specific type
     *
diff --git a/src/glsl/ir_equals.cpp b/src/glsl/ir_equals.cpp
new file mode 100644 (file)
index 0000000..7cfe1e6
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * 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 "ir.h"
+
+/**
+ * Helper for checking equality when one instruction might be NULL, since you
+ * can't access a's vtable in that case.
+ */
+static bool
+possibly_null_equals(ir_instruction *a, ir_instruction *b)
+{
+   if (!a || !b)
+      return !a && !b;
+
+   return a->equals(b);
+}
+
+/**
+ * The base equality function: Return not equal for anything we don't know
+ * about.
+ */
+bool
+ir_instruction::equals(ir_instruction *ir)
+{
+   return false;
+}
+
+bool
+ir_constant::equals(ir_instruction *ir)
+{
+   const ir_constant *other = ir->as_constant();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   for (unsigned i = 0; i < type->components(); i++) {
+      if (value.u[i] != other->value.u[i])
+         return false;
+   }
+
+   return true;
+}
+
+bool
+ir_dereference_variable::equals(ir_instruction *ir)
+{
+   const ir_dereference_variable *other = ir->as_dereference_variable();
+   if (!other)
+      return false;
+
+   return var == other->var;
+}
+
+bool
+ir_dereference_array::equals(ir_instruction *ir)
+{
+   const ir_dereference_array *other = ir->as_dereference_array();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   if (!array->equals(other->array))
+      return false;
+
+   if (!array_index->equals(other->array_index))
+      return false;
+
+   return true;
+}
+
+bool
+ir_swizzle::equals(ir_instruction *ir)
+{
+   const ir_swizzle *other = ir->as_swizzle();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   if (mask.x != other->mask.x ||
+       mask.y != other->mask.y ||
+       mask.z != other->mask.z ||
+       mask.w != other->mask.w) {
+      return false;
+   }
+
+   return val->equals(other->val);
+}
+
+bool
+ir_texture::equals(ir_instruction *ir)
+{
+   const ir_texture *other = ir->as_texture();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   if (op != other->op)
+      return false;
+
+   if (!possibly_null_equals(coordinate, other->coordinate))
+      return false;
+
+   if (!possibly_null_equals(projector, other->projector))
+      return false;
+
+   if (!possibly_null_equals(shadow_comparitor, other->shadow_comparitor))
+      return false;
+
+   if (!possibly_null_equals(offset, other->offset))
+      return false;
+
+   if (!sampler->equals(other->sampler))
+      return false;
+
+   switch (op) {
+   case ir_tex:
+   case ir_lod:
+   case ir_query_levels:
+      break;
+   case ir_txb:
+      if (!lod_info.bias->equals(other->lod_info.bias))
+         return false;
+      break;
+   case ir_txl:
+   case ir_txf:
+   case ir_txs:
+      if (!lod_info.lod->equals(other->lod_info.lod))
+         return false;
+      break;
+   case ir_txd:
+      if (!lod_info.grad.dPdx->equals(other->lod_info.grad.dPdx) ||
+          !lod_info.grad.dPdy->equals(other->lod_info.grad.dPdy))
+         return false;
+      break;
+   case ir_txf_ms:
+      if (!lod_info.sample_index->equals(other->lod_info.sample_index))
+         return false;
+      break;
+   case ir_tg4:
+      if (!lod_info.component->equals(other->lod_info.component))
+         return false;
+      break;
+   default:
+      assert(!"Unrecognized texture op");
+   }
+
+   return true;
+}
+
+bool
+ir_expression::equals(ir_instruction *ir)
+{
+   const ir_expression *other = ir->as_expression();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   if (operation != other->operation)
+      return false;
+
+   for (unsigned i = 0; i < get_num_operands(); i++) {
+      if (!operands[i]->equals(other->operands[i]))
+         return false;
+   }
+
+   return true;
+}
index c53b4c6e7378de3d52c57a603817f8958b16bac7..8f73940d85436c9a54955dfd6af081a88f233bcc 100644 (file)
@@ -243,184 +243,6 @@ is_cse_candidate(ir_rvalue *ir)
    return v.ok;
 }
 
-static bool
-equals(ir_rvalue *a, ir_rvalue *b);
-
-static bool
-equals(ir_constant *a, ir_constant *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   for (unsigned i = 0; i < a->type->components(); i++) {
-      if (a->value.u[i] != b->value.u[i])
-         return false;
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_dereference_variable *a, ir_dereference_variable *b)
-{
-   if (!a || !b)
-      return false;
-
-   return a->var == b->var;
-}
-
-static bool
-equals(ir_dereference_array *a, ir_dereference_array *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (!equals(a->array, b->array))
-      return false;
-
-   if (!equals(a->array_index, b->array_index))
-      return false;
-
-   return true;
-}
-
-static bool
-equals(ir_swizzle *a, ir_swizzle *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->mask.x != b->mask.x ||
-       a->mask.y != b->mask.y ||
-       a->mask.z != b->mask.z ||
-       a->mask.w != b->mask.w) {
-      return false;
-   }
-
-   return equals(a->val, b->val);
-}
-
-static bool
-equals(ir_texture *a, ir_texture *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->op != b->op)
-      return false;
-
-   if (!equals(a->coordinate, b->coordinate))
-      return false;
-
-   if (!equals(a->projector, b->projector))
-      return false;
-
-   if (!equals(a->shadow_comparitor, b->shadow_comparitor))
-      return false;
-
-   if (!equals(a->offset, b->offset))
-      return false;
-
-   if (!equals(a->sampler, b->sampler))
-      return false;
-
-   switch (a->op) {
-   case ir_tex:
-   case ir_lod:
-   case ir_query_levels:
-      break;
-   case ir_txb:
-      if (!equals(a->lod_info.bias, b->lod_info.bias))
-         return false;
-      break;
-   case ir_txl:
-   case ir_txf:
-   case ir_txs:
-      if (!equals(a->lod_info.lod, b->lod_info.lod))
-         return false;
-      break;
-   case ir_txd:
-      if (!equals(a->lod_info.grad.dPdx, b->lod_info.grad.dPdx) ||
-          !equals(a->lod_info.grad.dPdy, b->lod_info.grad.dPdy))
-         return false;
-      break;
-   case ir_txf_ms:
-      if (!equals(a->lod_info.sample_index, b->lod_info.sample_index))
-         return false;
-      break;
-   case ir_tg4:
-      if (!equals(a->lod_info.component, b->lod_info.component))
-         return false;
-      break;
-   default:
-      assert(!"Unrecognized texture op");
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_expression *a, ir_expression *b)
-{
-   if (!a || !b)
-      return false;
-
-   if (a->type != b->type)
-      return false;
-
-   if (a->operation != b->operation)
-      return false;
-
-   for (unsigned i = 0; i < a->get_num_operands(); i++) {
-      if (!equals(a->operands[i], b->operands[i]))
-         return false;
-   }
-
-   return true;
-}
-
-static bool
-equals(ir_rvalue *a, ir_rvalue *b)
-{
-   if (!a || !b)
-      return !a && !b;
-
-   if (a->type != b->type)
-      return false;
-
-   switch (a->ir_type) {
-   case ir_type_texture:
-      return equals(a->as_texture(), b->as_texture());
-
-   case ir_type_constant:
-      return equals(a->as_constant(), b->as_constant());
-
-   case ir_type_expression:
-      return equals(a->as_expression(), b->as_expression());
-
-   case ir_type_dereference_variable:
-      return equals(a->as_dereference_variable(), b->as_dereference_variable());
-
-   case ir_type_dereference_array:
-      return equals(a->as_dereference_array(), b->as_dereference_array());
-
-   case ir_type_swizzle:
-      return equals(a->as_swizzle(), b->as_swizzle());
-
-   default:
-      return false;
-   }
-}
-
 /**
  * Tries to find and return a reference to a previous computation of a given
  * expression.
@@ -441,7 +263,7 @@ cse_visitor::try_cse(ir_rvalue *rvalue)
          printf("\n");
       }
 
-      if (!equals(rvalue, *entry->val))
+      if (!rvalue->equals(*entry->val))
          continue;
 
       if (debug) {