diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 655a8e89fdcedc28e8a029bcea124ef0074a174e..478463b237adfb32a46f0c857a8091090ed95bde 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -3565,6 +3565,7 @@ avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname, { cum->nregs = AVR_TINY ? 6 : 18; cum->regno = FIRST_CUM_REG; + cum->has_stack_args = 0; if (!libname && stdarg_p (fntype)) cum->nregs = 0; @@ -3605,6 +3606,8 @@ avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) if (cum->nregs && bytes <= cum->nregs) return gen_rtx_REG (arg.mode, cum->regno - bytes); + cum->has_stack_args = 1; + return NULL_RTX; } @@ -6014,6 +6017,8 @@ out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen) return ""; } + +/* Implement `TARGET_FRAME_POINTER_REQUIRED'. */ /* Return 1 if frame pointer for current function required. */ static bool @@ -6022,7 +6027,7 @@ avr_frame_pointer_required_p (void) return (cfun->calls_alloca || cfun->calls_setjmp || cfun->has_nonlocal_label - || crtl->args.info.nregs == 0 + || crtl->args.info.has_stack_args || get_frame_size () > 0); } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index ff2738df78c734850e8fb5950914fdd87f875f59..56211fa9cd00ec856eb000aa25a3d2058c452778 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -333,6 +333,10 @@ typedef struct avr_args /* Next available register number */ int regno; + + /* Whether some of the arguments are passed on the stack, + and hence an arg pointer is needed. */ + int has_stack_args; } CUMULATIVE_ARGS; #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \ diff --git a/gcc/testsuite/gcc.target/avr/pr114132-1.c b/gcc/testsuite/gcc.target/avr/pr114132-1.c new file mode 100644 index 0000000000000000000000000000000000000000..209eca823bd1d5a1ff9de2814a1f9c30e62548a9 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr114132-1.c @@ -0,0 +1,15 @@ +/* { dg-additional-options "-Os -std=c99" } */ + +#ifdef __AVR_TINY__ +int func (int a, int b, char c) +#else +int func (long long a, long long b, char c) +#endif +{ + (void) a; + (void) b; + + return c; +} + +/* { dg-final { scan-assembler-not "push r28" } } */ diff --git a/gcc/testsuite/gcc.target/avr/torture/pr114132-2.c b/gcc/testsuite/gcc.target/avr/torture/pr114132-2.c new file mode 100644 index 0000000000000000000000000000000000000000..c2bcbacec37052102bffde1c4bccd304bbe0dc6c --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/pr114132-2.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-additional-options "-std=c99" } */ + +__attribute__((noinline,noclone)) +#ifdef __AVR_TINY__ +int func (int a, int b, char c) +#else +int func (long long a, long long b, char c) +#endif +{ + (void) a; + (void) b; + return 10 + c; +} + +int main (void) +{ + if (func (0, 0, 91) != 101) + __builtin_abort(); + return 0; +} +