re PR target/8340 (ICE on x86 inline asm w/ -fPIC)
authorKirill Yukhin <kyukhin@gcc.gnu.org>
Mon, 13 Oct 2014 17:26:49 +0000 (17:26 +0000)
committerKirill Yukhin <kyukhin@gcc.gnu.org>
Mon, 13 Oct 2014 17:26:49 +0000 (17:26 +0000)
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

18 files changed:
gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/function.c
gcc/init-regs.c
gcc/ira-color.c
gcc/ira-emit.c
gcc/ira.c
gcc/lra-assigns.c
gcc/lra-constraints.c
gcc/shrink-wrap.c
gcc/target.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pic-1.c
gcc/testsuite/gcc.target/i386/pr23098.c
gcc/testsuite/gcc.target/i386/pr55458.c

index 2ab2046eece7755942628dec66859cdc4f4b7454..66fecb931196e0731d4fa11f623b96d3f41c4b88 100644 (file)
@@ -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):
index 4c4a6eb317d58a8cf935da2174cb133009de71b3..2a64d2d3611ce88901fcf1e2067d2cef426d21f3 100644 (file)
@@ -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
index 63005460783f91fd1e8067f0da7bba79414bec73..61beb6676c52557fbd8ab750768d238c51f806a0 100644 (file)
@@ -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_"
 
index 10af50e1b8bec19ab64a9dcfc9b7e56360695d3f..5036d4fe60d648badebb2230380da19f956d6ede 100644 (file)
@@ -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
index f6f241b5093f0785cba5ae63b6b7c1abf4da694f..5674e6c6b9e84163ad5825b2ec5709107f6018e7 100644 (file)
@@ -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
index 71b5f0de0aa7315c914e62992c121a0d588ebcdb..2becdfb591e49e0f8d1e9533460425eac0a3c402 100644 (file)
@@ -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);
index 91b123d8ef68ac7a7891508dedd6de47cc6c7079..bf83e51aa929544b0f2f43c04a01dfecec965099 100644 (file)
@@ -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
index 841d0d155a936c7778bd0a44ea685bcffc444c10..dffe40a15502b3633206bc0c3906333046c8f22e 100644 (file)
@@ -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))
                {
index a3bf41e984f4282d8c75bae910b13872337db5e4..676ee1acc97f20d542597f9977cc2a99c56143fe 100644 (file)
@@ -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
index d057ea6ddfef0ab1a10165df87c1ec4ebf9fe0e5..6194d3480a4c2b2cb8e6d7934e0e8deca843228e 100644 (file)
--- 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);
 }
 \f
index 6df2d6359228c41c018eaf0d1950eb9b3dd39fb9..7b862a488e6f387a576c3507f07eb7ac207376f4 100644 (file)
@@ -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];
index f1642f3b390cad715c6f765c9f114fc65a60fb24..f90d13be0a38539acd763e0047779f93b36ab7ed 100644 (file)
@@ -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;
index 257812c02fbb66e623e41b0a6ad9ba3bc651d1a4..5f6f27cc7b004ccf59a61a83d19e2abbb24fb8e3 100644 (file)
@@ -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)
index ce11eae444dd413d7ae0f1a80be3bffab04776bb..4d90fc23dcf07d325cbc85c1596ae15de1199f38 100644 (file)
@@ -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
index c1dce8b89a4c7611a9468610094592af92fd3ef5..139ea44dfcbf14012c74d496ea28abe4e94a7ec8 100644 (file)
@@ -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
index af2424b075b2bf284bf6ed338214926b2fa975ac..9b7da4d2e16515a7193df90dc8af6cba946afd88 100644 (file)
@@ -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)
index 66ab0e1222e09257be7f5a329eec177937e9417b..7f118dcfbf6ad8dd31422dce65c63c55f715fdf8 100644 (file)
@@ -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 } */
 
index 81d85ec8f8f7aa3beb328c5870f30ac34f68b11f..7164ca905db279e2f2fd6dbc12f794cef2005825 100644 (file)
@@ -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));
 }