diff options
author | Richard Henderson <rth@redhat.com> | 2002-03-22 11:23:05 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2002-03-22 11:23:05 -0800 |
commit | 648fe28b9dc62616ded2f6eafe5c945887b68bcc (patch) | |
tree | 239508eee576e0a370dc1c3feb1e8b63a73a1950 | |
parent | 1813dafd906295f5a6b441490440c548f53123f6 (diff) | |
download | gcc-648fe28b9dc62616ded2f6eafe5c945887b68bcc.zip gcc-648fe28b9dc62616ded2f6eafe5c945887b68bcc.tar.gz gcc-648fe28b9dc62616ded2f6eafe5c945887b68bcc.tar.bz2 |
re PR target/3177 (Invalid sibcall optimisation on ia64)
PR target/3177
* config/ia64/ia64.h (CUMULATIVE_ARGS): Add int_regs.
(INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Update.
* config/ia64/ia64.c (ia64_function_arg_advance): Set int_regs.
(ia64_expand_prologue): Look at int_regs, not words, for number
of incomming int regs.
From-SVN: r51180
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 15 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20020321-1.c | 20 |
4 files changed, 40 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c3e96de..4dfc46a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-03-22 Richard Henderson <rth@redhat.com> + + PR target/3177 + * config/ia64/ia64.h (CUMULATIVE_ARGS): Add int_regs. + (INIT_CUMULATIVE_ARGS, INIT_CUMULATIVE_INCOMING_ARGS): Update. + * config/ia64/ia64.c (ia64_function_arg_advance): Set int_regs. + (ia64_expand_prologue): Look at int_regs, not words, for number + of incomming int regs. + 2002-03-22 Andrew MacLeod <amacleod@redhat.com> * expr.c (expand_expr): A RESULT_DECL is part of a call. diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index bbe771f..de0c1c9 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -2047,7 +2047,7 @@ ia64_expand_prologue () /* We don't need an alloc instruction if we've used no outputs or locals. */ if (current_frame_info.n_local_regs == 0 && current_frame_info.n_output_regs == 0 - && current_frame_info.n_input_regs <= current_function_args_info.words) + && current_frame_info.n_input_regs <= current_function_args_info.int_regs) { /* If there is no alloc, but there are input registers used, then we need a .regstk directive. */ @@ -3188,14 +3188,14 @@ ia64_function_arg_advance (cum, mode, type, named) FR registers, then FP values must also go in general registers. This can happen when we have a SFmode HFA. */ else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS) - return; + cum->int_regs = cum->words; /* If there is a prototype, then FP values go in a FR register when named, and in a GR registeer when unnamed. */ else if (cum->prototype) { if (! named) - return; + cum->int_regs = cum->words; else /* ??? Complex types should not reach here. */ cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1); @@ -3203,10 +3203,11 @@ ia64_function_arg_advance (cum, mode, type, named) /* If there is no prototype, then FP values go in both FR and GR registers. */ else - /* ??? Complex types should not reach here. */ - cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1); - - return; + { + /* ??? Complex types should not reach here. */ + cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1); + cum->int_regs = cum->words; + } } /* Implement va_start. */ diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 8a4a759..8e3eaee 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1269,6 +1269,7 @@ enum reg_class typedef struct ia64_args { int words; /* # words of arguments so far */ + int int_regs; /* # GR registers used so far */ int fp_regs; /* # FR registers used so far */ int prototype; /* whether function prototyped */ } CUMULATIVE_ARGS; @@ -1279,6 +1280,7 @@ typedef struct ia64_args #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ do { \ (CUM).words = 0; \ + (CUM).int_regs = 0; \ (CUM).fp_regs = 0; \ (CUM).prototype = ((FNTYPE) && TYPE_ARG_TYPES (FNTYPE)) || (LIBNAME); \ } while (0) @@ -1292,6 +1294,7 @@ do { \ #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \ do { \ (CUM).words = 0; \ + (CUM).int_regs = 0; \ (CUM).fp_regs = 0; \ (CUM).prototype = 1; \ } while (0) diff --git a/gcc/testsuite/gcc.c-torture/execute/20020321-1.c b/gcc/testsuite/gcc.c-torture/execute/20020321-1.c new file mode 100644 index 0000000..d06dd0a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20020321-1.c @@ -0,0 +1,20 @@ +/* PR 3177 */ +/* Produced a SIGILL on ia64 with sibcall from F to G. We hadn't + widened the register window to allow for the fourth outgoing + argument as an "in" register. */ + +float g (void *a, void *b, int e, int c, float d) +{ + return d; +} + +float f (void *a, void *b, int c, float d) +{ + return g (a, b, 0, c, d); +} + +int main () +{ + f (0, 0, 1, 1); + return 0; +} |