OSDN Git Service

Fix 41787
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Oct 2009 15:05:20 +0000 (15:05 +0000)
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Oct 2009 15:05:20 +0000 (15:05 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153498 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/vsx-vrsave.c [new file with mode: 0644]

index 7e51d68..e7068a9 100644 (file)
@@ -1,3 +1,23 @@
+2009-10-23  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/41787
+       * config/rs6000/rs6000.c (struct machine_function): Add
+       vsx_or_altivec_used_p to record if vector types are used.
+       (rs6000_expand_to_rtl_hook): Rename from
+       rs6000_alloc_sdmode_stack_slot.  If VSX, check to see if there are
+       any vector operations, so if there are, we can set VRSAVE to
+       non-zero when only floating point vector registers are used.
+       (TARGET_EXPAND_TO_RTL_HOOK): Use rs6000_expand_to_rtl_hook.
+       (rs6000_check_vector_mode): Inner function to check if vector
+       types are used in the code.
+       (compute_vrsave_mask): If VSX, make sure VRSAVE is non-zero if
+       vector instructions are used.
+
+       * config/rs6000/rs6000.h (HARD_REGNO_CALL_PART_CLOBBERED):
+       Indicate that VSX registers which overlap floating point
+       registers, can't be used across a call, since the ABI only states
+       the scalar part of the register will be saved and restored.
+
 2009-10-23  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/41673
index 9b03a9b..88649ea 100644 (file)
@@ -130,6 +130,8 @@ typedef struct GTY(()) machine_function
      64-bits wide and is allocated early enough so that the offset
      does not overflow the 16-bit load/store offset field.  */
   rtx sdmode_stack_slot;
+  /* True if any VSX or ALTIVEC vector type was used.  */
+  bool vsx_or_altivec_used_p;
 } machine_function;
 
 /* Target cpu type */
@@ -913,7 +915,7 @@ static void rs6000_elf_encode_section_info (tree, rtx, int)
      ATTRIBUTE_UNUSED;
 #endif
 static bool rs6000_use_blocks_for_constant_p (enum machine_mode, const_rtx);
-static void rs6000_alloc_sdmode_stack_slot (void);
+static void rs6000_expand_to_rtl_hook (void);
 static void rs6000_instantiate_decls (void);
 #if TARGET_XCOFF
 static void rs6000_xcoff_asm_output_anchor (rtx);
@@ -1505,7 +1507,7 @@ static const struct attribute_spec rs6000_attribute_table[] =
 #define TARGET_BUILTIN_RECIPROCAL rs6000_builtin_reciprocal
 
 #undef TARGET_EXPAND_TO_RTL_HOOK
-#define TARGET_EXPAND_TO_RTL_HOOK rs6000_alloc_sdmode_stack_slot
+#define TARGET_EXPAND_TO_RTL_HOOK rs6000_expand_to_rtl_hook
 
 #undef TARGET_INSTANTIATE_DECLS
 #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
@@ -13190,6 +13192,38 @@ rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
   return NULL_TREE;
 }
 
+static tree
+rs6000_check_vector_mode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+  /* Don't walk into types.  */
+  if (*tp == NULL_TREE || *tp == error_mark_node || TYPE_P (*tp))
+    {
+      *walk_subtrees = 0;
+      return NULL_TREE;
+    }
+
+  switch (TREE_CODE (*tp))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+    case FIELD_DECL:
+    case RESULT_DECL:
+    case SSA_NAME:
+    case REAL_CST:
+    case INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
+    case VIEW_CONVERT_EXPR:
+      if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (*tp))))
+       return *tp;
+      break;
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+
 enum reload_reg_type {
   GPR_REGISTER_TYPE,
   VECTOR_REGISTER_TYPE,
@@ -13630,11 +13664,17 @@ rs6000_ira_cover_classes (void)
   return (TARGET_VSX) ? cover_vsx : cover_pre_vsx;
 }
 
-/* Allocate a 64-bit stack slot to be used for copying SDmode
-   values through if this function has any SDmode references.  */
+/* Scan the trees looking for certain types.
+
+   Allocate a 64-bit stack slot to be used for copying SDmode values through if
+   this function has any SDmode references.
+
+   If VSX, note whether any vector operation was done so we can set VRSAVE to
+   non-zero, even if we just use the floating point registers to tell the
+   kernel to save the vector registers.  */
 
 static void
-rs6000_alloc_sdmode_stack_slot (void)
+rs6000_expand_to_rtl_hook (void)
 {
   tree t;
   basic_block bb;
@@ -13642,6 +13682,24 @@ rs6000_alloc_sdmode_stack_slot (void)
 
   gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
 
+  /* Check for vectors.  */
+  if (TARGET_VSX)
+    {
+      FOR_EACH_BB (bb)
+       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+         {
+           if (walk_gimple_op (gsi_stmt (gsi), rs6000_check_vector_mode,
+                               NULL))
+             {
+               cfun->machine->vsx_or_altivec_used_p = true;
+               goto found_vector;
+             }
+         }
+    found_vector:
+      ;
+    }
+
+  /* Check for SDmode being used.  */
   FOR_EACH_BB (bb)
     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
       {
@@ -16783,6 +16841,15 @@ compute_vrsave_mask (void)
     if (df_regs_ever_live_p (i))
       mask |= ALTIVEC_REG_BIT (i);
 
+  /* If VSX is used, we might have used a traditional floating point register
+     in a vector mode without using any altivec registers.  However the VRSAVE
+     register does not have room to indicate the floating point registers.
+     Modern kernels only look to see if the value is non-zero to determine if
+     they need to save the vector registers, so we just set an arbitrary
+     value if any vector type was used.  */
+  if (mask == 0 && TARGET_VSX && cfun->machine->vsx_or_altivec_used_p)
+    mask = 0xFFF;
+
   if (mask == 0)
     return mask;
 
index 25d760a..4b1ca3d 100644 (file)
@@ -1033,10 +1033,12 @@ extern unsigned rs6000_pointer_size;
 
 #define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)]
 
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)    \
-  ((TARGET_32BIT && TARGET_POWERPC64                   \
-    && (GET_MODE_SIZE (MODE) > 4)  \
-    && INT_REGNO_P (REGNO)) ? 1 : 0)
+#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE)                    \
+  (((TARGET_32BIT && TARGET_POWERPC64                                  \
+     && (GET_MODE_SIZE (MODE) > 4)                                     \
+     && INT_REGNO_P (REGNO)) ? 1 : 0)                                  \
+   || (TARGET_VSX && FP_REGNO_P (REGNO)                                        \
+       && GET_MODE_SIZE (MODE) > 8))
 
 #define VSX_VECTOR_MODE(MODE)          \
         ((MODE) == V4SFmode            \
index 81d39b5..03d2165 100644 (file)
@@ -1,3 +1,8 @@
+2009-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/41787
+       * gcc.target/powerpc/vsx-vrsave.c: New file.
+
 2009-10-23  Joseph Myers  <joseph@codesourcery.com>
 
        PR c/41673
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vrsave.c b/gcc/testsuite/gcc.target/powerpc/vsx-vrsave.c
new file mode 100644 (file)
index 0000000..83125f6
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler-times "mtvrsave" 2 } } */
+
+/* Check whether VRSAVE is set to non-zero if VSX vector operations were
+   used, but it should not be set if there are no vector operations.  */
+
+void
+generates_vrsave (vector double *a, vector double *b, vector double *c)
+{
+  *a = *b + *c;
+}
+
+void
+no_vrsave (double *a, double *b, double *c)
+{
+  *a = *b + *c;
+}