1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2015 Intel Corporation 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include "nir.h" 25b8e80941Smrg 26b8e80941Smrg/** 27b8e80941Smrg * \file nir_sweep.c 28b8e80941Smrg * 29b8e80941Smrg * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated 30b8e80941Smrg * memory - anything still connected to the program will be kept, and any dead memory 31b8e80941Smrg * we dropped on the floor will be freed. 32b8e80941Smrg * 33b8e80941Smrg * The expectation is that drivers should call this when finished compiling the shader 34b8e80941Smrg * (after any optimization, lowering, and so on). However, it's also fine to call it 35b8e80941Smrg * earlier, and even many times, trading CPU cycles for memory savings. 36b8e80941Smrg */ 37b8e80941Smrg 38b8e80941Smrg#define steal_list(mem_ctx, type, list) \ 39b8e80941Smrg foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); } 40b8e80941Smrg 41b8e80941Smrgstatic void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node); 42b8e80941Smrg 43b8e80941Smrgstatic bool 44b8e80941Smrgsweep_src_indirect(nir_src *src, void *nir) 45b8e80941Smrg{ 46b8e80941Smrg if (!src->is_ssa && src->reg.indirect) 47b8e80941Smrg ralloc_steal(nir, src->reg.indirect); 48b8e80941Smrg 49b8e80941Smrg return true; 50b8e80941Smrg} 51b8e80941Smrg 52b8e80941Smrgstatic bool 53b8e80941Smrgsweep_dest_indirect(nir_dest *dest, void *nir) 54b8e80941Smrg{ 55b8e80941Smrg if (!dest->is_ssa && dest->reg.indirect) 56b8e80941Smrg ralloc_steal(nir, dest->reg.indirect); 57b8e80941Smrg 58b8e80941Smrg return true; 59b8e80941Smrg} 60b8e80941Smrg 61b8e80941Smrgstatic void 62b8e80941Smrgsweep_block(nir_shader *nir, nir_block *block) 63b8e80941Smrg{ 64b8e80941Smrg ralloc_steal(nir, block); 65b8e80941Smrg 66b8e80941Smrg /* sweep_impl will mark all metadata invalid. We can safely release all of 67b8e80941Smrg * this here. 68b8e80941Smrg */ 69b8e80941Smrg ralloc_free(block->live_in); 70b8e80941Smrg block->live_in = NULL; 71b8e80941Smrg 72b8e80941Smrg ralloc_free(block->live_out); 73b8e80941Smrg block->live_out = NULL; 74b8e80941Smrg 75b8e80941Smrg nir_foreach_instr(instr, block) { 76b8e80941Smrg ralloc_steal(nir, instr); 77b8e80941Smrg 78b8e80941Smrg nir_foreach_src(instr, sweep_src_indirect, nir); 79b8e80941Smrg nir_foreach_dest(instr, sweep_dest_indirect, nir); 80b8e80941Smrg } 81b8e80941Smrg} 82b8e80941Smrg 83b8e80941Smrgstatic void 84b8e80941Smrgsweep_if(nir_shader *nir, nir_if *iff) 85b8e80941Smrg{ 86b8e80941Smrg ralloc_steal(nir, iff); 87b8e80941Smrg 88b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) { 89b8e80941Smrg sweep_cf_node(nir, cf_node); 90b8e80941Smrg } 91b8e80941Smrg 92b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) { 93b8e80941Smrg sweep_cf_node(nir, cf_node); 94b8e80941Smrg } 95b8e80941Smrg} 96b8e80941Smrg 97b8e80941Smrgstatic void 98b8e80941Smrgsweep_loop(nir_shader *nir, nir_loop *loop) 99b8e80941Smrg{ 100b8e80941Smrg ralloc_steal(nir, loop); 101b8e80941Smrg 102b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) { 103b8e80941Smrg sweep_cf_node(nir, cf_node); 104b8e80941Smrg } 105b8e80941Smrg} 106b8e80941Smrg 107b8e80941Smrgstatic void 108b8e80941Smrgsweep_cf_node(nir_shader *nir, nir_cf_node *cf_node) 109b8e80941Smrg{ 110b8e80941Smrg switch (cf_node->type) { 111b8e80941Smrg case nir_cf_node_block: 112b8e80941Smrg sweep_block(nir, nir_cf_node_as_block(cf_node)); 113b8e80941Smrg break; 114b8e80941Smrg case nir_cf_node_if: 115b8e80941Smrg sweep_if(nir, nir_cf_node_as_if(cf_node)); 116b8e80941Smrg break; 117b8e80941Smrg case nir_cf_node_loop: 118b8e80941Smrg sweep_loop(nir, nir_cf_node_as_loop(cf_node)); 119b8e80941Smrg break; 120b8e80941Smrg default: 121b8e80941Smrg unreachable("Invalid CF node type"); 122b8e80941Smrg } 123b8e80941Smrg} 124b8e80941Smrg 125b8e80941Smrgstatic void 126b8e80941Smrgsweep_impl(nir_shader *nir, nir_function_impl *impl) 127b8e80941Smrg{ 128b8e80941Smrg ralloc_steal(nir, impl); 129b8e80941Smrg 130b8e80941Smrg steal_list(nir, nir_variable, &impl->locals); 131b8e80941Smrg steal_list(nir, nir_register, &impl->registers); 132b8e80941Smrg 133b8e80941Smrg foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) { 134b8e80941Smrg sweep_cf_node(nir, cf_node); 135b8e80941Smrg } 136b8e80941Smrg 137b8e80941Smrg sweep_block(nir, impl->end_block); 138b8e80941Smrg 139b8e80941Smrg /* Wipe out all the metadata, if any. */ 140b8e80941Smrg nir_metadata_preserve(impl, nir_metadata_none); 141b8e80941Smrg} 142b8e80941Smrg 143b8e80941Smrgstatic void 144b8e80941Smrgsweep_function(nir_shader *nir, nir_function *f) 145b8e80941Smrg{ 146b8e80941Smrg ralloc_steal(nir, f); 147b8e80941Smrg ralloc_steal(nir, f->params); 148b8e80941Smrg 149b8e80941Smrg if (f->impl) 150b8e80941Smrg sweep_impl(nir, f->impl); 151b8e80941Smrg} 152b8e80941Smrg 153b8e80941Smrgvoid 154b8e80941Smrgnir_sweep(nir_shader *nir) 155b8e80941Smrg{ 156b8e80941Smrg void *rubbish = ralloc_context(NULL); 157b8e80941Smrg 158b8e80941Smrg /* First, move ownership of all the memory to a temporary context; assume dead. */ 159b8e80941Smrg ralloc_adopt(rubbish, nir); 160b8e80941Smrg 161b8e80941Smrg ralloc_steal(nir, (char *)nir->info.name); 162b8e80941Smrg if (nir->info.label) 163b8e80941Smrg ralloc_steal(nir, (char *)nir->info.label); 164b8e80941Smrg 165b8e80941Smrg /* Variables and registers are not dead. Steal them back. */ 166b8e80941Smrg steal_list(nir, nir_variable, &nir->uniforms); 167b8e80941Smrg steal_list(nir, nir_variable, &nir->inputs); 168b8e80941Smrg steal_list(nir, nir_variable, &nir->outputs); 169b8e80941Smrg steal_list(nir, nir_variable, &nir->shared); 170b8e80941Smrg steal_list(nir, nir_variable, &nir->globals); 171b8e80941Smrg steal_list(nir, nir_variable, &nir->system_values); 172b8e80941Smrg 173b8e80941Smrg /* Recurse into functions, stealing their contents back. */ 174b8e80941Smrg foreach_list_typed(nir_function, func, node, &nir->functions) { 175b8e80941Smrg sweep_function(nir, func); 176b8e80941Smrg } 177b8e80941Smrg 178b8e80941Smrg ralloc_steal(nir, nir->constant_data); 179b8e80941Smrg 180b8e80941Smrg /* Free everything we didn't steal back. */ 181b8e80941Smrg ralloc_free(rubbish); 182b8e80941Smrg} 183