summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkyukhin <kyukhin@138bc75d-0d04-0410-961f-82ee72b054a4>2014-10-13 17:26:49 +0000
committerkyukhin <kyukhin@138bc75d-0d04-0410-961f-82ee72b054a4>2014-10-13 17:26:49 +0000
commita9d8ab3820ccd10d2ac547295dadf75a33077f14 (patch)
tree6c2ee30ea96f8dde643e082a6ab50870b1a8de9e
parentec4bcc2244e0eb7825cf9de7b09bc967ba6c2741 (diff)
downloadgcc-a9d8ab3820ccd10d2ac547295dadf75a33077f14.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@216154 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog46
-rw-r--r--gcc/config/i386/i386.c169
-rw-r--r--gcc/config/i386/i386.h14
-rw-r--r--gcc/doc/tm.texi10
-rw-r--r--gcc/doc/tm.texi.in4
-rw-r--r--gcc/function.c5
-rw-r--r--gcc/init-regs.c5
-rw-r--r--gcc/ira-color.c8
-rw-r--r--gcc/ira-emit.c5
-rw-r--r--gcc/ira.c16
-rw-r--r--gcc/lra-assigns.c20
-rw-r--r--gcc/lra-constraints.c42
-rw-r--r--gcc/shrink-wrap.c3
-rw-r--r--gcc/target.def14
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.target/i386/pic-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr23098.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55458.c4
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 <ilya.enkovich@intel.com>
+ Vladimir Makarov <vmakarov@redhat.com>
+
+ 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 <evstupac@gmail.com>
* 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 <evstupac@gmail.com>
+
+ 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 <hubicka@ucw.cz>
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));
}