/* Analyze functions to determine if callers need to allocate a frame header
   on the stack.  The frame header is used by callees to save their arguments.
   This optimization is specific to TARGET_OLDABI targets.  For TARGET_NEWABI
   targets, if a frame header is required, it is allocated by the callee.


   Copyright (C) 2015-2021 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/>.  */


#define IN_TARGET_CODE 1

#include "config.h"
#include "system.h"
#include "context.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "tree-core.h"
#include "tree-pass.h"
#include "target.h"
#include "target-globals.h"
#include "profile-count.h"
#include "cgraph.h"
#include "function.h"
#include "basic-block.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "gimple-walk.h"

static unsigned int frame_header_opt (void);

namespace {

const pass_data pass_data_ipa_frame_header_opt =
{
  IPA_PASS, /* type */
  "frame-header-opt", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_CGRAPHOPT, /* tv_id */
  0, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_ipa_frame_header_opt : public ipa_opt_pass_d
{
public:
  pass_ipa_frame_header_opt (gcc::context *ctxt)
    : ipa_opt_pass_d (pass_data_ipa_frame_header_opt, ctxt,
                      NULL, /* generate_summary */
                      NULL, /* write_summary */
                      NULL, /* read_summary */
                      NULL, /* write_optimization_summary */
                      NULL, /* read_optimization_summary */
                      NULL, /* stmt_fixup */
                      0, /* function_transform_todo_flags_start */
                      NULL, /* function_transform */
                      NULL) /* variable_transform */
  {}

  /* opt_pass methods: */
  virtual bool gate (function *)
    {
      /* This optimization has no affect if TARGET_NEWABI.   If optimize
         is not at least 1 then the data needed for the optimization is
         not available and nothing will be done anyway.  */
      return TARGET_OLDABI && flag_frame_header_optimization && optimize > 0;
    }

  virtual unsigned int execute (function *) { return frame_header_opt (); }

}; // class pass_ipa_frame_header_opt

} // anon namespace

static ipa_opt_pass_d *
make_pass_ipa_frame_header_opt (gcc::context *ctxt)
{
  return new pass_ipa_frame_header_opt (ctxt);
}

void
mips_register_frame_header_opt (void)
{
  opt_pass *p = make_pass_ipa_frame_header_opt (g);
  struct register_pass_info f = { p, "comdats", 1, PASS_POS_INSERT_AFTER };
  register_pass (&f);
}


/* Return true if it is certain that this is a leaf function.  False if it is
   not a leaf function or if it is impossible to tell.  */

static bool
is_leaf_function (function *fn)
{
  basic_block bb;
  gimple_stmt_iterator gsi;

  /* If we do not have a cfg for this function be conservative and assume
     it is not a leaf function.  */
  if (fn->cfg == NULL)
    return false;

  FOR_EACH_BB_FN (bb, fn)
    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
      if (is_gimple_call (gsi_stmt (gsi)))
	return false;
  return true;
}

/* Return true if this function has inline assembly code or if we cannot
   be certain that it does not.  False if we know that there is no inline
   assembly.  */

static bool
has_inlined_assembly (function *fn)
{
  basic_block bb;
  gimple_stmt_iterator gsi;

  /* If we do not have a cfg for this function be conservative and assume
     it is may have inline assembly.  */
  if (fn->cfg == NULL)
    return true;

  FOR_EACH_BB_FN (bb, fn)
    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
      if (gimple_code (gsi_stmt (gsi)) == GIMPLE_ASM)
	return true;

  return false;
}

/* Return true if this function will use the stack space allocated by its
   caller or if we cannot determine for certain that it does not.  */

static bool
needs_frame_header_p (function *fn)
{
  tree t;

  if (fn->decl == NULL)
    return true;

  if (fn->stdarg)
    return true;

  for (t = DECL_ARGUMENTS (fn->decl); t; t = TREE_CHAIN (t))
    {
      if (!use_register_for_decl (t))
	return true;

      /* Some 64-bit types may get copied to general registers using the frame
	 header, see mips_output_64bit_xfer.  Checking for SImode only may be
         overly restrictive but it is guaranteed to be safe. */
      if (DECL_MODE (t) != SImode)
	return true;
    }

  return false;
}

/* Return true if the argument stack space allocated by function FN is used.
   Return false if the space is needed or if the need for the space cannot
   be determined.  */

static bool
callees_functions_use_frame_header (function *fn)
{
  basic_block bb;
  gimple_stmt_iterator gsi;
  gimple *stmt;
  tree called_fn_tree;
  function *called_fn;

  if (fn->cfg == NULL)
    return true;

  FOR_EACH_BB_FN (bb, fn)
    {
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
	{
	  stmt = gsi_stmt (gsi);
	  if (is_gimple_call (stmt))
	    {
	      called_fn_tree = gimple_call_fndecl (stmt);
	      if (called_fn_tree != NULL)
	        {
	          called_fn = DECL_STRUCT_FUNCTION (called_fn_tree);
		  if (called_fn == NULL
		      || DECL_WEAK (called_fn_tree) 
		      || has_inlined_assembly (called_fn)
		      || !is_leaf_function (called_fn)
		      || !called_fn->machine->does_not_use_frame_header)
		    return true;
	        }
	      else
		return true;
            }
        }
    }
  return false;
}

/* Set the callers_may_not_allocate_frame flag for any function which
   function FN calls because FN may not allocate a frame header.  */

static void
set_callers_may_not_allocate_frame (function *fn)
{
  basic_block bb;
  gimple_stmt_iterator gsi;
  gimple *stmt;
  tree called_fn_tree;
  function *called_fn;

  if (fn->cfg == NULL)
    return;

  FOR_EACH_BB_FN (bb, fn)
    {
      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
	{
	  stmt = gsi_stmt (gsi);
	  if (is_gimple_call (stmt))
	    {
	      called_fn_tree = gimple_call_fndecl (stmt);
	      if (called_fn_tree != NULL)
	        {
	          called_fn = DECL_STRUCT_FUNCTION (called_fn_tree);
		  if (called_fn != NULL)
		    called_fn->machine->callers_may_not_allocate_frame = true;
	        }
            }
        }
    }
  return;
}

/* Scan each function to determine those that need its frame headers.  Perform
   a second scan to determine if the allocation can be skipped because none of
   their callees require the frame header.  */

static unsigned int
frame_header_opt ()
{
  struct cgraph_node *node;
  function *fn;

  FOR_EACH_DEFINED_FUNCTION (node)
    {
      fn = node->get_fun ();
      if (fn != NULL)
	fn->machine->does_not_use_frame_header = !needs_frame_header_p (fn);
    }

  FOR_EACH_DEFINED_FUNCTION (node)
    {
      fn = node->get_fun ();
      if (fn != NULL)
	fn->machine->optimize_call_stack
	  = !callees_functions_use_frame_header (fn) && !is_leaf_function (fn);
    }

  FOR_EACH_DEFINED_FUNCTION (node)
    {
      fn = node->get_fun ();
      if (fn != NULL && fn->machine->optimize_call_stack)
	set_callers_may_not_allocate_frame (fn);
    }

  return 0;
}
