123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- /* Discover if the stack pointer is modified in a function.
- Copyright (C) 2007-2015 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 "tm.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "rtl.h"
- #include "regs.h"
- #include "hashtab.h"
- #include "hard-reg-set.h"
- #include "function.h"
- #include "flags.h"
- #include "statistics.h"
- #include "real.h"
- #include "fixed-value.h"
- #include "insn-config.h"
- #include "expmed.h"
- #include "dojump.h"
- #include "explow.h"
- #include "calls.h"
- #include "emit-rtl.h"
- #include "varasm.h"
- #include "stmt.h"
- #include "expr.h"
- #include "tree-pass.h"
- #include "predict.h"
- #include "dominance.h"
- #include "cfg.h"
- #include "basic-block.h"
- #include "output.h"
- #include "df.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: */
- virtual unsigned int execute (function *);
- }; // 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 (PATTERN (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);
- }
|