Commit 07eef816 by Kazu Hirata Committed by Kazu Hirata

re PR middle-end/23150 (20050713-1.c fails on arm-none-eabi with -O2 or -Os.)

	PR middle-end/23150
	* calls.c (mem_overlaps_already_clobbered_arg_p): New.
	(load_register_parameters): Call it.
	(check_sibcall_argument_overlap_1): Likewise.
	(store_one_arg): Likewise.

From-SVN: r105114
parent 3dbb4dce
2005-10-08 Kazu Hirata <kazu@codesourcery.com>
PR middle-end/23150
* calls.c (mem_overlaps_already_clobbered_arg_p): New.
(load_register_parameters): Call it.
(check_sibcall_argument_overlap_1): Likewise.
(store_one_arg): Likewise.
2005-10-07 James E. Wilson <wilson@specifix.com> 2005-10-07 James E. Wilson <wilson@specifix.com>
* config/ia64/vect.md (ashl<mode>3, ashr<mode>3, lshr<mode>3): Use * config/ia64/vect.md (ashl<mode>3, ashr<mode>3, lshr<mode>3): Use
......
...@@ -1437,6 +1437,42 @@ rtx_for_function_call (tree fndecl, tree addr) ...@@ -1437,6 +1437,42 @@ rtx_for_function_call (tree fndecl, tree addr)
return funexp; return funexp;
} }
/* Return true if and only if SIZE storage units (usually bytes)
starting from address ADDR overlap with already clobbered argument
area. This function is used to determine if we should give up a
sibcall. */
static bool
mem_overlaps_already_clobbered_arg_p (rtx addr, unsigned HOST_WIDE_INT size)
{
HOST_WIDE_INT i;
if (addr == current_function_internal_arg_pointer)
i = 0;
else if (GET_CODE (addr) == PLUS
&& (XEXP (addr, 0)
== current_function_internal_arg_pointer)
&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
i = INTVAL (XEXP (addr, 1));
else
return false;
#ifdef ARGS_GROW_DOWNWARD
i = -i - size;
#endif
if (size > 0)
{
unsigned HOST_WIDE_INT k;
for (k = 0; k < size; k++)
if (i + k < stored_args_map->n_bits
&& TEST_BIT (stored_args_map, i + k))
return true;
}
return false;
}
/* Do the register loads required for any wholly-register parms or any /* Do the register loads required for any wholly-register parms or any
parms which are passed both on the stack and in a register. Their parms which are passed both on the stack and in a register. Their
expressions were already evaluated. expressions were already evaluated.
...@@ -1534,6 +1570,12 @@ load_register_parameters (struct arg_data *args, int num_actuals, ...@@ -1534,6 +1570,12 @@ load_register_parameters (struct arg_data *args, int num_actuals,
{ {
rtx mem = validize_mem (args[i].value); rtx mem = validize_mem (args[i].value);
/* Check for overlap with already clobbered argument area. */
if (is_sibcall
&& mem_overlaps_already_clobbered_arg_p (XEXP (args[i].value, 0),
size))
*sibcall_failure = 1;
/* Handle a BLKmode that needs shifting. */ /* Handle a BLKmode that needs shifting. */
if (nregs == 1 && size < UNITS_PER_WORD if (nregs == 1 && size < UNITS_PER_WORD
#ifdef BLOCK_REG_PADDING #ifdef BLOCK_REG_PADDING
...@@ -1647,7 +1689,6 @@ check_sibcall_argument_overlap_1 (rtx x) ...@@ -1647,7 +1689,6 @@ check_sibcall_argument_overlap_1 (rtx x)
{ {
RTX_CODE code; RTX_CODE code;
int i, j; int i, j;
unsigned int k;
const char *fmt; const char *fmt;
if (x == NULL_RTX) if (x == NULL_RTX)
...@@ -1656,28 +1697,8 @@ check_sibcall_argument_overlap_1 (rtx x) ...@@ -1656,28 +1697,8 @@ check_sibcall_argument_overlap_1 (rtx x)
code = GET_CODE (x); code = GET_CODE (x);
if (code == MEM) if (code == MEM)
{ return mem_overlaps_already_clobbered_arg_p (XEXP (x, 0),
if (XEXP (x, 0) == current_function_internal_arg_pointer) GET_MODE_SIZE (GET_MODE (x)));
i = 0;
else if (GET_CODE (XEXP (x, 0)) == PLUS
&& XEXP (XEXP (x, 0), 0) ==
current_function_internal_arg_pointer
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
i = INTVAL (XEXP (XEXP (x, 0), 1));
else
return 0;
#ifdef ARGS_GROW_DOWNWARD
i = -i - GET_MODE_SIZE (GET_MODE (x));
#endif
for (k = 0; k < GET_MODE_SIZE (GET_MODE (x)); k++)
if (i + k < stored_args_map->n_bits
&& TEST_BIT (stored_args_map, i + k))
return 1;
return 0;
}
/* Scan all subexpressions. */ /* Scan all subexpressions. */
fmt = GET_RTX_FORMAT (code); fmt = GET_RTX_FORMAT (code);
...@@ -4080,41 +4101,11 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, ...@@ -4080,41 +4101,11 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags,
} }
/* Check for overlap with already clobbered argument area. */ /* Check for overlap with already clobbered argument area. */
if ((flags & ECF_SIBCALL) && MEM_P (arg->value)) if ((flags & ECF_SIBCALL)
{ && MEM_P (arg->value)
int i = -1; && mem_overlaps_already_clobbered_arg_p (XEXP (arg->value, 0),
unsigned HOST_WIDE_INT k; arg->locate.size.constant))
rtx x = arg->value; sibcall_failure = 1;
if (XEXP (x, 0) == current_function_internal_arg_pointer)
i = 0;
else if (GET_CODE (XEXP (x, 0)) == PLUS
&& XEXP (XEXP (x, 0), 0) ==
current_function_internal_arg_pointer
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
i = INTVAL (XEXP (XEXP (x, 0), 1));
else
i = -1;
if (i >= 0)
{
#ifdef ARGS_GROW_DOWNWARD
i = -i - arg->locate.size.constant;
#endif
if (arg->locate.size.constant > 0)
{
unsigned HOST_WIDE_INT sc = arg->locate.size.constant;
for (k = 0; k < sc; k++)
if (i + k < stored_args_map->n_bits
&& TEST_BIT (stored_args_map, i + k))
{
sibcall_failure = 1;
break;
}
}
}
}
/* Don't allow anything left on stack from computation /* Don't allow anything left on stack from computation
of argument to alloca. */ of argument to alloca. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment