xref: /aosp_15_r20/external/mesa3d/src/compiler/spirv/vtn_cfg.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2015 Intel Corporation
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 #include "vtn_private.h"
25 #include "spirv_info.h"
26 #include "nir/nir_vla.h"
27 #include "util/u_debug.h"
28 
29 static unsigned
glsl_type_count_function_params(const struct glsl_type * type)30 glsl_type_count_function_params(const struct glsl_type *type)
31 {
32    if (glsl_type_is_vector_or_scalar(type)) {
33       return 1;
34    } else if (glsl_type_is_array_or_matrix(type)) {
35       return glsl_get_length(type) *
36              glsl_type_count_function_params(glsl_get_array_element(type));
37    } else {
38       assert(glsl_type_is_struct_or_ifc(type));
39       unsigned count = 0;
40       unsigned elems = glsl_get_length(type);
41       for (unsigned i = 0; i < elems; i++) {
42          const struct glsl_type *elem_type = glsl_get_struct_field(type, i);
43          count += glsl_type_count_function_params(elem_type);
44       }
45       return count;
46    }
47 }
48 
49 static void
glsl_type_add_to_function_params(const struct glsl_type * type,nir_function * func,unsigned * param_idx)50 glsl_type_add_to_function_params(const struct glsl_type *type,
51                                  nir_function *func,
52                                  unsigned *param_idx)
53 {
54    if (glsl_type_is_vector_or_scalar(type)) {
55       func->params[(*param_idx)++] = (nir_parameter) {
56          .num_components = glsl_get_vector_elements(type),
57          .bit_size = glsl_get_bit_size(type),
58       };
59    } else if (glsl_type_is_array_or_matrix(type)) {
60       unsigned elems = glsl_get_length(type);
61       const struct glsl_type *elem_type = glsl_get_array_element(type);
62       for (unsigned i = 0; i < elems; i++)
63          glsl_type_add_to_function_params(elem_type,func, param_idx);
64    } else {
65       assert(glsl_type_is_struct_or_ifc(type));
66       unsigned elems = glsl_get_length(type);
67       for (unsigned i = 0; i < elems; i++) {
68          const struct glsl_type *elem_type = glsl_get_struct_field(type, i);
69          glsl_type_add_to_function_params(elem_type, func, param_idx);
70       }
71    }
72 }
73 
74 static void
vtn_ssa_value_add_to_call_params(struct vtn_builder * b,struct vtn_ssa_value * value,nir_call_instr * call,unsigned * param_idx)75 vtn_ssa_value_add_to_call_params(struct vtn_builder *b,
76                                  struct vtn_ssa_value *value,
77                                  nir_call_instr *call,
78                                  unsigned *param_idx)
79 {
80    if (glsl_type_is_vector_or_scalar(value->type)) {
81       call->params[(*param_idx)++] = nir_src_for_ssa(value->def);
82    } else {
83       unsigned elems = glsl_get_length(value->type);
84       for (unsigned i = 0; i < elems; i++) {
85          vtn_ssa_value_add_to_call_params(b, value->elems[i],
86                                           call, param_idx);
87       }
88    }
89 }
90 
91 struct vtn_func_arg_info {
92    bool by_value;
93 };
94 
95 static void
function_parameter_decoration_cb(struct vtn_builder * b,struct vtn_value * val,int member,const struct vtn_decoration * dec,void * arg_info)96 function_parameter_decoration_cb(struct vtn_builder *b, struct vtn_value *val,
97                                  int member, const struct vtn_decoration *dec,
98                                  void *arg_info)
99 {
100    struct vtn_func_arg_info *info = arg_info;
101 
102    switch (dec->decoration) {
103    case SpvDecorationFuncParamAttr:
104       for (uint32_t i = 0; i < dec->num_operands; i++) {
105          uint32_t attr = dec->operands[i];
106          switch (attr) {
107          /* ignore for now */
108          case SpvFunctionParameterAttributeNoAlias:
109          case SpvFunctionParameterAttributeSext:
110          case SpvFunctionParameterAttributeZext:
111             break;
112 
113          case SpvFunctionParameterAttributeByVal:
114             info->by_value = true;
115             break;
116 
117          default:
118             vtn_warn("Function parameter Decoration not handled: %s",
119                      spirv_functionparameterattribute_to_string(attr));
120             break;
121          }
122       }
123       break;
124 
125    /* ignore for now */
126    case SpvDecorationAliased:
127    case SpvDecorationAliasedPointer:
128    case SpvDecorationAlignment:
129    case SpvDecorationRelaxedPrecision:
130    case SpvDecorationRestrict:
131    case SpvDecorationRestrictPointer:
132    case SpvDecorationVolatile:
133       break;
134 
135    default:
136       vtn_warn("Function parameter Decoration not handled: %s",
137                spirv_decoration_to_string(dec->decoration));
138       break;
139    }
140 }
141 
142 static void
vtn_ssa_value_load_function_param(struct vtn_builder * b,struct vtn_ssa_value * value,struct vtn_type * type,struct vtn_func_arg_info * info,unsigned * param_idx)143 vtn_ssa_value_load_function_param(struct vtn_builder *b,
144                                   struct vtn_ssa_value *value,
145                                   struct vtn_type *type,
146                                   struct vtn_func_arg_info *info,
147                                   unsigned *param_idx)
148 {
149    if (glsl_type_is_vector_or_scalar(value->type)) {
150       /* if the parameter is passed by value, we need to create a local copy if it's a pointer */
151       if (info->by_value && type && type->base_type == vtn_base_type_pointer) {
152          struct vtn_type *pointee_type = type->pointed;
153 
154          nir_variable *copy =
155             nir_local_variable_create(b->nb.impl, pointee_type->type, NULL);
156 
157          nir_variable_mode mode;
158          vtn_storage_class_to_mode(b, type->storage_class, NULL, &mode);
159 
160          nir_def *param = nir_load_param(&b->nb, (*param_idx)++);
161          nir_deref_instr *src = nir_build_deref_cast(&b->nb, param, mode, copy->type, 0);
162          nir_deref_instr *dst = nir_build_deref_var(&b->nb, copy);
163 
164          nir_copy_deref(&b->nb, dst, src);
165 
166          nir_deref_instr *load =
167             nir_build_deref_cast(&b->nb, &dst->def, nir_var_function_temp, type->type, 0);
168          value->def = &load->def;
169       } else {
170          value->def = nir_load_param(&b->nb, (*param_idx)++);
171       }
172    } else {
173       unsigned elems = glsl_get_length(value->type);
174       for (unsigned i = 0; i < elems; i++)
175          vtn_ssa_value_load_function_param(b, value->elems[i], NULL, info, param_idx);
176    }
177 }
178 
179 void
vtn_handle_function_call(struct vtn_builder * b,SpvOp opcode,const uint32_t * w,unsigned count)180 vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
181                          const uint32_t *w, unsigned count)
182 {
183    struct vtn_function *vtn_callee =
184       vtn_value(b, w[3], vtn_value_type_function)->func;
185 
186    vtn_callee->referenced = true;
187 
188    nir_call_instr *call = nir_call_instr_create(b->nb.shader,
189                                                 vtn_callee->nir_func);
190 
191    unsigned param_idx = 0;
192 
193    nir_deref_instr *ret_deref = NULL;
194    struct vtn_type *ret_type = vtn_callee->type->return_type;
195    if (ret_type->base_type != vtn_base_type_void) {
196       nir_variable *ret_tmp =
197          nir_local_variable_create(b->nb.impl,
198                                    glsl_get_bare_type(ret_type->type),
199                                    "return_tmp");
200       ret_deref = nir_build_deref_var(&b->nb, ret_tmp);
201       call->params[param_idx++] = nir_src_for_ssa(&ret_deref->def);
202    }
203 
204    for (unsigned i = 0; i < vtn_callee->type->length; i++) {
205       vtn_ssa_value_add_to_call_params(b, vtn_ssa_value(b, w[4 + i]),
206                                        call, &param_idx);
207    }
208    assert(param_idx == call->num_params);
209 
210    nir_builder_instr_insert(&b->nb, &call->instr);
211 
212    if (ret_type->base_type == vtn_base_type_void) {
213       vtn_push_value(b, w[2], vtn_value_type_undef);
214    } else {
215       vtn_push_ssa_value(b, w[2], vtn_local_load(b, ret_deref, 0));
216    }
217 }
218 
219 static void
function_decoration_cb(struct vtn_builder * b,struct vtn_value * val,int member,const struct vtn_decoration * dec,void * void_func)220 function_decoration_cb(struct vtn_builder *b, struct vtn_value *val, int member,
221                        const struct vtn_decoration *dec, void *void_func)
222 {
223    struct vtn_function *func = void_func;
224 
225    switch (dec->decoration) {
226    case SpvDecorationLinkageAttributes: {
227       unsigned name_words;
228       const char *name =
229          vtn_string_literal(b, dec->operands, dec->num_operands, &name_words);
230       vtn_fail_if(name_words >= dec->num_operands,
231                   "Malformed LinkageAttributes decoration");
232       (void)name; /* TODO: What is this? */
233       func->linkage = dec->operands[name_words];
234       break;
235    }
236 
237    default:
238       break;
239    }
240 }
241 
242 bool
vtn_cfg_handle_prepass_instruction(struct vtn_builder * b,SpvOp opcode,const uint32_t * w,unsigned count)243 vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
244                                    const uint32_t *w, unsigned count)
245 {
246    switch (opcode) {
247    case SpvOpFunction: {
248       vtn_assert(b->func == NULL);
249       b->func = vtn_zalloc(b, struct vtn_function);
250 
251       list_inithead(&b->func->body);
252       b->func->linkage = SpvLinkageTypeMax;
253       b->func->control = w[3];
254       list_inithead(&b->func->constructs);
255 
256       UNUSED const struct glsl_type *result_type = vtn_get_type(b, w[1])->type;
257       struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_function);
258       val->func = b->func;
259 
260       vtn_foreach_decoration(b, val, function_decoration_cb, b->func);
261 
262       b->func->type = vtn_get_type(b, w[4]);
263       const struct vtn_type *func_type = b->func->type;
264 
265       vtn_assert(func_type->return_type->type == result_type);
266 
267       nir_function *func =
268          nir_function_create(b->shader, ralloc_strdup(b->shader, val->name));
269 
270       unsigned num_params = 0;
271       for (unsigned i = 0; i < func_type->length; i++)
272          num_params += glsl_type_count_function_params(func_type->params[i]->type);
273 
274       /* Add one parameter for the function return value */
275       if (func_type->return_type->base_type != vtn_base_type_void)
276          num_params++;
277 
278       func->should_inline = b->func->control & SpvFunctionControlInlineMask;
279       func->dont_inline = b->func->control & SpvFunctionControlDontInlineMask;
280       func->is_exported = b->func->linkage == SpvLinkageTypeExport;
281 
282       func->num_params = num_params;
283       func->params = ralloc_array(b->shader, nir_parameter, num_params);
284 
285       unsigned idx = 0;
286       if (func_type->return_type->base_type != vtn_base_type_void) {
287          nir_address_format addr_format =
288             vtn_mode_to_address_format(b, vtn_variable_mode_function);
289          /* The return value is a regular pointer */
290          func->params[idx++] = (nir_parameter) {
291             .num_components = nir_address_format_num_components(addr_format),
292             .bit_size = nir_address_format_bit_size(addr_format),
293          };
294       }
295 
296       for (unsigned i = 0; i < func_type->length; i++)
297          glsl_type_add_to_function_params(func_type->params[i]->type, func, &idx);
298       assert(idx == num_params);
299 
300       b->func->nir_func = func;
301 
302       /* Set up a nir_function_impl and the builder so we can load arguments
303        * directly in our OpFunctionParameter handler.
304        */
305       nir_function_impl *impl = nir_function_impl_create(func);
306       b->nb = nir_builder_at(nir_before_impl(impl));
307       b->nb.exact = b->exact;
308 
309       b->func_param_idx = 0;
310 
311       /* The return value is the first parameter */
312       if (func_type->return_type->base_type != vtn_base_type_void)
313          b->func_param_idx++;
314       break;
315    }
316 
317    case SpvOpFunctionEnd:
318       b->func->end = w;
319       if (b->func->start_block == NULL) {
320          vtn_fail_if(b->func->linkage != SpvLinkageTypeImport,
321                      "A function declaration (an OpFunction with no basic "
322                      "blocks), must have a Linkage Attributes Decoration "
323                      "with the Import Linkage Type.");
324 
325          /* In this case, the function didn't have any actual blocks.  It's
326           * just a prototype so delete the function_impl.
327           */
328          b->func->nir_func->impl = NULL;
329       } else {
330          vtn_fail_if(b->func->linkage == SpvLinkageTypeImport,
331                      "A function definition (an OpFunction with basic blocks) "
332                      "cannot be decorated with the Import Linkage Type.");
333       }
334       b->func = NULL;
335       break;
336 
337    case SpvOpFunctionParameter: {
338       vtn_assert(b->func_param_idx < b->func->nir_func->num_params);
339 
340       struct vtn_func_arg_info arg_info = {0};
341       struct vtn_type *type = vtn_get_type(b, w[1]);
342       struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, type->type);
343       struct vtn_value *val = vtn_untyped_value(b, w[2]);
344 
345       vtn_foreach_decoration(b, val, function_parameter_decoration_cb, &arg_info);
346       vtn_ssa_value_load_function_param(b, ssa, type, &arg_info, &b->func_param_idx);
347       vtn_push_ssa_value(b, w[2], ssa);
348       break;
349    }
350 
351    case SpvOpLabel: {
352       vtn_assert(b->block == NULL);
353       b->block = vtn_zalloc(b, struct vtn_block);
354       b->block->label = w;
355       vtn_push_value(b, w[1], vtn_value_type_block)->block = b->block;
356 
357       b->func->block_count++;
358 
359       if (b->func->start_block == NULL) {
360          /* This is the first block encountered for this function.  In this
361           * case, we set the start block and add it to the list of
362           * implemented functions that we'll walk later.
363           */
364          b->func->start_block = b->block;
365          list_addtail(&b->func->link, &b->functions);
366       }
367       break;
368    }
369 
370    case SpvOpSelectionMerge:
371    case SpvOpLoopMerge:
372       vtn_assert(b->block && b->block->merge == NULL);
373       b->block->merge = w;
374       break;
375 
376    case SpvOpBranch:
377    case SpvOpBranchConditional:
378    case SpvOpSwitch:
379    case SpvOpKill:
380    case SpvOpTerminateInvocation:
381    case SpvOpIgnoreIntersectionKHR:
382    case SpvOpTerminateRayKHR:
383    case SpvOpEmitMeshTasksEXT:
384    case SpvOpReturn:
385    case SpvOpReturnValue:
386    case SpvOpUnreachable:
387       if (b->wa_ignore_return_after_emit_mesh_tasks &&
388           opcode == SpvOpReturn && !b->block) {
389             /* At this point block was already reset by
390              * SpvOpEmitMeshTasksEXT. */
391             break;
392       }
393       vtn_assert(b->block && b->block->branch == NULL);
394       b->block->branch = w;
395       b->block = NULL;
396       break;
397 
398    default:
399       /* Continue on as per normal */
400       return true;
401    }
402 
403    return true;
404 }
405 
406 /* returns the default block */
407 void
vtn_parse_switch(struct vtn_builder * b,const uint32_t * branch,struct list_head * case_list)408 vtn_parse_switch(struct vtn_builder *b,
409                  const uint32_t *branch,
410                  struct list_head *case_list)
411 {
412    const uint32_t *branch_end = branch + (branch[0] >> SpvWordCountShift);
413 
414    struct vtn_value *sel_val = vtn_untyped_value(b, branch[1]);
415    vtn_fail_if(!sel_val->type ||
416                sel_val->type->base_type != vtn_base_type_scalar,
417                "Selector of OpSwitch must have a type of OpTypeInt");
418 
419    nir_alu_type sel_type =
420       nir_get_nir_type_for_glsl_type(sel_val->type->type);
421    vtn_fail_if(nir_alu_type_get_base_type(sel_type) != nir_type_int &&
422                nir_alu_type_get_base_type(sel_type) != nir_type_uint,
423                "Selector of OpSwitch must have a type of OpTypeInt");
424 
425    struct hash_table *block_to_case = _mesa_pointer_hash_table_create(b);
426 
427    bool is_default = true;
428    const unsigned bitsize = nir_alu_type_get_type_size(sel_type);
429    for (const uint32_t *w = branch + 2; w < branch_end;) {
430       uint64_t literal = 0;
431       if (!is_default) {
432          if (bitsize <= 32) {
433             literal = *(w++);
434          } else {
435             assert(bitsize == 64);
436             literal = vtn_u64_literal(w);
437             w += 2;
438          }
439       }
440       struct vtn_block *case_block = vtn_block(b, *(w++));
441 
442       struct hash_entry *case_entry =
443          _mesa_hash_table_search(block_to_case, case_block);
444 
445       struct vtn_case *cse;
446       if (case_entry) {
447          cse = case_entry->data;
448       } else {
449          cse = vtn_zalloc(b, struct vtn_case);
450          cse->block = case_block;
451          cse->block->switch_case = cse;
452          util_dynarray_init(&cse->values, b);
453 
454          list_addtail(&cse->link, case_list);
455          _mesa_hash_table_insert(block_to_case, case_block, cse);
456       }
457 
458       if (is_default) {
459          cse->is_default = true;
460       } else {
461          util_dynarray_append(&cse->values, uint64_t, literal);
462       }
463 
464       is_default = false;
465    }
466 
467    _mesa_hash_table_destroy(block_to_case, NULL);
468 }
469 
470 void
vtn_build_cfg(struct vtn_builder * b,const uint32_t * words,const uint32_t * end)471 vtn_build_cfg(struct vtn_builder *b, const uint32_t *words, const uint32_t *end)
472 {
473    vtn_foreach_instruction(b, words, end,
474                            vtn_cfg_handle_prepass_instruction);
475 
476    if (b->shader->info.stage == MESA_SHADER_KERNEL)
477       return;
478 
479    vtn_build_structured_cfg(b, words, end);
480 }
481 
482 bool
vtn_handle_phis_first_pass(struct vtn_builder * b,SpvOp opcode,const uint32_t * w,unsigned count)483 vtn_handle_phis_first_pass(struct vtn_builder *b, SpvOp opcode,
484                            const uint32_t *w, unsigned count)
485 {
486    if (opcode == SpvOpLabel)
487       return true; /* Nothing to do */
488 
489    /* If this isn't a phi node, stop. */
490    if (opcode != SpvOpPhi)
491       return false;
492 
493    /* For handling phi nodes, we do a poor-man's out-of-ssa on the spot.
494     * For each phi, we create a variable with the appropreate type and
495     * do a load from that variable.  Then, in a second pass, we add
496     * stores to that variable to each of the predecessor blocks.
497     *
498     * We could do something more intelligent here.  However, in order to
499     * handle loops and things properly, we really need dominance
500     * information.  It would end up basically being the into-SSA
501     * algorithm all over again.  It's easier if we just let
502     * lower_vars_to_ssa do that for us instead of repeating it here.
503     */
504    struct vtn_type *type = vtn_get_type(b, w[1]);
505    nir_variable *phi_var =
506       nir_local_variable_create(b->nb.impl, type->type, "phi");
507 
508    struct vtn_value *phi_val = vtn_untyped_value(b, w[2]);
509    if (vtn_value_is_relaxed_precision(b, phi_val))
510       phi_var->data.precision = GLSL_PRECISION_MEDIUM;
511 
512    _mesa_hash_table_insert(b->phi_table, w, phi_var);
513 
514    vtn_push_ssa_value(b, w[2],
515       vtn_local_load(b, nir_build_deref_var(&b->nb, phi_var), 0));
516 
517    return true;
518 }
519 
520 static bool
vtn_handle_phi_second_pass(struct vtn_builder * b,SpvOp opcode,const uint32_t * w,unsigned count)521 vtn_handle_phi_second_pass(struct vtn_builder *b, SpvOp opcode,
522                            const uint32_t *w, unsigned count)
523 {
524    if (opcode != SpvOpPhi)
525       return true;
526 
527    struct hash_entry *phi_entry = _mesa_hash_table_search(b->phi_table, w);
528 
529    /* It's possible that this phi is in an unreachable block in which case it
530     * may never have been emitted and therefore may not be in the hash table.
531     * In this case, there's no var for it and it's safe to just bail.
532     */
533    if (phi_entry == NULL)
534       return true;
535 
536    nir_variable *phi_var = phi_entry->data;
537 
538    for (unsigned i = 3; i < count; i += 2) {
539       struct vtn_block *pred = vtn_block(b, w[i + 1]);
540 
541       /* If block does not have end_nop, that is because it is an unreacheable
542        * block, and hence it is not worth to handle it */
543       if (!pred->end_nop)
544          continue;
545 
546       b->nb.cursor = nir_after_instr(&pred->end_nop->instr);
547 
548       struct vtn_ssa_value *src = vtn_ssa_value(b, w[i]);
549 
550       vtn_local_store(b, src, nir_build_deref_var(&b->nb, phi_var), 0);
551    }
552 
553    return true;
554 }
555 
556 void
vtn_emit_ret_store(struct vtn_builder * b,const struct vtn_block * block)557 vtn_emit_ret_store(struct vtn_builder *b, const struct vtn_block *block)
558 {
559    if ((*block->branch & SpvOpCodeMask) != SpvOpReturnValue)
560       return;
561 
562    vtn_fail_if(b->func->type->return_type->base_type == vtn_base_type_void,
563                "Return with a value from a function returning void");
564    struct vtn_ssa_value *src = vtn_ssa_value(b, block->branch[1]);
565    const struct glsl_type *ret_type =
566       glsl_get_bare_type(b->func->type->return_type->type);
567    nir_deref_instr *ret_deref =
568       nir_build_deref_cast(&b->nb, nir_load_param(&b->nb, 0),
569                            nir_var_function_temp, ret_type, 0);
570    vtn_local_store(b, src, ret_deref, 0);
571 }
572 
573 static struct nir_block *
vtn_new_unstructured_block(struct vtn_builder * b,struct vtn_function * func)574 vtn_new_unstructured_block(struct vtn_builder *b, struct vtn_function *func)
575 {
576    struct nir_block *n = nir_block_create(b->shader);
577    exec_list_push_tail(&func->nir_func->impl->body, &n->cf_node.node);
578    n->cf_node.parent = &func->nir_func->impl->cf_node;
579    return n;
580 }
581 
582 static void
vtn_add_unstructured_block(struct vtn_builder * b,struct vtn_function * func,struct list_head * work_list,struct vtn_block * block)583 vtn_add_unstructured_block(struct vtn_builder *b,
584                            struct vtn_function *func,
585                            struct list_head *work_list,
586                            struct vtn_block *block)
587 {
588    if (!block->block) {
589       block->block = vtn_new_unstructured_block(b, func);
590       list_addtail(&block->link, work_list);
591    }
592 }
593 
594 static void
vtn_emit_cf_func_unstructured(struct vtn_builder * b,struct vtn_function * func,vtn_instruction_handler handler)595 vtn_emit_cf_func_unstructured(struct vtn_builder *b, struct vtn_function *func,
596                               vtn_instruction_handler handler)
597 {
598    struct list_head work_list;
599    list_inithead(&work_list);
600 
601    func->start_block->block = nir_start_block(func->nir_func->impl);
602    list_addtail(&func->start_block->link, &work_list);
603    while (!list_is_empty(&work_list)) {
604       struct vtn_block *block =
605          list_first_entry(&work_list, struct vtn_block, link);
606       list_del(&block->link);
607 
608       vtn_assert(block->block);
609 
610       const uint32_t *block_start = block->label;
611       const uint32_t *block_end = block->branch;
612 
613       b->nb.cursor = nir_after_block(block->block);
614       block_start = vtn_foreach_instruction(b, block_start, block_end,
615                                             vtn_handle_phis_first_pass);
616       vtn_foreach_instruction(b, block_start, block_end, handler);
617       block->end_nop = nir_nop(&b->nb);
618 
619       SpvOp op = *block_end & SpvOpCodeMask;
620       switch (op) {
621       case SpvOpBranch: {
622          struct vtn_block *branch_block = vtn_block(b, block->branch[1]);
623          vtn_add_unstructured_block(b, func, &work_list, branch_block);
624          nir_goto(&b->nb, branch_block->block);
625          break;
626       }
627 
628       case SpvOpBranchConditional: {
629          nir_def *cond = vtn_ssa_value(b, block->branch[1])->def;
630          struct vtn_block *then_block = vtn_block(b, block->branch[2]);
631          struct vtn_block *else_block = vtn_block(b, block->branch[3]);
632 
633          vtn_add_unstructured_block(b, func, &work_list, then_block);
634          if (then_block == else_block) {
635             nir_goto(&b->nb, then_block->block);
636          } else {
637             vtn_add_unstructured_block(b, func, &work_list, else_block);
638             nir_goto_if(&b->nb, then_block->block, cond, else_block->block);
639          }
640 
641          break;
642       }
643 
644       case SpvOpSwitch: {
645          struct list_head cases;
646          list_inithead(&cases);
647          vtn_parse_switch(b, block->branch, &cases);
648 
649          nir_def *sel = vtn_get_nir_ssa(b, block->branch[1]);
650 
651          struct vtn_case *def = NULL;
652          vtn_foreach_case(cse, &cases) {
653             if (cse->is_default) {
654                assert(def == NULL);
655                def = cse;
656                continue;
657             }
658 
659             nir_def *cond = nir_imm_false(&b->nb);
660             util_dynarray_foreach(&cse->values, uint64_t, val)
661                cond = nir_ior(&b->nb, cond, nir_ieq_imm(&b->nb, sel, *val));
662 
663             /* block for the next check */
664             nir_block *e = vtn_new_unstructured_block(b, func);
665             vtn_add_unstructured_block(b, func, &work_list, cse->block);
666 
667             /* add branching */
668             nir_goto_if(&b->nb, cse->block->block, cond, e);
669             b->nb.cursor = nir_after_block(e);
670          }
671 
672          vtn_assert(def != NULL);
673          vtn_add_unstructured_block(b, func, &work_list, def->block);
674 
675          /* now that all cases are handled, branch into the default block */
676          nir_goto(&b->nb, def->block->block);
677          break;
678       }
679 
680       case SpvOpKill: {
681          nir_discard(&b->nb);
682          nir_goto(&b->nb, b->func->nir_func->impl->end_block);
683          break;
684       }
685 
686       case SpvOpUnreachable:
687       case SpvOpReturn:
688       case SpvOpReturnValue: {
689          vtn_emit_ret_store(b, block);
690          nir_goto(&b->nb, b->func->nir_func->impl->end_block);
691          break;
692       }
693 
694       default:
695          vtn_fail("Unhandled opcode %s", spirv_op_to_string(op));
696       }
697    }
698 }
699 
700 void
vtn_function_emit(struct vtn_builder * b,struct vtn_function * func,vtn_instruction_handler instruction_handler)701 vtn_function_emit(struct vtn_builder *b, struct vtn_function *func,
702                   vtn_instruction_handler instruction_handler)
703 {
704    static int force_unstructured = -1;
705    if (force_unstructured < 0) {
706       force_unstructured =
707          debug_get_bool_option("MESA_SPIRV_FORCE_UNSTRUCTURED", false);
708    }
709 
710    nir_function_impl *impl = func->nir_func->impl;
711    b->nb = nir_builder_at(nir_after_impl(impl));
712    b->func = func;
713    b->nb.exact = b->exact;
714    b->phi_table = _mesa_pointer_hash_table_create(b);
715 
716    if (b->shader->info.stage == MESA_SHADER_KERNEL || force_unstructured) {
717       impl->structured = false;
718       vtn_emit_cf_func_unstructured(b, func, instruction_handler);
719    } else {
720       vtn_emit_cf_func_structured(b, func, instruction_handler);
721    }
722 
723    vtn_foreach_instruction(b, func->start_block->label, func->end,
724                            vtn_handle_phi_second_pass);
725 
726    if (func->nir_func->impl->structured)
727       nir_copy_prop_impl(impl);
728    nir_rematerialize_derefs_in_use_blocks_impl(impl);
729 
730    /*
731     * There are some cases where we need to repair SSA to insert
732     * the needed phi nodes:
733     *
734     * - Early termination instructions `OpKill` and `OpTerminateInvocation`,
735     *   in NIR. They're represented by regular intrinsics with no control-flow
736     *   semantics. This means that the SSA form from the SPIR-V may not
737     *   100% match NIR.
738     *
739     * - Switches with only default case may also define SSA which may
740     *   subsequently be used out of the switch.
741     */
742    if (func->nir_func->impl->structured)
743       nir_repair_ssa_impl(impl);
744 
745    func->emitted = true;
746 }
747