diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-10-08 03:33:46 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-10-08 03:33:46 +0000 |
commit | ff6c0ab2fff65030fc325c84259e935f2ad40355 (patch) | |
tree | 5149051171e2a14191cc4236f39dee629b2c797b | |
parent | 46894cb34838ae83fa820967b980e47e0d6f979b (diff) | |
download | gcc-ff6c0ab2fff65030fc325c84259e935f2ad40355.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105114 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/calls.c | 107 |
2 files changed, 57 insertions, 58 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 86ba1b278df..6aeade95bb2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +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> * config/ia64/vect.md (ashl<mode>3, ashr<mode>3, lshr<mode>3): Use diff --git a/gcc/calls.c b/gcc/calls.c index 8d5379fac9b..7dbc21fe415 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1437,6 +1437,42 @@ rtx_for_function_call (tree fndecl, tree addr) 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 parms which are passed both on the stack and in a register. Their expressions were already evaluated. @@ -1534,6 +1570,12 @@ load_register_parameters (struct arg_data *args, int num_actuals, { 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. */ if (nregs == 1 && size < UNITS_PER_WORD #ifdef BLOCK_REG_PADDING @@ -1647,7 +1689,6 @@ check_sibcall_argument_overlap_1 (rtx x) { RTX_CODE code; int i, j; - unsigned int k; const char *fmt; if (x == NULL_RTX) @@ -1656,28 +1697,8 @@ check_sibcall_argument_overlap_1 (rtx x) code = GET_CODE (x); if (code == MEM) - { - 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 - 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; - } + return mem_overlaps_already_clobbered_arg_p (XEXP (x, 0), + GET_MODE_SIZE (GET_MODE (x))); /* Scan all subexpressions. */ fmt = GET_RTX_FORMAT (code); @@ -4080,41 +4101,11 @@ store_one_arg (struct arg_data *arg, rtx argblock, int flags, } /* Check for overlap with already clobbered argument area. */ - if ((flags & ECF_SIBCALL) && MEM_P (arg->value)) - { - int i = -1; - unsigned HOST_WIDE_INT k; - rtx x = arg->value; - - 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; - } - } - } - } + if ((flags & ECF_SIBCALL) + && MEM_P (arg->value) + && mem_overlaps_already_clobbered_arg_p (XEXP (arg->value, 0), + arg->locate.size.constant)) + sibcall_failure = 1; /* Don't allow anything left on stack from computation of argument to alloca. */ |