This provides some protection against misuse of r0, r11 and r12. I found it useful when enabling out-of-line saves for large frames. ;-)
* config/rs6000/rs6000.c (START_USE, END_USE, NOT_INUSE): Define. (rs6000_emit_prologue): Use the above to catch register overlap. diff -urp gcc-alan3/gcc/config/rs6000/rs6000.c gcc-alan4/gcc/config/rs6000/rs6000.c --- gcc-alan3/gcc/config/rs6000/rs6000.c 2012-04-17 07:19:42.927931887 +0930 +++ gcc-alan4/gcc/config/rs6000/rs6000.c 2012-04-17 09:11:31.760669589 +0930 @@ -19301,6 +19301,29 @@ rs6000_emit_prologue (void) HOST_WIDE_INT frame_off = 0; HOST_WIDE_INT sp_off = 0; +#ifdef ENABLE_CHECKING + /* Track and check usage of r0, r11, r12. */ + int reg_inuse = using_static_chain_p ? 1 << 11 : 0; +#define START_USE(R) do \ + { \ + gcc_assert ((reg_inuse & (1 << (R))) == 0); \ + reg_inuse |= 1 << (R); \ + } while (0) +#define END_USE(R) do \ + { \ + gcc_assert ((reg_inuse & (1 << (R))) != 0); \ + reg_inuse &= ~(1 << (R)); \ + } while (0) +#define NOT_INUSE(R) do \ + { \ + gcc_assert ((reg_inuse & (1 << (R))) == 0); \ + } while (0) +#else +#define START_USE(R) do {} while (0) +#define END_USE(R) do {} while (0) +#define NOT_INUSE(R) do {} while (0) +#endif + if (flag_stack_usage_info) current_function_static_stack_size = info->total_size; @@ -19465,6 +19488,7 @@ rs6000_emit_prologue (void) if (need_r11) { ptr_reg = gen_rtx_REG (Pmode, 11); + START_USE (11); } else if (info->total_size < 32767) frame_off = info->total_size; @@ -19477,6 +19501,7 @@ rs6000_emit_prologue (void) || crtl->calls_eh_return) { ptr_reg = gen_rtx_REG (Pmode, 12); + START_USE (12); } else { @@ -19509,6 +19534,7 @@ rs6000_emit_prologue (void) rtx addr, reg, mem; reg = gen_rtx_REG (Pmode, 0); + START_USE (0); insn = emit_move_insn (reg, gen_rtx_REG (Pmode, LR_REGNO)); RTX_FRAME_RELATED_P (insn) = 1; @@ -19524,6 +19550,7 @@ rs6000_emit_prologue (void) insn = emit_move_insn (mem, reg); rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off, NULL_RTX, NULL_RTX); + END_USE (0); } } @@ -19536,6 +19563,7 @@ rs6000_emit_prologue (void) rtx set; cr_save_rtx = gen_rtx_REG (SImode, cr_save_regno); + START_USE (cr_save_regno); insn = emit_insn (gen_movesi_from_cr (cr_save_rtx)); RTX_FRAME_RELATED_P (insn) = 1; /* Now, there's no way that dwarf2out_frame_debug_expr is going @@ -19579,6 +19607,8 @@ rs6000_emit_prologue (void) /*savep=*/true, /*gpr=*/false, lr); rs6000_frame_related (insn, frame_reg_rtx, sp_off, NULL_RTX, NULL_RTX); + if (lr) + END_USE (0); } /* Save GPRs. This is done as a PARALLEL if we are using @@ -19623,10 +19653,15 @@ rs6000_emit_prologue (void) if (using_static_chain_p) { rtx r0 = gen_rtx_REG (Pmode, 0); + + START_USE (0); gcc_assert (info->first_gp_reg_save > 11); emit_move_insn (r0, spe_save_area_ptr); } + else if (REGNO (frame_reg_rtx) != 11) + START_USE (11); + emit_insn (gen_addsi3 (spe_save_area_ptr, frame_reg_rtx, GEN_INT (offset))); if (!using_static_chain_p && REGNO (frame_reg_rtx) == 11) @@ -19657,8 +19692,16 @@ rs6000_emit_prologue (void) } /* Move the static chain pointer back. */ - if (using_static_chain_p && !spe_regs_addressable) - emit_move_insn (spe_save_area_ptr, gen_rtx_REG (Pmode, 0)); + if (!spe_regs_addressable) + { + if (using_static_chain_p) + { + emit_move_insn (spe_save_area_ptr, gen_rtx_REG (Pmode, 0)); + END_USE (0); + } + else if (REGNO (frame_reg_rtx) != 11) + END_USE (11); + } } else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline) { @@ -19679,10 +19722,13 @@ rs6000_emit_prologue (void) if (ptr_set_up) frame_off = -end_save; + else + NOT_INUSE (ptr_regno); emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset)); } else if (!ptr_set_up) { + NOT_INUSE (ptr_regno); emit_move_insn (ptr_reg, frame_reg_rtx); } ptr_off = -end_save; @@ -19693,6 +19739,8 @@ rs6000_emit_prologue (void) /*savep=*/true, /*gpr=*/true, lr); rs6000_frame_related (insn, ptr_reg, sp_off - ptr_off, NULL_RTX, NULL_RTX); + if (lr) + END_USE (0); } else if (!WORLD_SAVE_P (info) && using_store_multiple) { @@ -19751,12 +19799,15 @@ rs6000_emit_prologue (void) rtx save_insn, join_insn, note; long toc_restore_insn; - gcc_assert (REGNO (frame_reg_rtx) != 11); tmp_reg = gen_rtx_REG (Pmode, 11); tmp_reg_si = gen_rtx_REG (SImode, 11); if (using_static_chain_p) - emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg); - gcc_assert (saving_GPRs_inline && saving_FPRs_inline); + { + START_USE (0); + emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg); + } + else + START_USE (11); emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO)); /* Peek at instruction to which this function returns. If it's restoring r2, then we know we've already saved r2. We can't @@ -19809,7 +19860,12 @@ rs6000_emit_prologue (void) RTX_FRAME_RELATED_P (join_insn) = 1; if (using_static_chain_p) - emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0)); + { + emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0)); + END_USE (0); + } + else + END_USE (11); } /* Save CR if we use any that must be preserved. */ @@ -19826,6 +19882,7 @@ rs6000_emit_prologue (void) { rtx set; + START_USE (0); cr_save_rtx = gen_rtx_REG (SImode, 0); insn = emit_insn (gen_movesi_from_cr (cr_save_rtx)); RTX_FRAME_RELATED_P (insn) = 1; @@ -19833,6 +19890,7 @@ rs6000_emit_prologue (void) add_reg_note (insn, REG_FRAME_RELATED_EXPR, set); } insn = emit_move_insn (mem, cr_save_rtx); + END_USE (REGNO (cr_save_rtx)); rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off, NULL_RTX, NULL_RTX); @@ -19854,6 +19912,7 @@ rs6000_emit_prologue (void) && (info->vrsave_save_offset + info->total_size - frame_off) > 32767)) { + START_USE (12); ptr_reg = gen_rtx_REG (Pmode, 12); frame_reg_rtx = ptr_reg; frame_off = -(info->altivec_save_offset + info->altivec_size); @@ -19893,6 +19952,7 @@ rs6000_emit_prologue (void) savereg = gen_rtx_REG (V4SImode, i); + NOT_INUSE (0); areg = gen_rtx_REG (Pmode, 0); emit_move_insn (areg, GEN_INT (offset)); @@ -19925,6 +19985,7 @@ rs6000_emit_prologue (void) /* Get VRSAVE onto a GPR. Note that ABI_V4 might be using r12 as frame_reg_rtx and r11 as the static chain pointer for nested functions. */ + NOT_INUSE (0); reg = gen_rtx_REG (SImode, 0); vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO); if (TARGET_MACHO) -- Alan Modra Australia Development Lab, IBM