diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-06 19:31:55 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-06 19:31:55 +0000 |
commit | c189c8e3ff356ca9a1a1fd2c8c7d78e8aa6df3d7 (patch) | |
tree | dcfa70361ebbee4fe6fd329aae2b75ba7ac4b3f1 /gcc/combine-stack-adj.c | |
parent | c8de116dd87b9f7a0e0c2cb5713356d9a83069f7 (diff) | |
download | gcc-c189c8e3ff356ca9a1a1fd2c8c7d78e8aa6df3d7.tar.gz |
PR bootstrap/41241
* combine-stack-adj.c (struct csa_memlist): Rename to...
(struct csa_reflist): ... this. Rename mem field to ref.
(free_csa_memlist): Rename to...
(free_csa_reflist): ... this.
(record_one_stack_memref): Rename to...
(record_one_stack_ref): ... this. Handle also REG_P.
(try_apply_stack_adjustment): Handle also REG_P.
(struct record_stack_memrefs_data): Rename to...
(struct record_stack_refs_data): ... this. Rename memlist field to
reflist.
(record_stack_memrefs): Rename to...
(record_stack_refs): ... this. For DEBUG_INSNs keep traversing
subexpressions instead of failing when a MEM contains SP references.
For SP itself in DEBUG_INSNs queue it also onto reflist chain.
(combine_stack_adjustments_for_block): Adjust for mem to ref renaming.
* gcc.dg/pr41241.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151462 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine-stack-adj.c')
-rw-r--r-- | gcc/combine-stack-adj.c | 158 |
1 files changed, 89 insertions, 69 deletions
diff --git a/gcc/combine-stack-adj.c b/gcc/combine-stack-adj.c index 1f1759e1049..babd6d27e93 100644 --- a/gcc/combine-stack-adj.c +++ b/gcc/combine-stack-adj.c @@ -71,25 +71,26 @@ along with GCC; see the file COPYING3. If not see #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. */ @@ -157,65 +158,75 @@ single_set_for_csa (rtx insn) 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); - 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 +235,20 @@ try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT 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 +260,11 @@ record_stack_memrefs (rtx *xp, void *data) 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 +274,17 @@ record_stack_memrefs (rtx *xp, void *data) 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; @@ -343,9 +363,9 @@ combine_stack_adjustments_for_block (basic_block bb) { 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) @@ -379,7 +399,7 @@ combine_stack_adjustments_for_block (basic_block bb) 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. @@ -403,7 +423,7 @@ combine_stack_adjustments_for_block (basic_block bb) /* 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)) { @@ -422,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb) 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)) { @@ -430,8 +450,8 @@ combine_stack_adjustments_for_block (basic_block bb) 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; } } @@ -441,8 +461,8 @@ combine_stack_adjustments_for_block (basic_block bb) 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; @@ -451,7 +471,7 @@ combine_stack_adjustments_for_block (basic_block bb) /* 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 + if (reflist == NULL && MEM_P (dest) && ((GET_CODE (XEXP (dest, 0)) == PRE_DEC && (last_sp_adjust @@ -472,8 +492,8 @@ combine_stack_adjustments_for_block (basic_block bb) 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; continue; @@ -481,14 +501,14 @@ combine_stack_adjustments_for_block (basic_block bb) } 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. */ @@ -498,8 +518,8 @@ combine_stack_adjustments_for_block (basic_block bb) { 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; } @@ -508,8 +528,8 @@ combine_stack_adjustments_for_block (basic_block bb) 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); } |