From: Ian Romanick <ian.d.roman...@intel.com> Like equals(), but it determines that an expression has the negative value of another expression.
Signed-off-by: Ian Romanick <ian.d.roman...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev