From: Ian Lance Taylor Date: Tue, 27 Jan 2004 14:48:02 +0000 (+0000) Subject: arm.c (output_return_instruction): Only restore IP into SP if frame_pointer_needed. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b034930ffb2b6c44a85d7316b622cf4cc4df2737;p=gcc.git arm.c (output_return_instruction): Only restore IP into SP if frame_pointer_needed. * config/arm/arm.c (output_return_instruction): Only restore IP into SP if frame_pointer_needed. * gcc.dg/arm-mmx-1.c: New test. From-SVN: r76710 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 58a742c0c28..119c20ab649 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-01-27 Ian Lance Taylor + + * config/arm/arm.c (output_return_instruction): Only restore IP + into SP if frame_pointer_needed. + 2004-01-27 Eric Botcazou * config/sparc/sparc.c (function_arg_pass_by_reference): Return 1 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 768678d1b51..b70e68b1e18 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -8260,15 +8260,25 @@ output_return_instruction (rtx operand, int really_return, int reverse) return_reg = reg_names[LR_REGNUM]; if ((live_regs_mask & (1 << IP_REGNUM)) == (1 << IP_REGNUM)) - /* There are two possible reasons for the IP register being saved. - Either a stack frame was created, in which case IP contains the - old stack pointer, or an ISR routine corrupted it. If this in an - ISR routine then just restore IP, otherwise restore IP into SP. */ - if (! IS_INTERRUPT (func_type)) - { - live_regs_mask &= ~ (1 << IP_REGNUM); - live_regs_mask |= (1 << SP_REGNUM); - } + { + /* There are three possible reasons for the IP register + being saved. 1) a stack frame was created, in which case + IP contains the old stack pointer, or 2) an ISR routine + corrupted it, or 3) it was saved to align the stack on + iWMMXt. In case 1, restore IP into SP, otherwise just + restore IP. */ + if (frame_pointer_needed) + { + live_regs_mask &= ~ (1 << IP_REGNUM); + live_regs_mask |= (1 << SP_REGNUM); + } + else + { + if (! IS_INTERRUPT (func_type) + && ! TARGET_REALLY_IWMMXT) + abort (); + } + } /* On some ARM architectures it is faster to use LDR rather than LDM to load a single register. On other architectures, the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 330d38a3c8c..a89844292bd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-01-27 Ian Lance Taylor + + * gcc.dg/arm-mmx-1.c: New test. + 2004-01-27 Eric Botcazou * gcc.dg/20040127-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/arm-mmx-1.c b/gcc/testsuite/gcc.dg/arm-mmx-1.c new file mode 100644 index 00000000000..4f95d8d1fed --- /dev/null +++ b/gcc/testsuite/gcc.dg/arm-mmx-1.c @@ -0,0 +1,26 @@ +/* Verify that if IP is saved to ensure stack alignment, we don't load + it into sp. */ +/* { dg-do compile { target arm*-*-* strongarm*-*-* xscale*-*-*} } */ +/* { dg-options "-O -mno-apcs-frame -mcpu=iwmmxt" } */ +/* { dg-final { scan-assembler "ldmfd\[ ]sp!.*ip,\[ ]*pc" } } */ + +/* This function uses all the call-saved registers, namely r4, r5, r6, + r7, r8, r9, sl, fp. Since we also save pc, that leaves an odd + number of registers, and the compiler will push ip to align the + stack. Make sure that we restore ip into ip, not into sp as is + done when using a frame pointer. The -mno-apcs-frame option + permits the frame pointer to be used as an ordinary register. */ +int +foo(int *a, int *b, int *c, int *d, int *tot) +{ + int i, j, k, l, m, n, o; + + *tot = 0; + for (i = *a; i < *b; i += *c) + for (j = *a; j < *b; j += *d) + for (k = *a; k < *c; k += *d) + for (l = *b; k < *c; k += *d) + for (m = *d; k < *c; k += *b) + *tot += i + j + k + l + m; + return *tot; +}