Re: [Mesa-dev] [PATCH 5/6] nir: Add a pass for moving SPIR-V continue blocks to the ends of loops
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
Jason Ekstrandwrites: > 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
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
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
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 >