Home | History | Annotate | Line # | Download | only in gcc
combine-stack-adj.cc revision 1.1.1.1
      1  1.1  mrg /* Combine stack adjustments.
      2  1.1  mrg    Copyright (C) 1987-2022 Free Software Foundation, Inc.
      3  1.1  mrg 
      4  1.1  mrg This file is part of GCC.
      5  1.1  mrg 
      6  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      7  1.1  mrg the terms of the GNU General Public License as published by the Free
      8  1.1  mrg Software Foundation; either version 3, or (at your option) any later
      9  1.1  mrg version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  1.1  mrg for more details.
     15  1.1  mrg 
     16  1.1  mrg You should have received a copy of the GNU General Public License
     17  1.1  mrg along with GCC; see the file COPYING3.  If not see
     18  1.1  mrg <http://www.gnu.org/licenses/>.  */
     19  1.1  mrg 
     20  1.1  mrg /* Track stack adjustments and stack memory references.  Attempt to
     21  1.1  mrg    reduce the number of stack adjustments by back-propagating across
     22  1.1  mrg    the memory references.
     23  1.1  mrg 
     24  1.1  mrg    This is intended primarily for use with targets that do not define
     25  1.1  mrg    ACCUMULATE_OUTGOING_ARGS.  It is of significantly more value to
     26  1.1  mrg    targets that define PREFERRED_STACK_BOUNDARY more aligned than
     27  1.1  mrg    STACK_BOUNDARY (e.g. x86), or if not all registers can be pushed
     28  1.1  mrg    (e.g. x86 fp regs) which would ordinarily have to be implemented
     29  1.1  mrg    as a sub/mov pair due to restrictions in calls.cc.
     30  1.1  mrg 
     31  1.1  mrg    Propagation stops when any of the insns that need adjusting are
     32  1.1  mrg    (a) no longer valid because we've exceeded their range, (b) a
     33  1.1  mrg    non-trivial push instruction, or (c) a call instruction.
     34  1.1  mrg 
     35  1.1  mrg    Restriction B is based on the assumption that push instructions
     36  1.1  mrg    are smaller or faster.  If a port really wants to remove all
     37  1.1  mrg    pushes, it should have defined ACCUMULATE_OUTGOING_ARGS.  The
     38  1.1  mrg    one exception that is made is for an add immediately followed
     39  1.1  mrg    by a push.  */
     40  1.1  mrg 
     41  1.1  mrg #include "config.h"
     42  1.1  mrg #include "system.h"
     43  1.1  mrg #include "coretypes.h"
     44  1.1  mrg #include "backend.h"
     45  1.1  mrg #include "rtl.h"
     46  1.1  mrg #include "df.h"
     47  1.1  mrg #include "insn-config.h"
     48  1.1  mrg #include "memmodel.h"
     49  1.1  mrg #include "emit-rtl.h"
     50  1.1  mrg #include "recog.h"
     51  1.1  mrg #include "cfgrtl.h"
     52  1.1  mrg #include "tree-pass.h"
     53  1.1  mrg #include "rtl-iter.h"
     54  1.1  mrg 
     55  1.1  mrg 
     56  1.1  mrg /* This structure records two kinds of stack references between stack
     58  1.1  mrg    adjusting instructions: stack references in memory addresses for
     59  1.1  mrg    regular insns and all stack references for debug insns.  */
     60  1.1  mrg 
     61  1.1  mrg struct csa_reflist
     62  1.1  mrg {
     63  1.1  mrg   HOST_WIDE_INT sp_offset;
     64  1.1  mrg   rtx_insn *insn;
     65  1.1  mrg   rtx *ref;
     66  1.1  mrg   struct csa_reflist *next;
     67  1.1  mrg };
     68  1.1  mrg 
     69  1.1  mrg static int stack_memref_p (rtx);
     70  1.1  mrg static rtx single_set_for_csa (rtx_insn *);
     71  1.1  mrg static void free_csa_reflist (struct csa_reflist *);
     72  1.1  mrg static struct csa_reflist *record_one_stack_ref (rtx_insn *, rtx *,
     73  1.1  mrg 						 struct csa_reflist *);
     74  1.1  mrg static bool try_apply_stack_adjustment (rtx_insn *, struct csa_reflist *,
     75  1.1  mrg 					HOST_WIDE_INT, HOST_WIDE_INT,
     76  1.1  mrg 					bitmap, rtx_insn *);
     77  1.1  mrg static void combine_stack_adjustments_for_block (basic_block, bitmap);
     78  1.1  mrg 
     79  1.1  mrg 
     80  1.1  mrg /* Main entry point for stack adjustment combination.  */
     81  1.1  mrg 
     82  1.1  mrg static void
     83  1.1  mrg combine_stack_adjustments (void)
     84  1.1  mrg {
     85  1.1  mrg   basic_block bb;
     86  1.1  mrg   bitmap live = BITMAP_ALLOC (&reg_obstack);
     87  1.1  mrg 
     88  1.1  mrg   FOR_EACH_BB_FN (bb, cfun)
     89  1.1  mrg     combine_stack_adjustments_for_block (bb, live);
     90  1.1  mrg 
     91  1.1  mrg   BITMAP_FREE (live);
     92  1.1  mrg }
     93  1.1  mrg 
     94  1.1  mrg /* Recognize a MEM of the form (sp) or (plus sp const).  */
     95  1.1  mrg 
     96  1.1  mrg static int
     97  1.1  mrg stack_memref_p (rtx x)
     98  1.1  mrg {
     99  1.1  mrg   if (!MEM_P (x))
    100  1.1  mrg     return 0;
    101  1.1  mrg   x = XEXP (x, 0);
    102  1.1  mrg 
    103  1.1  mrg   if (x == stack_pointer_rtx)
    104  1.1  mrg     return 1;
    105  1.1  mrg   if (GET_CODE (x) == PLUS
    106  1.1  mrg       && XEXP (x, 0) == stack_pointer_rtx
    107  1.1  mrg       && CONST_INT_P (XEXP (x, 1)))
    108  1.1  mrg     return 1;
    109  1.1  mrg 
    110  1.1  mrg   return 0;
    111  1.1  mrg }
    112  1.1  mrg 
    113  1.1  mrg /* Recognize either normal single_set or the hack in i386.md for
    114  1.1  mrg    tying fp and sp adjustments.  */
    115  1.1  mrg 
    116  1.1  mrg static rtx
    117  1.1  mrg single_set_for_csa (rtx_insn *insn)
    118  1.1  mrg {
    119  1.1  mrg   int i;
    120  1.1  mrg   rtx tmp = single_set (insn);
    121  1.1  mrg   if (tmp)
    122  1.1  mrg     return tmp;
    123  1.1  mrg 
    124  1.1  mrg   if (!NONJUMP_INSN_P (insn)
    125  1.1  mrg       || GET_CODE (PATTERN (insn)) != PARALLEL)
    126  1.1  mrg     return NULL_RTX;
    127  1.1  mrg 
    128  1.1  mrg   tmp = PATTERN (insn);
    129  1.1  mrg   if (GET_CODE (XVECEXP (tmp, 0, 0)) != SET)
    130  1.1  mrg     return NULL_RTX;
    131  1.1  mrg 
    132  1.1  mrg   for (i = 1; i < XVECLEN (tmp, 0); ++i)
    133  1.1  mrg     {
    134  1.1  mrg       rtx this_rtx = XVECEXP (tmp, 0, i);
    135  1.1  mrg 
    136  1.1  mrg       /* The special case is allowing a no-op set.  */
    137  1.1  mrg       if (GET_CODE (this_rtx) == SET
    138  1.1  mrg 	  && SET_SRC (this_rtx) == SET_DEST (this_rtx))
    139  1.1  mrg 	;
    140  1.1  mrg       else if (GET_CODE (this_rtx) != CLOBBER
    141  1.1  mrg 	       && GET_CODE (this_rtx) != USE)
    142  1.1  mrg 	return NULL_RTX;
    143  1.1  mrg     }
    144  1.1  mrg 
    145  1.1  mrg   return XVECEXP (tmp, 0, 0);
    146  1.1  mrg }
    147  1.1  mrg 
    148  1.1  mrg /* Free the list of csa_reflist nodes.  */
    149  1.1  mrg 
    150  1.1  mrg static void
    151  1.1  mrg free_csa_reflist (struct csa_reflist *reflist)
    152  1.1  mrg {
    153  1.1  mrg   struct csa_reflist *next;
    154  1.1  mrg   for (; reflist ; reflist = next)
    155  1.1  mrg     {
    156  1.1  mrg       next = reflist->next;
    157  1.1  mrg       free (reflist);
    158  1.1  mrg     }
    159  1.1  mrg }
    160  1.1  mrg 
    161  1.1  mrg /* Create a new csa_reflist node from the given stack reference.
    162  1.1  mrg    It is already known that the reference is either a MEM satisfying the
    163  1.1  mrg    predicate stack_memref_p or a REG representing the stack pointer.  */
    164  1.1  mrg 
    165  1.1  mrg static struct csa_reflist *
    166  1.1  mrg record_one_stack_ref (rtx_insn *insn, rtx *ref, struct csa_reflist *next_reflist)
    167  1.1  mrg {
    168  1.1  mrg   struct csa_reflist *ml;
    169  1.1  mrg 
    170  1.1  mrg   ml = XNEW (struct csa_reflist);
    171  1.1  mrg 
    172  1.1  mrg   if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx)
    173  1.1  mrg     ml->sp_offset = 0;
    174  1.1  mrg   else
    175  1.1  mrg     ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1));
    176  1.1  mrg 
    177  1.1  mrg   ml->insn = insn;
    178  1.1  mrg   ml->ref = ref;
    179  1.1  mrg   ml->next = next_reflist;
    180  1.1  mrg 
    181  1.1  mrg   return ml;
    182  1.1  mrg }
    183  1.1  mrg 
    184  1.1  mrg /* We only know how to adjust the CFA; no other frame-related changes
    185  1.1  mrg    may appear in any insn to be deleted.  */
    186  1.1  mrg 
    187  1.1  mrg static bool
    188  1.1  mrg no_unhandled_cfa (rtx_insn *insn)
    189  1.1  mrg {
    190  1.1  mrg   if (!RTX_FRAME_RELATED_P (insn))
    191  1.1  mrg     return true;
    192  1.1  mrg 
    193  1.1  mrg   /* No CFA notes at all is a legacy interpretation like
    194  1.1  mrg      FRAME_RELATED_EXPR, and is context sensitive within
    195  1.1  mrg      the prologue state machine.  We can't handle that here.  */
    196  1.1  mrg   bool has_cfa_adjust = false;
    197  1.1  mrg 
    198  1.1  mrg   for (rtx link = REG_NOTES (insn); link; link = XEXP (link, 1))
    199  1.1  mrg     switch (REG_NOTE_KIND (link))
    200  1.1  mrg       {
    201  1.1  mrg       default:
    202  1.1  mrg         break;
    203  1.1  mrg       case REG_CFA_ADJUST_CFA:
    204  1.1  mrg 	has_cfa_adjust = true;
    205  1.1  mrg 	break;
    206  1.1  mrg 
    207  1.1  mrg       case REG_FRAME_RELATED_EXPR:
    208  1.1  mrg       case REG_CFA_DEF_CFA:
    209  1.1  mrg       case REG_CFA_OFFSET:
    210  1.1  mrg       case REG_CFA_REGISTER:
    211  1.1  mrg       case REG_CFA_EXPRESSION:
    212  1.1  mrg       case REG_CFA_RESTORE:
    213  1.1  mrg       case REG_CFA_SET_VDRAP:
    214  1.1  mrg       case REG_CFA_WINDOW_SAVE:
    215  1.1  mrg       case REG_CFA_FLUSH_QUEUE:
    216  1.1  mrg       case REG_CFA_TOGGLE_RA_MANGLE:
    217  1.1  mrg 	return false;
    218  1.1  mrg       }
    219  1.1  mrg 
    220  1.1  mrg   return has_cfa_adjust;
    221  1.1  mrg }
    222  1.1  mrg 
    223  1.1  mrg /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
    224  1.1  mrg    as each of the memories and stack references in REFLIST.  Return true
    225  1.1  mrg    on success.  */
    226  1.1  mrg 
    227  1.1  mrg static bool
    228  1.1  mrg try_apply_stack_adjustment (rtx_insn *insn, struct csa_reflist *reflist,
    229  1.1  mrg 			    HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta,
    230  1.1  mrg 			    bitmap live, rtx_insn *other_insn)
    231  1.1  mrg {
    232  1.1  mrg   struct csa_reflist *ml;
    233  1.1  mrg   rtx set;
    234  1.1  mrg   bool remove_equal = false;
    235  1.1  mrg 
    236  1.1  mrg   set = single_set_for_csa (insn);
    237  1.1  mrg   if (MEM_P (SET_DEST (set)))
    238  1.1  mrg     validate_change (insn, &SET_DEST (set),
    239  1.1  mrg 		     replace_equiv_address (SET_DEST (set), stack_pointer_rtx),
    240  1.1  mrg 		     1);
    241  1.1  mrg   else if (REG_P (SET_SRC (set)))
    242  1.1  mrg     {
    243  1.1  mrg       if (other_insn == NULL_RTX || live == NULL)
    244  1.1  mrg 	return false;
    245  1.1  mrg       rtx other_set = single_set_for_csa (other_insn);
    246  1.1  mrg       if (SET_DEST (other_set) != stack_pointer_rtx
    247  1.1  mrg 	  || GET_CODE (SET_SRC (other_set)) != PLUS
    248  1.1  mrg 	  || XEXP (SET_SRC (other_set), 0) != stack_pointer_rtx
    249  1.1  mrg 	  || !CONST_INT_P (XEXP (SET_SRC (other_set), 1)))
    250  1.1  mrg 	return false;
    251  1.1  mrg       if (PATTERN (other_insn) != other_set)
    252  1.1  mrg 	{
    253  1.1  mrg 	  if (GET_CODE (PATTERN (other_insn)) != PARALLEL)
    254  1.1  mrg 	    return false;
    255  1.1  mrg 	  int i;
    256  1.1  mrg 	  rtx p = PATTERN (other_insn);
    257  1.1  mrg 	  for (i = 0; i < XVECLEN (p, 0); ++i)
    258  1.1  mrg 	    {
    259  1.1  mrg 	      rtx this_rtx = XVECEXP (p, 0, i);
    260  1.1  mrg 	      if (this_rtx == other_set)
    261  1.1  mrg 		continue;
    262  1.1  mrg 	      if (GET_CODE (this_rtx) != CLOBBER)
    263  1.1  mrg 		return false;
    264  1.1  mrg 	      if (!REG_P (XEXP (this_rtx, 0))
    265  1.1  mrg 		  || !HARD_REGISTER_P (XEXP (this_rtx, 0)))
    266  1.1  mrg 		return false;
    267  1.1  mrg 	      unsigned int end_regno = END_REGNO (XEXP (this_rtx, 0));
    268  1.1  mrg 	      for (unsigned int regno = REGNO (XEXP (this_rtx, 0));
    269  1.1  mrg 		   regno < end_regno; ++regno)
    270  1.1  mrg 		if (bitmap_bit_p (live, regno))
    271  1.1  mrg 		  return false;
    272  1.1  mrg 	    }
    273  1.1  mrg 	}
    274  1.1  mrg       validate_change (insn, &PATTERN (insn), copy_rtx (PATTERN (other_insn)),
    275  1.1  mrg 		       1);
    276  1.1  mrg       set = single_set_for_csa (insn);
    277  1.1  mrg       validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust),
    278  1.1  mrg 		       1);
    279  1.1  mrg       remove_equal = true;
    280  1.1  mrg     }
    281  1.1  mrg   else
    282  1.1  mrg     validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
    283  1.1  mrg 
    284  1.1  mrg   for (ml = reflist; ml ; ml = ml->next)
    285  1.1  mrg     {
    286  1.1  mrg       rtx new_addr = plus_constant (Pmode, stack_pointer_rtx,
    287  1.1  mrg 				    ml->sp_offset - delta);
    288  1.1  mrg       rtx new_val;
    289  1.1  mrg 
    290  1.1  mrg       if (MEM_P (*ml->ref))
    291  1.1  mrg 	new_val = replace_equiv_address_nv (*ml->ref, new_addr);
    292  1.1  mrg       else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx))
    293  1.1  mrg 	new_val = new_addr;
    294  1.1  mrg       else
    295  1.1  mrg 	new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr,
    296  1.1  mrg 				  GET_MODE (new_addr));
    297  1.1  mrg       validate_change (ml->insn, ml->ref, new_val, 1);
    298  1.1  mrg     }
    299  1.1  mrg 
    300  1.1  mrg   if (apply_change_group ())
    301  1.1  mrg     {
    302  1.1  mrg       /* Succeeded.  Update our knowledge of the stack references.  */
    303  1.1  mrg       for (ml = reflist; ml ; ml = ml->next)
    304  1.1  mrg 	ml->sp_offset -= delta;
    305  1.1  mrg 
    306  1.1  mrg       if (remove_equal)
    307  1.1  mrg 	remove_reg_equal_equiv_notes (insn);
    308  1.1  mrg       return true;
    309  1.1  mrg     }
    310  1.1  mrg   else
    311  1.1  mrg     return false;
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg /* For non-debug insns, record all stack memory references in INSN
    315  1.1  mrg    and return true if there were no other (unrecorded) references to the
    316  1.1  mrg    stack pointer.  For debug insns, record all stack references regardless
    317  1.1  mrg    of context and unconditionally return true.  */
    318  1.1  mrg 
    319  1.1  mrg static bool
    320  1.1  mrg record_stack_refs (rtx_insn *insn, struct csa_reflist **reflist)
    321  1.1  mrg {
    322  1.1  mrg   subrtx_ptr_iterator::array_type array;
    323  1.1  mrg   FOR_EACH_SUBRTX_PTR (iter, array, &PATTERN (insn), NONCONST)
    324  1.1  mrg     {
    325  1.1  mrg       rtx *loc = *iter;
    326  1.1  mrg       rtx x = *loc;
    327  1.1  mrg       switch (GET_CODE (x))
    328  1.1  mrg 	{
    329  1.1  mrg 	case MEM:
    330  1.1  mrg 	  if (!reg_mentioned_p (stack_pointer_rtx, x))
    331  1.1  mrg 	    iter.skip_subrtxes ();
    332  1.1  mrg 	  /* We are not able to handle correctly all possible memrefs
    333  1.1  mrg 	     containing stack pointer, so this check is necessary.  */
    334  1.1  mrg 	  else if (stack_memref_p (x))
    335  1.1  mrg 	    {
    336  1.1  mrg 	      *reflist = record_one_stack_ref (insn, loc, *reflist);
    337  1.1  mrg 	      iter.skip_subrtxes ();
    338  1.1  mrg 	    }
    339  1.1  mrg 	  /* Try harder for DEBUG_INSNs, handle e.g.
    340  1.1  mrg 	     (mem (mem (sp + 16) + 4).  */
    341  1.1  mrg 	  else if (!DEBUG_INSN_P (insn))
    342  1.1  mrg 	    return false;
    343  1.1  mrg 	  break;
    344  1.1  mrg 
    345  1.1  mrg 	case REG:
    346  1.1  mrg 	  /* ??? We want be able to handle non-memory stack pointer
    347  1.1  mrg 	     references later.  For now just discard all insns referring to
    348  1.1  mrg 	     stack pointer outside mem expressions.  We would probably
    349  1.1  mrg 	     want to teach validate_replace to simplify expressions first.
    350  1.1  mrg 
    351  1.1  mrg 	     We can't just compare with STACK_POINTER_RTX because the
    352  1.1  mrg 	     reference to the stack pointer might be in some other mode.
    353  1.1  mrg 	     In particular, an explicit clobber in an asm statement will
    354  1.1  mrg 	     result in a QImode clobber.
    355  1.1  mrg 
    356  1.1  mrg 	     In DEBUG_INSNs, we want to replace all occurrences, otherwise
    357  1.1  mrg 	     they will cause -fcompare-debug failures.  */
    358  1.1  mrg 	  if (REGNO (x) == STACK_POINTER_REGNUM)
    359  1.1  mrg 	    {
    360  1.1  mrg 	      if (!DEBUG_INSN_P (insn))
    361  1.1  mrg 		return false;
    362  1.1  mrg 	      *reflist = record_one_stack_ref (insn, loc, *reflist);
    363  1.1  mrg 	    }
    364  1.1  mrg 	  break;
    365  1.1  mrg 
    366  1.1  mrg 	default:
    367  1.1  mrg 	  break;
    368  1.1  mrg 	}
    369  1.1  mrg     }
    370  1.1  mrg   return true;
    371  1.1  mrg }
    372  1.1  mrg 
    373  1.1  mrg /* If INSN has a REG_ARGS_SIZE note, move it to LAST.
    374  1.1  mrg    AFTER is true iff LAST follows INSN in the instruction stream.  */
    375  1.1  mrg 
    376  1.1  mrg static void
    377  1.1  mrg maybe_move_args_size_note (rtx_insn *last, rtx_insn *insn, bool after)
    378  1.1  mrg {
    379  1.1  mrg   rtx note, last_note;
    380  1.1  mrg 
    381  1.1  mrg   note = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
    382  1.1  mrg   if (note == NULL)
    383  1.1  mrg     return;
    384  1.1  mrg 
    385  1.1  mrg   last_note = find_reg_note (last, REG_ARGS_SIZE, NULL_RTX);
    386  1.1  mrg   if (last_note)
    387  1.1  mrg     {
    388  1.1  mrg       /* The ARGS_SIZE notes are *not* cumulative.  They represent an
    389  1.1  mrg 	 absolute value, and the "most recent" note wins.  */
    390  1.1  mrg       if (!after)
    391  1.1  mrg         XEXP (last_note, 0) = XEXP (note, 0);
    392  1.1  mrg     }
    393  1.1  mrg   else
    394  1.1  mrg     add_reg_note (last, REG_ARGS_SIZE, XEXP (note, 0));
    395  1.1  mrg }
    396  1.1  mrg 
    397  1.1  mrg /* Merge any REG_CFA_ADJUST_CFA note from SRC into DST.
    398  1.1  mrg    AFTER is true iff DST follows SRC in the instruction stream.  */
    399  1.1  mrg 
    400  1.1  mrg static void
    401  1.1  mrg maybe_merge_cfa_adjust (rtx_insn *dst, rtx_insn *src, bool after)
    402  1.1  mrg {
    403  1.1  mrg   rtx snote = NULL, dnote = NULL;
    404  1.1  mrg   rtx sexp, dexp;
    405  1.1  mrg   rtx exp1, exp2;
    406  1.1  mrg 
    407  1.1  mrg   if (RTX_FRAME_RELATED_P (src))
    408  1.1  mrg     snote = find_reg_note (src, REG_CFA_ADJUST_CFA, NULL_RTX);
    409  1.1  mrg   if (snote == NULL)
    410  1.1  mrg     return;
    411  1.1  mrg   sexp = XEXP (snote, 0);
    412  1.1  mrg 
    413  1.1  mrg   if (RTX_FRAME_RELATED_P (dst))
    414  1.1  mrg     dnote = find_reg_note (dst, REG_CFA_ADJUST_CFA, NULL_RTX);
    415  1.1  mrg   if (dnote == NULL)
    416  1.1  mrg     {
    417  1.1  mrg       add_reg_note (dst, REG_CFA_ADJUST_CFA, sexp);
    418  1.1  mrg       return;
    419  1.1  mrg     }
    420  1.1  mrg   dexp = XEXP (dnote, 0);
    421  1.1  mrg 
    422  1.1  mrg   gcc_assert (GET_CODE (sexp) == SET);
    423  1.1  mrg   gcc_assert (GET_CODE (dexp) == SET);
    424  1.1  mrg 
    425  1.1  mrg   if (after)
    426  1.1  mrg     exp1 = dexp, exp2 = sexp;
    427  1.1  mrg   else
    428  1.1  mrg     exp1 = sexp, exp2 = dexp;
    429  1.1  mrg 
    430  1.1  mrg   SET_SRC (exp1) = simplify_replace_rtx (SET_SRC (exp1), SET_DEST (exp2),
    431  1.1  mrg 					 SET_SRC (exp2));
    432  1.1  mrg   XEXP (dnote, 0) = exp1;
    433  1.1  mrg }
    434  1.1  mrg 
    435  1.1  mrg /* Return the next (or previous) active insn within BB.  */
    436  1.1  mrg 
    437  1.1  mrg static rtx_insn *
    438  1.1  mrg prev_active_insn_bb (basic_block bb, rtx_insn *insn)
    439  1.1  mrg {
    440  1.1  mrg   for (insn = PREV_INSN (insn);
    441  1.1  mrg        insn != PREV_INSN (BB_HEAD (bb));
    442  1.1  mrg        insn = PREV_INSN (insn))
    443  1.1  mrg     if (active_insn_p (insn))
    444  1.1  mrg       return insn;
    445  1.1  mrg   return NULL;
    446  1.1  mrg }
    447  1.1  mrg 
    448  1.1  mrg static rtx_insn *
    449  1.1  mrg next_active_insn_bb (basic_block bb, rtx_insn *insn)
    450  1.1  mrg {
    451  1.1  mrg   for (insn = NEXT_INSN (insn);
    452  1.1  mrg        insn != NEXT_INSN (BB_END (bb));
    453  1.1  mrg        insn = NEXT_INSN (insn))
    454  1.1  mrg     if (active_insn_p (insn))
    455  1.1  mrg       return insn;
    456  1.1  mrg   return NULL;
    457  1.1  mrg }
    458  1.1  mrg 
    459  1.1  mrg /* If INSN has a REG_ARGS_SIZE note, if possible move it to PREV.  Otherwise
    460  1.1  mrg    search for a nearby candidate within BB where we can stick the note.  */
    461  1.1  mrg 
    462  1.1  mrg static void
    463  1.1  mrg force_move_args_size_note (basic_block bb, rtx_insn *prev, rtx_insn *insn)
    464  1.1  mrg {
    465  1.1  mrg   rtx note;
    466  1.1  mrg   rtx_insn *test, *next_candidate, *prev_candidate;
    467  1.1  mrg 
    468  1.1  mrg   /* If PREV exists, tail-call to the logic in the other function.  */
    469  1.1  mrg   if (prev)
    470  1.1  mrg     {
    471  1.1  mrg       maybe_move_args_size_note (prev, insn, false);
    472  1.1  mrg       return;
    473  1.1  mrg     }
    474  1.1  mrg 
    475  1.1  mrg   /* First, make sure there's anything that needs doing.  */
    476  1.1  mrg   note = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
    477  1.1  mrg   if (note == NULL)
    478  1.1  mrg     return;
    479  1.1  mrg 
    480  1.1  mrg   /* We need to find a spot between the previous and next exception points
    481  1.1  mrg      where we can place the note and "properly" deallocate the arguments.  */
    482  1.1  mrg   next_candidate = prev_candidate = NULL;
    483  1.1  mrg 
    484  1.1  mrg   /* It is often the case that we have insns in the order:
    485  1.1  mrg 	call
    486  1.1  mrg 	add sp (previous deallocation)
    487  1.1  mrg 	sub sp (align for next arglist)
    488  1.1  mrg 	push arg
    489  1.1  mrg      and the add/sub cancel.  Therefore we begin by searching forward.  */
    490  1.1  mrg 
    491  1.1  mrg   test = insn;
    492  1.1  mrg   while ((test = next_active_insn_bb (bb, test)) != NULL)
    493  1.1  mrg     {
    494  1.1  mrg       /* Found an existing note: nothing to do.  */
    495  1.1  mrg       if (find_reg_note (test, REG_ARGS_SIZE, NULL_RTX))
    496  1.1  mrg         return;
    497  1.1  mrg       /* Found something that affects unwinding.  Stop searching.  */
    498  1.1  mrg       if (CALL_P (test) || !insn_nothrow_p (test))
    499  1.1  mrg 	break;
    500  1.1  mrg       if (next_candidate == NULL)
    501  1.1  mrg 	next_candidate = test;
    502  1.1  mrg     }
    503  1.1  mrg 
    504  1.1  mrg   test = insn;
    505  1.1  mrg   while ((test = prev_active_insn_bb (bb, test)) != NULL)
    506  1.1  mrg     {
    507  1.1  mrg       rtx tnote;
    508  1.1  mrg       /* Found a place that seems logical to adjust the stack.  */
    509  1.1  mrg       tnote = find_reg_note (test, REG_ARGS_SIZE, NULL_RTX);
    510  1.1  mrg       if (tnote)
    511  1.1  mrg 	{
    512  1.1  mrg 	  XEXP (tnote, 0) = XEXP (note, 0);
    513  1.1  mrg 	  return;
    514  1.1  mrg 	}
    515  1.1  mrg       if (prev_candidate == NULL)
    516  1.1  mrg 	prev_candidate = test;
    517  1.1  mrg       /* Found something that affects unwinding.  Stop searching.  */
    518  1.1  mrg       if (CALL_P (test) || !insn_nothrow_p (test))
    519  1.1  mrg 	break;
    520  1.1  mrg     }
    521  1.1  mrg 
    522  1.1  mrg   if (prev_candidate)
    523  1.1  mrg     test = prev_candidate;
    524  1.1  mrg   else if (next_candidate)
    525  1.1  mrg     test = next_candidate;
    526  1.1  mrg   else
    527  1.1  mrg     {
    528  1.1  mrg       /* ??? We *must* have a place, lest we ICE on the lost adjustment.
    529  1.1  mrg 	 Options are: dummy clobber insn, nop, or prevent the removal of
    530  1.1  mrg 	 the sp += 0 insn.  */
    531  1.1  mrg       /* TODO: Find another way to indicate to the dwarf2 code that we
    532  1.1  mrg 	 have not in fact lost an adjustment.  */
    533  1.1  mrg       test = emit_insn_before (gen_rtx_CLOBBER (VOIDmode, const0_rtx), insn);
    534  1.1  mrg     }
    535  1.1  mrg   add_reg_note (test, REG_ARGS_SIZE, XEXP (note, 0));
    536  1.1  mrg }
    537  1.1  mrg 
    538  1.1  mrg /* Subroutine of combine_stack_adjustments, called for each basic block.  */
    539  1.1  mrg 
    540  1.1  mrg static void
    541  1.1  mrg combine_stack_adjustments_for_block (basic_block bb, bitmap live)
    542  1.1  mrg {
    543  1.1  mrg   HOST_WIDE_INT last_sp_adjust = 0;
    544  1.1  mrg   rtx_insn *last_sp_set = NULL;
    545  1.1  mrg   rtx_insn *last2_sp_set = NULL;
    546  1.1  mrg   bitmap last_sp_live = NULL;
    547  1.1  mrg   struct csa_reflist *reflist = NULL;
    548  1.1  mrg   bitmap copy = NULL;
    549  1.1  mrg   rtx_insn *insn, *next;
    550  1.1  mrg   rtx set;
    551  1.1  mrg   bool end_of_block = false;
    552  1.1  mrg 
    553  1.1  mrg   bitmap_copy (live, DF_LR_IN (bb));
    554  1.1  mrg   df_simulate_initialize_forwards (bb, live);
    555  1.1  mrg 
    556  1.1  mrg   for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
    557  1.1  mrg     {
    558  1.1  mrg       end_of_block = insn == BB_END (bb);
    559  1.1  mrg       next = NEXT_INSN (insn);
    560  1.1  mrg 
    561  1.1  mrg       if (! INSN_P (insn))
    562  1.1  mrg 	continue;
    563  1.1  mrg 
    564  1.1  mrg       set = single_set_for_csa (insn);
    565  1.1  mrg       if (set && find_reg_note (insn, REG_STACK_CHECK, NULL_RTX))
    566  1.1  mrg 	set = NULL_RTX;
    567  1.1  mrg       if (set)
    568  1.1  mrg 	{
    569  1.1  mrg 	  rtx dest = SET_DEST (set);
    570  1.1  mrg 	  rtx src = SET_SRC (set);
    571  1.1  mrg 	  HOST_WIDE_INT this_adjust = 0;
    572  1.1  mrg 
    573  1.1  mrg 	  /* Find constant additions to the stack pointer.  */
    574  1.1  mrg 	  if (dest == stack_pointer_rtx
    575  1.1  mrg 	      && GET_CODE (src) == PLUS
    576  1.1  mrg 	      && XEXP (src, 0) == stack_pointer_rtx
    577  1.1  mrg 	      && CONST_INT_P (XEXP (src, 1)))
    578  1.1  mrg 	    this_adjust = INTVAL (XEXP (src, 1));
    579  1.1  mrg 	  /* Or such additions turned by postreload into a store of
    580  1.1  mrg 	     equivalent register.  */
    581  1.1  mrg 	  else if (dest == stack_pointer_rtx
    582  1.1  mrg 		   && REG_P (src)
    583  1.1  mrg 		   && REGNO (src) != STACK_POINTER_REGNUM)
    584  1.1  mrg 	    if (rtx equal = find_reg_note (insn, REG_EQUAL, NULL_RTX))
    585  1.1  mrg 	      if (GET_CODE (XEXP (equal, 0)) == PLUS
    586  1.1  mrg 		  && XEXP (XEXP (equal, 0), 0) == stack_pointer_rtx
    587  1.1  mrg 		  && CONST_INT_P (XEXP (XEXP (equal, 0), 1)))
    588  1.1  mrg 		this_adjust = INTVAL (XEXP (XEXP (equal, 0), 1));
    589  1.1  mrg 
    590  1.1  mrg 	  if (this_adjust)
    591  1.1  mrg 	    {
    592  1.1  mrg 	      /* If we've not seen an adjustment previously, record
    593  1.1  mrg 		 it now and continue.  */
    594  1.1  mrg 	      if (! last_sp_set)
    595  1.1  mrg 		{
    596  1.1  mrg 		  last_sp_set = insn;
    597  1.1  mrg 		  last_sp_adjust = this_adjust;
    598  1.1  mrg 		  if (REG_P (src))
    599  1.1  mrg 		    {
    600  1.1  mrg 		      if (copy == NULL)
    601  1.1  mrg 			copy = BITMAP_ALLOC (&reg_obstack);
    602  1.1  mrg 		      last_sp_live = copy;
    603  1.1  mrg 		      bitmap_copy (last_sp_live, live);
    604  1.1  mrg 		    }
    605  1.1  mrg 		  else
    606  1.1  mrg 		    last_sp_live = NULL;
    607  1.1  mrg 		  df_simulate_one_insn_forwards (bb, insn, live);
    608  1.1  mrg 		  continue;
    609  1.1  mrg 		}
    610  1.1  mrg 
    611  1.1  mrg 	      /* If not all recorded refs can be adjusted, or the
    612  1.1  mrg 		 adjustment is now too large for a constant addition,
    613  1.1  mrg 		 we cannot merge the two stack adjustments.
    614  1.1  mrg 
    615  1.1  mrg 		 Also we need to be careful to not move stack pointer
    616  1.1  mrg 		 such that we create stack accesses outside the allocated
    617  1.1  mrg 		 area.  We can combine an allocation into the first insn,
    618  1.1  mrg 		 or a deallocation into the second insn.  We cannot
    619  1.1  mrg 		 combine an allocation followed by a deallocation.
    620  1.1  mrg 
    621  1.1  mrg 		 The only somewhat frequent occurrence of the later is when
    622  1.1  mrg 		 a function allocates a stack frame but does not use it.
    623  1.1  mrg 		 For this case, we would need to analyze rtl stream to be
    624  1.1  mrg 		 sure that allocated area is really unused.  This means not
    625  1.1  mrg 		 only checking the memory references, but also all registers
    626  1.1  mrg 		 or global memory references possibly containing a stack
    627  1.1  mrg 		 frame address.
    628  1.1  mrg 
    629  1.1  mrg 		 Perhaps the best way to address this problem is to teach
    630  1.1  mrg 		 gcc not to allocate stack for objects never used.  */
    631  1.1  mrg 
    632  1.1  mrg 	      /* Combine an allocation into the first instruction.  */
    633  1.1  mrg 	      if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0)
    634  1.1  mrg 		{
    635  1.1  mrg 		  if (no_unhandled_cfa (insn)
    636  1.1  mrg 		      && try_apply_stack_adjustment (last_sp_set, reflist,
    637  1.1  mrg 						     last_sp_adjust
    638  1.1  mrg 						     + this_adjust,
    639  1.1  mrg 						     this_adjust,
    640  1.1  mrg 						     last_sp_live,
    641  1.1  mrg 						     insn))
    642  1.1  mrg 		    {
    643  1.1  mrg 		      /* It worked!  */
    644  1.1  mrg 		      maybe_move_args_size_note (last_sp_set, insn, false);
    645  1.1  mrg 		      maybe_merge_cfa_adjust (last_sp_set, insn, false);
    646  1.1  mrg 		      delete_insn (insn);
    647  1.1  mrg 		      last_sp_adjust += this_adjust;
    648  1.1  mrg 		      last_sp_live = NULL;
    649  1.1  mrg 		      continue;
    650  1.1  mrg 		    }
    651  1.1  mrg 		}
    652  1.1  mrg 
    653  1.1  mrg 	      /* Otherwise we have a deallocation.  Do not combine with
    654  1.1  mrg 		 a previous allocation.  Combine into the second insn.  */
    655  1.1  mrg 	      else if (STACK_GROWS_DOWNWARD
    656  1.1  mrg 		       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
    657  1.1  mrg 		{
    658  1.1  mrg 		  if (no_unhandled_cfa (last_sp_set)
    659  1.1  mrg 		      && !REG_P (src)
    660  1.1  mrg 		      && try_apply_stack_adjustment (insn, reflist,
    661  1.1  mrg 						     last_sp_adjust
    662  1.1  mrg 						     + this_adjust,
    663  1.1  mrg 						     -last_sp_adjust,
    664  1.1  mrg 						     NULL, NULL))
    665  1.1  mrg 		    {
    666  1.1  mrg 		      /* It worked!  */
    667  1.1  mrg 		      maybe_move_args_size_note (insn, last_sp_set, true);
    668  1.1  mrg 		      maybe_merge_cfa_adjust (insn, last_sp_set, true);
    669  1.1  mrg 		      delete_insn (last_sp_set);
    670  1.1  mrg 		      last_sp_set = insn;
    671  1.1  mrg 		      last_sp_adjust += this_adjust;
    672  1.1  mrg 		      last_sp_live = NULL;
    673  1.1  mrg 		      free_csa_reflist (reflist);
    674  1.1  mrg 		      reflist = NULL;
    675  1.1  mrg 		      df_simulate_one_insn_forwards (bb, insn, live);
    676  1.1  mrg 		      continue;
    677  1.1  mrg 		    }
    678  1.1  mrg 		}
    679  1.1  mrg 
    680  1.1  mrg 	      /* Combination failed.  Restart processing from here.  If
    681  1.1  mrg 		 deallocation+allocation conspired to cancel, we can
    682  1.1  mrg 		 delete the old deallocation insn.  */
    683  1.1  mrg 	      if (last_sp_set)
    684  1.1  mrg 		{
    685  1.1  mrg 		  if (last_sp_adjust == 0 && no_unhandled_cfa (last_sp_set))
    686  1.1  mrg 		    {
    687  1.1  mrg 		      maybe_move_args_size_note (insn, last_sp_set, true);
    688  1.1  mrg 		      maybe_merge_cfa_adjust (insn, last_sp_set, true);
    689  1.1  mrg 		      delete_insn (last_sp_set);
    690  1.1  mrg 		    }
    691  1.1  mrg 		  else
    692  1.1  mrg 		    last2_sp_set = last_sp_set;
    693  1.1  mrg 		}
    694  1.1  mrg 	      free_csa_reflist (reflist);
    695  1.1  mrg 	      reflist = NULL;
    696  1.1  mrg 	      last_sp_set = insn;
    697  1.1  mrg 	      last_sp_adjust = this_adjust;
    698  1.1  mrg 	      if (REG_P (src))
    699  1.1  mrg 		{
    700  1.1  mrg 		  if (copy == NULL)
    701  1.1  mrg 		    copy = BITMAP_ALLOC (&reg_obstack);
    702  1.1  mrg 		  last_sp_live = copy;
    703  1.1  mrg 		  bitmap_copy (last_sp_live, live);
    704  1.1  mrg 		}
    705  1.1  mrg 	      else
    706  1.1  mrg 		last_sp_live = NULL;
    707  1.1  mrg 	      df_simulate_one_insn_forwards (bb, insn, live);
    708  1.1  mrg 	      continue;
    709  1.1  mrg 	    }
    710  1.1  mrg 
    711  1.1  mrg 	  /* Find a store with pre-(dec|inc)rement or pre-modify of exactly
    712  1.1  mrg 	     the previous adjustment and turn it into a simple store.  This
    713  1.1  mrg 	     is equivalent to anticipating the stack adjustment so this must
    714  1.1  mrg 	     be an allocation.  */
    715  1.1  mrg 	  if (MEM_P (dest)
    716  1.1  mrg 	      && ((STACK_GROWS_DOWNWARD
    717  1.1  mrg 		   ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC
    718  1.1  mrg 		      && known_eq (last_sp_adjust,
    719  1.1  mrg 				   GET_MODE_SIZE (GET_MODE (dest))))
    720  1.1  mrg 		   : (GET_CODE (XEXP (dest, 0)) == PRE_INC
    721  1.1  mrg 		      && known_eq (-last_sp_adjust,
    722  1.1  mrg 				   GET_MODE_SIZE (GET_MODE (dest)))))
    723  1.1  mrg 		  || ((STACK_GROWS_DOWNWARD
    724  1.1  mrg 		       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
    725  1.1  mrg 		      && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY
    726  1.1  mrg 		      && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS
    727  1.1  mrg 		      && XEXP (XEXP (XEXP (dest, 0), 1), 0)
    728  1.1  mrg 			 == stack_pointer_rtx
    729  1.1  mrg 		      && GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
    730  1.1  mrg 		         == CONST_INT
    731  1.1  mrg 		      && INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1))
    732  1.1  mrg 		         == -last_sp_adjust))
    733  1.1  mrg 	      && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx
    734  1.1  mrg 	      && !reg_mentioned_p (stack_pointer_rtx, src)
    735  1.1  mrg 	      && memory_address_p (GET_MODE (dest), stack_pointer_rtx)
    736  1.1  mrg 	      && try_apply_stack_adjustment (insn, reflist, 0,
    737  1.1  mrg 					     -last_sp_adjust,
    738  1.1  mrg 					     NULL, NULL))
    739  1.1  mrg 	    {
    740  1.1  mrg 	      if (last2_sp_set)
    741  1.1  mrg 		maybe_move_args_size_note (last2_sp_set, last_sp_set, false);
    742  1.1  mrg 	      else
    743  1.1  mrg 	        maybe_move_args_size_note (insn, last_sp_set, true);
    744  1.1  mrg 	      delete_insn (last_sp_set);
    745  1.1  mrg 	      free_csa_reflist (reflist);
    746  1.1  mrg 	      reflist = NULL;
    747  1.1  mrg 	      last_sp_set = NULL;
    748  1.1  mrg 	      last_sp_adjust = 0;
    749  1.1  mrg 	      last_sp_live = NULL;
    750  1.1  mrg 	      df_simulate_one_insn_forwards (bb, insn, live);
    751  1.1  mrg 	      continue;
    752  1.1  mrg 	    }
    753  1.1  mrg 	}
    754  1.1  mrg 
    755  1.1  mrg       if (!CALL_P (insn) && last_sp_set && record_stack_refs (insn, &reflist))
    756  1.1  mrg 	{
    757  1.1  mrg 	  df_simulate_one_insn_forwards (bb, insn, live);
    758  1.1  mrg 	  continue;
    759  1.1  mrg 	}
    760  1.1  mrg 
    761  1.1  mrg       /* Otherwise, we were not able to process the instruction.
    762  1.1  mrg 	 Do not continue collecting data across such a one.  */
    763  1.1  mrg       if (last_sp_set
    764  1.1  mrg 	  && (CALL_P (insn)
    765  1.1  mrg 	      || reg_mentioned_p (stack_pointer_rtx, PATTERN (insn))))
    766  1.1  mrg 	{
    767  1.1  mrg 	  if (last_sp_set && last_sp_adjust == 0)
    768  1.1  mrg 	    {
    769  1.1  mrg 	      force_move_args_size_note (bb, last2_sp_set, last_sp_set);
    770  1.1  mrg 	      delete_insn (last_sp_set);
    771  1.1  mrg 	    }
    772  1.1  mrg 	  free_csa_reflist (reflist);
    773  1.1  mrg 	  reflist = NULL;
    774  1.1  mrg 	  last2_sp_set = NULL;
    775  1.1  mrg 	  last_sp_set = NULL;
    776  1.1  mrg 	  last_sp_adjust = 0;
    777  1.1  mrg 	  last_sp_live = NULL;
    778  1.1  mrg 	}
    779  1.1  mrg 
    780  1.1  mrg       df_simulate_one_insn_forwards (bb, insn, live);
    781  1.1  mrg     }
    782  1.1  mrg 
    783  1.1  mrg   if (last_sp_set && last_sp_adjust == 0)
    784  1.1  mrg     {
    785  1.1  mrg       force_move_args_size_note (bb, last2_sp_set, last_sp_set);
    786  1.1  mrg       delete_insn (last_sp_set);
    787  1.1  mrg     }
    788  1.1  mrg 
    789  1.1  mrg   if (reflist)
    790  1.1  mrg     free_csa_reflist (reflist);
    791  1.1  mrg   if (copy)
    792  1.1  mrg     BITMAP_FREE (copy);
    793  1.1  mrg }
    794  1.1  mrg 
    795  1.1  mrg static unsigned int
    797  1.1  mrg rest_of_handle_stack_adjustments (void)
    798  1.1  mrg {
    799  1.1  mrg   df_note_add_problem ();
    800  1.1  mrg   df_analyze ();
    801  1.1  mrg   combine_stack_adjustments ();
    802  1.1  mrg   return 0;
    803  1.1  mrg }
    804  1.1  mrg 
    805  1.1  mrg namespace {
    806  1.1  mrg 
    807  1.1  mrg const pass_data pass_data_stack_adjustments =
    808  1.1  mrg {
    809  1.1  mrg   RTL_PASS, /* type */
    810  1.1  mrg   "csa", /* name */
    811  1.1  mrg   OPTGROUP_NONE, /* optinfo_flags */
    812  1.1  mrg   TV_COMBINE_STACK_ADJUST, /* tv_id */
    813  1.1  mrg   0, /* properties_required */
    814  1.1  mrg   0, /* properties_provided */
    815  1.1  mrg   0, /* properties_destroyed */
    816  1.1  mrg   0, /* todo_flags_start */
    817  1.1  mrg   TODO_df_finish, /* todo_flags_finish */
    818  1.1  mrg };
    819  1.1  mrg 
    820  1.1  mrg class pass_stack_adjustments : public rtl_opt_pass
    821  1.1  mrg {
    822  1.1  mrg public:
    823  1.1  mrg   pass_stack_adjustments (gcc::context *ctxt)
    824  1.1  mrg     : rtl_opt_pass (pass_data_stack_adjustments, ctxt)
    825  1.1  mrg   {}
    826  1.1  mrg 
    827  1.1  mrg   /* opt_pass methods: */
    828  1.1  mrg   virtual bool gate (function *);
    829  1.1  mrg   virtual unsigned int execute (function *)
    830  1.1  mrg     {
    831  1.1  mrg       return rest_of_handle_stack_adjustments ();
    832  1.1  mrg     }
    833  1.1  mrg 
    834  1.1  mrg }; // class pass_stack_adjustments
    835  1.1  mrg 
    836  1.1  mrg bool
    837  1.1  mrg pass_stack_adjustments::gate (function *)
    838  1.1  mrg {
    839  1.1  mrg   /* This is kind of a heuristic.  We need to run combine_stack_adjustments
    840  1.1  mrg      even for machines with possibly nonzero TARGET_RETURN_POPS_ARGS
    841  1.1  mrg      and ACCUMULATE_OUTGOING_ARGS.  We expect that only ports having
    842  1.1  mrg      push instructions will have popping returns.  */
    843  1.1  mrg #ifndef PUSH_ROUNDING
    844  1.1  mrg   if (ACCUMULATE_OUTGOING_ARGS)
    845  1.1  mrg     return false;
    846  1.1  mrg #endif
    847  1.1  mrg   return flag_combine_stack_adjustments;
    848  1.1  mrg }
    849  1.1  mrg 
    850  1.1  mrg } // anon namespace
    851  1.1  mrg 
    852  1.1  mrg rtl_opt_pass *
    853  1.1  mrg make_pass_stack_adjustments (gcc::context *ctxt)
    854  1.1  mrg {
    855             return new pass_stack_adjustments (ctxt);
    856           }
    857