The following patch fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64317

The patch was successfully bootstrapped on x86-64 and ppc64 and tested on x86-64.

  Committed as rev.220060.

2015-01-23  Vladimir Makarov  <vmaka...@redhat.com>

        PR target/64317
        * lra-lives.c (make_hard_regno_born): Add parameter.  Don't make
        REAL_PIC_OFFSET_TABLE_REGNUM conflicting with pic offset pseudo.
        (mark_regno_live, process_bb_lives): Pass new parameter value to
        make_hard_regno_born.

2015-01-23  Vladimir Makarov  <vmaka...@redhat.com>

        PR target/64317
        * gcc.target/i386/pr64317.c: New test.


Index: lra-lives.c
===================================================================
--- lra-lives.c (revision 219963)
+++ lra-lives.c (working copy)
@@ -264,10 +264,12 @@ lra_intersected_live_ranges_p (lra_live_
 }
 
 /* The function processing birth of hard register REGNO.  It updates
-   living hard regs, conflict hard regs for living pseudos, and
-   START_LIVING.  */
+   living hard regs, START_LIVING, and conflict hard regs for living
+   pseudos.  Conflict hard regs for the pic pseudo is not updated if
+   REGNO is REAL_PIC_OFFSET_TABLE_REGNUM and CHECK_PIC_PSEUDO_P is
+   true.  */
 static void
-make_hard_regno_born (int regno)
+make_hard_regno_born (int regno, bool check_pic_pseudo_p ATTRIBUTE_UNUSED)
 {
   unsigned int i;
 
@@ -277,7 +279,13 @@ make_hard_regno_born (int regno)
   SET_HARD_REG_BIT (hard_regs_live, regno);
   sparseset_set_bit (start_living, regno);
   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
-    SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
+#ifdef REAL_PIC_OFFSET_TABLE_REGNUM
+    if (! check_pic_pseudo_p
+       || regno != REAL_PIC_OFFSET_TABLE_REGNUM
+       || pic_offset_table_rtx == NULL
+       || i != REGNO (pic_offset_table_rtx))
+#endif
+      SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
 }
 
 /* Process the death of hard register REGNO.  This updates
@@ -352,7 +360,7 @@ mark_regno_live (int regno, machine_mode
       for (last = regno + hard_regno_nregs[regno][mode];
           regno < last;
           regno++)
-       make_hard_regno_born (regno);
+       make_hard_regno_born (regno, false);
     }
   else
     {
@@ -833,7 +841,7 @@ process_bb_lives (basic_block bb, int &c
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
        if (reg->type != OP_IN)
-         make_hard_regno_born (reg->regno);
+         make_hard_regno_born (reg->regno, false);
 
       sparseset_copy (unused_set, start_living);
 
@@ -892,12 +900,13 @@ process_bb_lives (basic_block bb, int &c
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
        if (reg->type == OP_IN)
-         make_hard_regno_born (reg->regno);
+         make_hard_regno_born (reg->regno, false);
 
       if (curr_id->arg_hard_regs != NULL)
-       /* Make argument hard registers live.  */
+       /* Make argument hard registers live.  Don't create conflict
+          of used REAL_PIC_OFFSET_TABLE_REGNUM and the pic pseudo.  */
        for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
-         make_hard_regno_born (regno);
+         make_hard_regno_born (regno, true);
 
       sparseset_and_compl (dead_set, start_living, start_dying);
 
@@ -953,7 +962,7 @@ process_bb_lives (basic_block bb, int &c
 
        if (regno == INVALID_REGNUM)
          break;
-       make_hard_regno_born (regno);
+       make_hard_regno_born (regno, false);
       }
 #endif
 
@@ -968,7 +977,7 @@ process_bb_lives (basic_block bb, int &c
       EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, px)
        lra_reg_info[px].no_stack_p = true;
       for (px = FIRST_STACK_REG; px <= LAST_STACK_REG; px++)
-       make_hard_regno_born (px);
+       make_hard_regno_born (px, false);
 #endif
       /* No need to record conflicts for call clobbered regs if we
         have nonlocal labels around, as we don't ever try to
@@ -976,7 +985,7 @@ process_bb_lives (basic_block bb, int &c
       if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
        for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
          if (call_used_regs[px])
-           make_hard_regno_born (px);
+           make_hard_regno_born (px, false);
     }
 
   bool live_change_p = false;
Index: testsuite/gcc.target/i386/pr64317.c
===================================================================
--- testsuite/gcc.target/i386/pr64317.c (revision 0)
+++ testsuite/gcc.target/i386/pr64317.c (working copy)
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2 -fPIE -pie" } */
+/* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" 
} } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOT\[(\]%ebx\[)\]" } } */
+/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" 
} } */
+long c;
+
+int bar();
+
+int foo (unsigned int iters)
+{
+  unsigned int i;
+  
+  int res = 0;
+  static long t1;
+  
+  for (i = 0; i < iters; i++)
+    {
+      res = bar();
+      t1 = c + res;
+    }
+  
+  return t1 + res;
+}

Reply via email to