This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Reserving stack space on a per-argument basis
- To: gcc-patches at gcc dot gnu dot org
- Subject: Reserving stack space on a per-argument basis
- From: Alexandre Oliva <aoliva at redhat dot com>
- Date: 18 Dec 2000 04:19:45 -0200
- Organization: GCC Team, Red Hat
FUNCTION_ARG may return a PARALLEL containing a NULL_RTX, indicating
that a copy of an argument must be passed on the stack. I'm working
on a port whose ABI requires stack space to be reserved for certain
types of arguments passed in registers. In order to not waste the CPU
and memory cycles of creating a useless copy of such registers in
memory, I've come up with this patch. Behavior is unchanged in ports
that don't use this new feature. Ok to install?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* tm.texi (FUNCTION_ARG): Document use of NULL_RTX in the last
entry of a PARALLEL.
* expr.c (emit_group_load, emit_group_store): Disregard such
uses.
* function.c (assign_parms): Take them into account when
computing stack usage.
* calls.c (initialize_argument_information): Likewise.
Index: gcc/calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.168
diff -u -p -r1.168 calls.c
--- gcc/calls.c 2000/11/30 20:15:10 1.168
+++ gcc/calls.c 2000/12/18 06:17:55
@@ -1125,6 +1125,7 @@ initialize_argument_information (num_act
tree type = TREE_TYPE (TREE_VALUE (p));
int unsignedp;
enum machine_mode mode;
+ int reserve_stack_space = 0;
args[i].tree_value = TREE_VALUE (p);
@@ -1270,9 +1271,16 @@ initialize_argument_information (num_act
/* If FUNCTION_ARG returned a (parallel [(expr_list (nil) ...) ...]),
it means that we are to pass this arg in the register(s) designated
by the PARALLEL, but also to pass it in the stack. */
- if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
- && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
- args[i].pass_on_stack = 1;
+ if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL)
+ {
+ if (XEXP (XVECEXP (args[i].reg, 0, 0), 0) == NULL_RTX)
+ args[i].pass_on_stack = 1;
+ else if (XVECLEN (args[i].reg, 0) > 1
+ && (XEXP (XVECEXP (args[i].reg, 0,
+ XVECLEN (args[i].reg, 0) - 1), 0)
+ == NULL_RTX))
+ reserve_stack_space = 1;
+ }
/* If this is an addressable type, we must preallocate the stack
since we must evaluate the object into its final location.
@@ -1291,7 +1299,8 @@ initialize_argument_information (num_act
/* Compute the stack-size of this argument. */
if (args[i].reg == 0 || args[i].partial != 0
|| reg_parm_stack_space > 0
- || args[i].pass_on_stack)
+ || args[i].pass_on_stack
+ || reserve_stack_space)
locate_and_pad_parm (mode, type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
Index: gcc/function.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.c,v
retrieving revision 1.235
diff -u -p -r1.235 function.c
--- gcc/function.c 2000/12/15 09:09:41 1.235
+++ gcc/function.c 2000/12/18 06:17:55
@@ -4505,7 +4505,11 @@ assign_parms (fndecl)
if (entry_parm == stack_parm
|| (GET_CODE (entry_parm) == PARALLEL
- && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
+ && (XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX
+ || (XVECLEN (entry_parm, 0) > 1
+ && (XEXP (XVECEXP (entry_parm, 0,
+ XVECLEN (entry_parm, 0) - 1), 0)
+ == NULL_RTX))))
#if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
/* On some machines, even if a parm value arrives in a register
there is still an (uninitialized) stack slot allocated for it.
Index: gcc/expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expr.c,v
retrieving revision 1.282
diff -u -p -r1.282 expr.c
--- gcc/expr.c 2000/12/09 03:42:29 1.282
+++ gcc/expr.c 2000/12/18 06:17:57
@@ -1919,7 +1919,7 @@ move_block_from_reg (regno, x, nregs, si
registers represented by a PARALLEL. SSIZE represents the total size of
block SRC in bytes, or -1 if not known. ALIGN is the known alignment of
SRC in bits. */
-/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatent assumption that
+/* ??? If SSIZE % UNITS_PER_WORD != 0, we make the blatant assumption that
the balance will be in what would be the low-order memory addresses, i.e.
left justified for big endian, right justified for little endian. This
happens to be true for the targets currently using this support. If this
@@ -1933,18 +1933,25 @@ emit_group_load (dst, orig_src, ssize, a
int ssize;
{
rtx *tmps, src;
- int start, i;
+ int start, i, len;
if (GET_CODE (dst) != PARALLEL)
abort ();
/* Check for a NULL entry, used to indicate that the parameter goes
both on the stack and in registers. */
- if (XEXP (XVECEXP (dst, 0, 0), 0))
+ if (XEXP (XVECEXP (dst, 0, 0), 0) != NULL_RTX)
start = 0;
else
start = 1;
+ len = XVECLEN (dst, 0);
+
+ /* Check for a NULL entry at the end, used to indicate that stack
+ space is reserved, but not used, for this argument. */
+ if (len > 0 && XEXP (XVECEXP (dst, 0, len - 1), 0) == NULL_RTX)
+ len--;
+
tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (dst, 0));
/* If we won't be loading directly from memory, protect the real source
@@ -1960,7 +1967,7 @@ emit_group_load (dst, orig_src, ssize, a
}
/* Process the pieces. */
- for (i = start; i < XVECLEN (dst, 0); i++)
+ for (i = start; i < len; i++)
{
enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
@@ -2016,7 +2023,7 @@ emit_group_load (dst, orig_src, ssize, a
emit_queue ();
/* Copy the extracted pieces into the proper (probable) hard regs. */
- for (i = start; i < XVECLEN (dst, 0); i++)
+ for (i = start; i < len; i++)
emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
}
@@ -2031,22 +2038,29 @@ emit_group_store (orig_dst, src, ssize,
unsigned int align;
{
rtx *tmps, dst;
- int start, i;
+ int start, i, len;
if (GET_CODE (src) != PARALLEL)
abort ();
/* Check for a NULL entry, used to indicate that the parameter goes
both on the stack and in registers. */
- if (XEXP (XVECEXP (src, 0, 0), 0))
+ if (XEXP (XVECEXP (src, 0, 0), 0) != NULL_RTX)
start = 0;
else
start = 1;
+ len = XVECLEN (src, 0);
+
+ /* Check for a NULL entry at the end, used to indicate that stack
+ space is reserved, but not used, for this argument. */
+ if (len > 1 && XEXP (XVECEXP (src, 0, len - 1), 0) == NULL_RTX)
+ len--;
+
tmps = (rtx *) alloca (sizeof (rtx) * XVECLEN (src, 0));
/* Copy the (probable) hard regs into pseudos. */
- for (i = start; i < XVECLEN (src, 0); i++)
+ for (i = start; i < len; i++)
{
rtx reg = XEXP (XVECEXP (src, 0, i), 0);
tmps[i] = gen_reg_rtx (GET_MODE (reg));
@@ -2084,7 +2098,7 @@ emit_group_store (orig_dst, src, ssize,
}
/* Process the pieces. */
- for (i = start; i < XVECLEN (src, 0); i++)
+ for (i = start; i < len; i++)
{
HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
enum machine_mode mode = GET_MODE (tmps[i]);
Index: gcc/tm.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tm.texi,v
retrieving revision 1.155
diff -u -p -r1.155 tm.texi
--- gcc/tm.texi 2000/12/15 09:09:41 1.155
+++ gcc/tm.texi 2000/12/18 06:17:59
@@ -2919,9 +2919,12 @@ register in which to pass this part of t
register RTX indicates how large this part of the argument is. The
second operand of the @code{expr_list} is a @code{const_int} which gives
the offset in bytes into the entire argument of where this part starts.
-As a special exception the first @code{expr_list} in the @code{parallel}
-RTX may have a first operand of zero. This indicates that the entire
-argument is also stored on the stack.
+As a special exception the first and the last @code{expr_list} in the
+@code{parallel} RTX may have a first operand of @code{NULL_RTX}. When
+the @code{NULL_RTX} appears in the first @code{expr_list}, it indicates
+that the entire argument is also stored on the stack. When it appears
+in the last @code{expr_list}, stack space is reserved for the whole
+argument, but this stack space is not used at all.
@cindex @file{stdarg.h} and register arguments
The usual way to make the ANSI library @file{stdarg.h} work on a machine
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me