/*
 * Copyright © 2014 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.
 *
 * Authors:
 *    Connor Abbott (cwabbott0@gmail.com)
 *
 */

#include "nir_control_flow_private.h"

/**
 * \name Control flow modification
 *
 * These functions modify the control flow tree while keeping the control flow
 * graph up-to-date. The invariants respected are:
 * 1. Each then statement, else statement, or loop body must have at least one
 *    control flow node.
 * 2. Each if-statement and loop must have one basic block before it and one
 *    after.
 * 3. Two basic blocks cannot be directly next to each other.
 * 4. If a basic block has a jump instruction, there must be only one and it
 *    must be at the end of the block.
 *
 * The purpose of the second one is so that we have places to insert code during
 * GCM, as well as eliminating the possibility of critical edges.
 */
/*@{*/

static bool
block_ends_in_jump(nir_block *block)
{
   return !exec_list_is_empty(&block->instr_list) &&
          nir_block_last_instr(block)->type == nir_instr_type_jump;
}

static inline void
block_add_pred(nir_block *block, nir_block *pred)
{
   _mesa_set_add(block->predecessors, pred);
}

static inline void
block_remove_pred(nir_block *block, nir_block *pred)
{
   struct set_entry *entry = _mesa_set_search(block->predecessors, pred);

   assert(entry);

   _mesa_set_remove(block->predecessors, entry);
}

static void
link_blocks(nir_block *pred, nir_block *succ1, nir_block *succ2)
{
   pred->successors[0] = succ1;
   if (succ1 != NULL)
      block_add_pred(succ1, pred);

   pred->successors[1] = succ2;
   if (succ2 != NULL)
      block_add_pred(succ2, pred);
}

static void
unlink_blocks(nir_block *pred, nir_block *succ)
{
   if (pred->successors[0] == succ) {
      pred->successors[0] = pred->successors[1];
      pred->successors[1] = NULL;
   } else {
      assert(pred->successors[1] == succ);
      pred->successors[1] = NULL;
   }

   block_remove_pred(succ, pred);
}

static void
unlink_block_successors(nir_block *block)
{
   if (block->successors[1] != NULL)
      unlink_blocks(block, block->successors[1]);
   if (block->successors[0] != NULL)
      unlink_blocks(block, block->successors[0]);
}

static void
link_non_block_to_block(nir_cf_node *node, nir_block *block)
{
   if (node->type == nir_cf_node_if) {
      /*
       * We're trying to link an if to a block after it; this just means linking
       * the last block of the then and else branches.
       */

      nir_if *if_stmt = nir_cf_node_as_if(node);

      nir_block *last_then_block = nir_if_last_then_block(if_stmt);
      nir_block *last_else_block = nir_if_last_else_block(if_stmt);

      if (!block_ends_in_jump(last_then_block)) {
         unlink_block_successors(last_then_block);
         link_blocks(last_then_block, block, NULL);
      }

      if (!block_ends_in_jump(last_else_block)) {
         unlink_block_successors(last_else_block);
         link_blocks(last_else_block, block, NULL);
      }
   } else {
      assert(node->type == nir_cf_node_loop);
   }
}

static void
link_block_to_non_block(nir_block *block, nir_cf_node *node)
{
   if (node->type == nir_cf_node_if) {
      /*
       * We're trying to link a block to an if after it; this just means linking
       * the block to the first block of the then and else branches.
       */

      nir_if *if_stmt = nir_cf_node_as_if(node);

      nir_block *first_then_block = nir_if_first_then_block(if_stmt);
      nir_block *first_else_block = nir_if_first_else_block(if_stmt);

      unlink_block_successors(block);
      link_blocks(block, first_then_block, first_else_block);
   } else {
      /*
       * For similar reasons as the corresponding case in
       * link_non_block_to_block(), don't worry about if the loop header has
       * any predecessors that need to be unlinked.
       */

      nir_loop *loop = nir_cf_node_as_loop(node);

      nir_block *loop_header_block = nir_loop_first_block(loop);

      unlink_block_successors(block);
      link_blocks(block, loop_header_block, NULL);
   }

}

/**
 * Replace a block's successor with a different one.
 */
