/* Shared code for before and after reload gcse implementations.
   Copyright (C) 1997-2022 Free Software Foundation, Inc.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify it under
   the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3, or (at your option) any later
   version.

   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>. 

   It is expected that more hunks of gcse.cc and postreload-gcse.cc should
   migrate into this file.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "df.h"
#include "gcse-common.h"


/* Record all of the canonicalized MEMs of record_last_mem_set_info's insn.
   Note we store a pair of elements in the list, so they have to be
   taken off pairwise.  */

void
canon_list_insert (rtx dest, const_rtx x ATTRIBUTE_UNUSED, void *data)
{
  rtx dest_addr;
  int bb;
  modify_pair pair;

  while (GET_CODE (dest) == SUBREG
      || GET_CODE (dest) == ZERO_EXTRACT
      || GET_CODE (dest) == STRICT_LOW_PART)
    dest = XEXP (dest, 0);

  /* If DEST is not a MEM, then it will not conflict with a load.  Note
     that function calls are assumed to clobber memory, but are handled
     elsewhere.  */

  if (! MEM_P (dest))
    return;

  dest_addr = get_addr (XEXP (dest, 0));
  dest_addr = canon_rtx (dest_addr);
  rtx_insn *insn = ((struct gcse_note_stores_info *)data)->insn;
  bb = BLOCK_FOR_INSN (insn)->index;

  pair.dest = dest;
  pair.dest_addr = dest_addr;
  vec<modify_pair> *canon_mem_list
    = ((struct gcse_note_stores_info *)data)->canon_mem_list;
  canon_mem_list[bb].safe_push (pair);
}

/* Record memory modification information for INSN.  We do not actually care
   about the memory location(s) that are set, or even how they are set (consider
   a CALL_INSN).  We merely need to record which insns modify memory.  */

void
record_last_mem_set_info_common (rtx_insn *insn,
				 vec<rtx_insn *> *modify_mem_list,
				 vec<modify_pair> *canon_modify_mem_list,
				 bitmap modify_mem_list_set,
				 bitmap blocks_with_calls)

{
  int bb;

  bb = BLOCK_FOR_INSN (insn)->index;
  modify_mem_list[bb].safe_push (insn);
  bitmap_set_bit (modify_mem_list_set, bb);

  if (CALL_P (insn))
    bitmap_set_bit (blocks_with_calls, bb);
  else
    {
      struct gcse_note_stores_info data;
      data.insn = insn;
      data.canon_mem_list = canon_modify_mem_list;
      note_stores (insn, canon_list_insert, (void*) &data);
    }
}


/* For each block, compute whether X is transparent.  X is either an
   expression or an assignment [though we don't care which, for this context
   an assignment is treated as an expression].  For each block where an
   element of X is modified, reset the INDX bit in BMAP. 

   BLOCKS_WITH_CALLS indicates which blocks contain CALL_INSNs which kill
   memory.

   MODIFY_MEM_LIST_SET indicates which blocks have memory stores which might
   kill a particular memory location.

   CANON_MODIFY_MEM_LIST is the canonicalized list of memory locations modified
   for each block.  */

void
compute_transp (const_rtx x, int indx, sbitmap *bmap,
		bitmap blocks_with_calls,
		bitmap modify_mem_list_set,
	        vec<modify_pair> *canon_modify_mem_list)
{
  int i, j;
  enum rtx_code code;
  const char *fmt;

  /* repeat is used to turn tail-recursion into iteration since GCC
     can't do it when there's no return value.  */
 repeat:

  if (x == 0)
    return;

  code = GET_CODE (x);
  switch (code)
    {
    case REG:
	{
	  df_ref def;
	  for (def = DF_REG_DEF_CHAIN (REGNO (x));
	       def;
	       def = DF_REF_NEXT_REG (def))
	    bitmap_clear_bit (bmap[DF_REF_BB (def)->index], indx);
	}

      return;

    case MEM:
      if (! MEM_READONLY_P (x))
	{
	  bitmap_iterator bi;
	  unsigned bb_index;
	  rtx x_addr;

	  x_addr = get_addr (XEXP (x, 0));
	  x_addr = canon_rtx (x_addr);

	  /* First handle all the blocks with calls.  We don't need to
	     do any list walking for them.  */
	  EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi)
	    {
	      bitmap_clear_bit (bmap[bb_index], indx);
	    }

	  /* Now iterate over the blocks which have memory modifications
	     but which do not have any calls.  */
	  EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set,
					  blocks_with_calls,
					  0, bb_index, bi)
	    {
	      vec<modify_pair> list
		= canon_modify_mem_list[bb_index];
	      modify_pair *pair;
	      unsigned ix;

	      FOR_EACH_VEC_ELT_REVERSE (list, ix, pair)
		{
		  rtx dest = pair->dest;
		  rtx dest_addr = pair->dest_addr;

		  if (canon_true_dependence (dest, GET_MODE (dest),
					     dest_addr, x, x_addr))
		    {
		      bitmap_clear_bit (bmap[bb_index], indx);
		      break;
		    }
	        }
	    }
	}

      x = XEXP (x, 0);
      goto repeat;

    case PC:
    case CONST:
    CASE_CONST_ANY:
    case SYMBOL_REF:
    case LABEL_REF:
    case ADDR_VEC:
    case ADDR_DIFF_VEC:
      return;

    default:
      break;
    }

  for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
    {
      if (fmt[i] == 'e')
	{
	  /* If we are about to do the last recursive call
	     needed at this level, change it into iteration.
	     This function is called enough to be worth it.  */
	  if (i == 0)
	    {
	      x = XEXP (x, i);
	      goto repeat;
	    }

	  compute_transp (XEXP (x, i), indx, bmap, blocks_with_calls,
			  modify_mem_list_set, canon_modify_mem_list);
	}
      else if (fmt[i] == 'E')
	for (j = 0; j < XVECLEN (x, i); j++)
	  compute_transp (XVECEXP (x, i, j), indx, bmap, blocks_with_calls,
			  modify_mem_list_set, canon_modify_mem_list);
    }
}
