Fix 41787

From-SVN: r153498
This commit is contained in:
Michael Meissner 2009-10-23 15:05:20 +00:00 committed by Michael Meissner
parent cb9c2485b2
commit 3fc841c85d
5 changed files with 123 additions and 9 deletions

View 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

View 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;

View 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 \

View 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

View File

@ -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;
}