nir: merge and extend nir_opt_move_comparisons and nir_opt_move_load_ubo

v2: add to series
v3: update Makefile.sources
v4: don't remove a comment and break statement
v4: use nir_can_move_instr

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Rhys Perry
2019-07-24 19:23:21 +01:00
committed by Rhys Perry
parent da8ed68aca
commit 7740149852
9 changed files with 37 additions and 153 deletions

View File

@@ -247,7 +247,7 @@ radv_optimize_nir(struct nir_shader *shader, bool optimize_conservatively,
NIR_PASS(progress, shader, nir_opt_conditional_discard); NIR_PASS(progress, shader, nir_opt_conditional_discard);
NIR_PASS(progress, shader, nir_opt_shrink_load); NIR_PASS(progress, shader, nir_opt_shrink_load);
NIR_PASS(progress, shader, nir_opt_move_load_ubo); NIR_PASS(progress, shader, nir_opt_move, nir_move_load_ubo);
} }
nir_shader * nir_shader *

View File

@@ -1360,7 +1360,7 @@ v3d_optimize_nir(struct nir_shader *s)
NIR_PASS(progress, s, nir_opt_undef); NIR_PASS(progress, s, nir_opt_undef);
} while (progress); } while (progress);
NIR_PASS(progress, s, nir_opt_move_load_ubo); NIR_PASS(progress, s, nir_opt_move, nir_move_load_ubo);
} }
static int static int

View File

@@ -305,8 +305,7 @@ NIR_FILES = \
nir/nir_opt_intrinsics.c \ nir/nir_opt_intrinsics.c \
nir/nir_opt_loop_unroll.c \ nir/nir_opt_loop_unroll.c \
nir/nir_opt_large_constants.c \ nir/nir_opt_large_constants.c \
nir/nir_opt_move_comparisons.c \ nir/nir_opt_move.c \
nir/nir_opt_move_load_ubo.c \
nir/nir_opt_peephole_select.c \ nir/nir_opt_peephole_select.c \
nir/nir_opt_rematerialize_compares.c \ nir/nir_opt_rematerialize_compares.c \
nir/nir_opt_remove_phis.c \ nir/nir_opt_remove_phis.c \

View File

