re PR target/3177 (Invalid sibcall optimisation on ia64)
authorRichard Henderson <rth@redhat.com>
Fri, 22 Mar 2002 19:23:05 +0000 (11:23 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 22 Mar 2002 19:23:05 +0000 (11:23 -0800)
        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

gcc/ChangeLog
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.h
gcc/testsuite/gcc.c-torture/execute/20020321-1.c [new file with mode: 0644]

index c3e96ded277260cc12f44f9e9a1369a074353343..4dfc46acee26957ae8c3a322ec56f6c1f9a32ce0 100644 (file)
@@ -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.
index bbe771fca6f742da38da33b8689aa9d98b06ba19..de0c1c941415a8f696e6ecce193429a64914abe8 100644 (file)
@@ -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;
+    }
 }
 \f
 /* Implement va_start.  */
index 8a4a759ec528b57b54f10888d9676122d2b374ae..8e3eaeea8bf8695a30cf5afa8589718ba6529e21 100644 (file)
@@ -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 (file)
index 0000000..d06dd0a
--- /dev/null
@@ -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;
+}