static void
replace_successor(nir_block *block, nir_block *old_succ, nir_block *new_succ)
{
   if (block->successors[0] == old_succ) {
      block->successors[0] = new_succ;
   } else {
      assert(block->successors[1] == old_succ);
      block->successors[1] = new_succ;
   }

   block_remove_pred(old_succ, block);
   block_add_pred(new_succ, block);
}

/**
 * Takes a basic block and inserts a new empty basic block before it, making its
 * predecessors point to the new block. This essentially splits the block into
 * an empty header and a body so that another non-block CF node can be inserted
 * between the two. Note that this does *not* link the two basic blocks, so
 * some kind of cleanup *must* be performed after this call.
 */

static nir_block *
split_block_beginning(nir_block *block)
{
   nir_block *new_block = nir_block_create(ralloc_parent(block));
   new_block->cf_node.parent = block->cf_node.parent;
   exec_node_insert_node_before(&block->cf_node.node, &new_block->cf_node.node);

   struct set_entry *entry;
   set_foreach(block->predecessors, entry) {
      nir_block *pred = (nir_block *) entry->key;
      replace_successor(pred, block, new_block);
   }

   /* Any phi nodes must stay part of the new block, or else their
    * sourcse will be messed up. This will reverse the order of the phi's, but
    * order shouldn't matter.
    */
   nir_foreach_instr_safe(instr, block) {
      if (instr->type != nir_instr_type_phi)
         break;

      exec_node_remove(&instr->node);
      instr->block = new_block;
      exec_list_push_head(&new_block->instr_list, &instr->node);
   }

   return new_block;
}

static void
rewrite_phi_preds(nir_block *block, nir_block *old_pred, nir_block *new_pred)
{
   nir_foreach_instr_safe(instr, block) {
      if (instr->type != nir_instr_type_phi)
         break;

      nir_phi_instr *phi = nir_instr_as_phi(instr);
      nir_foreach_phi_src(src, phi) {
         if (src->pred == old_pred) {
            src->pred = new_pred;
            break;
         }
      }
   }
}

static void
insert_phi_undef(nir_block *block, nir_block *pred)
{
   nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
   nir_foreach_instr(instr, block) {
      if (instr->type != nir_instr_type_phi)
         break;

      nir_phi_instr *phi = nir_instr_as_phi(instr);
      nir_ssa_undef_instr *undef =
         nir_ssa_undef_instr_create(ralloc_parent(phi),
                                    phi->dest.ssa.num_components,
                                    phi->dest.ssa.bit_size);
      nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
      nir_phi_src *src = ralloc(phi, nir_phi_src);
      src->pred = pred;
      src->src.parent_instr = &phi->instr;
      src->src.is_ssa = true;
      src->src.ssa = &undef->def;

      list_addtail(&src->src.use_link, &undef->def.uses);

      exec_list_push_tail(&phi->srcs, &src->node);
   }
}

/**
 * Moves the successors of source to the successors of dest, leaving both
 * successors of source NULL.
 */

static void
move_successors(nir_block *source, nir_block *dest)
{
   nir_block *succ1 = source->successors[0];
   nir_block *succ2 = source->successors[1];

   if (succ1) {
      unlink_blocks(source, succ1);
      rewrite_phi_preds(succ1, source, dest);
   }

   if (succ2) {
      unlink_blocks(source, succ2);
      rewrite_phi_preds(succ2, source, dest);
   }

   unlink_block_successors(dest);
   link_blocks(dest, succ1, succ2);
}

/* Given a basic block with no successors that has been inserted into the
 * control flow tree, gives it the successors it would normally have assuming
 * it doesn't end in a jump instruction. Also inserts phi sources with undefs
 * if necessary.
 */
static void
block_add_normal_succs(nir_block *block)
{
   if (exec_node_is_tail_sentinel(block->cf_node.node.next)) {
      nir_cf_node *parent = block->cf_node.parent;
      if (parent->type == nir_cf_node_if) {
         nir_cf_node *next = nir_cf_node_next(parent);
         nir_block *next_block = nir_cf_node_as_block(next);

         link_blocks(block, next_block, NULL);
      } else if (parent->type == nir_cf_node_loop) {
         nir_loop *loop = nir_cf_node_as_loop(parent);

         nir_block *head_block = nir_loop_first_block(loop);

         link_blocks(block, head_block, NULL);
         insert_phi_undef(head_block, block);
      } else {
         nir_function_impl *impl = nir_cf_node_as_function(parent);
         link_blocks(block, impl->end_block, NULL);
      }
   } else {
      nir_cf_node *next = nir_cf_node_next(&block->cf_node);
      if (next->type == nir_cf_node_if) {
         nir_if *next_if = nir_cf_node_as_if(next);

         nir_block *first_then_block = nir_if_first_then_block(next_if);
         nir_block *first_else_block = nir_if_first_else_block(next_if);

         link_blocks(block, first_then_block, first_else_block);
      } else {
         nir_loop *next_loop = nir_cf_node_as_loop(next);

         nir_block *first_block = nir_loop_first_block(next_loop);

         link_blocks(block, first_block, NULL);
         insert_phi_undef(first_block, block);
      }
   }
}

