aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerry Guo <terry.guo@arm.com>2012-10-23 03:49:17 +0000
committerXuepeng Guo <xguo@gcc.gnu.org>2012-10-23 03:49:17 +0000
commit0b7463235f0e23c624d1911c9b15f531108cc5a6 (patch)
treeb0acc3e8794fa85b6aa393551fe0bc4203fd523c
parente4878d25f33bcfd0c7224af55f0c364b3b518ad0 (diff)
downloadgcc-0b7463235f0e23c624d1911c9b15f531108cc5a6.zip
gcc-0b7463235f0e23c624d1911c9b15f531108cc5a6.tar.gz
gcc-0b7463235f0e23c624d1911c9b15f531108cc5a6.tar.bz2
re PR target/55019 (Incorrectly use live argument register to save high register in thumb1 prologue)
gcc/ PR target/55019 * config/arm/arm.c (thumb1_expand_prologue): Don't push high regs with live argument regs. gcc/testsuite/ PR target/55019 * gcc.dg/pr55019.c: New. From-SVN: r192703
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/arm/arm.c8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr55019.c41
4 files changed, 59 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9ec0467..236464f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2012-10-23 Terry Guo <terry.guo@arm.com>
+
+ PR target/55019
+ * config/arm/arm.c (thumb1_expand_prologue): Don't push high regs with
+ live argument regs.
+
2012-10-23 Hans-Peter Nilsson <hp@bitrange.com>
PR middle-end/55030
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1a822fb..e9b9463 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -22753,12 +22753,18 @@ thumb1_expand_prologue (void)
{
unsigned pushable_regs;
unsigned next_hi_reg;
+ unsigned arg_regs_num = TARGET_AAPCS_BASED ? crtl->args.info.aapcs_ncrn
+ : crtl->args.info.nregs;
+ unsigned arg_regs_mask = (1 << arg_regs_num) - 1;
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
if (live_regs_mask & (1 << next_hi_reg))
break;
- pushable_regs = l_mask & 0xff;
+ /* Here we need to mask out registers used for passing arguments
+ even if they can be pushed. This is to avoid using them to stash the high
+ registers. Such kind of stash may clobber the use of arguments. */
+ pushable_regs = l_mask & (~arg_regs_mask) & 0xff;
if (pushable_regs == 0)
pushable_regs = 1 << thumb_find_work_register (live_regs_mask);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 243d74e..16e6dd6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-23 Terry Guo <terry.guo@arm.com>
+
+ PR target/55019
+ * gcc.dg/pr55019.c: New.
+
2012-10-22 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
PR tree-optimization/55008
diff --git a/gcc/testsuite/gcc.dg/pr55019.c b/gcc/testsuite/gcc.dg/pr55019.c
new file mode 100644
index 0000000..1548fb2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr55019.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -funroll-loops" } */
+/* { dg-add-options ieee } */
+
+extern void exit (int);
+extern void abort (void);
+
+void
+compare (double a, double b)
+{
+ do
+ {
+ double s1 = __builtin_copysign ((double) 1.0, a);
+ double s2 = __builtin_copysign ((double) 1.0, b);
+
+ if (s1 != s2)
+ abort ();
+
+ if ((__builtin_isnan (a) != 0) != (__builtin_isnan (b) != 0))
+ abort ();
+
+ if ((a != b) != (__builtin_isnan (a) != 0))
+ abort ();
+ } while (0);
+}
+
+int
+main ()
+{
+ double a = 0.0;
+ double b = 0.0;
+ _Complex double cr = __builtin_complex (a, b);
+ static _Complex double cs = __builtin_complex (0.0, 0.0);
+
+ compare (__real__ cr, 0.0);
+ compare (__imag__ cr, 0.0);
+ compare (__real__ cs, 0.0);
+ compare (__imag__ cs, 0.0);
+
+ exit (0);
+}