[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