static nir_block *
split_block_end(nir_block *block)
{
   nir_block *new_block = nir_block_create(ralloc_parent(block));
   new_block->cf_node.parent = block->cf_node.parent;
   exec_node_insert_after(&block->cf_node.node, &new_block->cf_node.node);

   if (block_ends_in_jump(block)) {
      /* Figure out what successor block would've had if it didn't have a jump
       * instruction, and make new_block have that successor.
       */
      block_add_normal_succs(new_block);
   } else {
      move_successors(block, new_block);
   }

   return new_block;
}

static nir_block *
split_block_before_instr(nir_instr *instr)
{
   assert(instr->type != nir_instr_type_phi);
   nir_block *new_block = split_block_beginning(instr->block);

   nir_foreach_instr_safe(cur_instr, instr->block) {
      if (cur_instr == instr)
         break;

      exec_node_remove(&cur_instr->node);
      cur_instr->block = new_block;
      exec_list_push_tail(&new_block->instr_list, &cur_instr->node);
   }

   return new_block;
}

/* Splits a basic block at the point specified by the cursor. The "before" and
 * "after" arguments are filled out with the blocks resulting from the split
 * if non-NULL. Note that the "beginning" of the block is actually interpreted
 * as before the first non-phi instruction, and it's illegal to split a block
 * before a phi instruction.
 */

static void
split_block_cursor(nir_cursor cursor,
                   nir_block **_before, nir_block **_after)
{
   nir_block *before, *after;
   switch (cursor.option) {
   case nir_cursor_before_block:
      after = cursor.block;
      before = split_block_beginning(cursor.block);
      break;

   case nir_cursor_after_block:
      before = cursor.block;
      after = split_block_end(cursor.block);
      break;

   case nir_cursor_before_instr:
      after = cursor.instr->block;
      before = split_block_before_instr(cursor.instr);
      break;

   case nir_cursor_after_instr:
      /* We lower this to split_block_before_instr() so that we can keep the
       * after-a-jump-instr case contained to split_block_end().
       */
      if (nir_instr_is_last(cursor.instr)) {
         before = cursor.instr->block;
         after = split_block_end(cursor.instr->block);
      } else {
         after = cursor.instr->block;
         before = split_block_before_instr(nir_instr_next(cursor.instr));
      }
      break;

   default:
      unreachable("not reached");
   }

   if (_before)
      *_before = before;
   if (_after)
      *_after = after;
}

/**
 * Inserts a non-basic block between two basic blocks and links them together.
 */

static void
insert_non_block(nir_block *before, nir_cf_node *node, nir_block *after)
{
   node->parent = before->cf_node.parent;
   exec_node_insert_after(&before->cf_node.node, &node->node);
   link_block_to_non_block(before, node);
   link_non_block_to_block(node, after);
}

/* walk up the control flow tree to find the innermost enclosed loop */
static nir_loop *
nearest_loop(nir_cf_node *node)
{
   while (node->type != nir_cf_node_loop) {
      node = node->parent;
   }

   return nir_cf_node_as_loop(node);
}

/*
 * update the CFG after a jump instruction has been added to the end of a block
 */

void
nir_handle_add_jump(nir_block *block)
{
   nir_instr *instr = nir_block_last_instr(block);
   nir_jump_instr *jump_instr = nir_instr_as_jump(instr);

   unlink_block_successors(block);

   nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
   nir_metadata_preserve(impl, nir_metadata_none);

   if (jump_instr->type == nir_jump_break ||
       jump_instr->type == nir_jump_continue) {
      nir_loop *loop = nearest_loop(&block->cf_node);

      if (jump_instr->type == nir_jump_continue) {
         nir_block *first_block = nir_loop_first_block(loop);
         link_blocks(block, first_block, NULL);
      } else {
         nir_cf_node *after = nir_cf_node_next(&loop->cf_node);
         nir_block *after_block = nir_cf_node_as_block(after);
         link_blocks(block, after_block, NULL);
      }
   } else {
      assert(jump_instr->type == nir_jump_return);
      link_blocks(block, impl->end_block, NULL);
   }
}

