This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch PR43399] Fix bootstrap on arm-linux-gnueabi with VTA changes.
- From: Ramana Radhakrishnan <ramana dot radhakrishnan at arm dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>, jakub at gcc dot gnu dot org
- Date: Thu, 18 Mar 2010 21:39:40 +0000
- Subject: [Patch PR43399] Fix bootstrap on arm-linux-gnueabi with VTA changes.
- Reply-to: ramana dot radhakrishnan at arm dot com
Hi,
The attached patch fixes the ICE with bootstrap on the arm-linux-gnueabi
target and does this by using a PRE_MODIFY instead of a PRE_DEC in the
prologue for the push_multi pattern.
As mentioned in the audit trail, we could fix this by exposing the
entire push multiple sequence to the middle end but given some of the
restrictions with the various store multiple instructions. We need
slightly invasive changes in the backend which might not be
suitable for stage4.
I've tested this by completing a bootstrap with arm-linux-gnueabi for C
and C++ and a full testrun is on at the minute.
Ok to commit for trunk and backport to the 4.4 branch if this is a
regression there as well ?
cheers
Ramana
2010-03-18 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
PR target/43399
* config/arm/arm.c (emit_multi_reg_push): Update comments.
Use PRE_MODIFY instead of PRE_DEC.
(emit_sfm): Use PRE_MODIFY instead of PRE_DEC.
(vfp_emit_fstmd): Likewise.
Index: arm.c
===================================================================
--- arm.c (revision 157543)
+++ arm.c (working copy)
@@ -11656,8 +11656,10 @@ vfp_emit_fstmd (int base_reg, int count)
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
+ gen_rtx_PRE_MODIFY (Pmode,
+ stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx,
+ - (count * 8)))),
gen_rtx_UNSPEC (BLKmode,
gen_rtvec (1, reg),
UNSPEC_PUSH_MULT));
@@ -13910,11 +13912,12 @@ emit_multi_reg_push (unsigned long mask)
/* For the body of the insn we are going to generate an UNSPEC in
parallel with several USEs. This allows the insn to be recognized
- by the push_multi pattern in the arm.md file. The insn looks
- something like this:
+ by the push_multi pattern in the arm.md file.
+
+ The body of the insn looks something like this:
(parallel [
- (set (mem:BLK (pre_dec:BLK (reg:SI sp)))
+ (set (mem:BLK (pre_modify:SI (reg:SI sp)))
(unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT))
(use (reg:SI 11 fp))
(use (reg:SI 12 ip))
@@ -13922,6 +13925,7 @@ emit_multi_reg_push (unsigned long mask)
(use (reg:SI 15 pc))
])
+
For the frame note however, we try to be more explicit and actually
show each register being stored into the stack frame, plus a (single)
decrement of the stack pointer. We do it this way in order to be
@@ -13937,9 +13941,27 @@ emit_multi_reg_push (unsigned long mask)
(set (mem:SI (plus:SI (reg:SI sp) (const_int 12))) (reg:SI lr))
])
- This sequence is used both by the code to support stack unwinding for
- exceptions handlers and the code to generate dwarf2 frame debugging. */
+ 1. For the APCS i.e. arm-elf / arm-linux the registers saved using this scheme
+ are fp, ip, lr, pc.
+ 2. For the AAPCS i.e. arm-eabi and arm-linux-gnueabi targets
+ or what is known as AAPCS we generate a variation where the
+ note expression and the insn are controlled by the number of
+ registers being stored and could be any number of registers.
+
+ This sequence is used both by the code to support stack unwinding for
+ exception handlers and the code to generate dwarf2 frame debugging.
+
+ FIXME:: In an ideal world the PRE_MODIFY would not exist and
+ instead we'd have a parallel expression detailing all
+ the stores to the various memory addresses so that debug
+ information is more up-to-date. Remember however while writing
+ this to take care of the constraints with the push instruction.
+
+ Note also that this has to be taken care of for the VFP registers.
+
+ For more see PR43399. */
+
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1));
dwarf_par_index = 1;
@@ -13953,8 +13975,10 @@ emit_multi_reg_push (unsigned long mask)
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
+ gen_rtx_PRE_MODIFY (Pmode,
+ stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx,
+ -4 * num_regs))),
gen_rtx_UNSPEC (BLKmode,
gen_rtvec (1, reg),
UNSPEC_PUSH_MULT));
@@ -14040,8 +14064,10 @@ emit_sfm (int base_reg, int count)
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
gen_frame_mem (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
+ gen_rtx_PRE_MODIFY (Pmode,
+ stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx,
+ -12 * count))),
gen_rtx_UNSPEC (BLKmode,
gen_rtvec (1, reg),
UNSPEC_PUSH_MULT));