Mercurial > hg > CbC > CbC_gcc
diff gcc/combine-stack-adj.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/combine-stack-adj.c Sun Feb 07 18:28:00 2010 +0900 +++ b/gcc/combine-stack-adj.c Fri Feb 12 23:39:51 2010 +0900 @@ -1,6 +1,6 @@ /* Combine stack adjustments. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -71,25 +71,26 @@ #define STACK_GROWS_DOWNWARD 0 #endif -/* This structure records stack memory references between stack adjusting - instructions. */ +/* This structure records two kinds of stack references between stack + adjusting instructions: stack references in memory addresses for + regular insns and all stack references for debug insns. */ -struct csa_memlist +struct csa_reflist { HOST_WIDE_INT sp_offset; - rtx insn, *mem; - struct csa_memlist *next; + rtx insn, *ref; + struct csa_reflist *next; }; static int stack_memref_p (rtx); static rtx single_set_for_csa (rtx); -static void free_csa_memlist (struct csa_memlist *); -static struct csa_memlist *record_one_stack_memref (rtx, rtx *, - struct csa_memlist *); -static int try_apply_stack_adjustment (rtx, struct csa_memlist *, +static void free_csa_reflist (struct csa_reflist *); +static struct csa_reflist *record_one_stack_ref (rtx, rtx *, + struct csa_reflist *); +static int try_apply_stack_adjustment (rtx, struct csa_reflist *, HOST_WIDE_INT, HOST_WIDE_INT); static void combine_stack_adjustments_for_block (basic_block); -static int record_stack_memrefs (rtx *, void *); +static int record_stack_refs (rtx *, void *); /* Main entry point for stack adjustment combination. */ @@ -116,7 +117,7 @@ return 1; if (GET_CODE (x) == PLUS && XEXP (x, 0) == stack_pointer_rtx - && GET_CODE (XEXP (x, 1)) == CONST_INT) + && CONST_INT_P (XEXP (x, 1))) return 1; return 0; @@ -157,65 +158,80 @@ return XVECEXP (tmp, 0, 0); } -/* Free the list of csa_memlist nodes. */ +/* Free the list of csa_reflist nodes. */ static void -free_csa_memlist (struct csa_memlist *memlist) +free_csa_reflist (struct csa_reflist *reflist) { - struct csa_memlist *next; - for (; memlist ; memlist = next) + struct csa_reflist *next; + for (; reflist ; reflist = next) { - next = memlist->next; - free (memlist); + next = reflist->next; + free (reflist); } } -/* Create a new csa_memlist node from the given memory reference. - It is already known that the memory is stack_memref_p. */ +/* Create a new csa_reflist node from the given stack reference. + It is already known that the reference is either a MEM satisfying the + predicate stack_memref_p or a REG representing the stack pointer. */ -static struct csa_memlist * -record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist) +static struct csa_reflist * +record_one_stack_ref (rtx insn, rtx *ref, struct csa_reflist *next_reflist) { - struct csa_memlist *ml; + struct csa_reflist *ml; - ml = XNEW (struct csa_memlist); + ml = XNEW (struct csa_reflist); - if (XEXP (*mem, 0) == stack_pointer_rtx) + if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx) ml->sp_offset = 0; else - ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1)); + ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1)); ml->insn = insn; - ml->mem = mem; - ml->next = next_memlist; + ml->ref = ref; + ml->next = next_reflist; return ml; } /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well - as each of the memories in MEMLIST. Return true on success. */ + as each of the memories and stack references in REFLIST. Return true + on success. */ static int -try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust, - HOST_WIDE_INT delta) +try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist, + HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta) { - struct csa_memlist *ml; + struct csa_reflist *ml; rtx set; set = single_set_for_csa (insn); - validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1); + if (MEM_P (SET_DEST (set))) + validate_change (insn, &SET_DEST (set), + replace_equiv_address (SET_DEST (set), stack_pointer_rtx), + 1); + else + validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1); - for (ml = memlist; ml ; ml = ml->next) - validate_change - (ml->insn, ml->mem, - replace_equiv_address_nv (*ml->mem, - plus_constant (stack_pointer_rtx, - ml->sp_offset - delta)), 1); + for (ml = reflist; ml ; ml = ml->next) + { + rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta); + rtx new_val; + + if (MEM_P (*ml->ref)) + new_val = replace_equiv_address_nv (*ml->ref, new_addr); + else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx)) + new_val = new_addr; + else + new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr, + GET_MODE (new_addr)); + validate_change (ml->insn, ml->ref, new_val, 1); + } if (apply_change_group ()) { - /* Succeeded. Update our knowledge of the memory references. */ - for (ml = memlist; ml ; ml = ml->next) + /* Succeeded. Update our knowledge of the stack references. */ + for (ml = reflist; ml ; ml = ml->next) ml->sp_offset -= delta; return 1; @@ -224,20 +240,20 @@ return 0; } -/* Called via for_each_rtx and used to record all stack memory references in - the insn and discard all other stack pointer references. */ -struct record_stack_memrefs_data +/* Called via for_each_rtx and used to record all stack memory and other + references in the insn and discard all other stack pointer references. */ +struct record_stack_refs_data { rtx insn; - struct csa_memlist *memlist; + struct csa_reflist *reflist; }; static int -record_stack_memrefs (rtx *xp, void *data) +record_stack_refs (rtx *xp, void *data) { rtx x = *xp; - struct record_stack_memrefs_data *d = - (struct record_stack_memrefs_data *) data; + struct record_stack_refs_data *d = + (struct record_stack_refs_data *) data; if (!x) return 0; switch (GET_CODE (x)) @@ -249,10 +265,11 @@ stack pointer, so this check is necessary. */ if (stack_memref_p (x)) { - d->memlist = record_one_stack_memref (d->insn, xp, d->memlist); + d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); return -1; } - return 1; + /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4). */ + return !DEBUG_INSN_P (d->insn); case REG: /* ??? We want be able to handle non-memory stack pointer references later. For now just discard all insns referring to @@ -262,9 +279,17 @@ We can't just compare with STACK_POINTER_RTX because the reference to the stack pointer might be in some other mode. In particular, an explicit clobber in an asm statement will - result in a QImode clobber. */ + result in a QImode clobber. + + In DEBUG_INSNs, we want to replace all occurrences, otherwise + they will cause -fcompare-debug failures. */ if (REGNO (x) == STACK_POINTER_REGNUM) - return 1; + { + if (!DEBUG_INSN_P (d->insn)) + return 1; + d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); + return -1; + } break; default: break; @@ -298,7 +323,7 @@ && SET_DEST (last) == stack_pointer_rtx && GET_CODE (SET_SRC (last)) == PLUS && XEXP (SET_SRC (last), 0) == stack_pointer_rtx - && GET_CODE (XEXP (SET_SRC (last), 1)) == CONST_INT) + && CONST_INT_P (XEXP (SET_SRC (last), 1))) { XEXP (SET_SRC (last), 1) = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust); @@ -333,9 +358,7 @@ if (note) XEXP (note, 0) = new_expr; else - REG_NOTES (last_sp_set) - = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, new_expr, - REG_NOTES (last_sp_set)); + add_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, new_expr); } /* Subroutine of combine_stack_adjustments, called for each basic block. */ @@ -345,9 +368,9 @@ { HOST_WIDE_INT last_sp_adjust = 0; rtx last_sp_set = NULL_RTX; - struct csa_memlist *memlist = NULL; + struct csa_reflist *reflist = NULL; rtx insn, next, set; - struct record_stack_memrefs_data data; + struct record_stack_refs_data data; bool end_of_block = false; for (insn = BB_HEAD (bb); !end_of_block ; insn = next) @@ -368,7 +391,7 @@ if (dest == stack_pointer_rtx && GET_CODE (src) == PLUS && XEXP (src, 0) == stack_pointer_rtx - && GET_CODE (XEXP (src, 1)) == CONST_INT) + && CONST_INT_P (XEXP (src, 1))) { HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1)); @@ -381,7 +404,7 @@ continue; } - /* If not all recorded memrefs can be adjusted, or the + /* If not all recorded refs can be adjusted, or the adjustment is now too large for a constant addition, we cannot merge the two stack adjustments. @@ -405,7 +428,7 @@ /* Combine an allocation into the first instruction. */ if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0) { - if (try_apply_stack_adjustment (last_sp_set, memlist, + if (try_apply_stack_adjustment (last_sp_set, reflist, last_sp_adjust + this_adjust, this_adjust)) { @@ -424,7 +447,7 @@ else if (STACK_GROWS_DOWNWARD ? last_sp_adjust >= 0 : last_sp_adjust <= 0) { - if (try_apply_stack_adjustment (insn, memlist, + if (try_apply_stack_adjustment (insn, reflist, last_sp_adjust + this_adjust, -last_sp_adjust)) { @@ -432,8 +455,8 @@ delete_insn (last_sp_set); last_sp_set = insn; last_sp_adjust += this_adjust; - free_csa_memlist (memlist); - memlist = NULL; + free_csa_reflist (reflist); + reflist = NULL; continue; } } @@ -443,39 +466,44 @@ delete the old deallocation insn. */ if (last_sp_set && last_sp_adjust == 0) delete_insn (last_sp_set); - free_csa_memlist (memlist); - memlist = NULL; + free_csa_reflist (reflist); + reflist = NULL; last_sp_set = insn; last_sp_adjust = this_adjust; continue; } - /* Find a predecrement of exactly the previous adjustment and - turn it into a direct store. Obviously we can't do this if - there were any intervening uses of the stack pointer. */ - if (memlist == NULL - && MEM_P (dest) - && ((GET_CODE (XEXP (dest, 0)) == PRE_DEC - && (last_sp_adjust - == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))) - || (GET_CODE (XEXP (dest, 0)) == PRE_MODIFY + /* Find a store with pre-(dec|inc)rement or pre-modify of exactly + the previous adjustment and turn it into a simple store. This + is equivalent to anticipating the stack adjustment so this must + be an allocation. */ + if (MEM_P (dest) + && ((STACK_GROWS_DOWNWARD + ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC + && last_sp_adjust + == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))) + : (GET_CODE (XEXP (dest, 0)) == PRE_INC + && last_sp_adjust + == -(HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))) + || ((STACK_GROWS_DOWNWARD + ? last_sp_adjust >= 0 : last_sp_adjust <= 0) + && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS - && XEXP (XEXP (XEXP (dest, 0), 1), 0) == stack_pointer_rtx - && (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) - == CONST_INT) - && (INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)) - == -last_sp_adjust))) + && XEXP (XEXP (XEXP (dest, 0), 1), 0) + == stack_pointer_rtx + && GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) + == CONST_INT + && INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)) + == -last_sp_adjust)) && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx - && ! reg_mentioned_p (stack_pointer_rtx, src) + && !reg_mentioned_p (stack_pointer_rtx, src) && memory_address_p (GET_MODE (dest), stack_pointer_rtx) - && validate_change (insn, &SET_DEST (set), - replace_equiv_address (dest, - stack_pointer_rtx), - 0)) + && try_apply_stack_adjustment (insn, reflist, 0, + -last_sp_adjust)) { delete_insn (last_sp_set); - free_csa_memlist (memlist); - memlist = NULL; + free_csa_reflist (reflist); + reflist = NULL; last_sp_set = NULL_RTX; last_sp_adjust = 0; continue; @@ -483,14 +511,14 @@ } data.insn = insn; - data.memlist = memlist; + data.reflist = reflist; if (!CALL_P (insn) && last_sp_set - && !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data)) + && !for_each_rtx (&PATTERN (insn), record_stack_refs, &data)) { - memlist = data.memlist; + reflist = data.reflist; continue; } - memlist = data.memlist; + reflist = data.reflist; /* Otherwise, we were not able to process the instruction. Do not continue collecting data across such a one. */ @@ -500,8 +528,8 @@ { if (last_sp_set && last_sp_adjust == 0) delete_insn (last_sp_set); - free_csa_memlist (memlist); - memlist = NULL; + free_csa_reflist (reflist); + reflist = NULL; last_sp_set = NULL_RTX; last_sp_adjust = 0; } @@ -510,8 +538,8 @@ if (last_sp_set && last_sp_adjust == 0) delete_insn (last_sp_set); - if (memlist) - free_csa_memlist (memlist); + if (reflist) + free_csa_reflist (reflist); } @@ -551,7 +579,7 @@ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - 0, /* tv_id */ + TV_COMBINE_STACK_ADJUST, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -561,4 +589,3 @@ TODO_ggc_collect, /* todo_flags_finish */ } }; -