101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2015 Intel Corporation 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 2401e04c3fSmrg#include "nir.h" 2501e04c3fSmrg 2601e04c3fSmrg/** 2701e04c3fSmrg * \file nir_sweep.c 2801e04c3fSmrg * 2901e04c3fSmrg * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated 3001e04c3fSmrg * memory - anything still connected to the program will be kept, and any dead memory 3101e04c3fSmrg * we dropped on the floor will be freed. 3201e04c3fSmrg * 3301e04c3fSmrg * The expectation is that drivers should call this when finished compiling the shader 3401e04c3fSmrg * (after any optimization, lowering, and so on). However, it's also fine to call it 3501e04c3fSmrg * earlier, and even many times, trading CPU cycles for memory savings. 3601e04c3fSmrg */ 3701e04c3fSmrg 3801e04c3fSmrg#define steal_list(mem_ctx, type, list) \ 3901e04c3fSmrg foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); } 4001e04c3fSmrg 4101e04c3fSmrgstatic void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node); 4201e04c3fSmrg 4301e04c3fSmrgstatic void 4401e04c3fSmrgsweep_block(nir_shader *nir, nir_block *block) 4501e04c3fSmrg{ 4601e04c3fSmrg ralloc_steal(nir, block); 4701e04c3fSmrg 487e102996Smaya /* sweep_impl will mark all metadata invalid. We can safely release all of 497e102996Smaya * this here. 507e102996Smaya */ 517e102996Smaya ralloc_free(block->live_in); 527e102996Smaya block->live_in = NULL; 537e102996Smaya 547e102996Smaya ralloc_free(block->live_out); 557e102996Smaya block->live_out = NULL; 567e102996Smaya 5701e04c3fSmrg nir_foreach_instr(instr, block) { 587ec681f3Smrg list_del(&instr->gc_node); 597ec681f3Smrg list_add(&instr->gc_node, &nir->gc_list); 6001e04c3fSmrg } 6101e04c3fSmrg} 6201e04c3fSmrg 6301e04c3fSmrgstatic void 6401e04c3fSmrgsweep_if(nir_shader *nir, nir_if *iff) 6501e04c3fSmrg{ 6601e04c3fSmrg ralloc_steal(nir, iff); 6701e04c3fSmrg 6801e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) { 6901e04c3fSmrg sweep_cf_node(nir, cf_node); 7001e04c3fSmrg } 7101e04c3fSmrg 7201e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) { 7301e04c3fSmrg sweep_cf_node(nir, cf_node); 7401e04c3fSmrg } 7501e04c3fSmrg} 7601e04c3fSmrg 7701e04c3fSmrgstatic void 7801e04c3fSmrgsweep_loop(nir_shader *nir, nir_loop *loop) 7901e04c3fSmrg{ 8001e04c3fSmrg ralloc_steal(nir, loop); 8101e04c3fSmrg 8201e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) { 8301e04c3fSmrg sweep_cf_node(nir, cf_node); 8401e04c3fSmrg } 8501e04c3fSmrg} 8601e04c3fSmrg 8701e04c3fSmrgstatic void 8801e04c3fSmrgsweep_cf_node(nir_shader *nir, nir_cf_node *cf_node) 8901e04c3fSmrg{ 9001e04c3fSmrg switch (cf_node->type) { 9101e04c3fSmrg case nir_cf_node_block: 9201e04c3fSmrg sweep_block(nir, nir_cf_node_as_block(cf_node)); 9301e04c3fSmrg break; 9401e04c3fSmrg case nir_cf_node_if: 9501e04c3fSmrg sweep_if(nir, nir_cf_node_as_if(cf_node)); 9601e04c3fSmrg break; 9701e04c3fSmrg case nir_cf_node_loop: 9801e04c3fSmrg sweep_loop(nir, nir_cf_node_as_loop(cf_node)); 9901e04c3fSmrg break; 10001e04c3fSmrg default: 10101e04c3fSmrg unreachable("Invalid CF node type"); 10201e04c3fSmrg } 10301e04c3fSmrg} 10401e04c3fSmrg 10501e04c3fSmrgstatic void 10601e04c3fSmrgsweep_impl(nir_shader *nir, nir_function_impl *impl) 10701e04c3fSmrg{ 10801e04c3fSmrg ralloc_steal(nir, impl); 10901e04c3fSmrg 11001e04c3fSmrg steal_list(nir, nir_variable, &impl->locals); 11101e04c3fSmrg steal_list(nir, nir_register, &impl->registers); 11201e04c3fSmrg 11301e04c3fSmrg foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) { 11401e04c3fSmrg sweep_cf_node(nir, cf_node); 11501e04c3fSmrg } 11601e04c3fSmrg 11701e04c3fSmrg sweep_block(nir, impl->end_block); 11801e04c3fSmrg 11901e04c3fSmrg /* Wipe out all the metadata, if any. */ 12001e04c3fSmrg nir_metadata_preserve(impl, nir_metadata_none); 12101e04c3fSmrg} 12201e04c3fSmrg 12301e04c3fSmrgstatic void 12401e04c3fSmrgsweep_function(nir_shader *nir, nir_function *f) 12501e04c3fSmrg{ 12601e04c3fSmrg ralloc_steal(nir, f); 12701e04c3fSmrg ralloc_steal(nir, f->params); 12801e04c3fSmrg 12901e04c3fSmrg if (f->impl) 13001e04c3fSmrg sweep_impl(nir, f->impl); 13101e04c3fSmrg} 13201e04c3fSmrg 13301e04c3fSmrgvoid 13401e04c3fSmrgnir_sweep(nir_shader *nir) 13501e04c3fSmrg{ 13601e04c3fSmrg void *rubbish = ralloc_context(NULL); 13701e04c3fSmrg 1387ec681f3Smrg struct list_head instr_gc_list; 1397ec681f3Smrg list_inithead(&instr_gc_list); 1407ec681f3Smrg 1417ec681f3Smrg list_replace(&nir->gc_list, &instr_gc_list); 1427ec681f3Smrg list_inithead(&nir->gc_list); 1437ec681f3Smrg 14401e04c3fSmrg /* First, move ownership of all the memory to a temporary context; assume dead. */ 14501e04c3fSmrg ralloc_adopt(rubbish, nir); 14601e04c3fSmrg 14701e04c3fSmrg ralloc_steal(nir, (char *)nir->info.name); 14801e04c3fSmrg if (nir->info.label) 14901e04c3fSmrg ralloc_steal(nir, (char *)nir->info.label); 15001e04c3fSmrg 15101e04c3fSmrg /* Variables and registers are not dead. Steal them back. */ 1527ec681f3Smrg steal_list(nir, nir_variable, &nir->variables); 15301e04c3fSmrg 15401e04c3fSmrg /* Recurse into functions, stealing their contents back. */ 15501e04c3fSmrg foreach_list_typed(nir_function, func, node, &nir->functions) { 15601e04c3fSmrg sweep_function(nir, func); 15701e04c3fSmrg } 15801e04c3fSmrg 1597ec681f3Smrg /* Sweep instrs not found while walking the shader. */ 1607ec681f3Smrg list_for_each_entry_safe(nir_instr, instr, &instr_gc_list, gc_node) { 1617ec681f3Smrg nir_instr_free(instr); 1627ec681f3Smrg } 1637ec681f3Smrg assert(list_is_empty(&instr_gc_list)); 1647ec681f3Smrg 16501e04c3fSmrg ralloc_steal(nir, nir->constant_data); 16601e04c3fSmrg 16701e04c3fSmrg /* Free everything we didn't steal back. */ 16801e04c3fSmrg ralloc_free(rubbish); 16901e04c3fSmrg} 170