aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Earnshaw <rearnsha@arm.com>2010-03-21 20:27:00 +0000
committerRichard Earnshaw <rearnsha@gcc.gnu.org>2010-03-21 20:27:00 +0000
commitf8b68ed3c3dcd9bc49821677d8c23d4ad0f1d4f7 (patch)
tree2312aaf6703c79a8b840222145b8a7825f2990ef
parent474b97ce0ff47918ce4fb78b4ee970d4009ecf02 (diff)
downloadgcc-f8b68ed3c3dcd9bc49821677d8c23d4ad0f1d4f7.zip
gcc-f8b68ed3c3dcd9bc49821677d8c23d4ad0f1d4f7.tar.gz
gcc-f8b68ed3c3dcd9bc49821677d8c23d4ad0f1d4f7.tar.bz2
re PR target/42321 (NEON/VFP registers from inline assembly clobber list are saved/restored incorrectly)
PR target/42321 * arm.c (arm_output_epilogue): Correctly match VFP pop instructions with their corresponding prologue pushes. From-SVN: r157609
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c27
2 files changed, 22 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d098df7..06e2ffd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-03-21 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/42321
+ * arm.c (arm_output_epilogue): Correctly match VFP pop instructions
+ with their corresponding prologue pushes.
+
2010-03-20 Andrew Pinski <pinskia@gmail.com>
PR target/43156
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index cc023c1..6f42dd0 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13731,24 +13731,29 @@ arm_output_epilogue (rtx sibling)
if (TARGET_HARD_FLOAT && TARGET_VFP)
{
- start_reg = FIRST_VFP_REGNUM;
- for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
+ int end_reg = LAST_VFP_REGNUM + 1;
+
+ /* Scan the registers in reverse order. We need to match
+ any groupings made in the prologue and generate matching
+ pop operations. */
+ for (reg = LAST_VFP_REGNUM - 1; reg >= FIRST_VFP_REGNUM; reg -= 2)
{
if ((!df_regs_ever_live_p (reg) || call_used_regs[reg])
- && (!df_regs_ever_live_p (reg + 1) || call_used_regs[reg + 1]))
+ && (!df_regs_ever_live_p (reg + 1)
+ || call_used_regs[reg + 1]))
{
- if (start_reg != reg)
+ if (end_reg > reg + 2)
vfp_output_fldmd (f, SP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
- start_reg = reg + 2;
+ (reg + 2 - FIRST_VFP_REGNUM) / 2,
+ (end_reg - (reg + 2)) / 2);
+ end_reg = reg;
}
}
- if (start_reg != reg)
- vfp_output_fldmd (f, SP_REGNUM,
- (start_reg - FIRST_VFP_REGNUM) / 2,
- (reg - start_reg) / 2);
+ if (end_reg > reg + 2)
+ vfp_output_fldmd (f, SP_REGNUM, 0,
+ (end_reg - (reg + 2)) / 2);
}
+
if (TARGET_IWMMXT)
for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
if (df_regs_ever_live_p (reg) && !call_used_regs[reg])