explow.c (optimize_save_area_alloca): New function for targets where SETJMP_VIA_SAVE_AREA is true.
* explow.c (optimize_save_area_alloca): New function for targets where SETJMP_VIA_SAVE_AREA is true. (allocate_dynamic_stack_space): On SETJMP_VIA_SAVE_AREA targets, compute the amount of stack space needed should we find later that setjmp is never called by this function, stuff rtl for this inside a REG_NOTE of the final SET of stack_pointer_rtx. * toplev.c (rest_of_compilation): If SETJMP_VIA_SAVE_AREA and current_function_calls_alloca, call optimize_save_area_alloca. CVS ---------------------------------------------------------------------- From-SVN: r17402
This commit is contained in:
parent
ca097615db
commit
c9ec4f99bc
|
@ -1,3 +1,14 @@
|
|||
Sat Jan 17 23:41:36 1998 David S. Miller <davem@tanya.rutgers.edu>
|
||||
|
||||
* explow.c (optimize_save_area_alloca): New function for targets
|
||||
where SETJMP_VIA_SAVE_AREA is true.
|
||||
(allocate_dynamic_stack_space): On SETJMP_VIA_SAVE_AREA targets,
|
||||
compute the amount of stack space needed should we find later that
|
||||
setjmp is never called by this function, stuff rtl for this inside
|
||||
a REG_NOTE of the final SET of stack_pointer_rtx.
|
||||
* toplev.c (rest_of_compilation): If SETJMP_VIA_SAVE_AREA and
|
||||
current_function_calls_alloca, call optimize_save_area_alloca.
|
||||
|
||||
Sat Jan 17 23:22:59 1998 John Wehle (john@feith.com)
|
||||
|
||||
* i386.md: Remove redundant integer push patterns.
|
||||
|
|
133
gcc/explow.c
133
gcc/explow.c
|
@ -1004,6 +1004,86 @@ emit_stack_restore (save_level, sa, after)
|
|||
emit_insn (fcn (stack_pointer_rtx, sa));
|
||||
}
|
||||
|
||||
#ifdef SETJMP_VIA_SAVE_AREA
|
||||
/* Optimize RTL generated by allocate_dynamic_stack_space for targets
|
||||
where SETJMP_VIA_SAVE_AREA is true. The problem is that on these
|
||||
platforms, the dynamic stack space used can corrupt the original
|
||||
frame, thus causing a crash if a longjmp unwinds to it. */
|
||||
|
||||
void
|
||||
optimize_save_area_alloca (insns)
|
||||
rtx insns;
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
for (insn = insns; insn; insn = NEXT_INSN(insn))
|
||||
{
|
||||
rtx note;
|
||||
|
||||
if (GET_CODE (insn) != INSN)
|
||||
continue;
|
||||
|
||||
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
|
||||
{
|
||||
if (REG_NOTE_KIND (note) != REG_SAVE_AREA)
|
||||
continue;
|
||||
|
||||
if (!current_function_calls_setjmp)
|
||||
{
|
||||
rtx pat = PATTERN (insn);
|
||||
|
||||
/* If we do not see the note in a pattern matching
|
||||
these precise characteristics, we did something
|
||||
entirely wrong in allocate_dynamic_stack_space.
|
||||
|
||||
Note, one way this could happen if if SETJMP_VIA_SAVE_AREA
|
||||
was defined on a machine where stacks grow towards higher
|
||||
addresses.
|
||||
|
||||
Right now only supported port with stack that grow upward
|
||||
is the HPPA and it does not define SETJMP_VIA_SAVE_AREA. */
|
||||
if (GET_CODE (pat) != SET
|
||||
|| SET_DEST (pat) != stack_pointer_rtx
|
||||
|| GET_CODE (SET_SRC (pat)) != MINUS
|
||||
|| XEXP (SET_SRC (pat), 0) != stack_pointer_rtx)
|
||||
abort ();
|
||||
|
||||
/* This will now be transformed into a (set REG REG)
|
||||
so we can just blow away all the other notes. */
|
||||
XEXP (SET_SRC (pat), 1) = XEXP (note, 0);
|
||||
REG_NOTES (insn) = NULL_RTX;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* setjmp was called, we must remove the REG_SAVE_AREA
|
||||
note so that later passes do not get confused by its
|
||||
presence. */
|
||||
if (note == REG_NOTES (insn))
|
||||
{
|
||||
REG_NOTES (insn) = XEXP (note, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx srch;
|
||||
|
||||
for (srch = REG_NOTES (insn); srch; srch = XEXP (srch, 1))
|
||||
if (XEXP (srch, 1) == note)
|
||||
break;
|
||||
|
||||
if (srch == NULL_RTX)
|
||||
abort();
|
||||
|
||||
XEXP (srch, 1) = XEXP (note, 1);
|
||||
}
|
||||
}
|
||||
/* Once we've seen the note of interest, we need not look at
|
||||
the rest of them. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* SETJMP_VIA_SAVE_AREA */
|
||||
|
||||
/* Return an rtx representing the address of an area of memory dynamically
|
||||
pushed on the stack. This region of memory is always aligned to
|
||||
a multiple of BIGGEST_ALIGNMENT.
|
||||
|
@ -1021,6 +1101,10 @@ allocate_dynamic_stack_space (size, target, known_align)
|
|||
rtx target;
|
||||
int known_align;
|
||||
{
|
||||
#ifdef SETJMP_VIA_SAVE_AREA
|
||||
rtx setjmpless_size = NULL_RTX;
|
||||
#endif
|
||||
|
||||
/* If we're asking for zero bytes, it doesn't matter what we point
|
||||
to since we can't dereference it. But return a reasonable
|
||||
address anyway. */
|
||||
|
@ -1074,6 +1158,45 @@ allocate_dynamic_stack_space (size, target, known_align)
|
|||
rtx dynamic_offset
|
||||
= expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
|
||||
stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
|
||||
|
||||
if (!current_function_calls_setjmp)
|
||||
{
|
||||
int align = STACK_BOUNDARY / BITS_PER_UNIT;
|
||||
|
||||
/* See optimize_save_area_alloca to understand what is being
|
||||
set up here. */
|
||||
|
||||
#if !defined(STACK_BOUNDARY) || !defined(MUST_ALIGN) || (STACK_BOUNDARY != BIGGEST_ALIGNMENT)
|
||||
/* If anyone creates a target with these characteristics, let them
|
||||
know that our optimization cannot work correctly in such a case. */
|
||||
abort();
|
||||
#endif
|
||||
|
||||
if (GET_CODE (size) == CONST_INT)
|
||||
{
|
||||
int new = INTVAL (size) / align * align;
|
||||
|
||||
if (INTVAL (size) != new)
|
||||
setjmpless_size = GEN_INT (new);
|
||||
else
|
||||
setjmpless_size = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since we know overflow is not possible, we avoid using
|
||||
CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead. */
|
||||
setjmpless_size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
|
||||
GEN_INT (align), NULL_RTX, 1);
|
||||
setjmpless_size = expand_mult (Pmode, setjmpless_size,
|
||||
GEN_INT (align), NULL_RTX, 1);
|
||||
}
|
||||
/* Our optimization works based upon being able to perform a simple
|
||||
transformation of this RTL into a (set REG REG) so make sure things
|
||||
did in fact end up in a REG. */
|
||||
if (!arith_operand (setjmpless_size, Pmode))
|
||||
setjmpless_size = force_reg (Pmode, setjmpless_size);
|
||||
}
|
||||
|
||||
size = expand_binop (Pmode, add_optab, size, dynamic_offset,
|
||||
NULL_RTX, 1, OPTAB_LIB_WIDEN);
|
||||
}
|
||||
|
@ -1145,6 +1268,16 @@ allocate_dynamic_stack_space (size, target, known_align)
|
|||
#endif
|
||||
size = convert_modes (Pmode, ptr_mode, size, 1);
|
||||
anti_adjust_stack (size);
|
||||
#ifdef SETJMP_VIA_SAVE_AREA
|
||||
if (setjmpless_size != NULL_RTX)
|
||||
{
|
||||
rtx note_target = get_last_insn ();
|
||||
|
||||
REG_NOTES (note_target) = gen_rtx (EXPR_LIST, REG_SAVE_AREA,
|
||||
setjmpless_size,
|
||||
REG_NOTES (note_target));
|
||||
}
|
||||
#endif /* SETJMP_VIA_SAVE_AREA */
|
||||
#ifdef STACK_GROWS_DOWNWARD
|
||||
emit_move_insn (target, virtual_stack_dynamic_rtx);
|
||||
#endif
|
||||
|
|
|
@ -3242,6 +3242,12 @@ rest_of_compilation (decl)
|
|||
|
||||
unshare_all_rtl (insns);
|
||||
|
||||
#ifdef SETJMP_VIA_SAVE_AREA
|
||||
/* This must be performed before virutal register instantiation. */
|
||||
if (current_function_calls_alloca)
|
||||
optimize_save_area_alloca (insns);
|
||||
#endif
|
||||
|
||||
/* Instantiate all virtual registers. */
|
||||
|
||||
instantiate_virtual_regs (current_function_decl, get_insns ());
|
||||
|
|
Loading…
Reference in New Issue