Hello,
This patch is a followup of
http://gcc.gnu.org/ml/gcc-patches/2014-02/msg01042.html
If fixes a bunch of ICEs for the testsuite ran with
--target_board=arm-sim/\{-mapcs-frame\}, noticed on a reference branch
for testing the former patch.
One of the strange issue I had to deal with, for instance with
./gcc.c-torture/compile/991202-1.c, is that the epilogue emitted the
CFA notes in the following order:
(set/f (reg:SI 12 ip)
(plus:SI (reg:SI 12 ip)
(const_int 16 [0x10])))
(set/f (reg:DF 32 s16)
(mem/c:DF (reg:SI 12 ip) [3 S8 A64]))
(set/f (reg:DF 34 s18)
(mem/c:DF (plus:SI (reg:SI 12 ip)
(const_int 8 [0x8])) [3 S8 A64]))
]) /home/bruelc/tmp/991202-1.c:18 347
{*vfp_pop_multiple_with_writeback}
(expr_list:REG_UNUSED (reg:SI 12 ip)
(expr_list:REG_CFA_ADJUST_CFA (set (reg:SI 12 ip)
(plus:SI (reg:SI 12 ip)
(const_int 16 [0x10])))
(expr_list:REG_CFA_DEF_CFA (reg/f:SI 11 fp)
(expr_list:REG_CFA_RESTORE (reg:DF 34 s18)
(expr_list:REG_CFA_RESTORE (reg:DF 32 s16)
(nil)))))))
but shrink-wrapping duplicates it as
(insn/f:TI 140 137 171 (parallel [
(set/f (reg:SI 12 ip)
(plus:SI (reg:SI 12 ip)
(const_int 16 [0x10])))
(set/f (reg:DF 32 s16)
(mem/c:DF (reg:SI 12 ip) [3 S8 A64]))
(set/f (reg:DF 34 s18)
(mem/c:DF (plus:SI (reg:SI 12 ip)
(const_int 8 [0x8])) [3 S8 A64]))
]) /home/bruelc/tmp/991202-1.c:18 347
{*vfp_pop_multiple_with_writeback}
(expr_list:REG_UNUSED (reg:SI 12 ip)
(expr_list:REG_CFA_RESTORE (reg:DF 32 s16)
(expr_list:REG_CFA_RESTORE (reg:DF 34 s18)
(expr_list:REG_CFA_DEF_CFA (reg/f:SI 11 fp)
(expr_list:REG_CFA_ADJUST_CFA (set (reg:SI 12 ip)
(plus:SI (reg:SI 12 ip)
(const_int 16 [0x10])))
(nil)))))))
Since the CFA_RESTORE order is inverted with CFA_DEF_CFA, cur_cfa->reg
was set with IP instead of FP
I fixed this by not emitting the CFA_ADJUST_CFA in this case, since it's
not needed anyway as we have:
fldmfdd ip!, {d8-d9} @ 140 *vfp_pop_multiple_with_writeback
sub sp, fp, #12 @ 142
ldmfd sp, {fp, sp, pc} @ 143
so after @140 cur_cfa can't be IP.
Regression tested for for armv7-a
--target_board=arm-sim/\{,-mapcs-frame\}. Fixes a large number of tests
OK for trunk ?
Many thanks
--- config/arm/arm.c 2014-02-19 15:28:34.000000000 +0100
+++ /work1/bruel/superh_elf/gnu_trunk.devs/gcc/gcc/config/arm/arm.c 2014-02-19 14:30:44.000000000 +0100
@@ -19911,10 +19911,14 @@
/* Make sure cfa doesn't leave with IP_REGNUM. */
if (TARGET_VFP && REGNO (base_reg) == IP_REGNUM)
- add_reg_note (par, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
+ {
+ RTX_FRAME_RELATED_P (par) = 1;
+ add_reg_note (par, REG_CFA_DEF_CFA, hard_frame_pointer_rtx);
+ }
+ else
+ arm_add_cfa_adjust_cfa_note (par, 2 * UNITS_PER_WORD * num_regs,
+ base_reg, base_reg);
- arm_add_cfa_adjust_cfa_note (par, 2 * UNITS_PER_WORD * num_regs,
- base_reg, base_reg);
}
@@ -27109,8 +27113,8 @@
if (saved_size > 0)
{
rtx insn;
- floats_from_frame += saved_size;
- insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, IP_REGNUM),
+ floats_from_frame += saved_size;
+ insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, IP_REGNUM),
hard_frame_pointer_rtx,
GEN_INT (-floats_from_frame)));
RTX_FRAME_RELATED_P (insn) = 1;
@@ -27192,7 +27196,9 @@
insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
hard_frame_pointer_rtx,
GEN_INT (- 4 * num_regs)));
- RTX_FRAME_RELATED_P (insn) = 1;
+
+ arm_add_cfa_adjust_cfa_note (insn, - 4 * num_regs,
+ stack_pointer_rtx, hard_frame_pointer_rtx);
}
arm_emit_multi_reg_pop (saved_regs_mask);