@@ -184,8 +184,7 @@ files_libnir = files(
'nir_opt_intrinsics.c', 'nir_opt_intrinsics.c',
'nir_opt_large_constants.c', 'nir_opt_large_constants.c',
'nir_opt_loop_unroll.c', 'nir_opt_loop_unroll.c',
'nir_opt_move_comparisons.c', 'nir_opt_move.c',
'nir_opt_move_load_ubo.c',
'nir_opt_peephole_select.c', 'nir_opt_peephole_select.c',
'nir_opt_rematerialize_compares.c', 'nir_opt_rematerialize_compares.c',
'nir_opt_remove_phis.c', 'nir_opt_remove_phis.c',

View File

@@ -3975,9 +3975,7 @@ bool nir_can_move_instr(nir_instr *instr, nir_move_options options);
bool nir_opt_sink(nir_shader *shader, nir_move_options options); bool nir_opt_sink(nir_shader *shader, nir_move_options options);
bool nir_opt_move_comparisons(nir_shader *shader); bool nir_opt_move(nir_shader *shader, nir_move_options options);
bool nir_opt_move_load_ubo(nir_shader *shader);
bool nir_opt_peephole_select(nir_shader *shader, unsigned limit, bool nir_opt_peephole_select(nir_shader *shader, unsigned limit,
bool indirect_load_ok, bool expensive_alu_ok); bool indirect_load_ok, bool expensive_alu_ok);

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright © 2016 Intel Corporation * Copyright © 2016 Intel Corporation
* Copyright © 2019 Valve Corporation
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -24,15 +25,15 @@
#include "nir.h" #include "nir.h"
/** /**
* \file nir_opt_move_comparisons.c * \file nir_opt_move.c
* *
* This pass moves ALU comparison operations just before their first use. * This pass can move various operations just before their first use inside the
* same basic block. Usually this is to reduce register usage. It's probably
* not a good idea to use this in an optimization loop.
* *
* It only moves instructions within a single basic block; cross-block * Moving comparisons is useful because many GPUs generate condition codes
* movement is left to global code motion. * for comparisons, and use predication for conditional selects and control
* * flow. In a sequence such as:
* Many GPUs generate condition codes for comparisons, and use predication
* for conditional selects and control flow. In a sequence such as:
* *
* vec1 32 ssa_1 = flt a b * vec1 32 ssa_1 = flt a b
* <some other operations> * <some other operations>
@@ -51,17 +52,14 @@
*/ */
static bool static bool
move_comparison_source(nir_src *src, nir_block *block, nir_instr *before) move_source(nir_src *src, nir_block *block, nir_instr *before, nir_move_options options)
{ {
if (!src->is_ssa) if (!src->is_ssa)
return false; return false;
nir_instr *src_instr = src->ssa->parent_instr; nir_instr *src_instr = src->ssa->parent_instr;
if (src_instr->block == block && if (src_instr->block == block && nir_can_move_instr(src_instr, options)) {
src_instr->type == nir_instr_type_alu &&
nir_alu_instr_is_comparison(nir_instr_as_alu(src_instr))) {
exec_node_remove(&src_instr->node); exec_node_remove(&src_instr->node);
if (before) if (before)
@@ -71,24 +69,28 @@ move_comparison_source(nir_src *src, nir_block *block, nir_instr *before)
return true; return true;
} }
return false; return false;
} }
struct source_cb_data {
bool *progress;
nir_move_options options;
};
static bool static bool
move_comparison_source_cb(nir_src *src, void *data) move_source_cb(nir_src *src, void *data_ptr)
{ {
bool *progress = data; struct source_cb_data data = *(struct source_cb_data*)data_ptr;
nir_instr *instr = src->parent_instr; nir_instr *instr = src->parent_instr;
if (move_comparison_source(src, instr->block, instr)) if (move_source(src, instr->block, instr, data.options))
*progress = true; *data.progress = true;
return true; /* nir_foreach_src should keep going */ return true; /* nir_foreach_src should keep going */
} }
static bool static bool
move_comparisons(nir_block *block) move(nir_block *block, nir_move_options options)
{ {
bool progress = false; bool progress = false;
@@ -106,7 +108,7 @@ move_comparisons(nir_block *block)
*/ */
nir_if *iff = nir_block_get_following_if(block); nir_if *iff = nir_block_get_following_if(block);
if (iff) { if (iff) {
progress |= move_comparison_source(&iff->condition, block, NULL); progress |= move_source(&iff->condition, block, NULL, options);
} }
nir_foreach_instr_reverse(instr, block) { nir_foreach_instr_reverse(instr, block) {
@@ -118,20 +120,23 @@ move_comparisons(nir_block *block)
* substantially more complicated and wouldn't gain us anything since * substantially more complicated and wouldn't gain us anything since
* the phi can't use a flag value anyway. * the phi can't use a flag value anyway.
*/ */
if (instr->type == nir_instr_type_phi) { if (instr->type == nir_instr_type_phi) {
/* We're going backwards so everything else is a phi too */ /* We're going backwards so everything else is a phi too */
break; break;
} else if (instr->type == nir_instr_type_alu) { } else if (instr->type == nir_instr_type_alu) {
/* Walk ALU instruction sources backwards so that bcsel's boolean /* Walk ALU instruction sources backwards so that bcsel's boolean
* condition is processed last. * condition is processed last for when comparisons are being moved.
*/ */
nir_alu_instr *alu = nir_instr_as_alu(instr); nir_alu_instr *alu = nir_instr_as_alu(instr);
for (int i = nir_op_infos[alu->op].num_inputs - 1; i >= 0; i--) { for (int i = nir_op_infos[alu->op].num_inputs - 1; i >= 0; i--) {
progress |= move_comparison_source(&alu->src[i].src, progress |= move_source(&alu->src[i].src, block, instr, options);
block, instr);
} }
} else { } else {
nir_foreach_src(instr, move_comparison_source_cb, &progress); struct source_cb_data data;
data.progress = &progress;
data.options = options;
nir_foreach_src(instr, move_source_cb, &data);
} }
} }
@@ -139,7 +144,7 @@ move_comparisons(nir_block *block)
} }
bool bool
nir_opt_move_comparisons(nir_shader *shader) nir_opt_move(nir_shader *shader, nir_move_options options)
{ {
bool progress = false; bool progress = false;
@@ -148,7 +153,7 @@ nir_opt_move_comparisons(nir_shader *shader)
continue; continue;
nir_foreach_block(block, func->impl) { nir_foreach_block(block, func->impl) {
if (move_comparisons(block)) { if (move(block, options)) {
nir_metadata_preserve(func->impl, nir_metadata_block_index | nir_metadata_preserve(func->impl, nir_metadata_block_index |
nir_metadata_dominance | nir_metadata_dominance |
nir_metadata_live_ssa_defs); nir_metadata_live_ssa_defs);

View File

@@ -1,117 +0,0 @@
/*
* Copyright © 2016 Intel Corporation
* Copyright © 2018 Valve 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 "nir.h"
/**
* \file nir_opt_move_load_ubo.c
*
* This pass moves load UBO operations just before their first use inside
* the same basic block.
*/
static bool
move_load_ubo_source(nir_src *src, nir_block *block, nir_instr *before)
{
if (!src->is_ssa)
return false;
nir_instr *src_instr = src->ssa->parent_instr;
if (src_instr->block == block &&
src_instr->type == nir_instr_type_intrinsic &&
nir_instr_as_intrinsic(src_instr)->intrinsic == nir_intrinsic_load_ubo) {
exec_node_remove(&src_instr->node);
if (before)
exec_node_insert_node_before(&before->node, &src_instr->node);
else
exec_list_push_tail(&block->instr_list, &src_instr->node);
return true;
}
return false;
}
static bool
move_load_ubo_source_cb(nir_src *src, void *data)
{
bool *progress = data;
nir_instr *instr = src->parent_instr;
if (move_load_ubo_source(src, instr->block, instr))
*progress = true;
return true; /* nir_foreach_src should keep going */
}
static bool
move_load_ubo(nir_block *block)
{
bool progress = false;
nir_if *iff = nir_block_get_following_if(block);
if (iff) {
progress |= move_load_ubo_source(&iff->condition, block, NULL);
}
nir_foreach_instr_reverse(instr, block) {
if (instr->type == nir_instr_type_phi) {
/* We're going backwards so everything else is a phi too */
} else if (instr->type == nir_instr_type_alu) {
nir_alu_instr *alu = nir_instr_as_alu(instr);
for (int i = nir_op_infos[alu->op].num_inputs - 1; i >= 0; i--) {
progress |= move_load_ubo_source(&alu->src[i].src, block, instr);
}
} else {
nir_foreach_src(instr, move_load_ubo_source_cb, &progress);
}
}
return progress;
}
bool
nir_opt_move_load_ubo(nir_shader *shader)
{
bool progress = false;
nir_foreach_function(func, shader) {
if (!func->impl)
continue;
nir_foreach_block(block, func->impl) {
if (move_load_ubo(block)) {
nir_metadata_preserve(func->impl, nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_live_ssa_defs);
progress = true;
}
}
}
return progress;
}

View File

@@ -1079,7 +1079,7 @@ ir2_nir_compile(struct ir2_context *ctx, bool binning)
OPT_V(ctx->nir, nir_copy_prop); OPT_V(ctx->nir, nir_copy_prop);
OPT_V(ctx->nir, nir_opt_dce); OPT_V(ctx->nir, nir_opt_dce);
OPT_V(ctx->nir, nir_opt_move_comparisons); OPT_V(ctx->nir, nir_opt_move, nir_move_comparisons);
OPT_V(ctx->nir, nir_lower_int_to_float); OPT_V(ctx->nir, nir_lower_int_to_float);
OPT_V(ctx->nir, nir_lower_bool_to_float); OPT_V(ctx->nir, nir_lower_bool_to_float);

View File

@@ -875,7 +875,7 @@ brw_postprocess_nir(nir_shader *nir, const struct brw_compiler *compiler,
OPT(nir_lower_to_source_mods, nir_lower_all_source_mods); OPT(nir_lower_to_source_mods, nir_lower_all_source_mods);
OPT(nir_copy_prop); OPT(nir_copy_prop);
OPT(nir_opt_dce); OPT(nir_opt_dce);
OPT(nir_opt_move_comparisons); OPT(nir_opt_move, nir_move_comparisons);
OPT(nir_lower_bool_to_int32); OPT(nir_lower_bool_to_int32);