From: Kazu Hirata Date: Sat, 8 Oct 2005 03:33:46 +0000 (+0000) Subject: re PR middle-end/23150 (20050713-1.c fails on arm-none-eabi with -O2 or -Os.) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=07eef8164aa7feb3aa60d5479894ea2d926643ce;p=gcc.git 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 --- 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 + + 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 * config/ia64/vect.md (ashl3, ashr3, lshr3): 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. */