aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-28 19:49:18 +0000
committermeissner <meissner@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-28 19:49:18 +0000
commit7dce9bb8623c6dd047497b8c8974c96683d723de (patch)
tree651ad4f0809a5d3f077e4144b065108d3a4a9533
parent7638d82cc5841b8a5a91d9ed133ec344877c2a75 (diff)
Make tonto, gamess, and calculix work again.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/ibm/gcc-4_3-branch@153684 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.ibm14
-rw-r--r--gcc/config/rs6000/predicates.md5
-rw-r--r--gcc/config/rs6000/rs6000.c32
3 files changed, 35 insertions, 16 deletions
diff --git a/gcc/ChangeLog.ibm b/gcc/ChangeLog.ibm
index 850762c0331..54dbbb00f61 100644
--- a/gcc/ChangeLog.ibm
+++ b/gcc/ChangeLog.ibm
@@ -1,3 +1,17 @@
+2009-10-28 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/predicates.md (vrsave_operation): Allow for there
+ to be no CLOBBERs on a vrsave instruction.
+
+ * config/rs6000/rs6000.c (direct_return): Functions that use VSX
+ vectors in registers that overlap with fprs but no registers that
+ overlap with the Altivec registers sets VRSAVE to non-zero even
+ though the vrsave mask is 0.
+ (rs6000_stack_info): Ditto.
+ (rs6000_emit_prologue): Ditto.
+ (rs6000_emit_epilogue): Ditto.
+ (compute_vrsave_mask): Undo 2009-10-22 change here.
+
2009-10-23 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-c.c (altivec_categorize_keyword): Undo
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 2cabf0943b5..5476312e4f4 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1131,7 +1131,7 @@
unsigned int dest_regno, src_regno;
int i;
- if (count <= 1
+ if (count == 0
|| GET_CODE (XVECEXP (op, 0, 0)) != SET
|| GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
|| GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC_VOLATILE
@@ -1144,6 +1144,9 @@
if (dest_regno != VRSAVE_REGNO || src_regno != VRSAVE_REGNO)
return 0;
+ /* Under VSX it is possible for there to be no clobbers if the function uses
+ vector registers that overlap with the floating point registers, but no
+ registers that overlap the altivec registers. */
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 1064f5fecd3..be0fab7b8ad 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3631,6 +3631,7 @@ direct_return (void)
&& ! info->lr_save_p
&& ! info->cr_save_p
&& info->vrsave_mask == 0
+ && ! cfun->machine->vsx_or_altivec_used_p
&& ! info->push_p)
return 1;
}
@@ -16724,15 +16725,6 @@ 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;
@@ -17054,7 +17046,8 @@ rs6000_stack_info (void)
else
info_ptr->vrsave_mask = 0;
- if (TARGET_ALTIVEC_VRSAVE && info_ptr->vrsave_mask)
+ if (TARGET_ALTIVEC_VRSAVE &&
+ (info_ptr->vrsave_mask || cfun->machine->vsx_or_altivec_used_p))
info_ptr->vrsave_size = 4;
else
info_ptr->vrsave_size = 0;
@@ -17208,7 +17201,8 @@ rs6000_stack_info (void)
if (! TARGET_ALTIVEC_ABI || info_ptr->altivec_size == 0)
info_ptr->altivec_save_offset = 0;
- if (! TARGET_ALTIVEC_ABI || info_ptr->vrsave_mask == 0)
+ if (! TARGET_ALTIVEC_ABI
+ || (info_ptr->vrsave_mask == 0 && !cfun->machine->vsx_or_altivec_used_p))
info_ptr->vrsave_save_offset = 0;
if (! TARGET_SPE_ABI
@@ -18860,6 +18854,7 @@ rs6000_emit_prologue (void)
(frame_reg_rtx != sp_reg_rtx
&& ((info->altivec_size != 0)
|| (info->vrsave_mask != 0)
+ || cfun->machine->vsx_or_altivec_used_p
)),
FALSE);
if (frame_reg_rtx != sp_reg_rtx)
@@ -18915,10 +18910,17 @@ rs6000_emit_prologue (void)
epilogue. */
if (TARGET_ALTIVEC && TARGET_ALTIVEC_VRSAVE
- && info->vrsave_mask != 0)
+ && (info->vrsave_mask != 0 || cfun->machine->vsx_or_altivec_used_p))
{
rtx reg, mem, vrsave;
int offset;
+ unsigned int mask = info->vrsave_mask;
+
+ /* If we only used VSX vector registers that overlap with floating point
+ registers, just set VRSAVE to non-zero to tell the kernel that we need
+ to save the vector registers. */
+ if (!mask && cfun->machine->vsx_or_altivec_used_p)
+ mask = 0x1;
/* Get VRSAVE onto a GPR. Note that ABI_V4 might be using r12
as frame_reg_rtx and r11 as the static chain pointer for
@@ -18941,7 +18943,7 @@ rs6000_emit_prologue (void)
}
/* Include the registers in the mask. */
- emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
+ emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) mask)));
insn = emit_insn (generate_set_vrsave (reg, info, 0));
}
@@ -19316,7 +19318,7 @@ rs6000_emit_epilogue (int sibcall)
/* Restore VRSAVE if we must do so before adjusting the stack. */
if (TARGET_ALTIVEC
&& TARGET_ALTIVEC_VRSAVE
- && info->vrsave_mask != 0
+ && (info->vrsave_mask != 0 || cfun->machine->vsx_or_altivec_used_p)
&& (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
|| (DEFAULT_ABI != ABI_V4
&& info->vrsave_save_offset < (TARGET_32BIT ? -220 : -288))))
@@ -19429,7 +19431,7 @@ rs6000_emit_epilogue (int sibcall)
if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
&& TARGET_ALTIVEC
&& TARGET_ALTIVEC_VRSAVE
- && info->vrsave_mask != 0
+ && (info->vrsave_mask != 0 || cfun->machine->vsx_or_altivec_used_p)
&& (DEFAULT_ABI == ABI_V4
|| info->vrsave_save_offset >= (TARGET_32BIT ? -220 : -288)))
{