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