aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-03-22 11:23:05 -0800
committerRichard Henderson <rth@gcc.gnu.org>2002-03-22 11:23:05 -0800
commit648fe28b9dc62616ded2f6eafe5c945887b68bcc (patch)
tree239508eee576e0a370dc1c3feb1e8b63a73a1950
parent1813dafd906295f5a6b441490440c548f53123f6 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/config/ia64/ia64.c15
-rw-r--r--gcc/config/ia64/ia64.h3
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20020321-1.c20
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;
+}