nir_sweep.c revision 01e04c3f
11.6Srillig/*
21.1Sroy * Copyright © 2015 Intel Corporation
31.1Sroy *
41.1Sroy * Permission is hereby granted, free of charge, to any person obtaining a
51.1Sroy * copy of this software and associated documentation files (the "Software"),
61.1Sroy * to deal in the Software without restriction, including without limitation
71.1Sroy * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81.1Sroy * and/or sell copies of the Software, and to permit persons to whom the
91.1Sroy * Software is furnished to do so, subject to the following conditions:
101.1Sroy *
111.1Sroy * The above copyright notice and this permission notice (including the next
121.1Sroy * paragraph) shall be included in all copies or substantial portions of the
131.1Sroy * Software.
141.1Sroy *
151.1Sroy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161.1Sroy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171.1Sroy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181.1Sroy * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191.1Sroy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201.1Sroy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
211.1Sroy * IN THE SOFTWARE.
221.1Sroy */
231.1Sroy
241.1Sroy#include "nir.h"
251.1Sroy
261.1Sroy/**
271.1Sroy * \file nir_sweep.c
281.1Sroy *
291.1Sroy * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
301.1Sroy * memory - anything still connected to the program will be kept, and any dead memory
311.1Sroy * we dropped on the floor will be freed.
321.1Sroy *
331.1Sroy * The expectation is that drivers should call this when finished compiling the shader
341.1Sroy * (after any optimization, lowering, and so on).  However, it's also fine to call it
351.1Sroy * earlier, and even many times, trading CPU cycles for memory savings.
361.6Srillig */
371.1Sroy
381.1Sroy#define steal_list(mem_ctx, type, list) \
391.1Sroy   foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }
401.1Sroy
411.1Sroystatic void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);
421.1Sroy
431.1Sroystatic bool
441.1Sroysweep_src_indirect(nir_src *src, void *nir)
451.6Srillig{
461.1Sroy   if (!src->is_ssa && src->reg.indirect)
471.1Sroy      ralloc_steal(nir, src->reg.indirect);
481.1Sroy
491.3Sroy   return true;
501.1Sroy}
511.1Sroy
521.1Sroystatic bool
531.1Sroysweep_dest_indirect(nir_dest *dest, void *nir)
541.1Sroy{
551.1Sroy   if (!dest->is_ssa && dest->reg.indirect)
561.1Sroy      ralloc_steal(nir, dest->reg.indirect);
571.1Sroy
581.1Sroy   return true;
591.1Sroy}
601.1Sroy
611.1Sroystatic void
621.1Sroysweep_block(nir_shader *nir, nir_block *block)
631.1Sroy{
641.1Sroy   ralloc_steal(nir, block);
651.1Sroy
661.1Sroy   nir_foreach_instr(instr, block) {
671.1Sroy      ralloc_steal(nir, instr);
681.1Sroy
691.1Sroy      nir_foreach_src(instr, sweep_src_indirect, nir);
701.1Sroy      nir_foreach_dest(instr, sweep_dest_indirect, nir);
711.4Sjoerg   }
721.1Sroy}
731.1Sroy
741.1Sroystatic void
751.1Sroysweep_if(nir_shader *nir, nir_if *iff)
761.1Sroy{
771.1Sroy   ralloc_steal(nir, iff);
781.1Sroy
791.1Sroy   foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {
801.1Sroy      sweep_cf_node(nir, cf_node);
811.1Sroy   }
821.1Sroy
831.1Sroy   foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {
841.1Sroy      sweep_cf_node(nir, cf_node);
851.3Sroy   }
861.3Sroy}
871.2Slukem
881.6Srilligstatic void
891.2Slukemsweep_loop(nir_shader *nir, nir_loop *loop)
901.1Sroy{
911.1Sroy   ralloc_steal(nir, loop);
921.2Slukem
931.2Slukem   foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
941.1Sroy      sweep_cf_node(nir, cf_node);
951.1Sroy   }
961.1Sroy}
971.1Sroy
981.1Sroystatic void
991.1Sroysweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)
1001.1Sroy{
1011.1Sroy   switch (cf_node->type) {
1021.6Srillig   case nir_cf_node_block:
1031.6Srillig      sweep_block(nir, nir_cf_node_as_block(cf_node));
1041.6Srillig      break;
1051.1Sroy   case nir_cf_node_if:
1061.1Sroy      sweep_if(nir, nir_cf_node_as_if(cf_node));
1071.6Srillig      break;
1081.1Sroy   case nir_cf_node_loop:
1091.1Sroy      sweep_loop(nir, nir_cf_node_as_loop(cf_node));
1101.1Sroy      break;
1111.1Sroy   default:
1121.1Sroy      unreachable("Invalid CF node type");
1131.1Sroy   }
1141.1Sroy}
1151.1Sroy
1161.1Sroystatic void
1171.1Sroysweep_impl(nir_shader *nir, nir_function_impl *impl)
1181.1Sroy{
1191.5Smrg   ralloc_steal(nir, impl);
1201.1Sroy
1211.1Sroy   steal_list(nir, nir_variable, &impl->locals);
1221.1Sroy   steal_list(nir, nir_register, &impl->registers);
1231.1Sroy
1241.1Sroy   foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {
1251.1Sroy      sweep_cf_node(nir, cf_node);
1261.1Sroy   }
1271.1Sroy
1281.1Sroy   sweep_block(nir, impl->end_block);
1291.6Srillig
1301.1Sroy   /* Wipe out all the metadata, if any. */
1311.1Sroy   nir_metadata_preserve(impl, nir_metadata_none);
1321.6Srillig}
1331.1Sroy
1341.1Sroystatic void
1351.1Sroysweep_function(nir_shader *nir, nir_function *f)
1361.1Sroy{
1371.1Sroy   ralloc_steal(nir, f);
1381.2Slukem   ralloc_steal(nir, f->params);
1391.1Sroy
1401.1Sroy   if (f->impl)
1411.1Sroy      sweep_impl(nir, f->impl);
1421.1Sroy}
1431.1Sroy
1441.1Sroyvoid
1451.1Sroynir_sweep(nir_shader *nir)
1461.1Sroy{
1471.1Sroy   void *rubbish = ralloc_context(NULL);
1481.1Sroy
1491.1Sroy   /* First, move ownership of all the memory to a temporary context; assume dead. */
1501.1Sroy   ralloc_adopt(rubbish, nir);
1511.1Sroy
1521.1Sroy   ralloc_steal(nir, (char *)nir->info.name);
1531.1Sroy   if (nir->info.label)
1541.1Sroy      ralloc_steal(nir, (char *)nir->info.label);
1551.1Sroy
1561.1Sroy   /* Variables and registers are not dead.  Steal them back. */
1571.1Sroy   steal_list(nir, nir_variable, &nir->uniforms);
1581.1Sroy   steal_list(nir, nir_variable, &nir->inputs);
1591.1Sroy   steal_list(nir, nir_variable, &nir->outputs);
1601.1Sroy   steal_list(nir, nir_variable, &nir->shared);
1611.6Srillig   steal_list(nir, nir_variable, &nir->globals);
1621.6Srillig   steal_list(nir, nir_variable, &nir->system_values);
1631.1Sroy   steal_list(nir, nir_register, &nir->registers);
1641.6Srillig
1651.1Sroy   /* Recurse into functions, stealing their contents back. */
1661.1Sroy   foreach_list_typed(nir_function, func, node, &nir->functions) {
1671.1Sroy      sweep_function(nir, func);
1681.1Sroy   }
1691.1Sroy
1701.1Sroy   ralloc_steal(nir, nir->constant_data);
1711.1Sroy
1721.1Sroy   /* Free everything we didn't steal back. */
1731.1Sroy   ralloc_free(rubbish);
1741.1Sroy}
1751.1Sroy