Hi Jeff, Hi Alex, I recently encountered a problem with the REG_SAVE_BYTES macro in the mn10300 backend. When compiling some code in -fPID mode it was producing a different result to the mask computed by mn10300_get_live_callee_saved_regs. The problem turned out to be that the macro was not checking the call_really_saved_regs array. Rather than update the macro, it seemed to me that it would be better to just make this computation in one place - the mn10300_get_live_callee_saved_regs function - and avoid problems like this in the future.
So attached is a patch that does this. Tested with no regressions on an mn10300-elf and an am33_2.0-linux-gnu toolchain. OK to apply ? Cheers Nick gcc/ChangeLog 2012-06-29 Nick Clifton <ni...@redhat.com> * config/mn10300/mn10300.c (REG_SAVE_BYTES): Delete. (mn10300_get_live_callee_saved_regs): If requested return a count of the number of bytes in the mask. (mn10300_expand_prologue): Add argument to invocation of mn10300_get_live_callee_regs. (mn10300_expand_epilogue): Compute reg_save_bytes by calling mn10300_get_live_callee_saved_regs. (mn10300_initial_offset): Likewise. * config/mn10300/mn10300-protos.h (mn10300_get_live_callee_saved_regs): Update prototype. * config/mn10300/mn10300.md (return_ret): Add argument to invocation of mn10300_get_live_callee_saved_regs. Index: gcc/config/mn10300/mn10300.md =================================================================== --- gcc/config/mn10300/mn10300.md (revision 189067) +++ gcc/config/mn10300/mn10300.md (working copy) @@ -2048,7 +2048,7 @@ { /* The RETF insn is up to 3 cycles faster than RET. */ fputs ((mn10300_can_use_retf_insn () ? "\tretf " : "\tret "), asm_out_file); - mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs ()); + mn10300_print_reg_list (asm_out_file, mn10300_get_live_callee_saved_regs (NULL)); fprintf (asm_out_file, ",%d\n", (int) INTVAL (operands[0])); return ""; }) Index: gcc/config/mn10300/mn10300-protos.h =================================================================== --- gcc/config/mn10300/mn10300-protos.h (revision 189067) +++ gcc/config/mn10300/mn10300-protos.h (working copy) @@ -25,7 +25,7 @@ extern rtx mn10300_legitimize_reload_address (rtx, enum machine_mode, int, int, int); extern bool mn10300_function_value_regno_p (const unsigned int); -extern int mn10300_get_live_callee_saved_regs (void); +extern unsigned int mn10300_get_live_callee_saved_regs (unsigned int *); extern bool mn10300_hard_regno_mode_ok (unsigned int, enum machine_mode); extern bool mn10300_modes_tieable (enum machine_mode, enum machine_mode); extern const char *mn10300_output_add (rtx[3], bool); Index: gcc/config/mn10300/mn10300.c =================================================================== --- gcc/config/mn10300/mn10300.c (revision 189067) +++ gcc/config/mn10300/mn10300.c (working copy) @@ -56,18 +56,6 @@ /* Selected processor type for tuning. */ enum processor_type mn10300_tune_cpu = PROCESSOR_DEFAULT; -/* The size of the callee register save area. Right now we save everything - on entry since it costs us nothing in code size. It does cost us from a - speed standpoint, so we want to optimize this sooner or later. */ -#define REG_SAVE_BYTES (4 * df_regs_ever_live_p (2) \ - + 4 * df_regs_ever_live_p (3) \ - + 4 * df_regs_ever_live_p (6) \ - + 4 * df_regs_ever_live_p (7) \ - + 16 * (df_regs_ever_live_p (14) \ - || df_regs_ever_live_p (15) \ - || df_regs_ever_live_p (16) \ - || df_regs_ever_live_p (17))) - #define CC_FLAG_Z 1 #define CC_FLAG_N 2 #define CC_FLAG_C 4 @@ -634,21 +622,36 @@ /* Returns the set of live, callee-saved registers as a bitmask. The callee-saved extended registers cannot be stored individually, so - all of them will be included in the mask if any one of them is used. */ + Also returns the number of bytes in the registers in the mask if + BYTES_SAVED is not NULL. */ -int -mn10300_get_live_callee_saved_regs (void) +unsigned int +mn10300_get_live_callee_saved_regs (unsigned int * bytes_saved) { int mask; int i; + unsigned int count; - mask = 0; + count = mask = 0; for (i = 0; i <= LAST_EXTENDED_REGNUM; i++) if (df_regs_ever_live_p (i) && ! call_really_used_regs[i]) - mask |= (1 << i); + { + mask |= (1 << i); + ++ count; + } + if ((mask & 0x3c000) != 0) - mask |= 0x3c000; + { + for (i = 0x04000; i < 0x40000; i <<= 1) + if ((mask & i) == 0) + ++ count; + + mask |= 0x3c000; + } + if (bytes_saved) + * bytes_saved = count * UNITS_PER_WORD; + return mask; } @@ -741,7 +744,7 @@ HOST_WIDE_INT size = mn10300_frame_size (); /* If we use any of the callee-saved registers, save them now. */ - mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ()); + mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs (NULL)); if (TARGET_AM33_2 && fp_regs_to_save ()) { @@ -998,8 +1001,10 @@ mn10300_expand_epilogue (void) { HOST_WIDE_INT size = mn10300_frame_size (); - int reg_save_bytes = REG_SAVE_BYTES; - + unsigned int reg_save_bytes; + + mn10300_get_live_callee_saved_regs (& reg_save_bytes); + if (TARGET_AM33_2 && fp_regs_to_save ()) { int num_regs_to_save = fp_regs_to_save (), i; @@ -1219,7 +1224,7 @@ if (mn10300_can_use_rets_insn ()) emit_jump_insn (ret_rtx); else - emit_jump_insn (gen_return_ret (GEN_INT (size + REG_SAVE_BYTES))); + emit_jump_insn (gen_return_ret (GEN_INT (size + reg_save_bytes))); } /* Recognize the PARALLEL rtx generated by mn10300_gen_multiple_store(). @@ -1434,7 +1439,10 @@ is the size of the callee register save area. */ if (from == ARG_POINTER_REGNUM) { - diff += REG_SAVE_BYTES; + unsigned int reg_save_bytes; + + mn10300_get_live_callee_saved_regs (& reg_save_bytes); + diff += reg_save_bytes; diff += 4 * fp_regs_to_save (); }