alpha.c (alpha_sa_size): Force procedure type to PT_STACK when frame_pointer_needed...
authorOlivier Hainque <hainque@adacore.com>
Tue, 11 Aug 2009 05:14:48 +0000 (05:14 +0000)
committerDouglas Rupp <rupp@gcc.gnu.org>
Tue, 11 Aug 2009 05:14:48 +0000 (05:14 +0000)
* config/alpha/alpha.c (alpha_sa_size): Force procedure type to
PT_STACK when frame_pointer_needed on OpenVMS.
(alpha_pv_save_size, alpha_using_fp): Remove.
(alpha_vms_can_eliminate): New function. Support for CAN_ELIMINATE
with proper processing for PT_NULL.
(alpha_vms_initial_elimination_offset): New function. Support for
INITIAL_ELIMINATION_OFFSET with proper processing for PT_NULL.
(alpha_sa_size): Force procedure type to PT_STACK when
frame_pointer_needed on OpenVMS.
* config/alpha/alpha-protos.h (alpha_pv_save_size): Remove prototype.
(alpha_using_fp): Likewise.
(alpha_vms_can_eliminate): Add prototype.
(alpha_vms_initial_elimination_offset): Likewise.
* config/alpha/vms.h (CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET):
Call alpha_vms_can_eliminate and alpha_vms_initial_elimination_offset.

Co-Authored-By: Douglas B Rupp <rupp@gnat.com>
From-SVN: r150646

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/vms.h

index 17d7f63..d15941a 100644 (file)
@@ -1,3 +1,22 @@
+2009-08-10  Olivier Hainque  <hainqueu@adacore.com>
+            Douglas B Rupp  <rupp@gnat.com>
+
+       * config/alpha/alpha.c (alpha_sa_size): Force procedure type to
+       PT_STACK when frame_pointer_needed on OpenVMS.
+       (alpha_pv_save_size, alpha_using_fp): Remove.
+       (alpha_vms_can_eliminate): New function. Support for CAN_ELIMINATE
+       with proper processing for PT_NULL.
+       (alpha_vms_initial_elimination_offset): New function. Support for
+       INITIAL_ELIMINATION_OFFSET with proper processing for PT_NULL.
+       (alpha_sa_size): Force procedure type to PT_STACK when
+       frame_pointer_needed on OpenVMS.
+       * config/alpha/alpha-protos.h (alpha_pv_save_size): Remove prototype.
+       (alpha_using_fp): Likewise.
+       (alpha_vms_can_eliminate): Add prototype.
+       (alpha_vms_initial_elimination_offset): Likewise.
+       * config/alpha/vms.h (CAN_ELIMINATE, INITIAL_ELIMINATION_OFFSET):
+       Call alpha_vms_can_eliminate and alpha_vms_initial_elimination_offset.
+
 2009-08-10  Eric Botcazou  <botcazou@adacore.com>
             Douglas B Rupp  <rupp@gnat.com>
 
index 39091b7..43665d3 100644 (file)
@@ -28,8 +28,6 @@ extern int direct_return (void);
 extern int alpha_sa_size (void);
 extern HOST_WIDE_INT alpha_initial_elimination_offset (unsigned int,
                                                       unsigned int);
-extern int alpha_pv_save_size (void);
-extern int alpha_using_fp (void);
 extern void alpha_expand_prologue (void);
 extern void alpha_expand_epilogue (void);
 extern void alpha_output_filename (FILE *, const char *);
@@ -116,7 +114,9 @@ extern void avms_asm_output_external (FILE *, tree, const char *);
 extern void vms_output_aligned_decl_common (FILE *, tree, const char *,
                                            unsigned HOST_WIDE_INT,
                                            unsigned int);
-
+extern int alpha_vms_can_eliminate (unsigned int, unsigned int);
+extern HOST_WIDE_INT alpha_vms_initial_elimination_offset (unsigned int,
+                                                          unsigned int);
 #endif
 
 extern rtx unicosmk_add_call_info_word (rtx);
