[Mesa-dev] [PATCH 2/4] i965/fs: use SSA values directly
Jason Ekstrand
jason at jlekstrand.net
Thu Jun 25 14:00:10 PDT 2015
On Thu, Jun 25, 2015 at 12:29 PM, Connor Abbott <cwabbott0 at gmail.com> wrote:
> Before, we would use registers, but set a magical "parent_instr" field
> to indicate that it was actually purely an SSA value (i.e., it wasn't
> involved in any phi nodes). Instead, just use SSA values directly, which
> lets us get rid of the hack and reduces memory usage since we're not
> allocating a nir_register for every value. It also makes our handling of
> load_const more consistent compared to the other instructions.
>
> Signed-off-by: Connor Abbott <cwabbott0 at gmail.com>
> ---
> src/mesa/drivers/dri/i965/brw_fs.h | 5 ++
> src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 73 ++++++++++++++--------
> src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 1 +
> src/mesa/drivers/dri/i965/brw_nir.c | 2 +-
> .../dri/i965/brw_nir_analyze_boolean_resolves.c | 12 ++--
> 5 files changed, 59 insertions(+), 34 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
> index 243baf6..a6fee35 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs.h
> +++ b/src/mesa/drivers/dri/i965/brw_fs.h
> @@ -249,6 +249,10 @@ public:
> void nir_emit_block(nir_block *block);
> void nir_emit_instr(nir_instr *instr);
> void nir_emit_alu(const brw::fs_builder &bld, nir_alu_instr *instr);
> + void nir_emit_load_const(const brw::fs_builder &bld,
> + nir_load_const_instr *instr);
> + void nir_emit_undef(const brw::fs_builder &bld,
> + nir_ssa_undef_instr *instr);
> void nir_emit_intrinsic(const brw::fs_builder &bld,
> nir_intrinsic_instr *instr);
> void nir_emit_texture(const brw::fs_builder &bld,
> @@ -345,6 +349,7 @@ public:
> unsigned max_grf;
>
> fs_reg *nir_locals;
> + fs_reg *nir_ssa_values;
> fs_reg *nir_globals;
> fs_reg nir_inputs;
> fs_reg nir_outputs;
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> index 59081ea..58896d7 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> @@ -366,6 +366,9 @@ fs_visitor::nir_emit_impl(nir_function_impl *impl)
> nir_locals[reg->index] = bld.vgrf(BRW_REGISTER_TYPE_F, size);
> }
>
> + nir_ssa_values = reralloc(mem_ctx, nir_ssa_values, fs_reg,
> + impl->ssa_alloc);
> +
> nir_emit_cf_list(&impl->body);
> }
>
> @@ -459,9 +462,11 @@ fs_visitor::nir_emit_instr(nir_instr *instr)
> break;
>
> case nir_instr_type_load_const:
> - /* We can hit these, but we do nothing now and use them as
> - * immediates later.
> - */
> + nir_emit_load_const(abld, nir_instr_as_load_const(instr));
> + break;
> +
> + case nir_instr_type_ssa_undef:
> + nir_emit_undef(abld, nir_instr_as_ssa_undef(instr));
> break;
>
> case nir_instr_type_jump:
> @@ -495,17 +500,12 @@ bool
> fs_visitor::optimize_frontfacing_ternary(nir_alu_instr *instr,
> const fs_reg &result)
> {
> - if (instr->src[0].src.is_ssa ||
> - !instr->src[0].src.reg.reg ||
> - !instr->src[0].src.reg.reg->parent_instr)
> - return false;
> -
> - if (instr->src[0].src.reg.reg->parent_instr->type !=
> - nir_instr_type_intrinsic)
> + if (!instr->src[0].src.is_ssa ||
> + instr->src[0].src.ssa->parent_instr->type != nir_instr_type_intrinsic)
> return false;
>
> nir_intrinsic_instr *src0 =
> - nir_instr_as_intrinsic(instr->src[0].src.reg.reg->parent_instr);
> + nir_instr_as_intrinsic(instr->src[0].src.ssa->parent_instr);
>
> if (src0->intrinsic != nir_intrinsic_load_front_face)
> return false;
> @@ -1146,6 +1146,25 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
> }
> }
>
> +void
> +fs_visitor::nir_emit_load_const(const fs_builder &bld,
> + nir_load_const_instr *instr)
> +{
> + fs_reg reg = bld.vgrf(BRW_REGISTER_TYPE_D, instr->def.num_components);
> +
> + for (unsigned i = 0; i < instr->def.num_components; i++)
> + bld.MOV(offset(reg, i), fs_reg(instr->value.i[i]));
> +
> + nir_ssa_values[instr->def.index] = reg;
> +}
> +
> +void
> +fs_visitor::nir_emit_undef(const fs_builder &bld, nir_ssa_undef_instr *instr)
> +{
> + nir_ssa_values[instr->def.index] = bld.vgrf(BRW_REGISTER_TYPE_D,
> + instr->def.num_components);
> +}
> +
> static fs_reg
> fs_reg_for_nir_reg(fs_visitor *v, nir_register *nir_reg,
> unsigned base_offset, nir_src *indirect)
> @@ -1171,30 +1190,30 @@ fs_reg_for_nir_reg(fs_visitor *v, nir_register *nir_reg,
> fs_reg
> fs_visitor::get_nir_src(nir_src src)
> {
> + fs_reg reg;
> if (src.is_ssa) {
> - assert(src.ssa->parent_instr->type == nir_instr_type_load_const);
> - nir_load_const_instr *load = nir_instr_as_load_const(src.ssa->parent_instr);
> - fs_reg reg = bld.vgrf(BRW_REGISTER_TYPE_D, src.ssa->num_components);
> -
> - for (unsigned i = 0; i < src.ssa->num_components; ++i)
> - bld.MOV(offset(reg, i), fs_reg(load->value.i[i]));
> -
> - return reg;
I understand that moving this stuff to emit_load_const has a very nice
unifying effect on the visitor. However, it also has a subtle effect
on generated code that's worth at least documenting in the commit
message. In particular, the MOV(dst, imm) is now in a different basic
block than the instruction that was using it. I don't think it's a
big deal, but you should put it in the commit message.
Reviewed-by: Jason Ekstrand <jason.ekstrand at intel.com>
> + reg = nir_ssa_values[src.ssa->index];
> } else {
> - fs_reg reg = fs_reg_for_nir_reg(this, src.reg.reg, src.reg.base_offset,
> - src.reg.indirect);
> -
> - /* to avoid floating-point denorm flushing problems, set the type by
> - * default to D - instructions that need floating point semantics will set
> - * this to F if they need to
> - */
> - return retype(reg, BRW_REGISTER_TYPE_D);
> + reg = fs_reg_for_nir_reg(this, src.reg.reg, src.reg.base_offset,
> + src.reg.indirect);
> }
> +
> + /* to avoid floating-point denorm flushing problems, set the type by
> + * default to D - instructions that need floating point semantics will set
> + * this to F if they need to
> + */
> + return retype(reg, BRW_REGISTER_TYPE_D);
> }
>
> fs_reg
> fs_visitor::get_nir_dest(nir_dest dest)
> {
> + if (dest.is_ssa) {
> + nir_ssa_values[dest.ssa.index] = bld.vgrf(BRW_REGISTER_TYPE_F,
> + dest.ssa.num_components);
> + return nir_ssa_values[dest.ssa.index];
> + }
> +
> return fs_reg_for_nir_reg(this, dest.reg.reg, dest.reg.base_offset,
> dest.reg.indirect);
> }
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> index 9a4bad6..90f6219 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
> @@ -2012,6 +2012,7 @@ fs_visitor::fs_visitor(const struct brw_compiler *compiler, void *log_data,
> this->no16_msg = NULL;
>
> this->nir_locals = NULL;
> + this->nir_ssa_values = NULL;
> this->nir_globals = NULL;
>
> memset(&this->payload, 0, sizeof(this->payload));
> diff --git a/src/mesa/drivers/dri/i965/brw_nir.c b/src/mesa/drivers/dri/i965/brw_nir.c
> index 3e154c1..d87e783 100644
> --- a/src/mesa/drivers/dri/i965/brw_nir.c
> +++ b/src/mesa/drivers/dri/i965/brw_nir.c
> @@ -156,7 +156,7 @@ brw_create_nir(struct brw_context *brw,
> nir_print_shader(nir, stderr);
> }
>
> - nir_convert_from_ssa(nir, true);
> + nir_convert_from_ssa(nir, false);
> nir_validate_shader(nir);
>
> /* This is the last pass we run before we start emitting stuff. It
> diff --git a/src/mesa/drivers/dri/i965/brw_nir_analyze_boolean_resolves.c b/src/mesa/drivers/dri/i965/brw_nir_analyze_boolean_resolves.c
> index f0b018c..9eb0ed9 100644
> --- a/src/mesa/drivers/dri/i965/brw_nir_analyze_boolean_resolves.c
> +++ b/src/mesa/drivers/dri/i965/brw_nir_analyze_boolean_resolves.c
> @@ -43,8 +43,8 @@
> static uint8_t
> get_resolve_status_for_src(nir_src *src)
> {
> - nir_instr *src_instr = nir_src_get_parent_instr(src);
> - if (src_instr) {
> + if (src->is_ssa) {
> + nir_instr *src_instr = src->ssa->parent_instr;
> uint8_t resolve_status = src_instr->pass_flags & BRW_NIR_BOOLEAN_MASK;
>
> /* If the source instruction needs resolve, then from the perspective
> @@ -66,8 +66,8 @@ get_resolve_status_for_src(nir_src *src)
> static bool
> src_mark_needs_resolve(nir_src *src, void *void_state)
> {
> - nir_instr *src_instr = nir_src_get_parent_instr(src);
> - if (src_instr) {
> + if (src->is_ssa) {
> + nir_instr *src_instr = src->ssa->parent_instr;
> uint8_t resolve_status = src_instr->pass_flags & BRW_NIR_BOOLEAN_MASK;
>
> /* If the source instruction is unresolved, then mark it as needing
> @@ -172,11 +172,11 @@ analyze_boolean_resolves_block(nir_block *block, void *void_state)
> resolve_status = BRW_NIR_NON_BOOLEAN;
> }
>
> - /* If the destination is SSA-like, go ahead allow unresolved booleans.
> + /* If the destination is SSA, go ahead allow unresolved booleans.
> * If the destination register doesn't have a well-defined parent_instr
> * we need to resolve immediately.
> */
> - if (alu->dest.dest.reg.reg->parent_instr == NULL &&
> + if (!alu->dest.dest.is_ssa &&
> resolve_status == BRW_NIR_BOOLEAN_UNRESOLVED) {
> resolve_status = BRW_NIR_BOOLEAN_NEEDS_RESOLVE;
> }
> --
> 2.4.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list