diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr55019.c | 41 |
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); +} |