1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 Red Hat
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "nir.h"
25bf215546Sopenharmony_ci#include "nir_control_flow.h"
26bf215546Sopenharmony_ci#include "nir_xfb_info.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/* Secret Decoder Ring:
29bf215546Sopenharmony_ci *   clone_foo():
30bf215546Sopenharmony_ci *        Allocate and clone a foo.
31bf215546Sopenharmony_ci *   __clone_foo():
32bf215546Sopenharmony_ci *        Clone body of foo (ie. parent class, embedded struct, etc)
33bf215546Sopenharmony_ci */
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_citypedef struct {
36bf215546Sopenharmony_ci   /* True if we are cloning an entire shader. */
37bf215546Sopenharmony_ci   bool global_clone;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci   /* If true allows the clone operation to fall back to the original pointer
40bf215546Sopenharmony_ci    * if no clone pointer is found in the remap table.  This allows us to
41bf215546Sopenharmony_ci    * clone a loop body without having to add srcs from outside the loop to
42bf215546Sopenharmony_ci    * the remap table. This is useful for loop unrolling.
43bf215546Sopenharmony_ci    */
44bf215546Sopenharmony_ci   bool allow_remap_fallback;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   /* maps orig ptr -> cloned ptr: */
47bf215546Sopenharmony_ci   struct hash_table *remap_table;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   /* List of phi sources. */
50bf215546Sopenharmony_ci   struct list_head phi_srcs;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   /* new shader object, used as memctx for just about everything else: */
53bf215546Sopenharmony_ci   nir_shader *ns;
54bf215546Sopenharmony_ci} clone_state;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistatic void
57bf215546Sopenharmony_ciinit_clone_state(clone_state *state, struct hash_table *remap_table,
58bf215546Sopenharmony_ci                 bool global, bool allow_remap_fallback)
59bf215546Sopenharmony_ci{
60bf215546Sopenharmony_ci   state->global_clone = global;
61bf215546Sopenharmony_ci   state->allow_remap_fallback = allow_remap_fallback;
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci   if (remap_table) {
64bf215546Sopenharmony_ci      state->remap_table = remap_table;
65bf215546Sopenharmony_ci   } else {
66bf215546Sopenharmony_ci      state->remap_table = _mesa_pointer_hash_table_create(NULL);
67bf215546Sopenharmony_ci   }
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   list_inithead(&state->phi_srcs);
70bf215546Sopenharmony_ci}
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_cistatic void
73bf215546Sopenharmony_cifree_clone_state(clone_state *state)
74bf215546Sopenharmony_ci{
75bf215546Sopenharmony_ci   _mesa_hash_table_destroy(state->remap_table, NULL);
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistatic inline void *
79bf215546Sopenharmony_ci_lookup_ptr(clone_state *state, const void *ptr, bool global)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci   struct hash_entry *entry;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   if (!ptr)
84bf215546Sopenharmony_ci      return NULL;
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci   if (!state->global_clone && global)
87bf215546Sopenharmony_ci      return (void *)ptr;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci   if (unlikely(!state->remap_table)) {
90bf215546Sopenharmony_ci      assert(state->allow_remap_fallback);
91bf215546Sopenharmony_ci      return (void *)ptr;
92bf215546Sopenharmony_ci   }
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci   entry = _mesa_hash_table_search(state->remap_table, ptr);
95bf215546Sopenharmony_ci   if (!entry) {
96bf215546Sopenharmony_ci      assert(state->allow_remap_fallback);
97bf215546Sopenharmony_ci      return (void *)ptr;
98bf215546Sopenharmony_ci   }
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci   return entry->data;
101bf215546Sopenharmony_ci}
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_cistatic void
104bf215546Sopenharmony_ciadd_remap(clone_state *state, void *nptr, const void *ptr)
105bf215546Sopenharmony_ci{
106bf215546Sopenharmony_ci   _mesa_hash_table_insert(state->remap_table, ptr, nptr);
107bf215546Sopenharmony_ci}
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_cistatic void *
110bf215546Sopenharmony_ciremap_local(clone_state *state, const void *ptr)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   return _lookup_ptr(state, ptr, false);
113bf215546Sopenharmony_ci}
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_cistatic void *
116bf215546Sopenharmony_ciremap_global(clone_state *state, const void *ptr)
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci   return _lookup_ptr(state, ptr, true);
119bf215546Sopenharmony_ci}
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_cistatic nir_register *
122bf215546Sopenharmony_ciremap_reg(clone_state *state, const nir_register *reg)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   return _lookup_ptr(state, reg, false);
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cistatic nir_variable *
128bf215546Sopenharmony_ciremap_var(clone_state *state, const nir_variable *var)
129bf215546Sopenharmony_ci{
130bf215546Sopenharmony_ci   return _lookup_ptr(state, var, nir_variable_is_global(var));
131bf215546Sopenharmony_ci}
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_cinir_constant *
134bf215546Sopenharmony_cinir_constant_clone(const nir_constant *c, nir_variable *nvar)
135bf215546Sopenharmony_ci{
136bf215546Sopenharmony_ci   nir_constant *nc = ralloc(nvar, nir_constant);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   memcpy(nc->values, c->values, sizeof(nc->values));
139bf215546Sopenharmony_ci   nc->num_elements = c->num_elements;
140bf215546Sopenharmony_ci   nc->elements = ralloc_array(nvar, nir_constant *, c->num_elements);
141bf215546Sopenharmony_ci   for (unsigned i = 0; i < c->num_elements; i++) {
142bf215546Sopenharmony_ci      nc->elements[i] = nir_constant_clone(c->elements[i], nvar);
143bf215546Sopenharmony_ci   }
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   return nc;
146bf215546Sopenharmony_ci}
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci/* NOTE: for cloning nir_variables, bypass nir_variable_create to avoid
149bf215546Sopenharmony_ci * having to deal with locals and globals separately:
150bf215546Sopenharmony_ci */
151bf215546Sopenharmony_cinir_variable *
152bf215546Sopenharmony_cinir_variable_clone(const nir_variable *var, nir_shader *shader)
153bf215546Sopenharmony_ci{
154bf215546Sopenharmony_ci   nir_variable *nvar = rzalloc(shader, nir_variable);
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   nvar->type = var->type;
157bf215546Sopenharmony_ci   nvar->name = ralloc_strdup(nvar, var->name);
158bf215546Sopenharmony_ci   nvar->data = var->data;
159bf215546Sopenharmony_ci   nvar->num_state_slots = var->num_state_slots;
160bf215546Sopenharmony_ci   if (var->num_state_slots) {
161bf215546Sopenharmony_ci      nvar->state_slots = ralloc_array(nvar, nir_state_slot, var->num_state_slots);
162bf215546Sopenharmony_ci      memcpy(nvar->state_slots, var->state_slots,
163bf215546Sopenharmony_ci             var->num_state_slots * sizeof(nir_state_slot));
164bf215546Sopenharmony_ci   }
165bf215546Sopenharmony_ci   if (var->constant_initializer) {
166bf215546Sopenharmony_ci      nvar->constant_initializer =
167bf215546Sopenharmony_ci         nir_constant_clone(var->constant_initializer, nvar);
168bf215546Sopenharmony_ci   }
169bf215546Sopenharmony_ci   nvar->interface_type = var->interface_type;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   nvar->num_members = var->num_members;
172bf215546Sopenharmony_ci   if (var->num_members) {
173bf215546Sopenharmony_ci      nvar->members = ralloc_array(nvar, struct nir_variable_data,
174bf215546Sopenharmony_ci                                   var->num_members);
175bf215546Sopenharmony_ci      memcpy(nvar->members, var->members,
176bf215546Sopenharmony_ci             var->num_members * sizeof(*var->members));
177bf215546Sopenharmony_ci   }
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   return nvar;
180bf215546Sopenharmony_ci}
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_cistatic nir_variable *
183bf215546Sopenharmony_ciclone_variable(clone_state *state, const nir_variable *var)
184bf215546Sopenharmony_ci{
185bf215546Sopenharmony_ci   nir_variable *nvar = nir_variable_clone(var, state->ns);
186bf215546Sopenharmony_ci   add_remap(state, nvar, var);
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   return nvar;
189bf215546Sopenharmony_ci}
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci/* clone list of nir_variable: */
192bf215546Sopenharmony_cistatic void
193bf215546Sopenharmony_ciclone_var_list(clone_state *state, struct exec_list *dst,
194bf215546Sopenharmony_ci               const struct exec_list *list)
195bf215546Sopenharmony_ci{
196bf215546Sopenharmony_ci   exec_list_make_empty(dst);
197bf215546Sopenharmony_ci   foreach_list_typed(nir_variable, var, node, list) {
198bf215546Sopenharmony_ci      nir_variable *nvar = clone_variable(state, var);
199bf215546Sopenharmony_ci      exec_list_push_tail(dst, &nvar->node);
200bf215546Sopenharmony_ci   }
201bf215546Sopenharmony_ci}
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci/* NOTE: for cloning nir_registers, bypass nir_global/local_reg_create()
204bf215546Sopenharmony_ci * to avoid having to deal with locals and globals separately:
205bf215546Sopenharmony_ci */
206bf215546Sopenharmony_cistatic nir_register *
207bf215546Sopenharmony_ciclone_register(clone_state *state, const nir_register *reg)
208bf215546Sopenharmony_ci{
209bf215546Sopenharmony_ci   nir_register *nreg = rzalloc(state->ns, nir_register);
210bf215546Sopenharmony_ci   add_remap(state, nreg, reg);
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci   nreg->num_components = reg->num_components;
213bf215546Sopenharmony_ci   nreg->bit_size = reg->bit_size;
214bf215546Sopenharmony_ci   nreg->num_array_elems = reg->num_array_elems;
215bf215546Sopenharmony_ci   nreg->index = reg->index;
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   /* reconstructing uses/defs/if_uses handled by nir_instr_insert() */
218bf215546Sopenharmony_ci   list_inithead(&nreg->uses);
219bf215546Sopenharmony_ci   list_inithead(&nreg->defs);
220bf215546Sopenharmony_ci   list_inithead(&nreg->if_uses);
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci   return nreg;
223bf215546Sopenharmony_ci}
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci/* clone list of nir_register: */
226bf215546Sopenharmony_cistatic void
227bf215546Sopenharmony_ciclone_reg_list(clone_state *state, struct exec_list *dst,
228bf215546Sopenharmony_ci               const struct exec_list *list)
229bf215546Sopenharmony_ci{
230bf215546Sopenharmony_ci   exec_list_make_empty(dst);
231bf215546Sopenharmony_ci   foreach_list_typed(nir_register, reg, node, list) {
232bf215546Sopenharmony_ci      nir_register *nreg = clone_register(state, reg);
233bf215546Sopenharmony_ci      exec_list_push_tail(dst, &nreg->node);
234bf215546Sopenharmony_ci   }
235bf215546Sopenharmony_ci}
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_cistatic void
238bf215546Sopenharmony_ci__clone_src(clone_state *state, void *ninstr_or_if,
239bf215546Sopenharmony_ci            nir_src *nsrc, const nir_src *src)
240bf215546Sopenharmony_ci{
241bf215546Sopenharmony_ci   nsrc->is_ssa = src->is_ssa;
242bf215546Sopenharmony_ci   if (src->is_ssa) {
243bf215546Sopenharmony_ci      nsrc->ssa = remap_local(state, src->ssa);
244bf215546Sopenharmony_ci   } else {
245bf215546Sopenharmony_ci      nsrc->reg.reg = remap_reg(state, src->reg.reg);
246bf215546Sopenharmony_ci      if (src->reg.indirect) {
247bf215546Sopenharmony_ci         nsrc->reg.indirect = malloc(sizeof(nir_src));
248bf215546Sopenharmony_ci         __clone_src(state, ninstr_or_if, nsrc->reg.indirect, src->reg.indirect);
249bf215546Sopenharmony_ci      }
250bf215546Sopenharmony_ci      nsrc->reg.base_offset = src->reg.base_offset;
251bf215546Sopenharmony_ci   }
252bf215546Sopenharmony_ci}
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_cistatic void
255bf215546Sopenharmony_ci__clone_dst(clone_state *state, nir_instr *ninstr,
256bf215546Sopenharmony_ci            nir_dest *ndst, const nir_dest *dst)
257bf215546Sopenharmony_ci{
258bf215546Sopenharmony_ci   ndst->is_ssa = dst->is_ssa;
259bf215546Sopenharmony_ci   if (dst->is_ssa) {
260bf215546Sopenharmony_ci      nir_ssa_dest_init(ninstr, ndst, dst->ssa.num_components,
261bf215546Sopenharmony_ci                        dst->ssa.bit_size, NULL);
262bf215546Sopenharmony_ci      if (likely(state->remap_table))
263bf215546Sopenharmony_ci         add_remap(state, &ndst->ssa, &dst->ssa);
264bf215546Sopenharmony_ci   } else {
265bf215546Sopenharmony_ci      ndst->reg.reg = remap_reg(state, dst->reg.reg);
266bf215546Sopenharmony_ci      if (dst->reg.indirect) {
267bf215546Sopenharmony_ci         ndst->reg.indirect = malloc(sizeof(nir_src));
268bf215546Sopenharmony_ci         __clone_src(state, ninstr, ndst->reg.indirect, dst->reg.indirect);
269bf215546Sopenharmony_ci      }
270bf215546Sopenharmony_ci      ndst->reg.base_offset = dst->reg.base_offset;
271bf215546Sopenharmony_ci   }
272bf215546Sopenharmony_ci}
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_cistatic nir_alu_instr *
275bf215546Sopenharmony_ciclone_alu(clone_state *state, const nir_alu_instr *alu)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   nir_alu_instr *nalu = nir_alu_instr_create(state->ns, alu->op);
278bf215546Sopenharmony_ci   nalu->exact = alu->exact;
279bf215546Sopenharmony_ci   nalu->no_signed_wrap = alu->no_signed_wrap;
280bf215546Sopenharmony_ci   nalu->no_unsigned_wrap = alu->no_unsigned_wrap;
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   __clone_dst(state, &nalu->instr, &nalu->dest.dest, &alu->dest.dest);
283bf215546Sopenharmony_ci   nalu->dest.saturate = alu->dest.saturate;
284bf215546Sopenharmony_ci   nalu->dest.write_mask = alu->dest.write_mask;
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
287bf215546Sopenharmony_ci      __clone_src(state, &nalu->instr, &nalu->src[i].src, &alu->src[i].src);
288bf215546Sopenharmony_ci      nalu->src[i].negate = alu->src[i].negate;
289bf215546Sopenharmony_ci      nalu->src[i].abs = alu->src[i].abs;
290bf215546Sopenharmony_ci      memcpy(nalu->src[i].swizzle, alu->src[i].swizzle,
291bf215546Sopenharmony_ci             sizeof(nalu->src[i].swizzle));
292bf215546Sopenharmony_ci   }
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci   return nalu;
295bf215546Sopenharmony_ci}
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_cinir_alu_instr *
298bf215546Sopenharmony_cinir_alu_instr_clone(nir_shader *shader, const nir_alu_instr *orig)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci   clone_state state = {
301bf215546Sopenharmony_ci      .allow_remap_fallback = true,
302bf215546Sopenharmony_ci      .ns = shader,
303bf215546Sopenharmony_ci   };
304bf215546Sopenharmony_ci   return clone_alu(&state, orig);
305bf215546Sopenharmony_ci}
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_cistatic nir_deref_instr *
308bf215546Sopenharmony_ciclone_deref_instr(clone_state *state, const nir_deref_instr *deref)
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   nir_deref_instr *nderef =
311bf215546Sopenharmony_ci      nir_deref_instr_create(state->ns, deref->deref_type);
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   __clone_dst(state, &nderef->instr, &nderef->dest, &deref->dest);
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   nderef->modes = deref->modes;
316bf215546Sopenharmony_ci   nderef->type = deref->type;
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci   if (deref->deref_type == nir_deref_type_var) {
319bf215546Sopenharmony_ci      nderef->var = remap_var(state, deref->var);
320bf215546Sopenharmony_ci      return nderef;
321bf215546Sopenharmony_ci   }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   __clone_src(state, &nderef->instr, &nderef->parent, &deref->parent);
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   switch (deref->deref_type) {
326bf215546Sopenharmony_ci   case nir_deref_type_struct:
327bf215546Sopenharmony_ci      nderef->strct.index = deref->strct.index;
328bf215546Sopenharmony_ci      break;
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci   case nir_deref_type_array:
331bf215546Sopenharmony_ci   case nir_deref_type_ptr_as_array:
332bf215546Sopenharmony_ci      __clone_src(state, &nderef->instr,
333bf215546Sopenharmony_ci                  &nderef->arr.index, &deref->arr.index);
334bf215546Sopenharmony_ci      nderef->arr.in_bounds = deref->arr.in_bounds;
335bf215546Sopenharmony_ci      break;
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   case nir_deref_type_array_wildcard:
338bf215546Sopenharmony_ci      /* Nothing to do */
339bf215546Sopenharmony_ci      break;
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   case nir_deref_type_cast:
342bf215546Sopenharmony_ci      nderef->cast.ptr_stride = deref->cast.ptr_stride;
343bf215546Sopenharmony_ci      nderef->cast.align_mul = deref->cast.align_mul;
344bf215546Sopenharmony_ci      nderef->cast.align_offset = deref->cast.align_offset;
345bf215546Sopenharmony_ci      break;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   default:
348bf215546Sopenharmony_ci      unreachable("Invalid instruction deref type");
349bf215546Sopenharmony_ci   }
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci   return nderef;
352bf215546Sopenharmony_ci}
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_cistatic nir_intrinsic_instr *
355bf215546Sopenharmony_ciclone_intrinsic(clone_state *state, const nir_intrinsic_instr *itr)
356bf215546Sopenharmony_ci{
357bf215546Sopenharmony_ci   nir_intrinsic_instr *nitr =
358bf215546Sopenharmony_ci      nir_intrinsic_instr_create(state->ns, itr->intrinsic);
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci   unsigned num_srcs = nir_intrinsic_infos[itr->intrinsic].num_srcs;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   if (nir_intrinsic_infos[itr->intrinsic].has_dest)
363bf215546Sopenharmony_ci      __clone_dst(state, &nitr->instr, &nitr->dest, &itr->dest);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   nitr->num_components = itr->num_components;
366bf215546Sopenharmony_ci   memcpy(nitr->const_index, itr->const_index, sizeof(nitr->const_index));
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_srcs; i++)
369bf215546Sopenharmony_ci      __clone_src(state, &nitr->instr, &nitr->src[i], &itr->src[i]);
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci   return nitr;
372bf215546Sopenharmony_ci}
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_cistatic nir_load_const_instr *
375bf215546Sopenharmony_ciclone_load_const(clone_state *state, const nir_load_const_instr *lc)
376bf215546Sopenharmony_ci{
377bf215546Sopenharmony_ci   nir_load_const_instr *nlc =
378bf215546Sopenharmony_ci      nir_load_const_instr_create(state->ns, lc->def.num_components,
379bf215546Sopenharmony_ci                                  lc->def.bit_size);
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci   memcpy(&nlc->value, &lc->value, sizeof(*nlc->value) * lc->def.num_components);
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci   add_remap(state, &nlc->def, &lc->def);
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   return nlc;
386bf215546Sopenharmony_ci}
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_cistatic nir_ssa_undef_instr *
389bf215546Sopenharmony_ciclone_ssa_undef(clone_state *state, const nir_ssa_undef_instr *sa)
390bf215546Sopenharmony_ci{
391bf215546Sopenharmony_ci   nir_ssa_undef_instr *nsa =
392bf215546Sopenharmony_ci      nir_ssa_undef_instr_create(state->ns, sa->def.num_components,
393bf215546Sopenharmony_ci                                 sa->def.bit_size);
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci   add_remap(state, &nsa->def, &sa->def);
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci   return nsa;
398bf215546Sopenharmony_ci}
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_cistatic nir_tex_instr *
401bf215546Sopenharmony_ciclone_tex(clone_state *state, const nir_tex_instr *tex)
402bf215546Sopenharmony_ci{
403bf215546Sopenharmony_ci   nir_tex_instr *ntex = nir_tex_instr_create(state->ns, tex->num_srcs);
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   ntex->sampler_dim = tex->sampler_dim;
406bf215546Sopenharmony_ci   ntex->dest_type = tex->dest_type;
407bf215546Sopenharmony_ci   ntex->op = tex->op;
408bf215546Sopenharmony_ci   __clone_dst(state, &ntex->instr, &ntex->dest, &tex->dest);
409bf215546Sopenharmony_ci   for (unsigned i = 0; i < ntex->num_srcs; i++) {
410bf215546Sopenharmony_ci      ntex->src[i].src_type = tex->src[i].src_type;
411bf215546Sopenharmony_ci      __clone_src(state, &ntex->instr, &ntex->src[i].src, &tex->src[i].src);
412bf215546Sopenharmony_ci   }
413bf215546Sopenharmony_ci   ntex->coord_components = tex->coord_components;
414bf215546Sopenharmony_ci   ntex->is_array = tex->is_array;
415bf215546Sopenharmony_ci   ntex->array_is_lowered_cube = tex->array_is_lowered_cube;
416bf215546Sopenharmony_ci   ntex->is_shadow = tex->is_shadow;
417bf215546Sopenharmony_ci   ntex->is_new_style_shadow = tex->is_new_style_shadow;
418bf215546Sopenharmony_ci   ntex->is_sparse = tex->is_sparse;
419bf215546Sopenharmony_ci   ntex->component = tex->component;
420bf215546Sopenharmony_ci   memcpy(ntex->tg4_offsets, tex->tg4_offsets, sizeof(tex->tg4_offsets));
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   ntex->texture_index = tex->texture_index;
423bf215546Sopenharmony_ci   ntex->sampler_index = tex->sampler_index;
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci   ntex->texture_non_uniform = tex->texture_non_uniform;
426bf215546Sopenharmony_ci   ntex->sampler_non_uniform = tex->sampler_non_uniform;
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci   return ntex;
429bf215546Sopenharmony_ci}
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_cistatic nir_phi_instr *
432bf215546Sopenharmony_ciclone_phi(clone_state *state, const nir_phi_instr *phi, nir_block *nblk)
433bf215546Sopenharmony_ci{
434bf215546Sopenharmony_ci   nir_phi_instr *nphi = nir_phi_instr_create(state->ns);
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   __clone_dst(state, &nphi->instr, &nphi->dest, &phi->dest);
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci   /* Cloning a phi node is a bit different from other instructions.  The
439bf215546Sopenharmony_ci    * sources of phi instructions are the only time where we can use an SSA
440bf215546Sopenharmony_ci    * def before it is defined.  In order to handle this, we just copy over
441bf215546Sopenharmony_ci    * the sources from the old phi instruction directly and then fix them up
442bf215546Sopenharmony_ci    * in a second pass once all the instrutions in the function have been
443bf215546Sopenharmony_ci    * properly cloned.
444bf215546Sopenharmony_ci    *
445bf215546Sopenharmony_ci    * In order to ensure that the copied sources (which are the same as the
446bf215546Sopenharmony_ci    * old phi instruction's sources for now) don't get inserted into the old
447bf215546Sopenharmony_ci    * shader's use-def lists, we have to add the phi instruction *before* we
448bf215546Sopenharmony_ci    * set up its sources.
449bf215546Sopenharmony_ci    */
450bf215546Sopenharmony_ci   nir_instr_insert_after_block(nblk, &nphi->instr);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   nir_foreach_phi_src(src, phi) {
453bf215546Sopenharmony_ci      nir_phi_src *nsrc = nir_phi_instr_add_src(nphi, src->pred, src->src);
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci      /* Stash it in the list of phi sources.  We'll walk this list and fix up
456bf215546Sopenharmony_ci       * sources at the very end of clone_function_impl.
457bf215546Sopenharmony_ci       */
458bf215546Sopenharmony_ci      list_add(&nsrc->src.use_link, &state->phi_srcs);
459bf215546Sopenharmony_ci   }
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   return nphi;
462bf215546Sopenharmony_ci}
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_cistatic nir_jump_instr *
465bf215546Sopenharmony_ciclone_jump(clone_state *state, const nir_jump_instr *jmp)
466bf215546Sopenharmony_ci{
467bf215546Sopenharmony_ci   /* These aren't handled because they require special block linking */
468bf215546Sopenharmony_ci   assert(jmp->type != nir_jump_goto && jmp->type != nir_jump_goto_if);
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci   nir_jump_instr *njmp = nir_jump_instr_create(state->ns, jmp->type);
471bf215546Sopenharmony_ci
472bf215546Sopenharmony_ci   return njmp;
473bf215546Sopenharmony_ci}
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_cistatic nir_call_instr *
476bf215546Sopenharmony_ciclone_call(clone_state *state, const nir_call_instr *call)
477bf215546Sopenharmony_ci{
478bf215546Sopenharmony_ci   nir_function *ncallee = remap_global(state, call->callee);
479bf215546Sopenharmony_ci   nir_call_instr *ncall = nir_call_instr_create(state->ns, ncallee);
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci   for (unsigned i = 0; i < ncall->num_params; i++)
482bf215546Sopenharmony_ci      __clone_src(state, ncall, &ncall->params[i], &call->params[i]);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci   return ncall;
485bf215546Sopenharmony_ci}
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_cistatic nir_instr *
488bf215546Sopenharmony_ciclone_instr(clone_state *state, const nir_instr *instr)
489bf215546Sopenharmony_ci{
490bf215546Sopenharmony_ci   switch (instr->type) {
491bf215546Sopenharmony_ci   case nir_instr_type_alu:
492bf215546Sopenharmony_ci      return &clone_alu(state, nir_instr_as_alu(instr))->instr;
493bf215546Sopenharmony_ci   case nir_instr_type_deref:
494bf215546Sopenharmony_ci      return &clone_deref_instr(state, nir_instr_as_deref(instr))->instr;
495bf215546Sopenharmony_ci   case nir_instr_type_intrinsic:
496bf215546Sopenharmony_ci      return &clone_intrinsic(state, nir_instr_as_intrinsic(instr))->instr;
497bf215546Sopenharmony_ci   case nir_instr_type_load_const:
498bf215546Sopenharmony_ci      return &clone_load_const(state, nir_instr_as_load_const(instr))->instr;
499bf215546Sopenharmony_ci   case nir_instr_type_ssa_undef:
500bf215546Sopenharmony_ci      return &clone_ssa_undef(state, nir_instr_as_ssa_undef(instr))->instr;
501bf215546Sopenharmony_ci   case nir_instr_type_tex:
502bf215546Sopenharmony_ci      return &clone_tex(state, nir_instr_as_tex(instr))->instr;
503bf215546Sopenharmony_ci   case nir_instr_type_phi:
504bf215546Sopenharmony_ci      unreachable("Cannot clone phis with clone_instr");
505bf215546Sopenharmony_ci   case nir_instr_type_jump:
506bf215546Sopenharmony_ci      return &clone_jump(state, nir_instr_as_jump(instr))->instr;
507bf215546Sopenharmony_ci   case nir_instr_type_call:
508bf215546Sopenharmony_ci      return &clone_call(state, nir_instr_as_call(instr))->instr;
509bf215546Sopenharmony_ci   case nir_instr_type_parallel_copy:
510bf215546Sopenharmony_ci      unreachable("Cannot clone parallel copies");
511bf215546Sopenharmony_ci   default:
512bf215546Sopenharmony_ci      unreachable("bad instr type");
513bf215546Sopenharmony_ci      return NULL;
514bf215546Sopenharmony_ci   }
515bf215546Sopenharmony_ci}
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_cinir_instr *
518bf215546Sopenharmony_cinir_instr_clone(nir_shader *shader, const nir_instr *orig)
519bf215546Sopenharmony_ci{
520bf215546Sopenharmony_ci   clone_state state = {
521bf215546Sopenharmony_ci      .allow_remap_fallback = true,
522bf215546Sopenharmony_ci      .ns = shader,
523bf215546Sopenharmony_ci   };
524bf215546Sopenharmony_ci   return clone_instr(&state, orig);
525bf215546Sopenharmony_ci}
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_cinir_instr *
528bf215546Sopenharmony_cinir_instr_clone_deep(nir_shader *shader, const nir_instr *orig,
529bf215546Sopenharmony_ci                     struct hash_table *remap_table)
530bf215546Sopenharmony_ci{
531bf215546Sopenharmony_ci   clone_state state = {
532bf215546Sopenharmony_ci      .allow_remap_fallback = true,
533bf215546Sopenharmony_ci      .ns = shader,
534bf215546Sopenharmony_ci      .remap_table = remap_table,
535bf215546Sopenharmony_ci   };
536bf215546Sopenharmony_ci   return clone_instr(&state, orig);
537bf215546Sopenharmony_ci}
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_cistatic nir_block *
540bf215546Sopenharmony_ciclone_block(clone_state *state, struct exec_list *cf_list, const nir_block *blk)
541bf215546Sopenharmony_ci{
542bf215546Sopenharmony_ci   /* Don't actually create a new block.  Just use the one from the tail of
543bf215546Sopenharmony_ci    * the list.  NIR guarantees that the tail of the list is a block and that
544bf215546Sopenharmony_ci    * no two blocks are side-by-side in the IR;  It should be empty.
545bf215546Sopenharmony_ci    */
546bf215546Sopenharmony_ci   nir_block *nblk =
547bf215546Sopenharmony_ci      exec_node_data(nir_block, exec_list_get_tail(cf_list), cf_node.node);
548bf215546Sopenharmony_ci   assert(nblk->cf_node.type == nir_cf_node_block);
549bf215546Sopenharmony_ci   assert(exec_list_is_empty(&nblk->instr_list));
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci   /* We need this for phi sources */
552bf215546Sopenharmony_ci   add_remap(state, nblk, blk);
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci   nir_foreach_instr(instr, blk) {
555bf215546Sopenharmony_ci      if (instr->type == nir_instr_type_phi) {
556bf215546Sopenharmony_ci         /* Phi instructions are a bit of a special case when cloning because
557bf215546Sopenharmony_ci          * we don't want inserting the instruction to automatically handle
558bf215546Sopenharmony_ci          * use/defs for us.  Instead, we need to wait until all the
559bf215546Sopenharmony_ci          * blocks/instructions are in so that we can set their sources up.
560bf215546Sopenharmony_ci          */
561bf215546Sopenharmony_ci         clone_phi(state, nir_instr_as_phi(instr), nblk);
562bf215546Sopenharmony_ci      } else {
563bf215546Sopenharmony_ci         nir_instr *ninstr = clone_instr(state, instr);
564bf215546Sopenharmony_ci         nir_instr_insert_after_block(nblk, ninstr);
565bf215546Sopenharmony_ci      }
566bf215546Sopenharmony_ci   }
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci   return nblk;
569bf215546Sopenharmony_ci}
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_cistatic void
572bf215546Sopenharmony_ciclone_cf_list(clone_state *state, struct exec_list *dst,
573bf215546Sopenharmony_ci              const struct exec_list *list);
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_cistatic nir_if *
576bf215546Sopenharmony_ciclone_if(clone_state *state, struct exec_list *cf_list, const nir_if *i)
577bf215546Sopenharmony_ci{
578bf215546Sopenharmony_ci   nir_if *ni = nir_if_create(state->ns);
579bf215546Sopenharmony_ci   ni->control = i->control;
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   __clone_src(state, ni, &ni->condition, &i->condition);
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   nir_cf_node_insert_end(cf_list, &ni->cf_node);
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci   clone_cf_list(state, &ni->then_list, &i->then_list);
586bf215546Sopenharmony_ci   clone_cf_list(state, &ni->else_list, &i->else_list);
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci   return ni;
589bf215546Sopenharmony_ci}
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_cistatic nir_loop *
592bf215546Sopenharmony_ciclone_loop(clone_state *state, struct exec_list *cf_list, const nir_loop *loop)
593bf215546Sopenharmony_ci{
594bf215546Sopenharmony_ci   nir_loop *nloop = nir_loop_create(state->ns);
595bf215546Sopenharmony_ci   nloop->control = loop->control;
596bf215546Sopenharmony_ci   nloop->partially_unrolled = loop->partially_unrolled;
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci   nir_cf_node_insert_end(cf_list, &nloop->cf_node);
599bf215546Sopenharmony_ci
600bf215546Sopenharmony_ci   clone_cf_list(state, &nloop->body, &loop->body);
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci   return nloop;
603bf215546Sopenharmony_ci}
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci/* clone list of nir_cf_node: */
606bf215546Sopenharmony_cistatic void
607bf215546Sopenharmony_ciclone_cf_list(clone_state *state, struct exec_list *dst,
608bf215546Sopenharmony_ci              const struct exec_list *list)
609bf215546Sopenharmony_ci{
610bf215546Sopenharmony_ci   foreach_list_typed(nir_cf_node, cf, node, list) {
611bf215546Sopenharmony_ci      switch (cf->type) {
612bf215546Sopenharmony_ci      case nir_cf_node_block:
613bf215546Sopenharmony_ci         clone_block(state, dst, nir_cf_node_as_block(cf));
614bf215546Sopenharmony_ci         break;
615bf215546Sopenharmony_ci      case nir_cf_node_if:
616bf215546Sopenharmony_ci         clone_if(state, dst, nir_cf_node_as_if(cf));
617bf215546Sopenharmony_ci         break;
618bf215546Sopenharmony_ci      case nir_cf_node_loop:
619bf215546Sopenharmony_ci         clone_loop(state, dst, nir_cf_node_as_loop(cf));
620bf215546Sopenharmony_ci         break;
621bf215546Sopenharmony_ci      default:
622bf215546Sopenharmony_ci         unreachable("bad cf type");
623bf215546Sopenharmony_ci      }
624bf215546Sopenharmony_ci   }
625bf215546Sopenharmony_ci}
626bf215546Sopenharmony_ci
627bf215546Sopenharmony_ci/* After we've cloned almost everything, we have to walk the list of phi
628bf215546Sopenharmony_ci * sources and fix them up.  Thanks to loops, the block and SSA value for a
629bf215546Sopenharmony_ci * phi source may not be defined when we first encounter it.  Instead, we
630bf215546Sopenharmony_ci * add it to the phi_srcs list and we fix it up here.
631bf215546Sopenharmony_ci */
632bf215546Sopenharmony_cistatic void
633bf215546Sopenharmony_cifixup_phi_srcs(clone_state *state)
634bf215546Sopenharmony_ci{
635bf215546Sopenharmony_ci   list_for_each_entry_safe(nir_phi_src, src, &state->phi_srcs, src.use_link) {
636bf215546Sopenharmony_ci      src->pred = remap_local(state, src->pred);
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci      /* Remove from this list */
639bf215546Sopenharmony_ci      list_del(&src->src.use_link);
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci      if (src->src.is_ssa) {
642bf215546Sopenharmony_ci         src->src.ssa = remap_local(state, src->src.ssa);
643bf215546Sopenharmony_ci         list_addtail(&src->src.use_link, &src->src.ssa->uses);
644bf215546Sopenharmony_ci      } else {
645bf215546Sopenharmony_ci         src->src.reg.reg = remap_reg(state, src->src.reg.reg);
646bf215546Sopenharmony_ci         list_addtail(&src->src.use_link, &src->src.reg.reg->uses);
647bf215546Sopenharmony_ci      }
648bf215546Sopenharmony_ci   }
649bf215546Sopenharmony_ci   assert(list_is_empty(&state->phi_srcs));
650bf215546Sopenharmony_ci}
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_civoid
653bf215546Sopenharmony_cinir_cf_list_clone(nir_cf_list *dst, nir_cf_list *src, nir_cf_node *parent,
654bf215546Sopenharmony_ci                  struct hash_table *remap_table)
655bf215546Sopenharmony_ci{
656bf215546Sopenharmony_ci   exec_list_make_empty(&dst->list);
657bf215546Sopenharmony_ci   dst->impl = src->impl;
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci   if (exec_list_is_empty(&src->list))
660bf215546Sopenharmony_ci      return;
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   clone_state state;
663bf215546Sopenharmony_ci   init_clone_state(&state, remap_table, false, true);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   /* We use the same shader */
666bf215546Sopenharmony_ci   state.ns = src->impl->function->shader;
667bf215546Sopenharmony_ci
668bf215546Sopenharmony_ci   /* The control-flow code assumes that the list of cf_nodes always starts
669bf215546Sopenharmony_ci    * and ends with a block.  We start by adding an empty block.
670bf215546Sopenharmony_ci    */
671bf215546Sopenharmony_ci   nir_block *nblk = nir_block_create(state.ns);
672bf215546Sopenharmony_ci   nblk->cf_node.parent = parent;
673bf215546Sopenharmony_ci   exec_list_push_tail(&dst->list, &nblk->cf_node.node);
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci   clone_cf_list(&state, &dst->list, &src->list);
676bf215546Sopenharmony_ci
677bf215546Sopenharmony_ci   fixup_phi_srcs(&state);
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   if (!remap_table)
680bf215546Sopenharmony_ci      free_clone_state(&state);
681bf215546Sopenharmony_ci}
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_cistatic nir_function_impl *
684bf215546Sopenharmony_ciclone_function_impl(clone_state *state, const nir_function_impl *fi)
685bf215546Sopenharmony_ci{
686bf215546Sopenharmony_ci   nir_function_impl *nfi = nir_function_impl_create_bare(state->ns);
687bf215546Sopenharmony_ci
688bf215546Sopenharmony_ci   if (fi->preamble)
689bf215546Sopenharmony_ci      nfi->preamble = remap_global(state, fi->preamble);
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci   clone_var_list(state, &nfi->locals, &fi->locals);
692bf215546Sopenharmony_ci   clone_reg_list(state, &nfi->registers, &fi->registers);
693bf215546Sopenharmony_ci   nfi->reg_alloc = fi->reg_alloc;
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   assert(list_is_empty(&state->phi_srcs));
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_ci   clone_cf_list(state, &nfi->body, &fi->body);
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci   fixup_phi_srcs(state);
700bf215546Sopenharmony_ci
701bf215546Sopenharmony_ci   /* All metadata is invalidated in the cloning process */
702bf215546Sopenharmony_ci   nfi->valid_metadata = 0;
703bf215546Sopenharmony_ci
704bf215546Sopenharmony_ci   return nfi;
705bf215546Sopenharmony_ci}
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_cinir_function_impl *
708bf215546Sopenharmony_cinir_function_impl_clone(nir_shader *shader, const nir_function_impl *fi)
709bf215546Sopenharmony_ci{
710bf215546Sopenharmony_ci   clone_state state;
711bf215546Sopenharmony_ci   init_clone_state(&state, NULL, false, false);
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci   state.ns = shader;
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci   nir_function_impl *nfi = clone_function_impl(&state, fi);
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci   free_clone_state(&state);
718bf215546Sopenharmony_ci
719bf215546Sopenharmony_ci   return nfi;
720bf215546Sopenharmony_ci}
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_cistatic nir_function *
723bf215546Sopenharmony_ciclone_function(clone_state *state, const nir_function *fxn, nir_shader *ns)
724bf215546Sopenharmony_ci{
725bf215546Sopenharmony_ci   assert(ns == state->ns);
726bf215546Sopenharmony_ci   nir_function *nfxn = nir_function_create(ns, fxn->name);
727bf215546Sopenharmony_ci
728bf215546Sopenharmony_ci   /* Needed for call instructions */
729bf215546Sopenharmony_ci   add_remap(state, nfxn, fxn);
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci   nfxn->num_params = fxn->num_params;
732bf215546Sopenharmony_ci   if (fxn->num_params) {
733bf215546Sopenharmony_ci           nfxn->params = ralloc_array(state->ns, nir_parameter, fxn->num_params);
734bf215546Sopenharmony_ci           memcpy(nfxn->params, fxn->params, sizeof(nir_parameter) * fxn->num_params);
735bf215546Sopenharmony_ci   }
736bf215546Sopenharmony_ci   nfxn->is_entrypoint = fxn->is_entrypoint;
737bf215546Sopenharmony_ci   nfxn->is_preamble = fxn->is_preamble;
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci   /* At first glance, it looks like we should clone the function_impl here.
740bf215546Sopenharmony_ci    * However, call instructions need to be able to reference at least the
741bf215546Sopenharmony_ci    * function and those will get processed as we clone the function_impls.
742bf215546Sopenharmony_ci    * We stop here and do function_impls as a second pass.
743bf215546Sopenharmony_ci    */
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_ci   return nfxn;
746bf215546Sopenharmony_ci}
747bf215546Sopenharmony_ci
748bf215546Sopenharmony_cinir_shader *
749bf215546Sopenharmony_cinir_shader_clone(void *mem_ctx, const nir_shader *s)
750bf215546Sopenharmony_ci{
751bf215546Sopenharmony_ci   clone_state state;
752bf215546Sopenharmony_ci   init_clone_state(&state, NULL, true, false);
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   nir_shader *ns = nir_shader_create(mem_ctx, s->info.stage, s->options, NULL);
755bf215546Sopenharmony_ci   state.ns = ns;
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci   clone_var_list(&state, &ns->variables, &s->variables);
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci   /* Go through and clone functions */
760bf215546Sopenharmony_ci   foreach_list_typed(nir_function, fxn, node, &s->functions)
761bf215546Sopenharmony_ci      clone_function(&state, fxn, ns);
762bf215546Sopenharmony_ci
763bf215546Sopenharmony_ci   /* Only after all functions are cloned can we clone the actual function
764bf215546Sopenharmony_ci    * implementations.  This is because nir_call_instrs and preambles need to
765bf215546Sopenharmony_ci    * reference the functions of other functions and we don't know what order
766bf215546Sopenharmony_ci    * the functions will have in the list.
767bf215546Sopenharmony_ci    */
768bf215546Sopenharmony_ci   nir_foreach_function(fxn, s) {
769bf215546Sopenharmony_ci      nir_function *nfxn = remap_global(&state, fxn);
770bf215546Sopenharmony_ci      nfxn->impl = clone_function_impl(&state, fxn->impl);
771bf215546Sopenharmony_ci      nfxn->impl->function = nfxn;
772bf215546Sopenharmony_ci   }
773bf215546Sopenharmony_ci
774bf215546Sopenharmony_ci   ns->info = s->info;
775bf215546Sopenharmony_ci   ns->info.name = ralloc_strdup(ns, ns->info.name);
776bf215546Sopenharmony_ci   if (ns->info.label)
777bf215546Sopenharmony_ci      ns->info.label = ralloc_strdup(ns, ns->info.label);
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci   ns->num_inputs = s->num_inputs;
780bf215546Sopenharmony_ci   ns->num_uniforms = s->num_uniforms;
781bf215546Sopenharmony_ci   ns->num_outputs = s->num_outputs;
782bf215546Sopenharmony_ci   ns->scratch_size = s->scratch_size;
783bf215546Sopenharmony_ci
784bf215546Sopenharmony_ci   ns->constant_data_size = s->constant_data_size;
785bf215546Sopenharmony_ci   if (s->constant_data_size > 0) {
786bf215546Sopenharmony_ci      ns->constant_data = ralloc_size(ns, s->constant_data_size);
787bf215546Sopenharmony_ci      memcpy(ns->constant_data, s->constant_data, s->constant_data_size);
788bf215546Sopenharmony_ci   }
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_ci   if (s->xfb_info) {
791bf215546Sopenharmony_ci      size_t size = nir_xfb_info_size(s->xfb_info->output_count);
792bf215546Sopenharmony_ci      ns->xfb_info = ralloc_size(ns, size);
793bf215546Sopenharmony_ci      memcpy(ns->xfb_info, s->xfb_info, size);
794bf215546Sopenharmony_ci   }
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci   free_clone_state(&state);
797bf215546Sopenharmony_ci
798bf215546Sopenharmony_ci   return ns;
799bf215546Sopenharmony_ci}
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_ci/** Overwrites dst and replaces its contents with src
802bf215546Sopenharmony_ci *
803bf215546Sopenharmony_ci * Everything ralloc parented to dst and src itself (but not its children)
804bf215546Sopenharmony_ci * will be freed.
805bf215546Sopenharmony_ci *
806bf215546Sopenharmony_ci * This should only be used by test code which needs to swap out shaders with
807bf215546Sopenharmony_ci * a cloned or deserialized version.
808bf215546Sopenharmony_ci */
809bf215546Sopenharmony_civoid
810bf215546Sopenharmony_cinir_shader_replace(nir_shader *dst, nir_shader *src)
811bf215546Sopenharmony_ci{
812bf215546Sopenharmony_ci   /* Delete all of dest's ralloc children */
813bf215546Sopenharmony_ci   void *dead_ctx = ralloc_context(NULL);
814bf215546Sopenharmony_ci   ralloc_adopt(dead_ctx, dst);
815bf215546Sopenharmony_ci   ralloc_free(dead_ctx);
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   list_for_each_entry_safe(nir_instr, instr, &dst->gc_list, gc_node) {
818bf215546Sopenharmony_ci      nir_instr_free(instr);
819bf215546Sopenharmony_ci   }
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci   /* Re-parent all of src's ralloc children to dst */
822bf215546Sopenharmony_ci   ralloc_adopt(dst, src);
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci   memcpy(dst, src, sizeof(*dst));
825bf215546Sopenharmony_ci
826bf215546Sopenharmony_ci   /* We have to move all the linked lists over separately because we need the
827bf215546Sopenharmony_ci    * pointers in the list elements to point to the lists in dst and not src.
828bf215546Sopenharmony_ci    */
829bf215546Sopenharmony_ci   list_replace(&src->gc_list, &dst->gc_list);
830bf215546Sopenharmony_ci   list_inithead(&src->gc_list);
831bf215546Sopenharmony_ci   exec_list_move_nodes_to(&src->variables, &dst->variables);
832bf215546Sopenharmony_ci
833bf215546Sopenharmony_ci   /* Now move the functions over.  This takes a tiny bit more work */
834bf215546Sopenharmony_ci   exec_list_move_nodes_to(&src->functions, &dst->functions);
835bf215546Sopenharmony_ci   nir_foreach_function(function, dst)
836bf215546Sopenharmony_ci      function->shader = dst;
837bf215546Sopenharmony_ci
838bf215546Sopenharmony_ci   ralloc_free(src);
839bf215546Sopenharmony_ci}
840