Richard, this patch fixes PR51271. It fixes the handling in scan_trace of an insn in the delay slot of an annulled branch that annuls the insn when the branch is not taken.
The way the insn is handled, is that: - the insn is applied to the state - the updated state is registered at the jump target - the state is reset to the original state, and we continue processing at the fall-through path the current related code in scan_insn is this: ... if (JUMP_P (control) && INSN_ANNULLED_BRANCH_P (control)) { /* ??? Hopefully multiple delay slots are not annulled. */ gcc_assert (n == 2); gcc_assert (!RTX_FRAME_RELATED_P (control)); gcc_assert (!find_reg_note (control, REG_ARGS_SIZE, NULL)); elt = XVECEXP (pat, 0, 1); /* If ELT is an instruction from target of an annulled branch, the effects are for the target only and so the args_size and CFA along the current path shouldn't change. */ if (INSN_FROM_TARGET_P (elt)) { HOST_WIDE_INT restore_args_size; add_cfi_insn = NULL; restore_args_size = cur_trace->end_true_args_size; cur_cfa = &cur_row->cfa; scan_insn_after (elt); /* ??? Should we instead save the entire row state? */ gcc_assert (!VEC_length (queued_reg_save, queued_reg_saves)); create_trace_edges (control); cur_trace->end_true_args_size = restore_args_size; cur_row->cfa = this_cfa; cur_cfa = &this_cfa; continue; } } ... The problem is that the state is not sufficiently restored, and this causes an ICE in maybe_record_trace_start. For the example from PR51271, the original state is this: ... .cfi_def_cfa 29, 16 .cfi_offset 28, -8 ... and after applying the following insn: ... (insn/s/f 143 79 162 (set (reg/f:SI 29 $sp) (plus:SI (reg/f:SI 29 $sp) (const_int 16 [0x10]))) 10 {*addsi3} (expr_list:REG_CFA_DEF_CFA (reg/f:SI 29 $sp) (expr_list:REG_CFA_RESTORE (reg:DI 28 $28) (nil)))) ... the state is updated to this and applied to the target: ... .cfi_def_cfa 29, 0 ... but after restoring the state it is not the original one: ... .cfi_def_cfa 29, 16 ... the patch additionally saves and restores cur_row->reg_save, which makes sure that the state is restored to the original state, and prevents the maybe_record_trace_start ICE. build & reg-tested on mips64el-linux-gnu. OK for trunk? Thanks, - Tom 2012-01-08 Tom de Vries <t...@codesourcery.com> * dwarf2cfi.c (scan_trace): Save and restore cur_row->reg_save when handling annulled branch.
Index: gcc/dwarf2cfi.c =================================================================== --- gcc/dwarf2cfi.c (revision 182903) +++ gcc/dwarf2cfi.c (working copy) @@ -2439,10 +2439,12 @@ scan_trace (dw_trace_info *trace) if (INSN_FROM_TARGET_P (elt)) { HOST_WIDE_INT restore_args_size; + cfi_vec save_row_reg_save; add_cfi_insn = NULL; restore_args_size = cur_trace->end_true_args_size; cur_cfa = &cur_row->cfa; + save_row_reg_save = VEC_copy (dw_cfi_ref, gc, cur_row->reg_save); scan_insn_after (elt); @@ -2453,6 +2455,7 @@ scan_trace (dw_trace_info *trace) cur_trace->end_true_args_size = restore_args_size; cur_row->cfa = this_cfa; + cur_row->reg_save = save_row_reg_save; cur_cfa = &this_cfa; continue; }