xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/stack-ptr-mod.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Discover if the stack pointer is modified in a function.
2*8feb0f0bSmrg    Copyright (C) 2007-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
71debfc3dSmrg the terms of the GNU General Public License as published by the Free
81debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
91debfc3dSmrg version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
121debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3.  If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>.  */
191debfc3dSmrg 
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "rtl.h"
251debfc3dSmrg #include "df.h"
261debfc3dSmrg #include "memmodel.h"
271debfc3dSmrg #include "emit-rtl.h"
281debfc3dSmrg #include "tree-pass.h"
291debfc3dSmrg 
301debfc3dSmrg /* Determine if the stack pointer is constant over the life of the function.
311debfc3dSmrg    Only useful before prologues have been emitted.  */
321debfc3dSmrg 
331debfc3dSmrg static void
notice_stack_pointer_modification_1(rtx x,const_rtx pat ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)341debfc3dSmrg notice_stack_pointer_modification_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
351debfc3dSmrg 				     void *data ATTRIBUTE_UNUSED)
361debfc3dSmrg {
371debfc3dSmrg   if (x == stack_pointer_rtx
381debfc3dSmrg       /* The stack pointer is only modified indirectly as the result
391debfc3dSmrg 	 of a push until later.  See the comments in rtl.texi
401debfc3dSmrg 	 regarding Embedded Side-Effects on Addresses.  */
411debfc3dSmrg       || (MEM_P (x)
421debfc3dSmrg 	  && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_AUTOINC
431debfc3dSmrg 	  && XEXP (XEXP (x, 0), 0) == stack_pointer_rtx))
441debfc3dSmrg     crtl->sp_is_unchanging = 0;
451debfc3dSmrg }
461debfc3dSmrg 
471debfc3dSmrg   /* Some targets can emit simpler epilogues if they know that sp was
481debfc3dSmrg      not ever modified during the function.  After reload, of course,
491debfc3dSmrg      we've already emitted the epilogue so there's no sense searching.  */
501debfc3dSmrg 
511debfc3dSmrg namespace {
521debfc3dSmrg 
531debfc3dSmrg const pass_data pass_data_stack_ptr_mod =
541debfc3dSmrg {
551debfc3dSmrg   RTL_PASS, /* type */
561debfc3dSmrg   "*stack_ptr_mod", /* name */
571debfc3dSmrg   OPTGROUP_NONE, /* optinfo_flags */
581debfc3dSmrg   TV_NONE, /* tv_id */
591debfc3dSmrg   0, /* properties_required */
601debfc3dSmrg   0, /* properties_provided */
611debfc3dSmrg   0, /* properties_destroyed */
621debfc3dSmrg   0, /* todo_flags_start */
631debfc3dSmrg   0, /* todo_flags_finish */
641debfc3dSmrg };
651debfc3dSmrg 
661debfc3dSmrg class pass_stack_ptr_mod : public rtl_opt_pass
671debfc3dSmrg {
681debfc3dSmrg public:
pass_stack_ptr_mod(gcc::context * ctxt)691debfc3dSmrg   pass_stack_ptr_mod (gcc::context *ctxt)
701debfc3dSmrg     : rtl_opt_pass (pass_data_stack_ptr_mod, ctxt)
711debfc3dSmrg   {}
721debfc3dSmrg 
731debfc3dSmrg   /* opt_pass methods: */
741debfc3dSmrg   virtual unsigned int execute (function *);
751debfc3dSmrg 
761debfc3dSmrg }; // class pass_stack_ptr_mod
771debfc3dSmrg 
781debfc3dSmrg unsigned int
execute(function * fun)791debfc3dSmrg pass_stack_ptr_mod::execute (function *fun)
801debfc3dSmrg {
811debfc3dSmrg   basic_block bb;
821debfc3dSmrg   rtx_insn *insn;
831debfc3dSmrg 
841debfc3dSmrg   /* Assume that the stack pointer is unchanging if alloca hasn't
851debfc3dSmrg      been used.  */
861debfc3dSmrg   crtl->sp_is_unchanging = !fun->calls_alloca;
871debfc3dSmrg   if (crtl->sp_is_unchanging)
881debfc3dSmrg     FOR_EACH_BB_FN (bb, fun)
891debfc3dSmrg       FOR_BB_INSNS (bb, insn)
901debfc3dSmrg         {
911debfc3dSmrg 	  if (INSN_P (insn))
921debfc3dSmrg 	    {
931debfc3dSmrg 	      /* Check if insn modifies the stack pointer.  */
94*8feb0f0bSmrg 	      note_stores (insn, notice_stack_pointer_modification_1, NULL);
951debfc3dSmrg 	      if (! crtl->sp_is_unchanging)
961debfc3dSmrg 		return 0;
971debfc3dSmrg 	    }
981debfc3dSmrg 	}
991debfc3dSmrg 
1001debfc3dSmrg   /* The value coming into this pass was 0, and the exit block uses
1011debfc3dSmrg      are based on this.  If the value is now 1, we need to redo the
1021debfc3dSmrg      exit block uses.  */
1031debfc3dSmrg   if (df && crtl->sp_is_unchanging)
1041debfc3dSmrg     df_update_exit_block_uses ();
1051debfc3dSmrg 
1061debfc3dSmrg   return 0;
1071debfc3dSmrg }
1081debfc3dSmrg 
1091debfc3dSmrg } // anon namespace
1101debfc3dSmrg 
1111debfc3dSmrg rtl_opt_pass *
make_pass_stack_ptr_mod(gcc::context * ctxt)1121debfc3dSmrg make_pass_stack_ptr_mod (gcc::context *ctxt)
1131debfc3dSmrg {
1141debfc3dSmrg   return new pass_stack_ptr_mod (ctxt);
1151debfc3dSmrg }
116