diff options
author | Terry Guo <terry.guo@arm.com> | 2012-10-23 03:49:17 +0000 |
---|---|---|
committer | Xuepeng Guo <xguo@gcc.gnu.org> | 2012-10-23 03:49:17 +0000 |
commit | 0b7463235f0e23c624d1911c9b15f531108cc5a6 (patch) | |
tree | b0acc3e8794fa85b6aa393551fe0bc4203fd523c /gcc | |
parent | e4878d25f33bcfd0c7224af55f0c364b3b518ad0 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-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); +} |