Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-25 Thread Jason Ekstrand
On Dec 25, 2016 2:15 PM, "Mark Janes"  wrote:

Jason Ekstrand  writes:

> When shaders come in from SPIR-V, we handle continue blocks by placing
> the contents of the continue inside of a "if (!first_iteration)".  We do
> this so that we can properly handle the fact that continues in SPIR-V
> jump to the continue block at the end of the loop rather than jumping
> directly to the top of the loop like they do in NIR.  In particular, the
> increment step of a simple for loop ends up in the continue block.  This
> pass looks for this case in loops that don't actually have any continues
> and moves the continue contents to the end of the loop instead.  We need
> this because loop unrolling doesn't work if the increment is inside of a
> condition.
> ---
>  src/compiler/Makefile.sources |   1 +
>  src/compiler/nir/nir.h|   2 +
>  src/compiler/nir/nir_opt_if.c | 253 ++

>  3 files changed, 256 insertions(+)
>  create mode 100644 src/compiler/nir/nir_opt_if.c
>
> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
> index a0abede..6f701af 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -239,6 +239,7 @@ NIR_FILES = \
>   nir/nir_opt_dead_cf.c \
>   nir/nir_opt_gcm.c \
>   nir/nir_opt_global_to_local.c \
> + nir/nir_opt_if.c \
>   nir/nir_opt_loop_unroll.c \
>   nir/nir_opt_peephole_select.c \
>   nir/nir_opt_remove_phis.c \
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index a6c8956..7b582a6 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
>
>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>
> +bool nir_opt_if(nir_shader *shader);
> +
>  bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode
indirect_mask);
>
>  bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
> diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
> new file mode 100644
> index 000..5590684
> --- /dev/null
> +++ b/src/compiler/nir/nir_opt_if.c
> @@ -0,0 +1,253 @@
> +/*
> + * Copyright © 2016 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_control_flow.h"
> +
> +/**
> + * This optimization detects if statements at the tops of loops where the
> + * condition is a phi node of two constants and moves half of the if to
above
> + * the loop and the other half of the if to the end of the loop.  A
simple for
> + * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V
front-end,
> + * ends up looking something like this:
> + *
> + * vec1 32 ssa_0 = load_const (0x)
> + * vec1 32 ssa_1 = load_const (0x)
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *if ssa_2 {
> + *   block block_2:
> + *   vec1 32 ssa_4 = load_const (0x0001)
> + *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
> + *} else {
> + *   block block_3:
> + *}
> + *block block_4:
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + *}
> + *block block_7:
> + * }
> + *
> + * This turns it into something like this:
> + *
> + * // Stuff from block 1
> + * // Stuff from block 3
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + * 

Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-25 Thread Mark Janes
Jason Ekstrand  writes:

> When shaders come in from SPIR-V, we handle continue blocks by placing
> the contents of the continue inside of a "if (!first_iteration)".  We do
> this so that we can properly handle the fact that continues in SPIR-V
> jump to the continue block at the end of the loop rather than jumping
> directly to the top of the loop like they do in NIR.  In particular, the
> increment step of a simple for loop ends up in the continue block.  This
> pass looks for this case in loops that don't actually have any continues
> and moves the continue contents to the end of the loop instead.  We need
> this because loop unrolling doesn't work if the increment is inside of a
> condition.
> ---
>  src/compiler/Makefile.sources |   1 +
>  src/compiler/nir/nir.h|   2 +
>  src/compiler/nir/nir_opt_if.c | 253 
> ++
>  3 files changed, 256 insertions(+)
>  create mode 100644 src/compiler/nir/nir_opt_if.c
>
> diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
> index a0abede..6f701af 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -239,6 +239,7 @@ NIR_FILES = \
>   nir/nir_opt_dead_cf.c \
>   nir/nir_opt_gcm.c \
>   nir/nir_opt_global_to_local.c \
> + nir/nir_opt_if.c \
>   nir/nir_opt_loop_unroll.c \
>   nir/nir_opt_peephole_select.c \
>   nir/nir_opt_remove_phis.c \
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index a6c8956..7b582a6 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
>  
>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>  
> +bool nir_opt_if(nir_shader *shader);
> +
>  bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode 
> indirect_mask);
>  
>  bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
> diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
> new file mode 100644
> index 000..5590684
> --- /dev/null
> +++ b/src/compiler/nir/nir_opt_if.c
> @@ -0,0 +1,253 @@
> +/*
> + * Copyright © 2016 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_control_flow.h"
> +
> +/**
> + * This optimization detects if statements at the tops of loops where the
> + * condition is a phi node of two constants and moves half of the if to above
> + * the loop and the other half of the if to the end of the loop.  A simple 
> for
> + * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V front-end,
> + * ends up looking something like this:
> + *
> + * vec1 32 ssa_0 = load_const (0x)
> + * vec1 32 ssa_1 = load_const (0x)
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *if ssa_2 {
> + *   block block_2:
> + *   vec1 32 ssa_4 = load_const (0x0001)
> + *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
> + *} else {
> + *   block block_3:
> + *}
> + *block block_4:
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + *}
> + *block block_7:
> + * }
> + *
> + * This turns it into something like this:
> + *
> + * // Stuff from block 1
> + * // Stuff from block 3
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + *}
> + *block block_7:
> + *// Stuff from 

Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-21 Thread Timothy Arceri
On Wed, 2016-12-21 at 20:50 -0800, Jason Ekstrand wrote:
> On Dec 21, 2016 9:12 PM, "Timothy Arceri"  om> wrote:
> On Mon, 2016-12-19 at 20:11 -0800, Jason Ekstrand wrote:
> > When shaders come in from SPIR-V, we handle continue blocks by
> > placing
> > the contents of the continue inside of a "if
> (!first_iteration)".  We
> > do
> > this so that we can properly handle the fact that continues in
> SPIR-V
> > jump to the continue block at the end of the loop rather than
> jumping
> > directly to the top of the loop like they do in NIR.  In
> particular,
> > the
> > increment step of a simple for loop ends up in the continue
> > block.  This
> > pass looks for this case in loops that don't actually have any
> > continues
> > and moves the continue contents to the end of the loop instead.  We
> > need
> > this because loop unrolling doesn't work if the increment is inside
> > of a
> > condition.
> > ---
> >  src/compiler/Makefile.sources |   1 +
> >  src/compiler/nir/nir.h|   2 +
> >  src/compiler/nir/nir_opt_if.c | 253
> > ++
> >  3 files changed, 256 insertions(+)
> >  create mode 100644 src/compiler/nir/nir_opt_if.c
> >
> > diff --git a/src/compiler/Makefile.sources
> > b/src/compiler/Makefile.sources
> > index a0abede..6f701af 100644
> > --- a/src/compiler/Makefile.sources
> > +++ b/src/compiler/Makefile.sources
> > @@ -239,6 +239,7 @@ NIR_FILES = \
> >       nir/nir_opt_dead_cf.c \
> >       nir/nir_opt_gcm.c \
> >       nir/nir_opt_global_to_local.c \
> > +     nir/nir_opt_if.c \
> >       nir/nir_opt_loop_unroll.c \
> >       nir/nir_opt_peephole_select.c \
> >       nir/nir_opt_remove_phis.c \
> > diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> > index a6c8956..7b582a6 100644
> > --- a/src/compiler/nir/nir.h
> > +++ b/src/compiler/nir/nir.h
> > @@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
> >  
> >  bool nir_opt_gcm(nir_shader *shader, bool value_number);
> >  
> > +bool nir_opt_if(nir_shader *shader);
> > +
> >  bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode
> > indirect_mask);
> >  
> >  bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
> > diff --git a/src/compiler/nir/nir_opt_if.c
> > b/src/compiler/nir/nir_opt_if.c
> > new file mode 100644
> > index 000..5590684
> > --- /dev/null
> > +++ b/src/compiler/nir/nir_opt_if.c
> > @@ -0,0 +1,253 @@
> > +/*
> > + * Copyright © 2016 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_control_flow.h"
> > +
> > +/**
> > + * This optimization detects if statements at the tops of loops
> > where the
> > + * condition is a phi node of two constants and moves half of the
> if
> > to above
> > + * the loop and the other half of the if to the end of the
> loop.  A
> > simple for
> > + * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V
> > front-end,
> > + * ends up looking something like this:
> > + *
> > + * vec1 32 ssa_0 = load_const (0x)
> > + * vec1 32 ssa_1 = load_const (0x)
> > + * loop {
> > + *block block_1:
> > + *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
> > + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> > + *if ssa_2 {
> > + *   block block_2:
> > + *   vec1 32 ssa_4 = load_const (0x0001)
> > + *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
> > + *} else {
> > + *   block block_3:
> > + *}
> > + *block block_4:
> > + *vec1 32 ssa_6 = load_const (0x0004)
> > + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> > + *if ssa_7 {
> > + *   block block_5:
> > + *} else {
> > + *   block block_6:
> > + *   break
> > + *}
> > + *block 

Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-21 Thread Jason Ekstrand
On Dec 21, 2016 9:12 PM, "Timothy Arceri" 
wrote:

On Mon, 2016-12-19 at 20:11 -0800, Jason Ekstrand wrote:
> When shaders come in from SPIR-V, we handle continue blocks by
> placing
> the contents of the continue inside of a "if (!first_iteration)".  We
> do
> this so that we can properly handle the fact that continues in SPIR-V
> jump to the continue block at the end of the loop rather than jumping
> directly to the top of the loop like they do in NIR.  In particular,
> the
> increment step of a simple for loop ends up in the continue
> block.  This
> pass looks for this case in loops that don't actually have any
> continues
> and moves the continue contents to the end of the loop instead.  We
> need
> this because loop unrolling doesn't work if the increment is inside
> of a
> condition.
> ---
>  src/compiler/Makefile.sources |   1 +
>  src/compiler/nir/nir.h|   2 +
>  src/compiler/nir/nir_opt_if.c | 253
> ++
>  3 files changed, 256 insertions(+)
>  create mode 100644 src/compiler/nir/nir_opt_if.c
>
> diff --git a/src/compiler/Makefile.sources
> b/src/compiler/Makefile.sources
> index a0abede..6f701af 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -239,6 +239,7 @@ NIR_FILES = \
>   nir/nir_opt_dead_cf.c \
>   nir/nir_opt_gcm.c \
>   nir/nir_opt_global_to_local.c \
> + nir/nir_opt_if.c \
>   nir/nir_opt_loop_unroll.c \
>   nir/nir_opt_peephole_select.c \
>   nir/nir_opt_remove_phis.c \
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index a6c8956..7b582a6 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
>
>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>
> +bool nir_opt_if(nir_shader *shader);
> +
>  bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode
> indirect_mask);
>
>  bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
> diff --git a/src/compiler/nir/nir_opt_if.c
> b/src/compiler/nir/nir_opt_if.c
> new file mode 100644
> index 000..5590684
> --- /dev/null
> +++ b/src/compiler/nir/nir_opt_if.c
> @@ -0,0 +1,253 @@
> +/*
> + * Copyright © 2016 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_control_flow.h"
> +
> +/**
> + * This optimization detects if statements at the tops of loops
> where the
> + * condition is a phi node of two constants and moves half of the if
> to above
> + * the loop and the other half of the if to the end of the loop.  A
> simple for
> + * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V
> front-end,
> + * ends up looking something like this:
> + *
> + * vec1 32 ssa_0 = load_const (0x)
> + * vec1 32 ssa_1 = load_const (0x)
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *if ssa_2 {
> + *   block block_2:
> + *   vec1 32 ssa_4 = load_const (0x0001)
> + *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
> + *} else {
> + *   block block_3:
> + *}
> + *block block_4:
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + *}
> + *block block_7:
> + * }
> + *
> + * This turns it into something like this:
> + *
> + * // Stuff from block 1
> + * // Stuff from block 3
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block 

Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-21 Thread Timothy Arceri
On Mon, 2016-12-19 at 20:11 -0800, Jason Ekstrand wrote:
> When shaders come in from SPIR-V, we handle continue blocks by
> placing
> the contents of the continue inside of a "if (!first_iteration)".  We
> do
> this so that we can properly handle the fact that continues in SPIR-V
> jump to the continue block at the end of the loop rather than jumping
> directly to the top of the loop like they do in NIR.  In particular,
> the
> increment step of a simple for loop ends up in the continue
> block.  This
> pass looks for this case in loops that don't actually have any
> continues
> and moves the continue contents to the end of the loop instead.  We
> need
> this because loop unrolling doesn't work if the increment is inside
> of a
> condition.
> ---
>  src/compiler/Makefile.sources |   1 +
>  src/compiler/nir/nir.h|   2 +
>  src/compiler/nir/nir_opt_if.c | 253
> ++
>  3 files changed, 256 insertions(+)
>  create mode 100644 src/compiler/nir/nir_opt_if.c
> 
> diff --git a/src/compiler/Makefile.sources
> b/src/compiler/Makefile.sources
> index a0abede..6f701af 100644
> --- a/src/compiler/Makefile.sources
> +++ b/src/compiler/Makefile.sources
> @@ -239,6 +239,7 @@ NIR_FILES = \
>   nir/nir_opt_dead_cf.c \
>   nir/nir_opt_gcm.c \
>   nir/nir_opt_global_to_local.c \
> + nir/nir_opt_if.c \
>   nir/nir_opt_loop_unroll.c \
>   nir/nir_opt_peephole_select.c \
>   nir/nir_opt_remove_phis.c \
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index a6c8956..7b582a6 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
>  
>  bool nir_opt_gcm(nir_shader *shader, bool value_number);
>  
> +bool nir_opt_if(nir_shader *shader);
> +
>  bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode
> indirect_mask);
>  
>  bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
> diff --git a/src/compiler/nir/nir_opt_if.c
> b/src/compiler/nir/nir_opt_if.c
> new file mode 100644
> index 000..5590684
> --- /dev/null
> +++ b/src/compiler/nir/nir_opt_if.c
> @@ -0,0 +1,253 @@
> +/*
> + * Copyright © 2016 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_control_flow.h"
> +
> +/**
> + * This optimization detects if statements at the tops of loops
> where the
> + * condition is a phi node of two constants and moves half of the if
> to above
> + * the loop and the other half of the if to the end of the loop.  A
> simple for
> + * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V
> front-end,
> + * ends up looking something like this:
> + *
> + * vec1 32 ssa_0 = load_const (0x)
> + * vec1 32 ssa_1 = load_const (0x)
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *if ssa_2 {
> + *   block block_2:
> + *   vec1 32 ssa_4 = load_const (0x0001)
> + *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
> + *} else {
> + *   block block_3:
> + *}
> + *block block_4:
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> + *}
> + *block block_7:
> + * }
> + *
> + * This turns it into something like this:
> + *
> + * // Stuff from block 1
> + * // Stuff from block 3
> + * loop {
> + *block block_1:
> + *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
> + *vec1 32 ssa_6 = load_const (0x0004)
> + *vec1 32 ssa_7 = ilt ssa_5, ssa_6
> + *if ssa_7 {
> + *   block block_5:
> + *} else {
> + *   block block_6:
> + *   break
> 

[Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops

2016-12-19 Thread Jason Ekstrand
When shaders come in from SPIR-V, we handle continue blocks by placing
the contents of the continue inside of a "if (!first_iteration)".  We do
this so that we can properly handle the fact that continues in SPIR-V
jump to the continue block at the end of the loop rather than jumping
directly to the top of the loop like they do in NIR.  In particular, the
increment step of a simple for loop ends up in the continue block.  This
pass looks for this case in loops that don't actually have any continues
and moves the continue contents to the end of the loop instead.  We need
this because loop unrolling doesn't work if the increment is inside of a
condition.
---
 src/compiler/Makefile.sources |   1 +
 src/compiler/nir/nir.h|   2 +
 src/compiler/nir/nir_opt_if.c | 253 ++
 3 files changed, 256 insertions(+)
 create mode 100644 src/compiler/nir/nir_opt_if.c

diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
index a0abede..6f701af 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -239,6 +239,7 @@ NIR_FILES = \
nir/nir_opt_dead_cf.c \
nir/nir_opt_gcm.c \
nir/nir_opt_global_to_local.c \
+   nir/nir_opt_if.c \
nir/nir_opt_loop_unroll.c \
nir/nir_opt_peephole_select.c \
nir/nir_opt_remove_phis.c \
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index a6c8956..7b582a6 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2557,6 +2557,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
 
 bool nir_opt_gcm(nir_shader *shader, bool value_number);
 
+bool nir_opt_if(nir_shader *shader);
+
 bool nir_opt_loop_unroll(nir_shader *shader, nir_variable_mode indirect_mask);
 
 bool nir_opt_peephole_select(nir_shader *shader, unsigned limit);
diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c
new file mode 100644
index 000..5590684
--- /dev/null
+++ b/src/compiler/nir/nir_opt_if.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2016 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_control_flow.h"
+
+/**
+ * This optimization detects if statements at the tops of loops where the
+ * condition is a phi node of two constants and moves half of the if to above
+ * the loop and the other half of the if to the end of the loop.  A simple for
+ * loop "for (int i = 0; i < 4; i++)", when run through the SPIR-V front-end,
+ * ends up looking something like this:
+ *
+ * vec1 32 ssa_0 = load_const (0x)
+ * vec1 32 ssa_1 = load_const (0x)
+ * loop {
+ *block block_1:
+ *vec1 32 ssa_2 = phi block_0: ssa_0, block_7: ssa_5
+ *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
+ *if ssa_2 {
+ *   block block_2:
+ *   vec1 32 ssa_4 = load_const (0x0001)
+ *   vec1 32 ssa_5 = iadd ssa_2, ssa_4
+ *} else {
+ *   block block_3:
+ *}
+ *block block_4:
+ *vec1 32 ssa_6 = load_const (0x0004)
+ *vec1 32 ssa_7 = ilt ssa_5, ssa_6
+ *if ssa_7 {
+ *   block block_5:
+ *} else {
+ *   block block_6:
+ *   break
+ *}
+ *block block_7:
+ * }
+ *
+ * This turns it into something like this:
+ *
+ * // Stuff from block 1
+ * // Stuff from block 3
+ * loop {
+ *block block_1:
+ *vec1 32 ssa_3 = phi block_0: ssa_0, block_7: ssa_1
+ *vec1 32 ssa_6 = load_const (0x0004)
+ *vec1 32 ssa_7 = ilt ssa_5, ssa_6
+ *if ssa_7 {
+ *   block block_5:
+ *} else {
+ *   block block_6:
+ *   break
+ *}
+ *block block_7:
+ *// Stuff from block 1
+ *// Stuff from block 2
+ *vec1 32 ssa_4 = load_const (0x0001)
+ *vec1 32 ssa_5 = iadd ssa_2, ssa_4
+ * }
+ */
+static bool
+opt_peel_loop_initial_if(nir_loop *loop)
+{
+   nir_block *header_block = nir_loop_first_block(loop);
+   nir_block *prev_block =
+