Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-29 Thread Jason Ekstrand
On Wed, Aug 29, 2018 at 3:19 PM Caio Marcelo de Oliveira Filho <
caio.olive...@intel.com> wrote:

> Jason Ekstrand  writes:
>
> >> >> +static bool
> >> >> +remove_dead_write_vars_local(struct state *state, nir_block *block)
> >> >> +{
> >> >> +   bool progress = false;
> >> >> +
> >> >> +   struct util_dynarray unused_writes;
> >> >> +   util_dynarray_init(&unused_writes, state->mem_ctx);
> >> >> +
> >> >> +   nir_foreach_instr_safe(instr, block) {
> >> >>
> >> >
> >> > It wouldn't hurt to add a case for call instructions which does a
> barrier
> >> > on everything I mentioned below as well as globals and locals.
> >>
> >> Makes sense.  But I don't get locals are affect?  Is this to cover the
> >> parameters being passed to the call?
> >>
> >
> > Because a deref to a local might be passed in as a parameter.  This is
> the
> > way pass-by-reference works for SPIR-V.
>
> Will the parameter appear to the new function as local too?  If so, will
> they be tagged in a way I can identify the derefs?
>

They'll appear as writes to casts whose source is a load_param intrinsic.


> I'm thinking about what to do with unused writes for locals at the end
> of a function.  If it's the main function, we can just remove them, but
> depending on the answer of the question above, it is not so clear for
> non-main functions.
>

Yeah... That's a bit sticky and I'm not sure what the right answer is.  I
guess we could, in theory, have a new "param" mode which is sort-of like a
local only it crosses function boundaries.  I haven't given that much
though.  However, given that functions are always inlined right now, that's
not something we need to deal with just yet.

--Jason
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-29 Thread Caio Marcelo de Oliveira Filho
Jason Ekstrand  writes:

>> >> +static bool
>> >> +remove_dead_write_vars_local(struct state *state, nir_block *block)
>> >> +{
>> >> +   bool progress = false;
>> >> +
>> >> +   struct util_dynarray unused_writes;
>> >> +   util_dynarray_init(&unused_writes, state->mem_ctx);
>> >> +
>> >> +   nir_foreach_instr_safe(instr, block) {
>> >>
>> >
>> > It wouldn't hurt to add a case for call instructions which does a barrier
>> > on everything I mentioned below as well as globals and locals.
>>
>> Makes sense.  But I don't get locals are affect?  Is this to cover the
>> parameters being passed to the call?
>>
>
> Because a deref to a local might be passed in as a parameter.  This is the
> way pass-by-reference works for SPIR-V.

Will the parameter appear to the new function as local too?  If so, will
they be tagged in a way I can identify the derefs?

I'm thinking about what to do with unused writes for locals at the end
of a function.  If it's the main function, we can just remove them, but
depending on the answer of the question above, it is not so clear for
non-main functions.


Thanks,
Caio

___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-28 Thread Jason Ekstrand
On Mon, Aug 27, 2018 at 4:55 PM Caio Marcelo de Oliveira Filho <
caio.olive...@intel.com> wrote:

> (Disregard the incomplete mail, still adapting to notmuch-emacs).
>
> Jason Ekstrand  writes:
>
> >> +static nir_deref_path *
> >> +get_path(struct state *state, nir_deref_instr *deref)
> >> +{
> >> +   struct hash_entry *entry = _mesa_hash_table_search(state->paths,
> >> deref);
> >> +   if (!entry) {
> >> +  nir_deref_path *path = linear_zalloc_child(state->path_lin_ctx,
> >> sizeof(nir_deref_path));
> >> +  nir_deref_path_init(path, deref, state->mem_ctx);
> >> +  _mesa_hash_table_insert(state->paths, deref, path);
> >> +  return path;
> >> +   } else {
> >> +  return entry->data;
> >> +   }
> >> +}
> >>
> >
> > Do you have any proof that this actually helps?  The deref_path stuff was
> > designed to be put on the stack and absolutely as efficient as possible.
> > In the common case of a deref chain with only a couple of elements, I
> would
> > expect to actually be more work to look it up in a hash table.
>
> Storing those makes more sense if you read the next commit (the
> "global").  Since I've created the "local" commit as an aid for
> reviewing (perhaps a failure), I did not wanted to change it too much.
>
> When I wrote there were some savings when measuring executions with
> perf.
>
> (...)
>
> >> +static bool
> >> +remove_dead_write_vars_local(struct state *state, nir_block *block)
> >> +{
> >> +   bool progress = false;
> >> +
> >> +   struct util_dynarray unused_writes;
> >> +   util_dynarray_init(&unused_writes, state->mem_ctx);
> >> +
> >> +   nir_foreach_instr_safe(instr, block) {
> >>
> >
> > It wouldn't hurt to add a case for call instructions which does a barrier
> > on everything I mentioned below as well as globals and locals.
>
> Makes sense.  But I don't get locals are affect?  Is this to cover the
> parameters being passed to the call?
>

Because a deref to a local might be passed in as a parameter.  This is the
way pass-by-reference works for SPIR-V.


> >
> >> +  if (instr->type != nir_instr_type_intrinsic)
> >> + continue;
> >> +
> >> +  nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
> >> +  switch (intrin->intrinsic) {
> >> +  case nir_intrinsic_barrier:
> >> +  case nir_intrinsic_memory_barrier: {
> >> + nir_variable_mode modes = ~(nir_var_local | nir_var_global |
> >> + nir_var_shader_in |
> nir_var_uniform);
> >>
> >
> > The only thing a barrier like this affects is shared, storage, and
> output.
> > Locals and globals can't cross between shader channels so there's no
> reason
> > to do anything with them on a barrier.  For inputs and uniforms, they're
> > never written anyway so there's no point in doing anything with them on a
> > barrier.
>
> This came from previous code, but except for "system values" it seems to
> do the right thing (note the ~).  Is the suggestion to use a "positive"
> enumeration, e.g.
>

Drp... I completely missed the ~.  Ignore my comment.  Yeah, we could throw
in system values. :D
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-27 Thread Caio Marcelo de Oliveira Filho
(Disregard the incomplete mail, still adapting to notmuch-emacs).

Jason Ekstrand  writes:

>> +static nir_deref_path *
>> +get_path(struct state *state, nir_deref_instr *deref)
>> +{
>> +   struct hash_entry *entry = _mesa_hash_table_search(state->paths,
>> deref);
>> +   if (!entry) {
>> +  nir_deref_path *path = linear_zalloc_child(state->path_lin_ctx,
>> sizeof(nir_deref_path));
>> +  nir_deref_path_init(path, deref, state->mem_ctx);
>> +  _mesa_hash_table_insert(state->paths, deref, path);
>> +  return path;
>> +   } else {
>> +  return entry->data;
>> +   }
>> +}
>>
>
> Do you have any proof that this actually helps?  The deref_path stuff was
> designed to be put on the stack and absolutely as efficient as possible.
> In the common case of a deref chain with only a couple of elements, I would
> expect to actually be more work to look it up in a hash table.

Storing those makes more sense if you read the next commit (the
"global").  Since I've created the "local" commit as an aid for
reviewing (perhaps a failure), I did not wanted to change it too much.

When I wrote there were some savings when measuring executions with
perf.

(...)

>> +static bool
>> +remove_dead_write_vars_local(struct state *state, nir_block *block)
>> +{
>> +   bool progress = false;
>> +
>> +   struct util_dynarray unused_writes;
>> +   util_dynarray_init(&unused_writes, state->mem_ctx);
>> +
>> +   nir_foreach_instr_safe(instr, block) {
>>
>
> It wouldn't hurt to add a case for call instructions which does a barrier
> on everything I mentioned below as well as globals and locals.

Makes sense.  But I don't get locals are affect?  Is this to cover the
parameters being passed to the call?

>
>> +  if (instr->type != nir_instr_type_intrinsic)
>> + continue;
>> +
>> +  nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
>> +  switch (intrin->intrinsic) {
>> +  case nir_intrinsic_barrier:
>> +  case nir_intrinsic_memory_barrier: {
>> + nir_variable_mode modes = ~(nir_var_local | nir_var_global |
>> + nir_var_shader_in | nir_var_uniform);
>>
>
> The only thing a barrier like this affects is shared, storage, and output.
> Locals and globals can't cross between shader channels so there's no reason
> to do anything with them on a barrier.  For inputs and uniforms, they're
> never written anyway so there's no point in doing anything with them on a
> barrier.

This came from previous code, but except for "system values" it seems to
do the right thing (note the ~).  Is the suggestion to use a "positive"
enumeration, e.g.

clear_unused_for_modes(&unused_writes, nir_var_shader_out |
   nir_var_shader_storage |
   nir_var_shared);



Thanks,
Caio
___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-27 Thread Caio Marcelo de Oliveira Filho
Jason Ekstrand  writes:

> On Wed, Aug 15, 2018 at 4:57 PM Caio Marcelo de Oliveira Filho <
> caio.olive...@intel.com> wrote:
>
>> Instead of doing this as part of the existing (local) copy prop vars
>> pass.  This is an intermediate step before changing both the dead
>> write and the copy prop vars to act on the whole program instead of on
>> local blocks.  The nature of data we store and the way we iterate is
>> different enough that would be awkward keeping those together.
>> ---
>>  src/compiler/Makefile.sources  |   1 +
>>  src/compiler/nir/meson.build   |   1 +
>>  src/compiler/nir/nir.h |   2 +
>>  src/compiler/nir/nir_opt_dead_write_vars.c | 243 +
>>  4 files changed, 247 insertions(+)
>>  create mode 100644 src/compiler/nir/nir_opt_dead_write_vars.c
>>
>> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
>> index 27a54e0be09..fa93ad08a16 100644
>> --- a/src/compiler/Makefile.sources
>> +++ b/src/compiler/Makefile.sources
>> @@ -274,6 +274,7 @@ NIR_FILES = \
>> nir/nir_opt_cse.c \
>> nir/nir_opt_dce.c \
>> nir/nir_opt_dead_cf.c \
>> +   nir/nir_opt_dead_write_vars.c \
>> nir/nir_opt_gcm.c \
>> nir/nir_opt_global_to_local.c \
>> nir/nir_opt_if.c \
>> diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
>> index 8708f9b069c..1c164a548a7 100644
>> --- a/src/compiler/nir/meson.build
>> +++ b/src/compiler/nir/meson.build
>> @@ -158,6 +158,7 @@ files_libnir = files(
>>'nir_opt_cse.c',
>>'nir_opt_dce.c',
>>'nir_opt_dead_cf.c',
>> +  'nir_opt_dead_write_vars.c',
>>'nir_opt_gcm.c',
>>'nir_opt_global_to_local.c',
>>'nir_opt_if.c',
>> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
>> index d0fa693884b..becf6e351c3 100644
>> --- a/src/compiler/nir/nir.h
>> +++ b/src/compiler/nir/nir.h
>> @@ -2968,6 +2968,8 @@ bool nir_opt_dce(nir_shader *shader);
>>
>>  bool nir_opt_dead_cf(nir_shader *shader);
>>
>> +bool nir_opt_dead_write_vars(nir_shader *shader);
>> +
>>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>>
>>  bool nir_opt_if(nir_shader *shader);
>> diff --git a/src/compiler/nir/nir_opt_dead_write_vars.c
>> b/src/compiler/nir/nir_opt_dead_write_vars.c
>> new file mode 100644
>> index 000..822bfa5595d
>> --- /dev/null
>> +++ b/src/compiler/nir/nir_opt_dead_write_vars.c
>> @@ -0,0 +1,243 @@
>> +/*
>> + * Copyright © 2018 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 "nir.h"
>> +#include "nir_builder.h"
>> +#include "nir_deref.h"
>> +
>> +#include "util/u_dynarray.h"
>> +
>> +struct state {
>> +   void *mem_ctx;
>> +
>> +   /* Maps nir_deref_instr to a corresponding nir_deref_path.  Avoids
>> +* rebuilding the paths for the same deref. */
>> +   struct hash_table *paths;
>> +   void *path_lin_ctx;
>> +};
>> +
>> +static nir_deref_path *
>> +get_path(struct state *state, nir_deref_instr *deref)
>> +{
>> +   struct hash_entry *entry = _mesa_hash_table_search(state->paths,
>> deref);
>> +   if (!entry) {
>> +  nir_deref_path *path = linear_zalloc_child(state->path_lin_ctx,
>> sizeof(nir_deref_path));
>> +  nir_deref_path_init(path, deref, state->mem_ctx);
>> +  _mesa_hash_table_insert(state->paths, deref, path);
>> +  return path;
>> +   } else {
>> +  return entry->data;
>> +   }
>> +}
>>
>
> Do you have any proof that this actually helps?  The deref_path stuff was
> designed to be put on the stack and absolutely as efficient as possible.
> In the common case of a deref chain with only a couple of elements, I would
> expect to actually be more work to look it up in a hash table.
>
>
>> +
>> +/* Entry for unused_writes arrays. */
>> +struct write_entry {
>> +   /* If NULL indicates the e

Re: [Mesa-dev] [PATCH 5/9] nir: Add a local dead write vars removal pass

2018-08-22 Thread Jason Ekstrand
On Wed, Aug 15, 2018 at 4:57 PM Caio Marcelo de Oliveira Filho <
caio.olive...@intel.com> wrote:

> Instead of doing this as part of the existing (local) copy prop vars
> pass.  This is an intermediate step before changing both the dead
> write and the copy prop vars to act on the whole program instead of on
> local blocks.  The nature of data we store and the way we iterate is
> different enough that would be awkward keeping those together.
> ---
>  src/compiler/Makefile.sources  |   1 +
>  src/compiler/nir/meson.build   |   1 +
>  src/compiler/nir/nir.h |   2 +
>  src/compiler/nir/nir_opt_dead_write_vars.c | 243 +
>  4 files changed, 247 insertions(+)
>  create mode 100644 src/compiler/nir/nir_opt_dead_write_vars.c
>
> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
> index 27a54e0be09..fa93ad08a16 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -274,6 +274,7 @@ NIR_FILES = \
> nir/nir_opt_cse.c \
> nir/nir_opt_dce.c \
> nir/nir_opt_dead_cf.c \
> +   nir/nir_opt_dead_write_vars.c \
> nir/nir_opt_gcm.c \
> nir/nir_opt_global_to_local.c \
> nir/nir_opt_if.c \
> diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
> index 8708f9b069c..1c164a548a7 100644
> --- a/src/compiler/nir/meson.build
> +++ b/src/compiler/nir/meson.build
> @@ -158,6 +158,7 @@ files_libnir = files(
>'nir_opt_cse.c',
>'nir_opt_dce.c',
>'nir_opt_dead_cf.c',
> +  'nir_opt_dead_write_vars.c',
>'nir_opt_gcm.c',
>'nir_opt_global_to_local.c',
>'nir_opt_if.c',
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index d0fa693884b..becf6e351c3 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2968,6 +2968,8 @@ bool nir_opt_dce(nir_shader *shader);
>
>  bool nir_opt_dead_cf(nir_shader *shader);
>
> +bool nir_opt_dead_write_vars(nir_shader *shader);
> +
>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>
>  bool nir_opt_if(nir_shader *shader);
> diff --git a/src/compiler/nir/nir_opt_dead_write_vars.c
> b/src/compiler/nir/nir_opt_dead_write_vars.c
> new file mode 100644
> index 000..822bfa5595d
> --- /dev/null
> +++ b/src/compiler/nir/nir_opt_dead_write_vars.c
> @@ -0,0 +1,243 @@
> +/*
> + * Copyright © 2018 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 "nir.h"
> +#include "nir_builder.h"
> +#include "nir_deref.h"
> +
> +#include "util/u_dynarray.h"
> +
> +struct state {
> +   void *mem_ctx;
> +
> +   /* Maps nir_deref_instr to a corresponding nir_deref_path.  Avoids
> +* rebuilding the paths for the same deref. */
> +   struct hash_table *paths;
> +   void *path_lin_ctx;
> +};
> +
> +static nir_deref_path *
> +get_path(struct state *state, nir_deref_instr *deref)
> +{
> +   struct hash_entry *entry = _mesa_hash_table_search(state->paths,
> deref);
> +   if (!entry) {
> +  nir_deref_path *path = linear_zalloc_child(state->path_lin_ctx,
> sizeof(nir_deref_path));
> +  nir_deref_path_init(path, deref, state->mem_ctx);
> +  _mesa_hash_table_insert(state->paths, deref, path);
> +  return path;
> +   } else {
> +  return entry->data;
> +   }
> +}
>

Do you have any proof that this actually helps?  The deref_path stuff was
designed to be put on the stack and absolutely as efficient as possible.
In the common case of a deref chain with only a couple of elements, I would
expect to actually be more work to look it up in a hash table.


> +
> +/* Entry for unused_writes arrays. */
> +struct write_entry {
> +   /* If NULL indicates the entry is free to be reused. */
> +   nir_intrinsic_instr *intrin;
> +   uintptr_t mask;
> +   nir_deref_path *path;
> +};
> +
> +static void
> +clear_unused_for_modes(