<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>