lima/gpir: add helper function for emit load node
[mesa.git] / src / gallium / drivers / lima / ir / gp / nir.c
1 /*
2 * Copyright (c) 2017 Lima Project
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, sub license,
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
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the 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 NON-INFRINGEMENT. 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
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24
25 #include "util/ralloc.h"
26 #include "compiler/nir/nir.h"
27
28 #include "gpir.h"
29 #include "lima_context.h"
30
31
32 static inline void *gpir_node_create_ssa(gpir_block *block, gpir_op op, nir_ssa_def *ssa)
33 {
34 int index = ssa->index;
35 gpir_node *node = gpir_node_create(block, op);
36
37 block->comp->var_nodes[index] = node;
38 snprintf(node->name, sizeof(node->name), "ssa%d", index);
39 list_addtail(&node->list, &block->node_list);
40 return node;
41 }
42
43 static inline void *gpir_node_create_reg(gpir_block *block, gpir_op op, nir_reg_dest *reg)
44 {
45 int index = reg->reg->index;
46 gpir_node *node = gpir_node_create(block, op);
47 gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);
48
49 snprintf(node->name, sizeof(node->name), "reg%d", index);
50
51 store->child = node;
52 gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);
53
54 list_for_each_entry(gpir_reg, reg, &block->comp->reg_list, list) {
55 if (reg->index == index) {
56 store->reg = reg;
57 list_addtail(&store->reg_link, &reg->defs_list);
58 break;
59 }
60 }
61
62 list_addtail(&node->list, &block->node_list);
63 list_addtail(&store->node.list, &block->node_list);
64 return node;
65 }
66
67 static void *gpir_node_create_dest(gpir_block *block, gpir_op op, nir_dest *dest)
68 {
69 if (dest->is_ssa)
70 return gpir_node_create_ssa(block, op, &dest->ssa);
71 else
72 return gpir_node_create_reg(block, op, &dest->reg);
73 }
74
75 static gpir_node *gpir_node_find(gpir_block *block, gpir_node *succ, nir_src *src)
76 {
77 gpir_node *pred;
78
79 if (src->is_ssa) {
80 pred = block->comp->var_nodes[src->ssa->index];
81 assert(pred);
82 }
83 else {
84 pred = gpir_node_create(block, gpir_op_load_reg);
85 list_addtail(&pred->list, &succ->list);
86
87 gpir_load_node *load = gpir_node_to_load(pred);
88 list_for_each_entry(gpir_reg, reg, &block->comp->reg_list, list) {
89 if (reg->index == src->reg.reg->index) {
90 load->reg = reg;
91 list_addtail(&load->reg_link, &reg->uses_list);
92 break;
93 }
94 }
95 }
96
97 return pred;
98 }
99
100 static int nir_to_gpir_opcodes[nir_num_opcodes] = {
101 /* not supported */
102 [0 ... nir_last_opcode] = -1,
103
104 [nir_op_fmul] = gpir_op_mul,
105 [nir_op_fadd] = gpir_op_add,
106 [nir_op_fneg] = gpir_op_neg,
107 [nir_op_fnot] = gpir_op_not,
108 [nir_op_fmin] = gpir_op_min,
109 [nir_op_fmax] = gpir_op_max,
110 [nir_op_frcp] = gpir_op_rcp,
111 [nir_op_frsq] = gpir_op_rsqrt,
112 [nir_op_slt] = gpir_op_lt,
113 [nir_op_sge] = gpir_op_ge,
114 [nir_op_fcsel] = gpir_op_select,
115 [nir_op_ffloor] = gpir_op_floor,
116 [nir_op_fsign] = gpir_op_sign,
117 [nir_op_seq] = gpir_op_eq,
118 [nir_op_sne] = gpir_op_ne,
119 [nir_op_fand] = gpir_op_min,
120 [nir_op_for] = gpir_op_max,
121 [nir_op_fabs] = gpir_op_abs,
122 [nir_op_fmov] = gpir_op_mov,
123 };
124
125 static bool gpir_emit_alu(gpir_block *block, nir_instr *ni)
126 {
127 nir_alu_instr *instr = nir_instr_as_alu(ni);
128 int op = nir_to_gpir_opcodes[instr->op];
129
130 if (op < 0) {
131 gpir_error("unsupported nir_op: %s\n", nir_op_infos[instr->op].name);
132 return false;
133 }
134
135 gpir_alu_node *node = gpir_node_create_dest(block, op, &instr->dest.dest);
136 if (unlikely(!node))
137 return false;
138
139 unsigned num_child = nir_op_infos[instr->op].num_inputs;
140 assert(num_child <= ARRAY_SIZE(node->children));
141 node->num_child = num_child;
142
143 for (int i = 0; i < num_child; i++) {
144 nir_alu_src *src = instr->src + i;
145 node->children_negate[i] = src->negate;
146
147 gpir_node *child = gpir_node_find(block, &node->node, &src->src);
148 node->children[i] = child;
149
150 gpir_node_add_dep(&node->node, child, GPIR_DEP_INPUT);
151 }
152
153 return true;
154 }
155
156 static gpir_node *gpir_create_load(gpir_block *block, nir_dest *dest,
157 int op, int index, int component)
158 {
159 gpir_load_node *load = gpir_node_create_dest(block, op, dest);
160 if (unlikely(!load))
161 return NULL;
162
163 load->index = index;
164 load->component = component;
165 return &load->node;
166 }
167
168 static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni)
169 {
170 nir_intrinsic_instr *instr = nir_instr_as_intrinsic(ni);
171
172 switch (instr->intrinsic) {
173 case nir_intrinsic_load_input:
174 return gpir_create_load(block, &instr->dest,
175 gpir_op_load_attribute,
176 nir_intrinsic_base(instr),
177 nir_intrinsic_component(instr)) != NULL;
178 case nir_intrinsic_load_uniform:
179 {
180 int offset = nir_intrinsic_base(instr);
181 offset += (int)nir_src_as_float(instr->src[0]);
182
183 return gpir_create_load(block, &instr->dest,
184 gpir_op_load_uniform,
185 offset / 4, offset % 4) != NULL;
186 }
187 case nir_intrinsic_store_output:
188 {
189 gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying);
190 if (unlikely(!store))
191 return false;
192 list_addtail(&store->node.list, &block->node_list);
193
194 store->index = nir_intrinsic_base(instr);
195 store->component = nir_intrinsic_component(instr);
196
197 gpir_node *child = gpir_node_find(block, &store->node, instr->src);
198 store->child = child;
199 gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT);
200
201 return true;
202 }
203 default:
204 gpir_error("unsupported nir_intrinsic_instr %s\n",
205 nir_intrinsic_infos[instr->intrinsic].name);
206 return false;
207 }
208 }
209
210 static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni)
211 {
212 nir_load_const_instr *instr = nir_instr_as_load_const(ni);
213 gpir_const_node *node =
214 gpir_node_create_ssa(block, gpir_op_const, &instr->def);
215 if (unlikely(!node))
216 return false;
217
218 assert(instr->def.bit_size == 32);
219 assert(instr->def.num_components == 1);
220
221 node->value.i = instr->value[0].i32;
222
223 return true;
224 }
225
226 static bool gpir_emit_ssa_undef(gpir_block *block, nir_instr *ni)
227 {
228 gpir_error("nir_ssa_undef_instr not support\n");
229 return false;
230 }
231
232 static bool gpir_emit_tex(gpir_block *block, nir_instr *ni)
233 {
234 gpir_error("nir_jump_instr not support\n");
235 return false;
236 }
237
238 static bool gpir_emit_jump(gpir_block *block, nir_instr *ni)
239 {
240 gpir_error("nir_jump_instr not support\n");
241 return false;
242 }
243
244 static bool (*gpir_emit_instr[nir_instr_type_phi])(gpir_block *, nir_instr *) = {
245 [nir_instr_type_alu] = gpir_emit_alu,
246 [nir_instr_type_intrinsic] = gpir_emit_intrinsic,
247 [nir_instr_type_load_const] = gpir_emit_load_const,
248 [nir_instr_type_ssa_undef] = gpir_emit_ssa_undef,
249 [nir_instr_type_tex] = gpir_emit_tex,
250 [nir_instr_type_jump] = gpir_emit_jump,
251 };
252
253 static gpir_block *gpir_block_create(gpir_compiler *comp)
254 {
255 gpir_block *block = ralloc(comp, gpir_block);
256 if (!block)
257 return NULL;
258
259 list_inithead(&block->node_list);
260 list_inithead(&block->instr_list);
261
262 return block;
263 }
264
265 static bool gpir_emit_block(gpir_compiler *comp, nir_block *nblock)
266 {
267 gpir_block *block = gpir_block_create(comp);
268 if (!block)
269 return false;
270
271 list_addtail(&block->list, &comp->block_list);
272 block->comp = comp;
273
274 nir_foreach_instr(instr, nblock) {
275 assert(instr->type < nir_instr_type_phi);
276 if (!gpir_emit_instr[instr->type](block, instr))
277 return false;
278 }
279
280 return true;
281 }
282
283 static bool gpir_emit_if(gpir_compiler *comp, nir_if *nif)
284 {
285 gpir_error("if nir_cf_node not support\n");
286 return false;
287 }
288
289 static bool gpir_emit_loop(gpir_compiler *comp, nir_loop *nloop)
290 {
291 gpir_error("loop nir_cf_node not support\n");
292 return false;
293 }
294
295 static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *nfunc)
296 {
297 gpir_error("function nir_cf_node not support\n");
298 return false;
299 }
300
301 static bool gpir_emit_cf_list(gpir_compiler *comp, struct exec_list *list)
302 {
303 foreach_list_typed(nir_cf_node, node, node, list) {
304 bool ret;
305
306 switch (node->type) {
307 case nir_cf_node_block:
308 ret = gpir_emit_block(comp, nir_cf_node_as_block(node));
309 break;
310 case nir_cf_node_if:
311 ret = gpir_emit_if(comp, nir_cf_node_as_if(node));
312 break;
313 case nir_cf_node_loop:
314 ret = gpir_emit_loop(comp, nir_cf_node_as_loop(node));
315 break;
316 case nir_cf_node_function:
317 ret = gpir_emit_function(comp, nir_cf_node_as_function(node));
318 break;
319 default:
320 gpir_error("unknown NIR node type %d\n", node->type);
321 return false;
322 }
323
324 if (!ret)
325 return false;
326 }
327
328 return true;
329 }
330
331 gpir_reg *gpir_create_reg(gpir_compiler *comp)
332 {
333 gpir_reg *reg = ralloc(comp, gpir_reg);
334 reg->index = comp->cur_reg++;
335 list_addtail(&reg->list, &comp->reg_list);
336 list_inithead(&reg->defs_list);
337 list_inithead(&reg->uses_list);
338 return reg;
339 }
340
341 static gpir_compiler *gpir_compiler_create(void *prog, unsigned num_reg, unsigned num_ssa)
342 {
343 gpir_compiler *comp = rzalloc(prog, gpir_compiler);
344
345 list_inithead(&comp->block_list);
346 list_inithead(&comp->reg_list);
347
348 for (int i = 0; i < num_reg; i++)
349 gpir_create_reg(comp);
350
351 comp->var_nodes = rzalloc_array(comp, gpir_node *, num_ssa);
352 comp->prog = prog;
353 return comp;
354 }
355
356 static int gpir_glsl_type_size(enum glsl_base_type type)
357 {
358 /* only support GLSL_TYPE_FLOAT */
359 assert(type == GLSL_TYPE_FLOAT);
360 return 4;
361 }
362
363 bool gpir_compile_nir(struct lima_vs_shader_state *prog, struct nir_shader *nir)
364 {
365 nir_function_impl *func = nir_shader_get_entrypoint(nir);
366 gpir_compiler *comp = gpir_compiler_create(prog, func->reg_alloc, func->ssa_alloc);
367 if (!comp)
368 return false;
369
370 comp->constant_base = nir->num_uniforms;
371 prog->uniform_pending_offset = nir->num_uniforms * 16;
372
373 if (!gpir_emit_cf_list(comp, &func->body))
374 goto err_out0;
375
376 gpir_node_print_prog_seq(comp);
377 gpir_node_print_prog_dep(comp);
378
379 if (!gpir_pre_rsched_lower_prog(comp))
380 goto err_out0;
381
382 if (!gpir_reduce_reg_pressure_schedule_prog(comp))
383 goto err_out0;
384
385 if (!gpir_post_rsched_lower_prog(comp))
386 goto err_out0;
387
388 if (!gpir_value_regalloc_prog(comp))
389 goto err_out0;
390
391 if (!gpir_physical_regalloc_prog(comp))
392 goto err_out0;
393
394 if (!gpir_schedule_prog(comp))
395 goto err_out0;
396
397 if (!gpir_codegen_prog(comp))
398 goto err_out0;
399
400 nir_foreach_variable(var, &nir->outputs) {
401 if (var->data.location == VARYING_SLOT_POS)
402 assert(var->data.driver_location == 0);
403
404 struct lima_varying_info *v = prog->varying + var->data.driver_location;
405 if (!v->components) {
406 v->component_size = gpir_glsl_type_size(glsl_get_base_type(var->type));
407 prog->num_varying++;
408 }
409
410 v->components += glsl_get_components(var->type);
411 }
412
413 ralloc_free(comp);
414 return true;
415
416 err_out0:
417 ralloc_free(comp);
418 return false;
419 }
420