/* Discover if the stack pointer is modified in a function.
   Copyright (C) 2007-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/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "df.h"
#include "memmodel.h"
#include "emit-rtl.h"
#include "tree-pass.h"

/* Determine if the stack pointer is constant over the life of the function.
   Only useful before prologues have been emitted.  */

static void
notice_stack_pointer_modification_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
				     void *data ATTRIBUTE_UNUSED)
{
  if (x == stack_pointer_rtx
      /* The stack pointer is only modified indirectly as the result
	 of a push until later.  See the comments in rtl.texi
	 regarding Embedded Side-Effects on Addresses.  */
      || (MEM_P (x)
	  && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_AUTOINC
	  && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx))
    crtl->sp_is_unchanging = 0;
}

  /* Some targets can emit simpler epilogues if they know that sp was
     not ever modified during the function.  After reload, of course,
     we've already emitted the epilogue so there's no sense searching.  */

namespace {

const pass_data pass_data_stack_ptr_mod =
{
  RTL_PASS, /* type */
  "*stack_ptr_mod", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_NONE, /* tv_id */
  0, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_stack_ptr_mod : public rtl_opt_pass
{
public:
  pass_stack_ptr_mod (gcc::context *ctxt)
    : rtl_opt_pass (pass_data_stack_ptr_mod, ctxt)
  {}

  /* opt_pass methods: */
  unsigned int execute (function *) final override;

}; // class pass_stack_ptr_mod

unsigned int
pass_stack_ptr_mod::execute (function *fun)
{
  basic_block bb;
  rtx_insn *insn;

  /* Assume that the stack pointer is unchanging if alloca hasn't
     been used.  */
  crtl->sp_is_unchanging = !fun->calls_alloca;
  if (crtl->sp_is_unchanging)
    FOR_EACH_BB_FN (bb, fun)
      FOR_BB_INSNS (bb, insn)
        {
	  if (INSN_P (insn))
	    {
	      /* Check if insn modifies the stack pointer.  */
	      note_stores (insn, notice_stack_pointer_modification_1, NULL);
	      if (! crtl->sp_is_unchanging)
		return 0;
	    }
	}

  /* The value coming into this pass was 0, and the exit block uses
     are based on this.  If the value is now 1, we need to redo the
     exit block uses.  */
  if (df && crtl->sp_is_unchanging)
    df_update_exit_block_uses ();

  return 0;
}

} // anon namespace

rtl_opt_pass *
make_pass_stack_ptr_mod (gcc::context *ctxt)
{
  return new pass_stack_ptr_mod (ctxt);
}
