1 /* Combine stack adjustments.
2 Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 /* Track stack adjustments and stack memory references. Attempt to
24 reduce the number of stack adjustments by back-propagating across
25 the memory references.
27 This is intended primarily for use with targets that do not define
28 ACCUMULATE_OUTGOING_ARGS. It is of significantly more value to
29 targets that define PREFERRED_STACK_BOUNDARY more aligned than
30 STACK_BOUNDARY (e.g. x86), or if not all registers can be pushed
31 (e.g. x86 fp regs) which would ordinarily have to be implemented
32 as a sub/mov pair due to restrictions in calls.c.
34 Propagation stops when any of the insns that need adjusting are
35 (a) no longer valid because we've exceeded their range, (b) a
36 non-trivial push instruction, or (c) a call instruction.
38 Restriction B is based on the assumption that push instructions
39 are smaller or faster. If a port really wants to remove all
40 pushes, it should have defined ACCUMULATE_OUTGOING_ARGS. The
41 one exception that is made is for an add immediately followed
46 #include "coretypes.h"
50 #include "insn-config.h"
54 #include "hard-reg-set.h"
58 #include "basic-block.h"
64 #include "tree-pass.h"
67 /* Turn STACK_GROWS_DOWNWARD into a boolean. */
68 #ifdef STACK_GROWS_DOWNWARD
69 #undef STACK_GROWS_DOWNWARD
70 #define STACK_GROWS_DOWNWARD 1
72 #define STACK_GROWS_DOWNWARD 0
75 /* This structure records stack memory references between stack adjusting
80 HOST_WIDE_INT sp_offset;
82 struct csa_memlist *next;
85 static int stack_memref_p (rtx);
86 static rtx single_set_for_csa (rtx);
87 static void free_csa_memlist (struct csa_memlist *);
88 static struct csa_memlist *record_one_stack_memref (rtx, rtx *,
89 struct csa_memlist *);
90 static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
91 HOST_WIDE_INT, HOST_WIDE_INT);
92 static void combine_stack_adjustments_for_block (basic_block);
93 static int record_stack_memrefs (rtx *, void *);
96 /* Main entry point for stack adjustment combination. */
99 combine_stack_adjustments (void)
104 combine_stack_adjustments_for_block (bb);
107 /* Recognize a MEM of the form (sp) or (plus sp const). */
110 stack_memref_p (rtx x)
116 if (x == stack_pointer_rtx)
118 if (GET_CODE (x) == PLUS
119 && XEXP (x, 0) == stack_pointer_rtx
120 && GET_CODE (XEXP (x, 1)) == CONST_INT)
126 /* Recognize either normal single_set or the hack in i386.md for
127 tying fp and sp adjustments. */
130 single_set_for_csa (rtx insn)
133 rtx tmp = single_set (insn);
137 if (!NONJUMP_INSN_P (insn)
138 || GET_CODE (PATTERN (insn)) != PARALLEL)
141 tmp = PATTERN (insn);
142 if (GET_CODE (XVECEXP (tmp, 0, 0)) != SET)
145 for (i = 1; i < XVECLEN (tmp, 0); ++i)
147 rtx this = XVECEXP (tmp, 0, i);
149 /* The special case is allowing a no-op set. */
150 if (GET_CODE (this) == SET
151 && SET_SRC (this) == SET_DEST (this))
153 else if (GET_CODE (this) != CLOBBER
154 && GET_CODE (this) != USE)
158 return XVECEXP (tmp, 0, 0);
161 /* Free the list of csa_memlist nodes. */
164 free_csa_memlist (struct csa_memlist *memlist)
166 struct csa_memlist *next;
167 for (; memlist ; memlist = next)
169 next = memlist->next;
174 /* Create a new csa_memlist node from the given memory reference.
175 It is already known that the memory is stack_memref_p. */
177 static struct csa_memlist *
178 record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
180 struct csa_memlist *ml;
182 ml = XNEW (struct csa_memlist);
184 if (XEXP (*mem, 0) == stack_pointer_rtx)
187 ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1));
191 ml->next = next_memlist;
196 /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
197 as each of the memories in MEMLIST. Return true on success. */
200 try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust,
203 struct csa_memlist *ml;
206 set = single_set_for_csa (insn);
207 validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
209 for (ml = memlist; ml ; ml = ml->next)
212 replace_equiv_address_nv (*ml->mem,
213 plus_constant (stack_pointer_rtx,
214 ml->sp_offset - delta)), 1);
216 if (apply_change_group ())
218 /* Succeeded. Update our knowledge of the memory references. */
219 for (ml = memlist; ml ; ml = ml->next)
220 ml->sp_offset -= delta;
228 /* Called via for_each_rtx and used to record all stack memory references in
229 the insn and discard all other stack pointer references. */
230 struct record_stack_memrefs_data
233 struct csa_memlist *memlist;
237 record_stack_memrefs (rtx *xp, void *data)
240 struct record_stack_memrefs_data *d =
241 (struct record_stack_memrefs_data *) data;
244 switch (GET_CODE (x))
247 if (!reg_mentioned_p (stack_pointer_rtx, x))
249 /* We are not able to handle correctly all possible memrefs containing
250 stack pointer, so this check is necessary. */
251 if (stack_memref_p (x))
253 d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
258 /* ??? We want be able to handle non-memory stack pointer
259 references later. For now just discard all insns referring to
260 stack pointer outside mem expressions. We would probably
261 want to teach validate_replace to simplify expressions first.
263 We can't just compare with STACK_POINTER_RTX because the
264 reference to the stack pointer might be in some other mode.
265 In particular, an explicit clobber in an asm statement will
266 result in a QImode clobber. */
267 if (REGNO (x) == STACK_POINTER_REGNUM)
276 /* Subroutine of combine_stack_adjustments, called for each basic block. */
279 combine_stack_adjustments_for_block (basic_block bb)
281 HOST_WIDE_INT last_sp_adjust = 0;
282 rtx last_sp_set = NULL_RTX;
283 struct csa_memlist *memlist = NULL;
285 struct record_stack_memrefs_data data;
286 bool end_of_block = false;
288 for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
290 end_of_block = insn == BB_END (bb);
291 next = NEXT_INSN (insn);
296 set = single_set_for_csa (insn);
299 rtx dest = SET_DEST (set);
300 rtx src = SET_SRC (set);
302 /* Find constant additions to the stack pointer. */
303 if (dest == stack_pointer_rtx
304 && GET_CODE (src) == PLUS
305 && XEXP (src, 0) == stack_pointer_rtx
306 && GET_CODE (XEXP (src, 1)) == CONST_INT)
308 HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1));
310 /* If we've not seen an adjustment previously, record
311 it now and continue. */
315 last_sp_adjust = this_adjust;
319 /* If not all recorded memrefs can be adjusted, or the
320 adjustment is now too large for a constant addition,
321 we cannot merge the two stack adjustments.
323 Also we need to be careful to not move stack pointer
324 such that we create stack accesses outside the allocated
325 area. We can combine an allocation into the first insn,
326 or a deallocation into the second insn. We can not
327 combine an allocation followed by a deallocation.
329 The only somewhat frequent occurrence of the later is when
330 a function allocates a stack frame but does not use it.
331 For this case, we would need to analyze rtl stream to be
332 sure that allocated area is really unused. This means not
333 only checking the memory references, but also all registers
334 or global memory references possibly containing a stack
337 Perhaps the best way to address this problem is to teach
338 gcc not to allocate stack for objects never used. */
340 /* Combine an allocation into the first instruction. */
341 if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0)
343 if (try_apply_stack_adjustment (last_sp_set, memlist,
344 last_sp_adjust + this_adjust,
349 last_sp_adjust += this_adjust;
354 /* Otherwise we have a deallocation. Do not combine with
355 a previous allocation. Combine into the second insn. */
356 else if (STACK_GROWS_DOWNWARD
357 ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
359 if (try_apply_stack_adjustment (insn, memlist,
360 last_sp_adjust + this_adjust,
364 delete_insn (last_sp_set);
366 last_sp_adjust += this_adjust;
367 free_csa_memlist (memlist);
373 /* Combination failed. Restart processing from here. If
374 deallocation+allocation conspired to cancel, we can
375 delete the old deallocation insn. */
376 if (last_sp_set && last_sp_adjust == 0)
378 free_csa_memlist (memlist);
381 last_sp_adjust = this_adjust;
385 /* Find a predecrement of exactly the previous adjustment and
386 turn it into a direct store. Obviously we can't do this if
387 there were any intervening uses of the stack pointer. */
390 && ((GET_CODE (XEXP (dest, 0)) == PRE_DEC
392 == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))))
393 || (GET_CODE (XEXP (dest, 0)) == PRE_MODIFY
394 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS
395 && XEXP (XEXP (XEXP (dest, 0), 1), 0) == stack_pointer_rtx
396 && (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
398 && (INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1))
399 == -last_sp_adjust)))
400 && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx
401 && ! reg_mentioned_p (stack_pointer_rtx, src)
402 && memory_address_p (GET_MODE (dest), stack_pointer_rtx)
403 && validate_change (insn, &SET_DEST (set),
404 replace_equiv_address (dest,
408 delete_insn (last_sp_set);
409 free_csa_memlist (memlist);
411 last_sp_set = NULL_RTX;
418 data.memlist = memlist;
419 if (!CALL_P (insn) && last_sp_set
420 && !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data))
422 memlist = data.memlist;
425 memlist = data.memlist;
427 /* Otherwise, we were not able to process the instruction.
428 Do not continue collecting data across such a one. */
431 || reg_mentioned_p (stack_pointer_rtx, PATTERN (insn))))
433 if (last_sp_set && last_sp_adjust == 0)
434 delete_insn (last_sp_set);
435 free_csa_memlist (memlist);
437 last_sp_set = NULL_RTX;
442 if (last_sp_set && last_sp_adjust == 0)
443 delete_insn (last_sp_set);
446 free_csa_memlist (memlist);
451 gate_handle_stack_adjustments (void)
453 return (optimize > 0);
457 rest_of_handle_stack_adjustments (void)
459 cleanup_cfg (flag_crossjumping ? CLEANUP_CROSSJUMP : 0);
461 /* This is kind of a heuristic. We need to run combine_stack_adjustments
462 even for machines with possibly nonzero RETURN_POPS_ARGS
463 and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having
464 push instructions will have popping returns. */
465 #ifndef PUSH_ROUNDING
466 if (!ACCUMULATE_OUTGOING_ARGS)
469 df_note_add_problem ();
471 combine_stack_adjustments ();
476 struct tree_opt_pass pass_stack_adjustments =
479 gate_handle_stack_adjustments, /* gate */
480 rest_of_handle_stack_adjustments, /* execute */
483 0, /* static_pass_number */
485 0, /* properties_required */
486 0, /* properties_provided */
487 0, /* properties_destroyed */
488 0, /* todo_flags_start */
491 TODO_ggc_collect, /* todo_flags_finish */