aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-05-01 01:27:22 +0200
committerRichard Henderson <rth@gcc.gnu.org>2001-04-30 16:27:22 -0700
commit595c2290274554b0164229642206fc5e8a7bfb2f (patch)
treeb5e2deb5406973fb7e6c37c3bdf2a9c4ef77598b
parentdad362764fe456881661e192c595a6774794eb82 (diff)
downloadgcc-595c2290274554b0164229642206fc5e8a7bfb2f.zip
gcc-595c2290274554b0164229642206fc5e8a7bfb2f.tar.gz
gcc-595c2290274554b0164229642206fc5e8a7bfb2f.tar.bz2
regmove.c (try_apply_stack_adjustment): Remove now redundant sanity checks.
* regmove.c (try_apply_stack_adjustment): Remove now redundant sanity checks. (combine_stack_adjustments_for_block): Don't combine stack allocation followed by deallocations. Handle grow-up stacks. Co-Authored-By: Richard Henderson <rth@redhat.com> From-SVN: r41707
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/regmove.c98
2 files changed, 68 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b50c9c9..ba3fc47 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2001-04-30 Jan Hubicka <jh@suse.cz>
+ Richard Henderson <rth@redhat.com>
+
+ * regmove.c (try_apply_stack_adjustment): Remove now redundant
+ sanity checks.
+ (combine_stack_adjustments_for_block): Don't combine stack
+ allocation followed by deallocations. Handle grow-up stacks.
+
2001-04-30 Mark Mitchell <mark@codesourcery.com>
* fdl.texi: New file.
diff --git a/gcc/regmove.c b/gcc/regmove.c
index bb22700..a151d6f 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -42,6 +42,15 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "reload.h"
+
+/* Turn STACK_GROWS_DOWNWARD into a boolean. */
+#ifdef STACK_GROWS_DOWNWARD
+#undef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
+#else
+#define STACK_GROWS_DOWNWARD 0
+#endif
+
static int perhaps_ends_bb_p PARAMS ((rtx));
static int optimize_reg_copy_1 PARAMS ((rtx, rtx, rtx));
static void optimize_reg_copy_2 PARAMS ((rtx, rtx, rtx));
@@ -2231,14 +2240,6 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta)
struct csa_memlist *ml;
rtx set;
- /* We know INSN matches single_set_for_csa, because that's what we
- recognized earlier. However, if INSN is not single_set, it is
- doing double duty as a barrier for frame pointer memory accesses,
- which we are not recording. Therefore, an adjust insn that is not
- single_set may not have a positive delta applied. */
-
- if (delta > 0 && ! single_set (insn))
- return 0;
set = single_set_for_csa (insn);
validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
@@ -2248,13 +2249,6 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta)
rtx new = gen_rtx_MEM (GET_MODE (*ml->mem),
plus_constant (stack_pointer_rtx, c));
- /* Don't reference memory below the stack pointer. */
- if (c < 0)
- {
- cancel_changes (0);
- return 0;
- }
-
MEM_COPY_ATTRIBUTES (new, *ml->mem);
validate_change (ml->insn, ml->mem, new, 1);
}
@@ -2369,35 +2363,63 @@ combine_stack_adjustments_for_block (bb)
/* If not all recorded memrefs can be adjusted, or the
adjustment is now too large for a constant addition,
- we cannot merge the two stack adjustments. */
- if (! try_apply_stack_adjustment (last_sp_set, memlist,
- last_sp_adjust + this_adjust,
- this_adjust))
+ we cannot merge the two stack adjustments.
+
+ Also we need to be carefull to not move stack pointer
+ such that we create stack accesses outside the allocated
+ area. We can combine an allocation into the first insn,
+ or a deallocation into the second insn. We can not
+ combine an allocation followed by a deallocation.
+
+ The only somewhat frequent ocurrence of the later is when
+ a function allocates a stack frame but does not use it.
+ For this case, we would need to analyze rtl stream to be
+ sure that allocated area is really unused. This means not
+ only checking the memory references, but also all registers
+ or global memory references possibly containing a stack
+ frame address.
+
+ Perhaps the best way to address this problem is to teach
+ gcc not to allocate stack for objects never used. */
+
+ /* Combine an allocation into the first instruction. */
+ if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0)
{
- free_csa_memlist (memlist);
- memlist = NULL;
- last_sp_set = insn;
- last_sp_adjust = this_adjust;
- goto processed;
+ if (try_apply_stack_adjustment (last_sp_set, memlist,
+ last_sp_adjust + this_adjust,
+ this_adjust))
+ {
+ /* It worked! */
+ pending_delete = insn;
+ last_sp_adjust += this_adjust;
+ goto processed;
+ }
}
- /* It worked! */
- pending_delete = insn;
- last_sp_adjust += this_adjust;
-
- /* If, by some accident, the adjustments cancel out,
- delete both insns and start from scratch. */
- if (last_sp_adjust == 0)
+ /* Otherwise we have a deallocation. Do not combine with
+ a previous allocation. Combine into the second insn. */
+ else if (STACK_GROWS_DOWNWARD
+ ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
{
- if (last_sp_set == bb->head)
- bb->head = NEXT_INSN (last_sp_set);
- flow_delete_insn (last_sp_set);
-
- free_csa_memlist (memlist);
- memlist = NULL;
- last_sp_set = NULL_RTX;
+ if (try_apply_stack_adjustment (insn, memlist,
+ last_sp_adjust + this_adjust,
+ -last_sp_adjust))
+ {
+ /* It worked! */
+ flow_delete_insn (last_sp_set);
+ last_sp_set = insn;
+ last_sp_adjust += this_adjust;
+ free_csa_memlist (memlist);
+ memlist = NULL;
+ goto processed;
+ }
}
+ /* Combination failed. Restart processing from here. */
+ free_csa_memlist (memlist);
+ memlist = NULL;
+ last_sp_set = insn;
+ last_sp_adjust = this_adjust;
goto processed;
}