summaryrefslogtreecommitdiff
path: root/src/compiler/nir/nir_opt_comparison_pre.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/nir/nir_opt_comparison_pre.c')
-rw-r--r--src/compiler/nir/nir_opt_comparison_pre.c109
1 files changed, 65 insertions, 44 deletions
diff --git a/src/compiler/nir/nir_opt_comparison_pre.c b/src/compiler/nir/nir_opt_comparison_pre.c
index f48dbe59d04..614bc469086 100644
--- a/src/compiler/nir/nir_opt_comparison_pre.c
+++ b/src/compiler/nir/nir_opt_comparison_pre.c
@@ -21,10 +21,10 @@
* IN THE SOFTWARE.
*/
+#include "util/u_vector.h"
+#include "nir_builder.h"
#include "nir_instr_set.h"
#include "nir_search_helpers.h"
-#include "nir_builder.h"
-#include "util/u_vector.h"
/* Partial redundancy elimination of compares
*
@@ -82,12 +82,12 @@ block_queue_finish(struct block_queue *bq)
{
struct block_instructions *n;
- while ((n = (struct block_instructions *) exec_list_pop_head(&bq->blocks)) != NULL) {
+ while ((n = (struct block_instructions *)exec_list_pop_head(&bq->blocks)) != NULL) {
u_vector_finish(&n->instructions);
free(n);
}
- while ((n = (struct block_instructions *) exec_list_pop_head(&bq->reusable_blocks)) != NULL) {
+ while ((n = (struct block_instructions *)exec_list_pop_head(&bq->reusable_blocks)) != NULL) {
free(n);
}
}
@@ -96,7 +96,7 @@ static struct block_instructions *
push_block(struct block_queue *bq)
{
struct block_instructions *bi =
- (struct block_instructions *) exec_list_pop_head(&bq->reusable_blocks);
+ (struct block_instructions *)exec_list_pop_head(&bq->reusable_blocks);
if (bi == NULL) {
bi = calloc(1, sizeof(struct block_instructions));
@@ -105,9 +105,7 @@ push_block(struct block_queue *bq)
return NULL;
}
- if (!u_vector_init(&bi->instructions,
- sizeof(nir_alu_instr *),
- 8 * sizeof(nir_alu_instr *))) {
+ if (!u_vector_init_pow2(&bi->instructions, 8, sizeof(nir_alu_instr *))) {
free(bi);
return NULL;
}
@@ -135,6 +133,34 @@ add_instruction_for_block(struct block_instructions *bi,
*data = alu;
}
+/**
+ * Determine if the ALU instruction is used by an if-condition or used by a
+ * logic-not that is used by an if-condition.
+ */
+static bool
+is_compatible_condition(const nir_alu_instr *instr)
+{
+ if (is_used_by_if(instr))
+ return true;
+
+ nir_foreach_use(src, &instr->def) {
+ const nir_instr *const user_instr = nir_src_parent_instr(src);
+
+ if (user_instr->type != nir_instr_type_alu)
+ continue;
+
+ const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
+
+ if (user_alu->op != nir_op_inot)
+ continue;
+
+ if (is_used_by_if(user_alu))
+ return true;
+ }
+
+ return false;
+}
+
static void
rewrite_compare_instruction(nir_builder *bld, nir_alu_instr *orig_cmp,
nir_alu_instr *orig_add, bool zero_on_left)
@@ -153,19 +179,19 @@ rewrite_compare_instruction(nir_builder *bld, nir_alu_instr *orig_cmp,
* zero_on_left is false, the resulting compare instruction is (fcmp,
* (fadd, x, y), 0.0) and x = a and y = -b.
*/
- nir_ssa_def *const a = nir_ssa_for_alu_src(bld, orig_cmp, 0);
- nir_ssa_def *const b = nir_ssa_for_alu_src(bld, orig_cmp, 1);
+ nir_def *const a = nir_ssa_for_alu_src(bld, orig_cmp, 0);
+ nir_def *const b = nir_ssa_for_alu_src(bld, orig_cmp, 1);
- nir_ssa_def *const fadd = zero_on_left
- ? nir_fadd(bld, b, nir_fneg(bld, a))
- : nir_fadd(bld, a, nir_fneg(bld, b));
+ nir_def *const fadd = zero_on_left
+ ? nir_fadd(bld, b, nir_fneg(bld, a))
+ : nir_fadd(bld, a, nir_fneg(bld, b));
- nir_ssa_def *const zero =
- nir_imm_floatN_t(bld, 0.0, orig_add->dest.dest.ssa.bit_size);
+ nir_def *const zero =
+ nir_imm_floatN_t(bld, 0.0, orig_add->def.bit_size);
- nir_ssa_def *const cmp = zero_on_left
- ? nir_build_alu(bld, orig_cmp->op, zero, fadd, NULL, NULL)
- : nir_build_alu(bld, orig_cmp->op, fadd, zero, NULL, NULL);
+ nir_def *const cmp = zero_on_left
+ ? nir_build_alu(bld, orig_cmp->op, zero, fadd, NULL, NULL)
+ : nir_build_alu(bld, orig_cmp->op, fadd, zero, NULL, NULL);
/* Generating extra moves of the results is the easy way to make sure the
* writemasks match the original instructions. Later optimization passes
@@ -173,27 +199,25 @@ rewrite_compare_instruction(nir_builder *bld, nir_alu_instr *orig_cmp,
* nir_search.c).
*/
nir_alu_instr *mov_add = nir_alu_instr_create(bld->shader, nir_op_mov);
- mov_add->dest.write_mask = orig_add->dest.write_mask;
- nir_ssa_dest_init(&mov_add->instr, &mov_add->dest.dest,
- orig_add->dest.dest.ssa.num_components,
- orig_add->dest.dest.ssa.bit_size, NULL);
+ nir_def_init(&mov_add->instr, &mov_add->def,
+ orig_add->def.num_components,
+ orig_add->def.bit_size);
mov_add->src[0].src = nir_src_for_ssa(fadd);
nir_builder_instr_insert(bld, &mov_add->instr);
nir_alu_instr *mov_cmp = nir_alu_instr_create(bld->shader, nir_op_mov);
- mov_cmp->dest.write_mask = orig_cmp->dest.write_mask;
- nir_ssa_dest_init(&mov_cmp->instr, &mov_cmp->dest.dest,
- orig_cmp->dest.dest.ssa.num_components,
- orig_cmp->dest.dest.ssa.bit_size, NULL);
+ nir_def_init(&mov_cmp->instr, &mov_cmp->def,
+ orig_cmp->def.num_components,
+ orig_cmp->def.bit_size);
mov_cmp->src[0].src = nir_src_for_ssa(cmp);
nir_builder_instr_insert(bld, &mov_cmp->instr);
- nir_ssa_def_rewrite_uses(&orig_cmp->dest.dest.ssa,
- &mov_cmp->dest.dest.ssa);
- nir_ssa_def_rewrite_uses(&orig_add->dest.dest.ssa,
- &mov_add->dest.dest.ssa);
+ nir_def_rewrite_uses(&orig_cmp->def,
+ &mov_cmp->def);
+ nir_def_rewrite_uses(&orig_add->def,
+ &mov_add->def);
/* We know these have no more uses because we just rewrote them all, so we
* can remove them.
@@ -229,13 +253,10 @@ comparison_pre_block(nir_block *block, struct block_queue *bq, nir_builder *bld)
nir_alu_instr *const alu = nir_instr_as_alu(instr);
- if (alu->dest.dest.ssa.num_components != 1)
- continue;
-
- if (alu->dest.saturate)
+ if (alu->def.num_components != 1)
continue;
- static const uint8_t swizzle[NIR_MAX_VEC_COMPONENTS] = {0};
+ static const uint8_t swizzle[NIR_MAX_VEC_COMPONENTS] = { 0 };
switch (alu->op) {
case nir_op_fadd: {
@@ -243,13 +264,14 @@ comparison_pre_block(nir_block *block, struct block_queue *bq, nir_builder *bld)
* instructions that dominate it.
*/
struct block_instructions *b =
- (struct block_instructions *) exec_list_get_head_raw(&bq->blocks);
+ (struct block_instructions *)exec_list_get_head_raw(&bq->blocks);
while (b->node.next != NULL) {
nir_alu_instr **a;
bool rewrote_compare = false;
- u_vector_foreach(a, &b->instructions) {
+ u_vector_foreach(a, &b->instructions)
+ {
nir_alu_instr *const cmp = *a;
if (cmp == NULL)
@@ -309,7 +331,7 @@ comparison_pre_block(nir_block *block, struct block_queue *bq, nir_builder *bld)
break;
}
- b = (struct block_instructions *) b->node.next;
+ b = (struct block_instructions *)b->node.next;
}
break;
@@ -322,7 +344,7 @@ comparison_pre_block(nir_block *block, struct block_queue *bq, nir_builder *bld)
/* If the instruction is a comparison that is used by an if-statement
* and neither operand is immediate value 0, add it to the set.
*/
- if (is_used_by_if(alu) &&
+ if (is_compatible_condition(alu) &&
is_not_const_zero(NULL, alu, 0, 1, swizzle) &&
is_not_const_zero(NULL, alu, 1, 1, swizzle))
add_instruction_for_block(bi, alu);
@@ -353,7 +375,7 @@ nir_opt_comparison_pre_impl(nir_function_impl *impl)
nir_builder bld;
block_queue_init(&bq);
- nir_builder_init(&bld, impl);
+ bld = nir_builder_create(impl);
nir_metadata_require(impl, nir_metadata_dominance);
@@ -364,7 +386,7 @@ nir_opt_comparison_pre_impl(nir_function_impl *impl)
if (progress) {
nir_metadata_preserve(impl, nir_metadata_block_index |
- nir_metadata_dominance);
+ nir_metadata_dominance);
} else {
nir_metadata_preserve(impl, nir_metadata_all);
}
@@ -377,9 +399,8 @@ nir_opt_comparison_pre(nir_shader *shader)
{
bool progress = false;
- nir_foreach_function(function, shader) {
- if (function->impl)
- progress |= nir_opt_comparison_pre_impl(function->impl);
+ nir_foreach_function_impl(impl, shader) {
+ progress |= nir_opt_comparison_pre_impl(impl);
}
return progress;