From bcb21886b9ea0c3836e401b75e0b8304b38aed2f Mon Sep 17 00:00:00 2001 From: Kirill Yukhin Date: Mon, 13 Oct 2014 17:26:49 +0000 Subject: [PATCH] re PR target/8340 (ICE on x86 inline asm w/ -fPIC) gcc/ PR target/8340 PR middle-end/47602 PR rtl-optimization/55458 * config/i386/i386.c (ix86_use_pseudo_pic_reg): New. (ix86_init_pic_reg): New. (ix86_select_alt_pic_regnum): Add check on pseudo register. (ix86_save_reg): Likewise. (ix86_expand_prologue): Remove PIC register initialization now performed in ix86_init_pic_reg. (ix86_output_function_epilogue): Add check on pseudo register. (set_pic_reg_ever_alive): New. (legitimize_pic_address): Replace df_set_regs_ever_live with new set_pic_reg_ever_alive. (legitimize_tls_address): Likewise. (ix86_pic_register_p): New check. (ix86_delegitimize_address): Add check on pseudo register. (ix86_expand_call): Insert move from pseudo PIC register to ABI defined REAL_PIC_OFFSET_TABLE_REGNUM. (TARGET_INIT_PIC_REG): New. (TARGET_USE_PSEUDO_PIC_REG): New. * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Return INVALID_REGNUM if pic_offset_table_rtx exists. * doc/tm.texi.in (TARGET_USE_PSEUDO_PIC_REG, TARGET_INIT_PIC_REG): Document. * doc/tm.texi: Regenerate. * function.c (assign_parms): Generate pseudo register for PIC. * init-regs.c (initialize_uninitialized_regs): Ignor pseudo PIC register. * ira-color.c (color_pass): Add check on pseudo register. * ira-emit.c (change_loop): Don't create copies for PIC pseudo register. * ira.c (split_live_ranges_for_shrink_wrap): Add check on pseudo register. (ira): Add target specific PIC register initialization. (do_reload): Keep PIC pseudo register. * lra-assigns.c (spill_for): Add checks on pseudo register. * lra-constraints.c (contains_symbol_ref_p): New. (lra_constraints): Enable lra risky transformations when PIC is pseudo register. * shrink-wrap.c (try_shrink_wrapping): Add check on pseudo register. * target.def (use_pseudo_pic_reg): New. (init_pic_reg): New. gcc/testsuite/ PR target/8340 PR middle-end/47602 PR rtl-optimization/55458 * gcc.target/i386/pic-1.c: Remove dg-error as test should pass now. * gcc.target/i386/pr55458.c: Likewise. * gcc.target/i386/pr47602.c: New. * gcc.target/i386/pr23098.c: Move to XFAIL. From-SVN: r216154 --- gcc/ChangeLog | 46 +++++++ gcc/config/i386/i386.c | 169 ++++++++++++++---------- gcc/config/i386/i386.h | 14 +- gcc/doc/tm.texi | 10 ++ gcc/doc/tm.texi.in | 4 + gcc/function.c | 5 + gcc/init-regs.c | 5 + gcc/ira-color.c | 8 +- gcc/ira-emit.c | 5 +- gcc/ira.c | 16 ++- gcc/lra-assigns.c | 20 ++- gcc/lra-constraints.c | 42 +++++- gcc/shrink-wrap.c | 3 +- gcc/target.def | 14 ++ gcc/testsuite/ChangeLog | 10 ++ gcc/testsuite/gcc.target/i386/pic-1.c | 4 +- gcc/testsuite/gcc.target/i386/pr23098.c | 2 +- gcc/testsuite/gcc.target/i386/pr55458.c | 4 +- 18 files changed, 289 insertions(+), 92 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ab2046eece..66fecb93119 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,49 @@ +2014-10-13 Ilya Enkovich + Vladimir Makarov + + PR target/8340 + PR middle-end/47602 + PR rtl-optimization/55458 + * config/i386/i386.c (ix86_use_pseudo_pic_reg): New. + (ix86_init_pic_reg): New. + (ix86_select_alt_pic_regnum): Add check on pseudo register. + (ix86_save_reg): Likewise. + (ix86_expand_prologue): Remove PIC register initialization + now performed in ix86_init_pic_reg. + (ix86_output_function_epilogue): Add check on pseudo register. + (set_pic_reg_ever_alive): New. + (legitimize_pic_address): Replace df_set_regs_ever_live with new + set_pic_reg_ever_alive. + (legitimize_tls_address): Likewise. + (ix86_pic_register_p): New check. + (ix86_delegitimize_address): Add check on pseudo register. + (ix86_expand_call): Insert move from pseudo PIC register to ABI + defined REAL_PIC_OFFSET_TABLE_REGNUM. + (TARGET_INIT_PIC_REG): New. + (TARGET_USE_PSEUDO_PIC_REG): New. + * config/i386/i386.h (PIC_OFFSET_TABLE_REGNUM): Return INVALID_REGNUM + if pic_offset_table_rtx exists. + * doc/tm.texi.in (TARGET_USE_PSEUDO_PIC_REG, TARGET_INIT_PIC_REG): + Document. + * doc/tm.texi: Regenerate. + * function.c (assign_parms): Generate pseudo register for PIC. + * init-regs.c (initialize_uninitialized_regs): Ignor pseudo PIC + register. + * ira-color.c (color_pass): Add check on pseudo register. + * ira-emit.c (change_loop): Don't create copies for PIC pseudo + register. + * ira.c (split_live_ranges_for_shrink_wrap): Add check on pseudo + register. + (ira): Add target specific PIC register initialization. + (do_reload): Keep PIC pseudo register. + * lra-assigns.c (spill_for): Add checks on pseudo register. + * lra-constraints.c (contains_symbol_ref_p): New. + (lra_constraints): Enable lra risky transformations when PIC is pseudo + register. + * shrink-wrap.c (try_shrink_wrapping): Add check on pseudo register. + * target.def (use_pseudo_pic_reg): New. + (init_pic_reg): New. + 2014-10-13 Evgeny Stupachenko * config/i386/x86-tune.def (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY): diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4c4a6eb317d..2a64d2d3611 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -6141,6 +6141,68 @@ ix86_maybe_switch_abi (void) reinit_regs (); } +/* Return 1 if pseudo register should be created and used to hold + GOT address for PIC code. */ +static bool +ix86_use_pseudo_pic_reg (void) +{ + if ((TARGET_64BIT + && (ix86_cmodel == CM_SMALL_PIC + || TARGET_PECOFF)) + || !flag_pic) + return false; + return true; +} + +/* Create and initialize PIC register if required. */ +static void +ix86_init_pic_reg (void) +{ + edge entry_edge; + rtx_insn *seq; + + if (!ix86_use_pseudo_pic_reg ()) + return; + + start_sequence (); + + if (TARGET_64BIT) + { + if (ix86_cmodel == CM_LARGE_PIC) + { + rtx_code_label *label; + rtx tmp_reg; + + gcc_assert (Pmode == DImode); + label = gen_label_rtx (); + emit_label (label); + LABEL_PRESERVE_P (label) = 1; + tmp_reg = gen_rtx_REG (Pmode, R11_REG); + gcc_assert (REGNO (pic_offset_table_rtx) != REGNO (tmp_reg)); + emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx, + label)); + emit_insn (gen_set_got_offset_rex64 (tmp_reg, label)); + emit_insn (ix86_gen_add3 (pic_offset_table_rtx, + pic_offset_table_rtx, tmp_reg)); + } + else + emit_insn (gen_set_got_rex64 (pic_offset_table_rtx)); + } + else + { + rtx insn = emit_insn (gen_set_got (pic_offset_table_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL_RTX); + } + + seq = get_insns (); + end_sequence (); + + entry_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + insert_insn_on_edge (seq, entry_edge); + commit_one_edge_insertion (entry_edge); +} + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ @@ -9383,6 +9445,9 @@ gen_pop (rtx arg) static unsigned int ix86_select_alt_pic_regnum (void) { + if (ix86_use_pseudo_pic_reg ()) + return INVALID_REGNUM; + if (crtl->is_leaf && !crtl->profile && !ix86_current_function_calls_tls_descriptor) @@ -9407,6 +9472,7 @@ static bool ix86_save_reg (unsigned int regno, bool maybe_eh_return) { if (pic_offset_table_rtx + && !ix86_use_pseudo_pic_reg () && regno == REAL_PIC_OFFSET_TABLE_REGNUM && (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM) || crtl->profile @@ -10759,7 +10825,6 @@ ix86_expand_prologue (void) { struct machine_function *m = cfun->machine; rtx insn, t; - bool pic_reg_used; struct ix86_frame frame; HOST_WIDE_INT allocate; bool int_registers_saved; @@ -11206,60 +11271,6 @@ ix86_expand_prologue (void) if (!sse_registers_saved) ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset); - pic_reg_used = false; - /* We don't use pic-register for pe-coff target. */ - if (pic_offset_table_rtx - && !TARGET_PECOFF - && (df_regs_ever_live_p (REAL_PIC_OFFSET_TABLE_REGNUM) - || crtl->profile)) - { - unsigned int alt_pic_reg_used = ix86_select_alt_pic_regnum (); - - if (alt_pic_reg_used != INVALID_REGNUM) - SET_REGNO (pic_offset_table_rtx, alt_pic_reg_used); - - pic_reg_used = true; - } - - if (pic_reg_used) - { - if (TARGET_64BIT) - { - if (ix86_cmodel == CM_LARGE_PIC) - { - rtx_code_label *label; - rtx tmp_reg; - - gcc_assert (Pmode == DImode); - label = gen_label_rtx (); - emit_label (label); - LABEL_PRESERVE_P (label) = 1; - tmp_reg = gen_rtx_REG (Pmode, R11_REG); - gcc_assert (REGNO (pic_offset_table_rtx) != REGNO (tmp_reg)); - insn = emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx, - label)); - insn = emit_insn (gen_set_got_offset_rex64 (tmp_reg, label)); - insn = emit_insn (ix86_gen_add3 (pic_offset_table_rtx, - pic_offset_table_rtx, tmp_reg)); - } - else - insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx)); - } - else - { - insn = emit_insn (gen_set_got (pic_offset_table_rtx)); - RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL_RTX); - } - } - - /* In the pic_reg_used case, make sure that the got load isn't deleted - when mcount needs it. Blockage to avoid call movement across mcount - call is emitted in generic code after the NOTE_INSN_PROLOGUE_END - note. */ - if (crtl->profile && !flag_fentry && pic_reg_used) - emit_insn (gen_prologue_use (pic_offset_table_rtx)); - if (crtl->drap_reg && !crtl->stack_realign_needed) { /* vDRAP is setup but after reload it turns out stack realign @@ -11800,7 +11811,8 @@ ix86_expand_epilogue (int style) static void ix86_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, HOST_WIDE_INT) { - if (pic_offset_table_rtx) + if (pic_offset_table_rtx + && !ix86_use_pseudo_pic_reg ()) SET_REGNO (pic_offset_table_rtx, REAL_PIC_OFFSET_TABLE_REGNUM); #if TARGET_MACHO /* Mach-O doesn't support labels at the end of objects, so if @@ -13120,6 +13132,15 @@ ix86_GOT_alias_set (void) return set; } +/* Set regs_ever_live for PIC base address register + to true if required. */ +static void +set_pic_reg_ever_live () +{ + if (reload_in_progress) + df_set_regs_ever_live (REGNO (pic_offset_table_rtx), true); +} + /* Return a legitimate reference for ORIG (an address) using the register REG. If REG is 0, a new pseudo is generated. @@ -13170,8 +13191,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* This symbol may be referenced via a displacement from the PIC base address (@GOTOFF). */ - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + set_pic_reg_ever_live (); if (GET_CODE (addr) == CONST) addr = XEXP (addr, 0); if (GET_CODE (addr) == PLUS) @@ -13203,8 +13223,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* This symbol may be referenced via a displacement from the PIC base address (@GOTOFF). */ - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + set_pic_reg_ever_live (); if (GET_CODE (addr) == CONST) addr = XEXP (addr, 0); if (GET_CODE (addr) == PLUS) @@ -13265,8 +13284,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* This symbol must be referenced via a load from the Global Offset Table (@GOT). */ - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + set_pic_reg_ever_live (); new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT); new_rtx = gen_rtx_CONST (Pmode, new_rtx); if (TARGET_64BIT) @@ -13318,8 +13336,7 @@ legitimize_pic_address (rtx orig, rtx reg) { if (!TARGET_64BIT) { - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + set_pic_reg_ever_live (); new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), UNSPEC_GOTOFF); new_rtx = gen_rtx_PLUS (Pmode, new_rtx, op1); @@ -13615,8 +13632,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) } else if (flag_pic) { - if (reload_in_progress) - df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true); + set_pic_reg_ever_live (); pic = pic_offset_table_rtx; type = TARGET_ANY_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF; } @@ -14247,6 +14263,8 @@ ix86_pic_register_p (rtx x) if (GET_CODE (x) == VALUE && CSELIB_VAL_PTR (x)) return (pic_offset_table_rtx && rtx_equal_for_cselib_p (x, pic_offset_table_rtx)); + else if (pic_offset_table_rtx) + return REG_P (x) && REGNO (x) == REGNO (pic_offset_table_rtx); else return REG_P (x) && REGNO (x) == PIC_OFFSET_TABLE_REGNUM; } @@ -14421,8 +14439,12 @@ ix86_delegitimize_address (rtx x) leal (%ebx, %ecx, 4), %ecx ... movl foo@GOTOFF(%ecx), %edx - in which case we return (%ecx - %ebx) + foo. */ - if (pic_offset_table_rtx) + in which case we return (%ecx - %ebx) + foo. + + Note that when pseudo_pic_reg is used we can generate it only + before reload_completed. */ + if (pic_offset_table_rtx + && (!reload_completed || !ix86_use_pseudo_pic_reg ())) result = gen_rtx_PLUS (Pmode, gen_rtx_MINUS (Pmode, copy_rtx (addend), pic_offset_table_rtx), result); @@ -24899,7 +24921,12 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, && DEFAULT_ABI != MS_ABI)) && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0))) - use_reg (&use, pic_offset_table_rtx); + { + use_reg (&use, gen_rtx_REG (Pmode, REAL_PIC_OFFSET_TABLE_REGNUM)); + if (ix86_use_pseudo_pic_reg ()) + emit_move_insn (gen_rtx_REG (Pmode, REAL_PIC_OFFSET_TABLE_REGNUM), + pic_offset_table_rtx); + } } if (TARGET_64BIT && INTVAL (callarg2) >= 0) @@ -47413,6 +47440,10 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #define TARGET_FUNCTION_ARG_ADVANCE ix86_function_arg_advance #undef TARGET_FUNCTION_ARG #define TARGET_FUNCTION_ARG ix86_function_arg +#undef TARGET_INIT_PIC_REG +#define TARGET_INIT_PIC_REG ix86_init_pic_reg +#undef TARGET_USE_PSEUDO_PIC_REG +#define TARGET_USE_PSEUDO_PIC_REG ix86_use_pseudo_pic_reg #undef TARGET_FUNCTION_ARG_BOUNDARY #define TARGET_FUNCTION_ARG_BOUNDARY ix86_function_arg_boundary #undef TARGET_PASS_BY_REFERENCE diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 63005460783..61beb6676c5 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1233,12 +1233,14 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define REAL_PIC_OFFSET_TABLE_REGNUM BX_REG -#define PIC_OFFSET_TABLE_REGNUM \ - ((TARGET_64BIT && (ix86_cmodel == CM_SMALL_PIC \ - || TARGET_PECOFF)) \ - || !flag_pic ? INVALID_REGNUM \ - : reload_completed ? REGNO (pic_offset_table_rtx) \ - : REAL_PIC_OFFSET_TABLE_REGNUM) +#define PIC_OFFSET_TABLE_REGNUM \ + ((TARGET_64BIT && (ix86_cmodel == CM_SMALL_PIC \ + || TARGET_PECOFF)) \ + || !flag_pic \ + ? INVALID_REGNUM \ + : pic_offset_table_rtx \ + ? INVALID_REGNUM \ + : REAL_PIC_OFFSET_TABLE_REGNUM) #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 10af50e1b8b..5036d4fe60d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3902,6 +3902,16 @@ If @code{TARGET_FUNCTION_INCOMING_ARG} is not defined, @code{TARGET_FUNCTION_ARG} serves both purposes. @end deftypefn +@deftypefn {Target Hook} bool TARGET_USE_PSEUDO_PIC_REG (void) +This hook should return 1 in case pseudo register should be created +for pic_offset_table_rtx during function expand. +@end deftypefn + +@deftypefn {Target Hook} void TARGET_INIT_PIC_REG (void) +Perform a target dependent initialization of pic_offset_table_rtx. +This hook is called at the start of register allocation. +@end deftypefn + @deftypefn {Target Hook} int TARGET_ARG_PARTIAL_BYTES (cumulative_args_t @var{cum}, enum machine_mode @var{mode}, tree @var{type}, bool @var{named}) This target hook returns the number of bytes at the beginning of an argument that must be put in registers. The value must be zero for diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f6f241b5093..5674e6c6b9e 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3348,6 +3348,10 @@ the stack. @hook TARGET_FUNCTION_INCOMING_ARG +@hook TARGET_USE_PSEUDO_PIC_REG + +@hook TARGET_INIT_PIC_REG + @hook TARGET_ARG_PARTIAL_BYTES @hook TARGET_PASS_BY_REFERENCE diff --git a/gcc/function.c b/gcc/function.c index 71b5f0de0aa..2becdfb591e 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3453,6 +3453,11 @@ assign_parms (tree fndecl) fnargs.release (); + /* Initialize pic_offset_table_rtx with a pseudo register + if required. */ + if (targetm.use_pseudo_pic_reg ()) + pic_offset_table_rtx = gen_reg_rtx (Pmode); + /* Output all parameter conversion instructions (possibly including calls) now that all parameters have been copied out of hard registers. */ emit_insn (all.first_conversion_insn); diff --git a/gcc/init-regs.c b/gcc/init-regs.c index 91b123d8ef6..bf83e51aa92 100644 --- a/gcc/init-regs.c +++ b/gcc/init-regs.c @@ -80,6 +80,11 @@ initialize_uninitialized_regs (void) if (regno < FIRST_PSEUDO_REGISTER) continue; + /* Ignore pseudo PIC register. */ + if (pic_offset_table_rtx + && regno == REGNO (pic_offset_table_rtx)) + continue; + /* Do not generate multiple moves for the same regno. This is common for sequences of subreg operations. They would be deleted during combine but there is no diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 841d0d155a9..dffe40a1550 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -3245,9 +3245,11 @@ color_pass (ira_loop_tree_node_t loop_tree_node) ira_assert (ALLOCNO_CLASS (subloop_allocno) == rclass); ira_assert (bitmap_bit_p (subloop_node->all_allocnos, ALLOCNO_NUM (subloop_allocno))); - if ((flag_ira_region == IRA_REGION_MIXED) - && (loop_tree_node->reg_pressure[pclass] - <= ira_class_hard_regs_num[pclass])) + if ((flag_ira_region == IRA_REGION_MIXED + && (loop_tree_node->reg_pressure[pclass] + <= ira_class_hard_regs_num[pclass])) + || (pic_offset_table_rtx != NULL + && regno == (int) REGNO (pic_offset_table_rtx))) { if (! ALLOCNO_ASSIGNED_P (subloop_allocno)) { diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index a3bf41e984f..676ee1acc97 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -620,7 +620,10 @@ change_loop (ira_loop_tree_node_t node) /* don't create copies because reload can spill an allocno set by copy although the allocno will not get memory slot. */ - || ira_equiv_no_lvalue_p (regno))) + || ira_equiv_no_lvalue_p (regno) + || (pic_offset_table_rtx != NULL + && (ALLOCNO_REGNO (allocno) + == (int) REGNO (pic_offset_table_rtx))))) continue; original_reg = allocno_emit_reg (allocno); if (parent_allocno == NULL diff --git a/gcc/ira.c b/gcc/ira.c index d057ea6ddfe..6194d3480a4 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -4896,7 +4896,7 @@ split_live_ranges_for_shrink_wrap (void) FOR_BB_INSNS (first, insn) { rtx dest = interesting_dest_for_shprep (insn, call_dom); - if (!dest) + if (!dest || dest == pic_offset_table_rtx) continue; rtx newreg = NULL_RTX; @@ -5048,6 +5048,9 @@ ira (FILE *f) bool saved_flag_caller_saves = flag_caller_saves; enum ira_region saved_flag_ira_region = flag_ira_region; + /* Perform target specific PIC register initialization. */ + targetm.init_pic_reg (); + ira_conflicts_p = optimize > 0; ira_use_lra_p = targetm.lra_p (); @@ -5299,10 +5302,18 @@ do_reload (void) { basic_block bb; bool need_dce; + unsigned pic_offset_table_regno = INVALID_REGNUM; if (flag_ira_verbose < 10) ira_dump_file = dump_file; + /* If pic_offset_table_rtx is a pseudo register, then keep it so + after reload to avoid possible wrong usages of hard reg assigned + to it. */ + if (pic_offset_table_rtx + && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) + pic_offset_table_regno = REGNO (pic_offset_table_rtx); + timevar_push (TV_RELOAD); if (ira_use_lra_p) { @@ -5407,6 +5418,9 @@ do_reload (void) inform (DECL_SOURCE_LOCATION (decl), "for %qD", decl); } + if (pic_offset_table_regno != INVALID_REGNUM) + pic_offset_table_rtx = gen_rtx_REG (Pmode, pic_offset_table_regno); + timevar_pop (TV_IRA); } diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c index 6df2d635922..7b862a488e6 100644 --- a/gcc/lra-assigns.c +++ b/gcc/lra-assigns.c @@ -879,11 +879,13 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p) } /* Spill pseudos. */ EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi) - if ((int) spill_regno >= lra_constraint_new_regno_start - && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) - && ! bitmap_bit_p (&lra_split_regs, spill_regno) - && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) - && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)) + if ((pic_offset_table_rtx != NULL + && spill_regno == REGNO (pic_offset_table_rtx)) + || ((int) spill_regno >= lra_constraint_new_regno_start + && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno) + && ! bitmap_bit_p (&lra_split_regs, spill_regno) + && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno) + && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))) goto fail; insn_pseudos_num = 0; if (lra_dump_file != NULL) @@ -1053,9 +1055,15 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap return; } for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) - if (reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0) + if ((pic_offset_table_rtx == NULL_RTX + || i != (int) REGNO (pic_offset_table_rtx)) + && reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0) sorted_pseudos[n++] = i; qsort (sorted_pseudos, n, sizeof (int), pseudo_compare_func); + if (pic_offset_table_rtx != NULL_RTX + && (regno = REGNO (pic_offset_table_rtx)) >= FIRST_PSEUDO_REGISTER + && reg_renumber[regno] >= 0 && lra_reg_info[regno].nrefs > 0) + sorted_pseudos[n++] = regno; for (i = n - 1; i >= 0; i--) { regno = sorted_pseudos[i]; diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index f1642f3b390..f90d13be0a3 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -3798,6 +3798,35 @@ contains_reg_p (rtx x, bool hard_reg_p, bool spilled_p) return false; } +/* Return true if X contains a symbol reg. */ +static bool +contains_symbol_ref_p (rtx x) +{ + int i, j; + const char *fmt; + enum rtx_code code; + + code = GET_CODE (x); + if (code == SYMBOL_REF) + return true; + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + { + if (contains_symbol_ref_p (XEXP (x, i))) + return true; + } + else if (fmt[i] == 'E') + { + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + if (contains_symbol_ref_p (XVECEXP (x, i, j))) + return true; + } + } + return false; +} + /* Process all regs in location *LOC and change them on equivalent substitution. Return true if any change was done. */ static bool @@ -4020,7 +4049,11 @@ lra_constraints (bool first_p) ("Maximum number of LRA constraint passes is achieved (%d)\n", LRA_MAX_CONSTRAINT_ITERATION_NUMBER); changed_p = false; - lra_risky_transformations_p = false; + if (pic_offset_table_rtx + && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) + lra_risky_transformations_p = true; + else + lra_risky_transformations_p = false; new_insn_uid_start = get_max_uid (); new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num (); /* Mark used hard regs for target stack size calulations. */ @@ -4088,7 +4121,12 @@ lra_constraints (bool first_p) paradoxical subregs. */ || (MEM_P (x) && (GET_MODE_SIZE (lra_reg_info[i].biggest_mode) - > GET_MODE_SIZE (GET_MODE (x))))) + > GET_MODE_SIZE (GET_MODE (x)))) + || (pic_offset_table_rtx + && ((CONST_POOL_OK_P (PSEUDO_REGNO_MODE (i), x) + && (targetm.preferred_reload_class + (x, lra_get_allocno_class (i)) == NO_REGS)) + || contains_symbol_ref_p (x)))) ira_reg_equiv[i].defined_p = false; if (contains_reg_p (x, false, true)) ira_reg_equiv[i].profitable_p = false; diff --git a/gcc/shrink-wrap.c b/gcc/shrink-wrap.c index 257812c02fb..5f6f27cc7b0 100644 --- a/gcc/shrink-wrap.c +++ b/gcc/shrink-wrap.c @@ -579,7 +579,8 @@ try_shrink_wrapping (edge *entry_edge, edge orig_entry_edge, if (frame_pointer_needed) add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, HARD_FRAME_POINTER_REGNUM); - if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) + if (pic_offset_table_rtx + && (unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, PIC_OFFSET_TABLE_REGNUM); if (crtl->drap_reg) diff --git a/gcc/target.def b/gcc/target.def index ce11eae444d..4d90fc23dcf 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4274,6 +4274,20 @@ DEFHOOK HOOK_VECTOR_END (calls) +DEFHOOK +(use_pseudo_pic_reg, + "This hook should return 1 in case pseudo register should be created\n\ +for pic_offset_table_rtx during function expand.", + bool, (void), + hook_bool_void_false) + +DEFHOOK +(init_pic_reg, + "Perform a target dependent initialization of pic_offset_table_rtx.\n\ +This hook is called at the start of register allocation.", + void, (void), + hook_void_void) + /* Return the diagnostic message string if conversion from FROMTYPE to TOTYPE is not allowed, NULL otherwise. */ DEFHOOK diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c1dce8b89a4..139ea44dfcb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2014-10-13 Evgeny Stupachenko + + PR target/8340 + PR middle-end/47602 + PR rtl-optimization/55458 + * gcc.target/i386/pic-1.c: Remove dg-error as test should pass now. + * gcc.target/i386/pr55458.c: Likewise. + * gcc.target/i386/pr47602.c: New. + * gcc.target/i386/pr23098.c: Move to XFAIL. + 2014-10-13 Jan Hubicka PR tree-optimization/62127 diff --git a/gcc/testsuite/gcc.target/i386/pic-1.c b/gcc/testsuite/gcc.target/i386/pic-1.c index af2424b075b..9b7da4d2e16 100644 --- a/gcc/testsuite/gcc.target/i386/pic-1.c +++ b/gcc/testsuite/gcc.target/i386/pic-1.c @@ -5,11 +5,13 @@ /* { dg-skip-if "No Windows PIC" { *-*-mingw* *-*-cygwin } { "*" } { "" } } */ /* { dg-options "-fPIC" } */ +/* Test verifies that %ebx is no longer fixed when generating PIC code on i686. */ + int foo () { static int a; - __asm__ __volatile__ ( /* { dg-error "PIC register" } */ + __asm__ __volatile__ ( "xorl %%ebx, %%ebx\n" "movl %%ebx, %0\n" : "=m" (a) diff --git a/gcc/testsuite/gcc.target/i386/pr23098.c b/gcc/testsuite/gcc.target/i386/pr23098.c index 66ab0e1222e..7f118dcfbf6 100644 --- a/gcc/testsuite/gcc.target/i386/pr23098.c +++ b/gcc/testsuite/gcc.target/i386/pr23098.c @@ -1,7 +1,7 @@ /* PR rtl-optimization/23098 */ /* { dg-do compile } */ /* { dg-options "-O2 -fPIC" } */ -/* { dg-final { scan-assembler-not "\.LC\[0-9\]" { xfail *-*-vxworks* } } } */ +/* { dg-final { scan-assembler-not "\.LC\[0-9\]" { xfail *-*-* } } } */ /* { dg-require-effective-target ia32 } */ /* { dg-require-effective-target fpic } */ diff --git a/gcc/testsuite/gcc.target/i386/pr55458.c b/gcc/testsuite/gcc.target/i386/pr55458.c index 81d85ec8f8f..7164ca905db 100644 --- a/gcc/testsuite/gcc.target/i386/pr55458.c +++ b/gcc/testsuite/gcc.target/i386/pr55458.c @@ -2,10 +2,12 @@ /* { dg-require-effective-target ia32 } */ /* { dg-options "-fPIC" } */ +/* Test verifies that %ebx is no longer fixed when generating PIC code on i686. */ + int a, b, c; void foo (void) { - asm volatile ("":"+m" (a), "+m" (b), "+m" (c)); /* { dg-error "operand has impossible constraints" } */ + asm volatile ("":"+m" (a), "+m" (b), "+m" (c)); } -- 2.30.2