<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Mar 7, 2018 at 6:47 AM, Bas Nieuwenhuizen <span dir="ltr"><<a href="mailto:bas@basnieuwenhuizen.nl" target="_blank">bas@basnieuwenhuizen.nl</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The old vote_eq implementation supported only booleans, but now<br>
we have to support arbitrary values, so use the read_first_invocation<br>
intrinsic + ballot.<br>
<br>
I took this as an opportunity to figure out how easy it was to do this<br>
in nir instead of in the nir_to_llvm pass, and it actually turned out<br>
pretty okay IMO. Only creating the pass is some extra code.<br></blockquote><div><br>We have nir_lower_subgroups for exactly this sort of thing.  You might 
as well put it in common code in case anyone else wants it.  Also, it means you can drop the boiler-plate. :-)  Just put it
 behind a flag lower_vote_to_cmp or something.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Reviewed-by: Dave Airlie <<a href="mailto:airlied@redhat.com">airlied@redhat.com</a>><br>
---<br>
 src/amd/Makefile.sources            |  1 +<br>
 src/amd/common/ac_lower_<wbr>subgroups.c | 92 ++++++++++++++++++++++++++++++<wbr>+++++++<br>
 src/amd/common/ac_nir_to_llvm.<wbr>c     |  8 ++--<br>
 src/amd/common/ac_nir_to_llvm.<wbr>h     |  2 +<br>
 src/amd/common/meson.build          |  1 +<br>
 5 files changed, 99 insertions(+), 5 deletions(-)<br>
 create mode 100644 src/amd/common/ac_lower_<wbr>subgroups.c<br>
<br>
diff --git a/src/amd/Makefile.sources b/src/amd/Makefile.sources<br>
index 10c4827e19..f57dd403c5 100644<br>
--- a/src/amd/Makefile.sources<br>
+++ b/src/amd/Makefile.sources<br>
@@ -44,6 +44,7 @@ AMD_COMPILER_FILES = \<br>
        common/ac_llvm_helper.cpp \<br>
        common/ac_llvm_util.c \<br>
        common/ac_llvm_util.h \<br>
+       common/ac_lower_subgroups.c \<br>
        common/ac_shader_abi.h \<br>
        common/ac_shader_info.c \<br>
        common/ac_shader_info.h \<br>