static void
remove_phi_src(nir_block *block, nir_block *pred)
{
   nir_foreach_instr(instr, block) {
      if (instr->type != nir_instr_type_phi)
         break;

      nir_phi_instr *phi = nir_instr_as_phi(instr);
      nir_foreach_phi_src_safe(src, phi) {
         if (src->pred == pred) {
            list_del(&src->src.use_link);
            exec_node_remove(&src->node);
         }
      }
   }
}

/* Removes the successor of a block with a jump. Note that the jump to be
 * eliminated may be free-floating.
 */

static void
unlink_jump(nir_block *block, nir_jump_type type, bool add_normal_successors)
{
   if (block->successors[0])
      remove_phi_src(block->successors[0], block);
   if (block->successors[1])
      remove_phi_src(block->successors[1], block);

   unlink_block_successors(block);
   if (add_normal_successors)
      block_add_normal_succs(block);
}

void
nir_handle_remove_jump(nir_block *block, nir_jump_type type)
{
   unlink_jump(block, type, true);

   nir_function_impl *impl = nir_cf_node_get_function(&block->cf_node);
   nir_metadata_preserve(impl, nir_metadata_none);
}

static void
update_if_uses(nir_cf_node *node)
{
   if (node->type != nir_cf_node_if)
      return;

   nir_if *if_stmt = nir_cf_node_as_if(node);

   if_stmt->condition.parent_if = if_stmt;
   if (if_stmt->condition.is_ssa) {
      list_addtail(&if_stmt->condition.use_link,
                   &if_stmt->condition.ssa->if_uses);
   } else {
      list_addtail(&if_stmt->condition.use_link,
                   &if_stmt->condition.reg.reg->if_uses);
   }
}

/**
 * Stitch two basic blocks together into one. The aggregate must have the same
 * predecessors as the first and the same successors as the second.
 */

static void
stitch_blocks(nir_block *before, nir_block *after)
{
   /*
    * We move after into before, so we have to deal with up to 2 successors vs.
    * possibly a large number of predecessors.
    *
    * TODO: special case when before is empty and after isn't?
    */

   if (block_ends_in_jump(before)) {
      assert(exec_list_is_empty(&after->instr_list));
      if (after->successors[0])
         remove_phi_src(after->successors[0], after);
      if (after->successors[1])
         remove_phi_src(after->successors[1], after);
      unlink_block_successors(after);
      exec_node_remove(&after->cf_node.node);
   } else {
      move_successors(after, before);

      foreach_list_typed(nir_instr, instr, node, &after->instr_list) {
         instr->block = before;
      }

      exec_list_append(&before->instr_list, &after->instr_list);
      exec_node_remove(&after->cf_node.node);
   }
}

void
nir_cf_node_insert(nir_cursor cursor, nir_cf_node *node)
{
   nir_block *before, *after;

   split_block_cursor(cursor, &before, &after);

   if (node->type == nir_cf_node_block) {
      nir_block *block = nir_cf_node_as_block(node);
      exec_node_insert_after(&before->cf_node.node, &block->cf_node.node);
      block->cf_node.parent = before->cf_node.parent;
      /* stitch_blocks() assumes that any block that ends with a jump has
       * already been setup with the correct successors, so we need to set
       * up jumps here as the block is being inserted.
       */
      if (block_ends_in_jump(block))
         nir_handle_add_jump(block);

      stitch_blocks(block, after);
      stitch_blocks(before, block);
   } else {
      update_if_uses(node);
      insert_non_block(before, node, after);
   }
}

static bool
replace_ssa_def_uses(nir_ssa_def *def, void *void_impl)
{
   nir_function_impl *impl = void_impl;
   void *mem_ctx = ralloc_parent(impl);

   nir_ssa_undef_instr *undef =
      nir_ssa_undef_instr_create(mem_ctx, def->num_components,
                                 def->bit_size);
   nir_instr_insert_before_cf_list(&impl->body, &undef->instr);
   nir_ssa_def_rewrite_uses(def, nir_src_for_ssa(&undef->def));
   return true;
}