index 84c2b7c..a1ec736 100644 (file)
@@ -7353,10 +7353,10 @@ alpha_sa_size (void)
     }
   else if (TARGET_ABI_OPEN_VMS)
     {
-      /* Start by assuming we can use a register procedure if we don't
-        make any calls (REG_RA not used) or need to save any
-        registers and a stack procedure if we do.  */
-      if ((mask[0] >> REG_RA) & 1)
+      /* Start with a stack procedure if we make any calls (REG_RA used), or
+        need a frame pointer, with a register procedure if we otherwise need
+        at least a slot, and with a null procedure in other cases.  */
+      if ((mask[0] >> REG_RA) & 1 || frame_pointer_needed)
        alpha_procedure_type = PT_STACK;
       else if (get_frame_size() != 0)
        alpha_procedure_type = PT_REGISTER;
@@ -7446,21 +7446,96 @@ alpha_initial_elimination_offset (unsigned int from,
   return ret;
 }
 
+#if TARGET_ABI_OPEN_VMS
+
 int
-alpha_pv_save_size (void)
+alpha_vms_can_eliminate (unsigned int from ATTRIBUTE_UNUSED, unsigned int to)
 {
+  /* We need the alpha_procedure_type to decide. Evaluate it now.  */
   alpha_sa_size ();
-  return alpha_procedure_type == PT_STACK ? 8 : 0;
+
+  switch (alpha_procedure_type)
+    {
+    case PT_NULL:
+      /* NULL procedures have no frame of their own and we only
+        know how to resolve from the current stack pointer.  */
+      return to == STACK_POINTER_REGNUM;
+
+    case PT_REGISTER:
+    case PT_STACK:
+      /* We always eliminate except to the stack pointer if there is no
+        usable frame pointer at hand.  */
+      return (to != STACK_POINTER_REGNUM
+             || vms_unwind_regno != HARD_FRAME_POINTER_REGNUM);
+    }
+
+  gcc_unreachable ();
 }
 
-int
-alpha_using_fp (void)
-{
-  alpha_sa_size ();
-  return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM;
+/* FROM is to be eliminated for TO. Return the offset so that TO+offset
+   designates the same location as FROM.  */
+
+HOST_WIDE_INT
+alpha_vms_initial_elimination_offset (unsigned int from, unsigned int to)
+{ 
+  /* The only possible attempts we ever expect are ARG or FRAME_PTR to
+     HARD_FRAME or STACK_PTR.  We need the alpha_procedure_type to decide
+     on the proper computations and will need the register save area size
+     in most cases.  */
+
+  HOST_WIDE_INT sa_size = alpha_sa_size ();
+
+  /* PT_NULL procedures have no frame of their own and we only allow
+     elimination to the stack pointer. This is the argument pointer and we
+     resolve the soft frame pointer to that as well.  */
+     
+  if (alpha_procedure_type == PT_NULL)
+    return 0;
+
+  /* For a PT_STACK procedure the frame layout looks as follows
+
+                      -----> decreasing addresses
+
+                  <             size rounded up to 16       |   likewise   >
+     --------------#------------------------------+++--------------+++-------#
+     incoming args # pretended args | "frame" | regs sa | PV | outgoing args #
+     --------------#---------------------------------------------------------#
+                                   ^         ^              ^               ^
+                             ARG_PTR FRAME_PTR HARD_FRAME_PTR       STACK_PTR
+
+                             
+     PT_REGISTER procedures are similar in that they may have a frame of their
+     own. They have no regs-sa/pv/outgoing-args area.
+
+     We first compute offset to HARD_FRAME_PTR, then add what we need to get
+     to STACK_PTR if need be.  */
+  
+  {
+    HOST_WIDE_INT offset;
+    HOST_WIDE_INT pv_save_size = alpha_procedure_type == PT_STACK ? 8 : 0;
+
+    switch (from)
+      {
+      case FRAME_POINTER_REGNUM:
+       offset = ALPHA_ROUND (sa_size + pv_save_size);
+       break;
+      case ARG_POINTER_REGNUM:
+       offset = (ALPHA_ROUND (sa_size + pv_save_size
+                              + get_frame_size ()
+                              + crtl->args.pretend_args_size)
+                 - crtl->args.pretend_args_size);
+       break;
+      default:
+       gcc_unreachable ();
+      }
+    
+    if (to == STACK_POINTER_REGNUM)
+      offset += ALPHA_ROUND (crtl->outgoing_args_size);
+    
+    return offset;
+  }
 }
 
-#if TARGET_ABI_OPEN_VMS
 #define COMMON_OBJECT "common_object"
 
 static tree
index fa7e3c2..d8d513e 100644 (file)
@@ -144,27 +144,12 @@ along with GCC; see the file COPYING3.  If not see
 
 #undef CAN_ELIMINATE
 #define CAN_ELIMINATE(FROM, TO)  \
-((TO) != STACK_POINTER_REGNUM || ! alpha_using_fp ())
+  (alpha_vms_can_eliminate ((FROM), (TO)))
 
 #undef INITIAL_ELIMINATION_OFFSET
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
-{ switch (FROM)                                                                \
-    {                                                                  \
-    case FRAME_POINTER_REGNUM:                                         \
-      (OFFSET) = alpha_sa_size () + alpha_pv_save_size ();             \
-      break;                                                           \
-    case ARG_POINTER_REGNUM:                                           \
-      (OFFSET) = (ALPHA_ROUND (alpha_sa_size () + alpha_pv_save_size ()        \
-                              + get_frame_size ()                      \
-                              + crtl->args.pretend_args_size)  \
-                 - crtl->args.pretend_args_size);              \
-      break;                                                           \
-    default:                                                           \
-      gcc_unreachable ();                                              \
-    }                                                                  \
-  if ((TO) == STACK_POINTER_REGNUM)                                    \
-    (OFFSET) += ALPHA_ROUND (crtl->outgoing_args_size);        \
-}
+  ((OFFSET) = alpha_vms_initial_elimination_offset(FROM, TO))
+
 \f
 /* Define a data type for recording info about an argument list
    during the scan of that argument list.  This data type should