1 |
From cf2e4490c396f33d1c186edab720d025264ddbc2 Mon Sep 17 00:00:00 2001 |
2 |
From: Jason Ekstrand <jason.ekstrand@intel.com> |
3 |
Date: Mon, 11 Mar 2019 18:47:39 -0500 |
4 |
Subject: [PATCH 17/24] nir: Add a new pass to lower array dereferences on |
5 |
vectors |
6 |
|
7 |
This pass was originally written for lowering TCS output reads and |
8 |
writes but it is also applicable just about anything including UBOs, |
9 |
SSBOs, and shared variables. |
10 |
|
11 |
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> |
12 |
(cherry picked from commit 35b8f6f40bb45dbffb04dd883ac6644300832981) |
13 |
--- |
14 |
src/compiler/Makefile.sources | 1 + |
15 |
src/compiler/nir/meson.build | 1 + |
16 |
src/compiler/nir/nir.h | 10 + |
17 |
.../nir/nir_lower_array_deref_of_vec.c | 190 ++++++++++++++++++ |
18 |
4 files changed, 202 insertions(+) |
19 |
create mode 100644 src/compiler/nir/nir_lower_array_deref_of_vec.c |
20 |
|
21 |
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources |
22 |
index 8465aa4d1de..0b40c3c6ebe 100644 |
23 |
--- a/src/compiler/Makefile.sources |
24 |
+++ b/src/compiler/Makefile.sources |
25 |
@@ -229,6 +229,7 @@ NIR_FILES = \ |
26 |
nir/nir_lower_alpha_test.c \ |
27 |
nir/nir_lower_alu.c \ |
28 |
nir/nir_lower_alu_to_scalar.c \ |
29 |
+ nir/nir_lower_array_deref_of_vec.c \ |
30 |
nir/nir_lower_atomics_to_ssbo.c \ |
31 |
nir/nir_lower_bitmap.c \ |
32 |
nir/nir_lower_bit_size.c \ |
33 |
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build |
34 |
index 95e9e2159dd..e6784fcd41f 100644 |
35 |
--- a/src/compiler/nir/meson.build |
36 |
+++ b/src/compiler/nir/meson.build |
37 |
@@ -112,6 +112,7 @@ files_libnir = files( |
38 |
'nir_lower_alu.c', |
39 |
'nir_lower_alu_to_scalar.c', |
40 |
'nir_lower_alpha_test.c', |
41 |
+ 'nir_lower_array_deref_of_vec.c', |
42 |
'nir_lower_atomics_to_ssbo.c', |
43 |
'nir_lower_bitmap.c', |
44 |
'nir_lower_bool_to_float.c', |
45 |
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h |
46 |
index 7d7a7698dca..4aedd6e4602 100644 |
47 |
--- a/src/compiler/nir/nir.h |
48 |
+++ b/src/compiler/nir/nir.h |
49 |
@@ -2910,6 +2910,16 @@ void nir_fixup_deref_modes(nir_shader *shader); |
50 |
|
51 |
bool nir_lower_global_vars_to_local(nir_shader *shader); |
52 |
|
53 |
+typedef enum { |
54 |
+ nir_lower_direct_array_deref_of_vec_load = (1 << 0), |
55 |
+ nir_lower_indirect_array_deref_of_vec_load = (1 << 1), |
56 |
+ nir_lower_direct_array_deref_of_vec_store = (1 << 2), |
57 |
+ nir_lower_indirect_array_deref_of_vec_store = (1 << 3), |
58 |
+} nir_lower_array_deref_of_vec_options; |
59 |
+ |
60 |
+bool nir_lower_array_deref_of_vec(nir_shader *shader, nir_variable_mode modes, |
61 |
+ nir_lower_array_deref_of_vec_options options); |
62 |
+ |
63 |
bool nir_lower_indirect_derefs(nir_shader *shader, nir_variable_mode modes); |
64 |
|
65 |
bool nir_lower_locals_to_regs(nir_shader *shader); |
66 |
diff --git a/src/compiler/nir/nir_lower_array_deref_of_vec.c b/src/compiler/nir/nir_lower_array_deref_of_vec.c |
67 |
new file mode 100644 |
68 |
index 00000000000..2a70dd1ddbc |
69 |
--- /dev/null |
70 |
+++ b/src/compiler/nir/nir_lower_array_deref_of_vec.c |
71 |
@@ -0,0 +1,190 @@ |
72 |
+/* |
73 |
+ * Copyright © 2019 Intel Corporation |
74 |
+ * |
75 |
+ * Permission is hereby granted, free of charge, to any person obtaining a |
76 |
+ * copy of this software and associated documentation files (the "Software"), |
77 |
+ * to deal in the Software without restriction, including without limitation |
78 |
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
79 |
+ * and/or sell copies of the Software, and to permit persons to whom the |
80 |
+ * Software is furnished to do so, subject to the following conditions: |
81 |
+ * |
82 |
+ * The above copyright notice and this permission notice (including the next |
83 |
+ * paragraph) shall be included in all copies or substantial portions of the |
84 |
+ * Software. |
85 |
+ * |
86 |
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
87 |
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
88 |
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
89 |
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
90 |
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
91 |
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
92 |
+ * IN THE SOFTWARE. |
93 |
+ */ |
94 |
+ |
95 |
+#include "nir.h" |
96 |
+#include "nir_builder.h" |
97 |
+ |
98 |
+static void |
99 |
+build_write_masked_store(nir_builder *b, nir_deref_instr *vec_deref, |
100 |
+ nir_ssa_def *value, unsigned component) |
101 |
+{ |
102 |
+ assert(value->num_components == 1); |
103 |
+ unsigned num_components = glsl_get_components(vec_deref->type); |
104 |
+ assert(num_components > 1 && num_components <= NIR_MAX_VEC_COMPONENTS); |
105 |
+ |
106 |
+ nir_ssa_def *u = nir_ssa_undef(b, 1, value->bit_size); |
107 |
+ nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS]; |
108 |
+ for (unsigned i = 0; i < num_components; i++) |
109 |
+ comps[i] = (i == component) ? value : u; |
110 |
+ |
111 |
+ nir_ssa_def *vec = nir_vec(b, comps, num_components); |
112 |
+ nir_store_deref(b, vec_deref, vec, (1u << component)); |
113 |
+} |
114 |
+ |
115 |
+static void |
116 |
+build_write_masked_stores(nir_builder *b, nir_deref_instr *vec_deref, |
117 |
+ nir_ssa_def *value, nir_ssa_def *index, |
118 |
+ unsigned start, unsigned end) |
119 |
+{ |
120 |
+ if (start == end - 1) { |
121 |
+ build_write_masked_store(b, vec_deref, value, start); |
122 |
+ } else { |
123 |
+ unsigned mid = start + (end - start) / 2; |
124 |
+ nir_push_if(b, nir_ilt(b, index, nir_imm_int(b, mid))); |
125 |
+ build_write_masked_stores(b, vec_deref, value, index, start, mid); |
126 |
+ nir_push_else(b, NULL); |
127 |
+ build_write_masked_stores(b, vec_deref, value, index, mid, end); |
128 |
+ nir_pop_if(b, NULL); |
129 |
+ } |
130 |
+} |
131 |
+ |
132 |
+static bool |
133 |
+nir_lower_array_deref_of_vec_impl(nir_function_impl *impl, |
134 |
+ nir_variable_mode modes, |
135 |
+ nir_lower_array_deref_of_vec_options options) |
136 |
+{ |
137 |
+ bool progress = false; |
138 |
+ |
139 |
+ nir_builder b; |
140 |
+ nir_builder_init(&b, impl); |
141 |
+ |
142 |
+ nir_foreach_block(block, impl) { |
143 |
+ nir_foreach_instr_safe(instr, block) { |
144 |
+ if (instr->type != nir_instr_type_intrinsic) |
145 |
+ continue; |
146 |
+ |
147 |
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); |
148 |
+ assert(intrin->intrinsic != nir_intrinsic_copy_deref); |
149 |
+ |
150 |
+ if (intrin->intrinsic != nir_intrinsic_load_deref && |
151 |
+ intrin->intrinsic != nir_intrinsic_interp_deref_at_centroid && |
152 |
+ intrin->intrinsic != nir_intrinsic_interp_deref_at_sample && |
153 |
+ intrin->intrinsic != nir_intrinsic_interp_deref_at_offset && |
154 |
+ intrin->intrinsic != nir_intrinsic_store_deref) |
155 |
+ continue; |
156 |
+ |
157 |
+ nir_deref_instr *deref = nir_src_as_deref(intrin->src[0]); |
158 |
+ if (!(deref->mode & modes)) |
159 |
+ continue; |
160 |
+ |
161 |
+ /* We only care about array derefs that act on vectors */ |
162 |
+ if (deref->deref_type != nir_deref_type_array) |
163 |
+ continue; |
164 |
+ |
165 |
+ nir_deref_instr *vec_deref = nir_deref_instr_parent(deref); |
166 |
+ if (!glsl_type_is_vector(vec_deref->type)) |
167 |
+ continue; |
168 |
+ |
169 |
+ assert(intrin->num_components == 1); |
170 |
+ unsigned num_components = glsl_get_components(vec_deref->type); |
171 |
+ assert(num_components > 1 && num_components <= NIR_MAX_VEC_COMPONENTS); |
172 |
+ |
173 |
+ b.cursor = nir_after_instr(&intrin->instr); |
174 |
+ |
175 |
+ if (intrin->intrinsic == nir_intrinsic_store_deref) { |
176 |
+ assert(intrin->src[1].is_ssa); |
177 |
+ nir_ssa_def *value = intrin->src[1].ssa; |
178 |
+ |
179 |
+ if (nir_src_is_const(deref->arr.index)) { |
180 |
+ if (!(options & nir_lower_direct_array_deref_of_vec_store)) |
181 |
+ continue; |
182 |
+ |
183 |
+ unsigned index = nir_src_as_uint(deref->arr.index); |
184 |
+ /* If index is OOB, we throw the old store away and don't |
185 |
+ * replace it with anything. |
186 |
+ */ |
187 |
+ if (index < num_components) |
188 |
+ build_write_masked_store(&b, vec_deref, value, index); |
189 |
+ } else { |
190 |
+ if (!(options & nir_lower_indirect_array_deref_of_vec_store)) |
191 |
+ continue; |
192 |
+ |
193 |
+ nir_ssa_def *index = nir_ssa_for_src(&b, deref->arr.index, 1); |
194 |
+ build_write_masked_stores(&b, vec_deref, value, index, |
195 |
+ 0, num_components); |
196 |
+ } |
197 |
+ nir_instr_remove(&intrin->instr); |
198 |
+ |
199 |
+ progress = true; |
200 |
+ } else { |
201 |
+ if (nir_src_is_const(deref->arr.index)) { |
202 |
+ if (!(options & nir_lower_direct_array_deref_of_vec_load)) |
203 |
+ continue; |
204 |
+ } else { |
205 |
+ if (!(options & nir_lower_indirect_array_deref_of_vec_load)) |
206 |
+ continue; |
207 |
+ } |
208 |
+ |
209 |
+ /* Turn the load into a vector load */ |
210 |
+ nir_instr_rewrite_src(&intrin->instr, &intrin->src[0], |
211 |
+ nir_src_for_ssa(&vec_deref->dest.ssa)); |
212 |
+ intrin->dest.ssa.num_components = num_components; |
213 |
+ intrin->num_components = num_components; |
214 |
+ |
215 |
+ nir_ssa_def *index = nir_ssa_for_src(&b, deref->arr.index, 1); |
216 |
+ nir_ssa_def *scalar = |
217 |
+ nir_vector_extract(&b, &intrin->dest.ssa, index); |
218 |
+ if (scalar->parent_instr->type == nir_instr_type_ssa_undef) { |
219 |
+ nir_ssa_def_rewrite_uses(&intrin->dest.ssa, |
220 |
+ nir_src_for_ssa(scalar)); |
221 |
+ nir_instr_remove(&intrin->instr); |
222 |
+ } else { |
223 |
+ nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, |
224 |
+ nir_src_for_ssa(scalar), |
225 |
+ scalar->parent_instr); |
226 |
+ } |
227 |
+ progress = true; |
228 |
+ } |
229 |
+ } |
230 |
+ } |
231 |
+ |
232 |
+ if (progress) { |
233 |
+ nir_metadata_preserve(impl, nir_metadata_block_index | |
234 |
+ nir_metadata_dominance); |
235 |
+ } |
236 |
+ |
237 |
+ return progress; |
238 |
+} |
239 |
+ |
240 |
+/* Lowers away array dereferences on vectors |
241 |
+ * |
242 |
+ * These are allowed on certain variable types such as SSBOs and TCS outputs. |
243 |
+ * However, not everyone can actually handle them everywhere. There are also |
244 |
+ * cases where we want to lower them for performance reasons. |
245 |
+ * |
246 |
+ * This patch assumes that copy_deref instructions have already been lowered. |
247 |
+ */ |
248 |
+bool |
249 |
+nir_lower_array_deref_of_vec(nir_shader *shader, nir_variable_mode modes, |
250 |
+ nir_lower_array_deref_of_vec_options options) |
251 |
+{ |
252 |
+ bool progress = false; |
253 |
+ |
254 |
+ nir_foreach_function(function, shader) { |
255 |
+ if (function->impl && |
256 |
+ nir_lower_array_deref_of_vec_impl(function->impl, modes, options)) |
257 |
+ progress = true; |
258 |
+ } |
259 |
+ |
260 |
+ return progress; |
261 |
+} |
262 |
-- |
263 |
2.21.0 |
264 |
|