nir: Fix typo in "ushr by 0" algebraic replacement
[mesa.git] / src / glsl / nir / nir_builder.h
1 /*
2 * Copyright © 2014-2015 Broadcom
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifndef NIR_BUILDER_H
25 #define NIR_BUILDER_H
26
27 struct exec_list;
28
29 typedef struct nir_builder {
30 struct exec_list *cf_node_list;
31 nir_instr *before_instr;
32
33 nir_shader *shader;
34 nir_function_impl *impl;
35 } nir_builder;
36
37 static inline void
38 nir_builder_init(nir_builder *build, nir_function_impl *impl)
39 {
40 memset(build, 0, sizeof(*build));
41 build->impl = impl;
42 build->shader = impl->overload->function->shader;
43 }
44
45 static inline void
46 nir_builder_insert_after_cf_list(nir_builder *build,
47 struct exec_list *cf_node_list)
48 {
49 build->cf_node_list = cf_node_list;
50 }
51
52 static inline void
53 nir_builder_insert_before_instr(nir_builder *build, nir_instr *before_instr)
54 {
55 build->before_instr = before_instr;
56 }
57
58 static inline void
59 nir_builder_instr_insert(nir_builder *build, nir_instr *instr)
60 {
61 if (build->cf_node_list) {
62 nir_instr_insert_after_cf_list(build->cf_node_list, instr);
63 } else {
64 assert(build->before_instr);
65 nir_instr_insert_before(build->before_instr, instr);
66 }
67 }
68
69 static inline nir_ssa_def *
70 nir_build_imm(nir_builder *build, unsigned num_components, nir_const_value value)
71 {
72 nir_load_const_instr *load_const =
73 nir_load_const_instr_create(build->shader, num_components);
74 if (!load_const)
75 return NULL;
76
77 load_const->value = value;
78
79 nir_builder_instr_insert(build, &load_const->instr);
80
81 return &load_const->def;
82 }
83
84 static inline nir_ssa_def *
85 nir_imm_float(nir_builder *build, float x)
86 {
87 nir_const_value v = { { .f = {x, 0, 0, 0} } };
88 return nir_build_imm(build, 1, v);
89 }
90
91 static inline nir_ssa_def *
92 nir_imm_vec4(nir_builder *build, float x, float y, float z, float w)
93 {
94 nir_const_value v = { { .f = {x, y, z, w} } };
95 return nir_build_imm(build, 4, v);
96 }
97
98 static inline nir_ssa_def *
99 nir_imm_int(nir_builder *build, int x)
100 {
101 nir_const_value v = { { .i = {x, 0, 0, 0} } };
102 return nir_build_imm(build, 1, v);
103 }
104
105 static inline nir_ssa_def *
106 nir_build_alu(nir_builder *build, nir_op op, nir_ssa_def *src0,
107 nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3)
108 {
109 const nir_op_info *op_info = &nir_op_infos[op];
110 nir_alu_instr *instr = nir_alu_instr_create(build->shader, op);
111 if (!instr)
112 return NULL;
113
114 instr->src[0].src = nir_src_for_ssa(src0);
115 if (src1)
116 instr->src[1].src = nir_src_for_ssa(src1);
117 if (src2)
118 instr->src[2].src = nir_src_for_ssa(src2);
119 if (src3)
120 instr->src[3].src = nir_src_for_ssa(src3);
121
122 /* Guess the number of components the destination temporary should have
123 * based on our input sizes, if it's not fixed for the op.
124 */
125 unsigned num_components = op_info->output_size;
126 if (num_components == 0) {
127 for (unsigned i = 0; i < op_info->num_inputs; i++) {
128 if (op_info->input_sizes[i] == 0)
129 num_components = MAX2(num_components,
130 instr->src[i].src.ssa->num_components);
131 }
132 }
133 assert(num_components != 0);
134
135 /* Make sure we don't swizzle from outside of our source vector (like if a
136 * scalar value was passed into a multiply with a vector).
137 */
138 for (unsigned i = 0; i < op_info->num_inputs; i++) {
139 for (unsigned j = instr->src[i].src.ssa->num_components; j < 4; j++) {
140 instr->src[i].swizzle[j] = instr->src[i].src.ssa->num_components - 1;
141 }
142 }
143
144 nir_ssa_dest_init(&instr->instr, &instr->dest.dest, num_components, NULL);
145 instr->dest.write_mask = (1 << num_components) - 1;
146
147 nir_builder_instr_insert(build, &instr->instr);
148
149 return &instr->dest.dest.ssa;
150 }
151
152 #define ALU1(op) \
153 static inline nir_ssa_def * \
154 nir_##op(nir_builder *build, nir_ssa_def *src0) \
155 { \
156 return nir_build_alu(build, nir_op_##op, src0, NULL, NULL, NULL); \
157 }
158
159 #define ALU2(op) \
160 static inline nir_ssa_def * \
161 nir_##op(nir_builder *build, nir_ssa_def *src0, nir_ssa_def *src1) \
162 { \
163 return nir_build_alu(build, nir_op_##op, src0, src1, NULL, NULL); \
164 }
165
166 #define ALU3(op) \
167 static inline nir_ssa_def * \
168 nir_##op(nir_builder *build, nir_ssa_def *src0, \
169 nir_ssa_def *src1, nir_ssa_def *src2) \
170 { \
171 return nir_build_alu(build, nir_op_##op, src0, src1, src2, NULL); \
172 }
173
174 #define ALU4(op) \
175 static inline nir_ssa_def * \
176 nir_##op(nir_builder *build, nir_ssa_def *src0, \
177 nir_ssa_def *src1, nir_ssa_def *src2, nir_ssa_def *src3) \
178 { \
179 return nir_build_alu(build, nir_op_##op, src0, src1, src2, src3); \
180 }
181
182 #include "nir_builder_opcodes.h"
183
184 /**
185 * Similar to nir_fmov, but takes a nir_alu_src instead of a nir_ssa_def.
186 */
187 static inline nir_ssa_def *
188 nir_fmov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
189 {
190 nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_fmov);
191 nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
192 mov->dest.write_mask = (1 << num_components) - 1;
193 mov->src[0] = src;
194 nir_builder_instr_insert(build, &mov->instr);
195
196 return &mov->dest.dest.ssa;
197 }
198
199 static inline nir_ssa_def *
200 nir_imov_alu(nir_builder *build, nir_alu_src src, unsigned num_components)
201 {
202 nir_alu_instr *mov = nir_alu_instr_create(build->shader, nir_op_imov);
203 nir_ssa_dest_init(&mov->instr, &mov->dest.dest, num_components, NULL);
204 mov->dest.write_mask = (1 << num_components) - 1;
205 mov->src[0] = src;
206 nir_builder_instr_insert(build, &mov->instr);
207
208 return &mov->dest.dest.ssa;
209 }
210
211 /**
212 * Construct an fmov or imov that reswizzles the source's components.
213 */
214 static inline nir_ssa_def *
215 nir_swizzle(nir_builder *build, nir_ssa_def *src, unsigned swiz[4],
216 unsigned num_components, bool use_fmov)
217 {
218 nir_alu_src alu_src;
219 memset(&alu_src, 0, sizeof(alu_src));
220 alu_src.src = nir_src_for_ssa(src);
221 for (int i = 0; i < 4; i++)
222 alu_src.swizzle[i] = swiz[i];
223
224 return use_fmov ? nir_fmov_alu(build, alu_src, num_components) :
225 nir_imov_alu(build, alu_src, num_components);
226 }
227
228 /**
229 * Turns a nir_src into a nir_ssa_def * so it can be passed to
230 * nir_build_alu()-based builder calls.
231 */
232 static inline nir_ssa_def *
233 nir_ssa_for_src(nir_builder *build, nir_src src, int num_components)
234 {
235 if (src.is_ssa && src.ssa->num_components == num_components)
236 return src.ssa;
237
238 nir_alu_src alu;
239 memset(&alu, 0, sizeof(alu));
240 alu.src = src;
241 for (int j = 0; j < 4; j++)
242 alu.swizzle[j] = j;
243
244 return nir_imov_alu(build, alu, num_components);
245 }
246
247 #endif /* NIR_BUILDER_H */