/*
 * Copyright © 2015 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */

#include "nir.h"

/**
 * \file nir_sweep.c
 *
 * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
 * memory - anything still connected to the program will be kept, and any dead memory
 * we dropped on the floor will be freed.
 *
 * The expectation is that drivers should call this when finished compiling the shader
 * (after any optimization, lowering, and so on).  However, it's also fine to call it
 * earlier, and even many times, trading CPU cycles for memory savings.
 */

#define steal_list(mem_ctx, type, list) \
   foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }

static void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);

static bool
sweep_src_indirect(nir_src *src, void *nir)
{
   if (!src->is_ssa && src->reg.indirect)
      ralloc_steal(nir, src->reg.indirect);

   return true;
}

static bool
sweep_dest_indirect(nir_dest *dest, void *nir)
{
   if (!dest->is_ssa && dest->reg.indirect)
      ralloc_steal(nir, dest->reg.indirect);

   return true;
}

static void
sweep_block(nir_shader *nir, nir_block *block)
{
   ralloc_steal(nir, block);

   nir_foreach_instr(instr, block) {
      ralloc_steal(nir, instr);

      nir_foreach_src(instr, sweep_src_indirect, nir);
      nir_foreach_dest(instr, sweep_dest_indirect, nir);
   }
}

static void
sweep_if(nir_shader *nir, nir_if *iff)
{
   ralloc_steal(nir, iff);

   foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {
      sweep_cf_node(nir, cf_node);
   }

   foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {
      sweep_cf_node(nir, cf_node);
   }
}

static void
sweep_loop(nir_shader *nir, nir_loop *loop)
{
   ralloc_steal(nir, loop);

   foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
      sweep_cf_node(nir, cf_node);
   }
}

static void
sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)
{
   switch (cf_node->type) {
   case nir_cf_node_block:
      sweep_block(nir, nir_cf_node_as_block(cf_node));
      break;
   case nir_cf_node_if:
      sweep_if(nir, nir_cf_node_as_if(cf_node));
      break;
   case nir_cf_node_loop:
      sweep_loop(nir, nir_cf_node_as_loop(cf_node));
      break;
   default:
      unreachable("Invalid CF node type");
   }
}

static void
sweep_impl(nir_shader *nir, nir_function_impl *impl)
{
   ralloc_steal(nir, impl);

   ralloc_steal(nir, impl->params);
   for (unsigned i = 0; i < impl->num_params; i++)
      ralloc_steal(nir, impl->params[i]);
   ralloc_steal(nir, impl->return_var);
   steal_list(nir, nir_variable, &impl->locals);
   steal_list(nir, nir_register, &impl->registers);

   foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {
      sweep_cf_node(nir, cf_node);
   }

   sweep_block(nir, impl->end_block);

   /* Wipe out all the metadata, if any. */
   nir_metadata_preserve(impl, nir_metadata_none);
}

static void
sweep_function(nir_shader *nir, nir_function *f)
{
   ralloc_steal(nir, f);
   ralloc_steal(nir, f->params);

   if (f->impl)
      sweep_impl(nir, f->impl);
}

void
nir_sweep(nir_shader *nir)
{
   void *rubbish = ralloc_context(NULL);

   /* The shader may not own shader_info so check first */
   bool steal_info = false;
   if (nir == ralloc_parent(nir->info))
      steal_info = true;

   /* First, move ownership of all the memory to a temporary context; assume dead. */
   ralloc_adopt(rubbish, nir);

   if (steal_info)
      ralloc_steal(nir, nir->info);

   ralloc_steal(nir, (char *)nir->info->name);
   if (nir->info->label)
      ralloc_steal(nir, (char *)nir->info->label);

   /* Variables and registers are not dead.  Steal them back. */
   steal_list(nir, nir_variable, &nir->uniforms);
   steal_list(nir, nir_variable, &nir->inputs);
   steal_list(nir, nir_variable, &nir->outputs);
   steal_list(nir, nir_variable, &nir->shared);
   steal_list(nir, nir_variable, &nir->globals);
   steal_list(nir, nir_variable, &nir->system_values);
   steal_list(nir, nir_register, &nir->registers);

   /* Recurse into functions, stealing their contents back. */
   foreach_list_typed(nir_function, func, node, &nir->functions) {
      sweep_function(nir, func);
   }

   /* Free everything we didn't steal back. */
   ralloc_free(rubbish);
}