diff --git a/src/amd/common/ac_lower_<wbr>subgroups.c b/src/amd/common/ac_lower_<wbr>subgroups.c<br>
new file mode 100644<br>
index 0000000000..d0782b481b<br>
--- /dev/null<br>
+++ b/src/amd/common/ac_lower_<wbr>subgroups.c<br>
@@ -0,0 +1,92 @@<br>
+/*<br>
+ * Copyright © 2018 Google Inc.<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include "nir/nir.h"<br>
+#include "nir/nir_builder.h"<br>
+<br>
+#include "ac_nir_to_llvm.h"<br>
+<br>
+static nir_ssa_def *ac_lower_subgroups_intrin(<wbr>nir_builder *b, nir_intrinsic_instr *intrin)<br>
+{<br>
+       switch(intrin->intrinsic) {<br>
+       case nir_intrinsic_vote_ieq:<br>
+       case nir_intrinsic_vote_feq: {<br>
+               nir_intrinsic_instr *rfi =<br>
+                       nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_read_first_<wbr>invocation);<br>
+               nir_ssa_dest_init(&rfi->instr, &rfi->dest,<br>
+                                 1, intrin->src[0].ssa->bit_size, NULL);<br>
+               nir_src_copy(&rfi->src[0], &intrin->src[0], rfi);<br>
+               rfi->num_components = 1;<br>
+<br>
+               nir_ssa_def *is_ne;<br>
+               if (intrin->intrinsic == nir_intrinsic_vote_feq)<br>
+                       is_ne = nir_fne(b, &rfi->dest.ssa, intrin->src[0].ssa);<br>
+               else<br>
+                       is_ne = nir_ine(b, &rfi->dest.ssa, intrin->src[0].ssa);<br>
+<br>
+               nir_intrinsic_instr *ballot =<br>
+                       nir_intrinsic_instr_create(b-><wbr>shader, nir_intrinsic_ballot);<br>
+               nir_ssa_dest_init(&ballot-><wbr>instr, &ballot->dest,<br>
+                                 1, 64, NULL);<br>
+               ballot->src[0] = nir_src_for_ssa(is_ne);<br>
+               ballot->num_components = 1;<br>
+<br>
+               return nir_ieq(b, &ballot->dest.ssa, nir_imm_int64(b, 0));<br>
+       }<br>
+       default:<br>
+               return NULL;<br>
+       }<br>
+}<br>
+<br>
+bool ac_lower_subgroups(struct nir_shader *shader)<br>
+{<br>
+       bool progress = false;<br>
+<br>
+       nir_foreach_function(function, shader) {<br>
+               if (!function->impl)<br>
+                       continue;<br>
+<br>
+               nir_builder b;<br>
+               nir_builder_init(&b, function->impl);<br>
+<br>
+               nir_foreach_block(block, function->impl) {<br>
+                       nir_foreach_instr_safe(instr, block) {<br>
+                               if (instr->type != nir_instr_type_intrinsic)<br>
+                                       continue;<br>
+<br>
+                               nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);<br>
+                               b.cursor = nir_before_instr(instr);<br>
+<br>
+                               nir_ssa_def *lower = ac_lower_subgroups_intrin(&b, intrin);<br>
+                               if (!lower)<br>
+                                       continue;<br>
+<br>
+                               nir_ssa_def_rewrite_uses(&<wbr>intrin->dest.ssa, nir_src_for_ssa(lower));<br>
+                               nir_instr_remove(instr);<br>
+                               progress = true;<br>
+                       }<br>
+               }<br>
+       }<br>
+<br>
+       return progress;<br>
+}<br>
diff --git a/src/amd/common/ac_nir_to_<wbr>llvm.c b/src/amd/common/ac_nir_to_<wbr>llvm.c<br>
index d2df2837c8..3bf1a4ba3c 100644<br>
--- a/src/amd/common/ac_nir_to_<wbr>llvm.c<br>
+++ b/src/amd/common/ac_nir_to_<wbr>llvm.c<br>
@@ -4563,11 +4563,6 @@ static void visit_intrinsic(struct ac_nir_context *ctx,<br>
                result = LLVMBuildSExt(ctx->ac.builder, tmp, ctx->ac.i32, "");<br>
                break;<br>
        }<br>
-       case nir_intrinsic_vote_eq: {<br>
-               LLVMValueRef tmp = ac_build_vote_eq(&ctx->ac, get_src(ctx, instr->src[0]));<br>
-               result = LLVMBuildSExt(ctx->ac.builder, tmp, ctx->ac.i32, "");<br>
-               break;<br>
-       }<br>
        default:<br>
                fprintf(stderr, "Unknown intrinsic: ");<br>
                nir_print_instr(&instr->instr, stderr);<br>
@@ -6737,6 +6732,9 @@ void ac_nir_translate(struct ac_llvm_context *ac, struct ac_shader_abi *abi,<br>
        struct ac_nir_context ctx = {};<br>
        struct nir_function *func;<br>
<br>
+       /* Last minute passes for both radv & radeonsi */<br>
+       ac_lower_subgroups(nir);<br>
+<br>
        <a href="http://ctx.ac" rel="noreferrer" target="_blank">ctx.ac</a> = *ac;<br>
        ctx.abi = abi;<br>
<br>
diff --git a/src/amd/common/ac_nir_to_<wbr>llvm.h b/src/amd/common/ac_nir_to_<wbr>llvm.h<br>
index eea393a9c2..306039aecf 100644<br>
--- a/src/amd/common/ac_nir_to_<wbr>llvm.h<br>
+++ b/src/amd/common/ac_nir_to_<wbr>llvm.h<br>
@@ -234,4 +234,6 @@ void ac_lower_indirect_derefs(<wbr>struct nir_shader *nir, enum chip_class);<br>
 void ac_nir_translate(struct ac_llvm_context *ac, struct ac_shader_abi *abi,<br>
                      struct nir_shader *nir);<br>
<br>
+bool ac_lower_subgroups(struct nir_shader *shader);<br>
+<br>
 #endif /* AC_NIR_TO_LLVM_H */<br>
diff --git a/src/amd/common/meson.build b/src/amd/common/meson.build<br>
index 22c13b955f..6c5c2f45ac 100644<br>
--- a/src/amd/common/meson.build<br>
+++ b/src/amd/common/meson.build<br>
@@ -35,6 +35,7 @@ amd_common_files = files(<br>
   'ac_llvm_helper.cpp',<br>
   'ac_llvm_util.c',<br>
   'ac_llvm_util.h',<br>
+  'ac_lower_subgroups.c',<br>
   'ac_shader_abi.h',<br>
   'ac_shader_info.c',<br>
   'ac_shader_info.h',<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.16.1<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>