Hi! crtbegin.o is miscompiled on powerpc64-linux with -mminimal-toc (and likely many other sources). The problem is that when flag_pic is 0, the shrink-wrapping code doesn't consider register r30 being set up by the prologue, so instructions that use r30 (TOC_REGISTER) can be considered usable even without an earlier prologue that computes it. Unfortunately the generic code adds just a couple of selected registers to set_up_by_prologue regset, and I don't see without a target hook a way to add further registers to the hard regset.
So, this patch implements such a hook and uses it on rs6000 to indicate that r30 is computed by the prologue if the prologue does that. Bootstrapped/regtested on powerpc64-linux (with -mminimal-toc in CFLAGS/CXXFLAGS/etc., which previously failed to bootstrap) and on x86_64-linux and i686-linux. Ok for trunk? 2012-01-17 Jakub Jelinek <ja...@redhat.com> PR bootstrap/51872 * hard-reg-set.h (struct hard_reg_set_container): New type. * target.h (struct hard_reg_set_container): Forward declare. * target.def (set_up_by_prologue): New target hook. * doc/tm.texi (TARGET_SET_UP_BY_PROLOGUE): Document it. * function.c (thread_prologue_and_epilogue_insns): Change set_up_by_prologue HARD_REG_SET into struct hard_reg_set_container. Call targetm.set_up_by_prologue on it. * config/rs6000/rs6000.c (rs6000_set_up_by_prologue): New function. (TARGET_SET_UP_BY_PROLOGUE): Redefine to it. --- gcc/hard-reg-set.h.jj 2011-11-28 17:58:04.000000000 +0100 +++ gcc/hard-reg-set.h 2012-01-16 17:27:35.837610779 +0100 @@ -54,6 +54,14 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[H #endif +/* HARD_REG_SET wrapped into a structure, to make it possible to + use HARD_REG_SET even in APIs that should not include + hard-reg-set.h. */ +struct hard_reg_set_container +{ + HARD_REG_SET set; +}; + /* HARD_CONST is used to cast a constant to the appropriate type for use with a HARD_REG_SET. */ --- gcc/target.h.jj 2011-06-17 11:02:19.000000000 +0200 +++ gcc/target.h 2012-01-16 17:28:13.348394331 +0100 @@ -92,6 +92,7 @@ extern bool target_default_pointer_addre struct stdarg_info; struct spec_info_def; +struct hard_reg_set_container; /* The struct used by the secondary_reload target hook. */ typedef struct secondary_reload_info --- gcc/target.def.jj 2011-12-27 11:39:49.000000000 +0100 +++ gcc/target.def 2012-01-16 19:51:00.171464193 +0100 @@ -2644,6 +2644,14 @@ DEFHOOK void, (bitmap regs), hook_void_bitmap) +/* Fill in additional registers set up by prologue into a regset. */ +DEFHOOK +(set_up_by_prologue, + "This hook should add additional registers that are computed by the prologue\ + to the hard regset for shrink-wrapping optimization purposes.", + void, (struct hard_reg_set_container *), + NULL) + /* Determine the type of unwind info to emit for debugging. */ DEFHOOK (debug_unwind_info, --- gcc/doc/tm.texi.jj 2011-12-27 11:39:47.000000000 +0100 +++ gcc/doc/tm.texi 2012-01-16 19:51:59.000000000 +0100 @@ -4959,6 +4959,10 @@ TARGET_STRUCT_VALUE_RTX, FRAME_POINTER_R FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, and the PIC_OFFSET_TABLE_REGNUM. @end deftypefn +@deftypefn {Target Hook} void TARGET_SET_UP_BY_PROLOGUE (struct hard_reg_set_container *@var{}) +This hook should add additional registers that are computed by the prologue to the hard regset for shrink-wrapping optimization purposes. +@end deftypefn + @node Stack Smashing Protection @subsection Stack smashing protection @cindex stack smashing protection --- gcc/doc/tm.texi.in.jj 2011-12-27 11:39:47.000000000 +0100 +++ gcc/doc/tm.texi.in 2012-01-16 19:51:38.531284609 +0100 @@ -4906,6 +4906,8 @@ TARGET_STRUCT_VALUE_RTX, FRAME_POINTER_R FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, and the PIC_OFFSET_TABLE_REGNUM. @end deftypefn +@hook TARGET_SET_UP_BY_PROLOGUE + @node Stack Smashing Protection @subsection Stack smashing protection @cindex stack smashing protection --- gcc/function.c.jj 2012-01-13 21:47:35.000000000 +0100 +++ gcc/function.c 2012-01-16 17:42:49.485331902 +0100 @@ -5899,7 +5899,7 @@ thread_prologue_and_epilogue_insns (void && nonempty_prologue && !crtl->calls_eh_return) { HARD_REG_SET prologue_clobbered, prologue_used, live_on_edge; - HARD_REG_SET set_up_by_prologue; + struct hard_reg_set_container set_up_by_prologue; rtx p_insn; VEC(basic_block, heap) *vec; basic_block bb; @@ -5939,18 +5939,22 @@ thread_prologue_and_epilogue_insns (void vec = VEC_alloc (basic_block, heap, n_basic_blocks); - CLEAR_HARD_REG_SET (set_up_by_prologue); - add_to_hard_reg_set (&set_up_by_prologue, Pmode, STACK_POINTER_REGNUM); - add_to_hard_reg_set (&set_up_by_prologue, Pmode, ARG_POINTER_REGNUM); + CLEAR_HARD_REG_SET (set_up_by_prologue.set); + add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, + STACK_POINTER_REGNUM); + add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, ARG_POINTER_REGNUM); if (frame_pointer_needed) - add_to_hard_reg_set (&set_up_by_prologue, Pmode, + add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, HARD_FRAME_POINTER_REGNUM); if (pic_offset_table_rtx) - add_to_hard_reg_set (&set_up_by_prologue, Pmode, + add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, PIC_OFFSET_TABLE_REGNUM); if (stack_realign_drap && crtl->drap_reg) - add_to_hard_reg_set (&set_up_by_prologue, GET_MODE (crtl->drap_reg), + add_to_hard_reg_set (&set_up_by_prologue.set, + GET_MODE (crtl->drap_reg), REGNO (crtl->drap_reg)); + if (targetm.set_up_by_prologue) + targetm.set_up_by_prologue (&set_up_by_prologue); /* We don't use a different max size depending on optimize_bb_for_speed_p because increasing shrink-wrapping @@ -5968,7 +5972,7 @@ thread_prologue_and_epilogue_insns (void if (NONDEBUG_INSN_P (insn)) { if (requires_stack_frame_p (insn, prologue_used, - set_up_by_prologue)) + set_up_by_prologue.set)) { if (bb == entry_edge->dest) goto fail_shrinkwrap; --- gcc/config/rs6000/rs6000.c.jj 2012-01-13 21:47:35.000000000 +0100 +++ gcc/config/rs6000/rs6000.c 2012-01-16 18:01:04.615010096 +0100 @@ -1227,6 +1227,7 @@ static bool rs6000_cannot_force_const_me static bool rs6000_legitimate_constant_p (enum machine_mode, rtx); static bool rs6000_save_toc_in_prologue_p (void); static void rs6000_code_end (void) ATTRIBUTE_UNUSED; +static void rs6000_set_up_by_prologue (struct hard_reg_set_container *); /* Hash table stuff for keeping track of TOC entries. */ @@ -1392,6 +1393,9 @@ static const struct attribute_spec rs600 #define TARGET_ASM_ASSEMBLE_VISIBILITY rs6000_assemble_visibility #endif +#undef TARGET_SET_UP_BY_PROLOGUE +#define TARGET_SET_UP_BY_PROLOGUE rs6000_set_up_by_prologue + #undef TARGET_HAVE_TLS #define TARGET_HAVE_TLS HAVE_AS_TLS @@ -27903,6 +27907,19 @@ rs6000_code_end (void) current_function_decl = NULL; } +/* Add r30 to hard reg set if the prologue sets it up and it is not + pic_offset_table_rtx. */ + +static void +rs6000_set_up_by_prologue (struct hard_reg_set_container *set) +{ + if (!TARGET_SINGLE_PIC_BASE + && TARGET_TOC + && TARGET_MINIMAL_TOC + && get_pool_size () != 0) + add_to_hard_reg_set (&set->set, Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); +} + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rs6000.h" Jakub