static void
cleanup_cf_node(nir_cf_node *node, nir_function_impl *impl)
{
   switch (node->type) {
   case nir_cf_node_block: {
      nir_block *block = nir_cf_node_as_block(node);
      /* We need to walk the instructions and clean up defs/uses */
      nir_foreach_instr_safe(instr, block) {
         if (instr->type == nir_instr_type_jump) {
            nir_jump_type jump_type = nir_instr_as_jump(instr)->type;
            unlink_jump(block, jump_type, false);
         } else {
            nir_foreach_ssa_def(instr, replace_ssa_def_uses, impl);
            nir_instr_remove(instr);
         }
      }
      break;
   }

   case nir_cf_node_if: {
      nir_if *if_stmt = nir_cf_node_as_if(node);
      foreach_list_typed(nir_cf_node, child, node, &if_stmt->then_list)
         cleanup_cf_node(child, impl);
      foreach_list_typed(nir_cf_node, child, node, &if_stmt->else_list)
         cleanup_cf_node(child, impl);

      list_del(&if_stmt->condition.use_link);
      break;
   }

   case nir_cf_node_loop: {
      nir_loop *loop = nir_cf_node_as_loop(node);
      foreach_list_typed(nir_cf_node, child, node, &loop->body)
         cleanup_cf_node(child, impl);
      break;
   }
   case nir_cf_node_function: {
      nir_function_impl *impl = nir_cf_node_as_function(node);
      foreach_list_typed(nir_cf_node, child, node, &impl->body)
         cleanup_cf_node(child, impl);
      break;
   }
   default:
      unreachable("Invalid CF node type");
   }
}

void
nir_cf_extract(nir_cf_list *extracted, nir_cursor begin, nir_cursor end)
{
   nir_block *block_begin, *block_end, *block_before, *block_after;

   if (nir_cursors_equal(begin, end)) {
      exec_list_make_empty(&extracted->list);
      extracted->impl = NULL; /* we shouldn't need this */
      return;
   }

   /* In the case where begin points to an instruction in some basic block and
    * end points to the end of the same basic block, we rely on the fact that
    * splitting on an instruction moves earlier instructions into a new basic
    * block. If the later instructions were moved instead, then the end cursor
    * would be pointing to the same place that begin used to point to, which
    * is obviously not what we want.
    */
   split_block_cursor(begin, &block_before, &block_begin);
   split_block_cursor(end, &block_end, &block_after);

   extracted->impl = nir_cf_node_get_function(&block_begin->cf_node);
   exec_list_make_empty(&extracted->list);

   /* Dominance and other block-related information is toast. */
   nir_metadata_preserve(extracted->impl, nir_metadata_none);

   nir_cf_node *cf_node = &block_begin->cf_node;
   nir_cf_node *cf_node_end = &block_end->cf_node;
   while (true) {
      nir_cf_node *next = nir_cf_node_next(cf_node);

      exec_node_remove(&cf_node->node);
      cf_node->parent = NULL;
      exec_list_push_tail(&extracted->list, &cf_node->node);

      if (cf_node == cf_node_end)
         break;

      cf_node = next;
   }

   stitch_blocks(block_before, block_after);
}

void
nir_cf_reinsert(nir_cf_list *cf_list, nir_cursor cursor)
{
   nir_block *before, *after;

   if (exec_list_is_empty(&cf_list->list))
      return;

   split_block_cursor(cursor, &before, &after);

   foreach_list_typed_safe(nir_cf_node, node, node, &cf_list->list) {
      exec_node_remove(&node->node);
      node->parent = before->cf_node.parent;
      exec_node_insert_node_before(&after->cf_node.node, &node->node);
   }

   stitch_blocks(before,
                 nir_cf_node_as_block(nir_cf_node_next(&before->cf_node)));
   stitch_blocks(nir_cf_node_as_block(nir_cf_node_prev(&after->cf_node)),
                 after);
}

void
nir_cf_delete(nir_cf_list *cf_list)
{
   foreach_list_typed(nir_cf_node, node, node, &cf_list->list) {
      cleanup_cf_node(node, cf_list->impl);
   }
}
