From 8957c6b887ff09f44e7b491e7a0551e94a265b8d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 30 Oct 2013 23:56:18 -0700 Subject: [PATCH] glsl: Move the CSE equality functions to the ir class. I want to reuse them in opt_algebraic. v2: Merge in Chris Forbes's break fix. Reviewed-by: Jordan Justen --- src/glsl/Makefile.sources | 1 + src/glsl/ir.h | 22 +++++ src/glsl/ir_equals.cpp | 198 ++++++++++++++++++++++++++++++++++++++ src/glsl/opt_cse.cpp | 180 +--------------------------------- 4 files changed, 222 insertions(+), 179 deletions(-) create mode 100644 src/glsl/ir_equals.cpp diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources index 744b0adcf5a..2e81deddabb 100644 --- a/src/glsl/Makefile.sources +++ b/src/glsl/Makefile.sources @@ -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 \ diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 2f06fb9eaa8..7859702ed01 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -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 index 00000000000..7cfe1e66ba8 --- /dev/null +++ b/src/glsl/ir_equals.cpp @@ -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; +} diff --git a/src/glsl/opt_cse.cpp b/src/glsl/opt_cse.cpp index c53b4c6e737..8f73940d854 100644 --- a/src/glsl/opt_cse.cpp +++ b/src/glsl/opt_cse.cpp @@ -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) { -- 2.30.2