[Mesa-dev] [PATCH 19/23] glsl: Add a negative_equals method

Ian Romanick idr at freedesktop.org
Fri Mar 20 13:58:19 PDT 2015


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

Like equals(), but it determines that an expression has the negative
value of another expression.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/glsl/ir.h          | 17 ++++++++++++++
 src/glsl/ir_equals.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 385d661..98761e5 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -186,6 +186,17 @@ public:
    virtual bool equals(const ir_instruction *ir,
                        enum ir_node_type ignore = ir_type_unset) const;
 
+   /**
+    * IR equality method: Return true if the referenced instruction would
+    * return the negated value of this ir_instruction.
+    *
+    * 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 negative_equals(const ir_instruction *ir,
+                                enum ir_node_type ignore = ir_type_unset) const;
+
 protected:
    ir_instruction(enum ir_node_type t)
       : ir_type(t)
@@ -1602,6 +1613,9 @@ public:
    virtual bool equals(const ir_instruction *ir,
                        enum ir_node_type ignore = ir_type_unset) const;
 
+   virtual bool negative_equals(const ir_instruction *ir,
+                                enum ir_node_type ignore = ir_type_unset) const;
+
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
 
    /**
@@ -2228,6 +2242,9 @@ public:
    virtual bool equals(const ir_instruction *ir,
                        enum ir_node_type ignore = ir_type_unset) const;
 
+   virtual bool negative_equals(const ir_instruction *ir,
+                                enum ir_node_type ignore = ir_type_unset) const;
+
    /**
     * 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
index d8066a0..5f5af5b 100644
--- a/src/glsl/ir_equals.cpp
+++ b/src/glsl/ir_equals.cpp
@@ -48,6 +48,12 @@ ir_instruction::equals(const ir_instruction *, enum ir_node_type) const
 }
 
 bool
+ir_instruction::negative_equals(const ir_instruction *, enum ir_node_type) const
+{
+   return false;
+}
+
+bool
 ir_constant::equals(const ir_instruction *ir, enum ir_node_type) const
 {
    const ir_constant *other = ((ir_instruction *)ir)->as_constant();
@@ -66,6 +72,21 @@ ir_constant::equals(const ir_instruction *ir, enum ir_node_type) const
 }
 
 bool
+ir_constant::negative_equals(const ir_instruction *ir, enum ir_node_type) const
+{
+   const ir_constant *const other = ((ir_instruction *)ir)->as_constant();
+   if (!other || 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(const ir_instruction *ir,
                                 enum ir_node_type) const
 {
@@ -204,3 +225,46 @@ ir_expression::equals(const ir_instruction *ir, enum ir_node_type ignore) const
 
    return true;
 }
+
+bool
+ir_expression::negative_equals(const ir_instruction *ir,
+                               enum ir_node_type ignore) const
+{
+   /* The concept of "negative equality" doesn't apply to types that are not
+    * signed.
+    */
+   if (type->base_type != GLSL_TYPE_INT && type->base_type != GLSL_TYPE_FLOAT)
+      return false;
+
+   /* Handle the case of -x and x.
+    */
+   if (operation == ir_unop_neg)
+      return operands[0]->equals(ir, ignore);
+
+   const ir_expression *other = ((ir_instruction *)ir)->as_expression();
+   if (!other)
+      return false;
+
+   if (type != other->type)
+      return false;
+
+   /* Handle the case of x and -x.
+    */
+   if (other->operation == ir_unop_neg)
+      return this->equals(other->operands[0], ignore);
+
+   if (operation != other->operation)
+      return false;
+
+   if (operation != ir_binop_mul && operation != ir_binop_div)
+      return false;
+
+   /* For multiplication and division we want an odd-parity of negations on
+    * operands.  This means that 'x * y' negative-equals '-x * y', but
+    * 'x * -y' does not negative-equal '-x * y'.
+    */
+   return ((operands[0]->equals(other->operands[0], ignore) &&
+            operands[1]->negative_equals(other->operands[1], ignore)) ||
+           (operands[0]->negative_equals(other->operands[0], ignore) &&
+            operands[1]->equals(other->operands[1], ignore)));
+}
-- 
2.1.0



More information about the mesa-dev mailing list