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
>