diff mbox

patch to fix PR64317

Message ID 54C2AC6E.9090004@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Jan. 23, 2015, 8:17 p.m. UTC
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  <vmakarov@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  <vmakarov@redhat.com>

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

Comments

Richard Sandiford Jan. 31, 2015, 11:33 a.m. UTC | #1
Vladimir Makarov <vmakarov@redhat.com> writes:
>    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.

Sorry for picking on this again, because I realise it isn't
your fault, but it seems unfortunate that the the i386-local macro
REAL_PIC_OFFSET_TABLE_REGNUM is leaking into target-independent code
like this.  c.f. https://gcc.gnu.org/ml/gcc-patches/2014-11/msg03365.html

IMO either REAL_PIC_OFFSET_TABLE_REGNUM should become part of the target
interface, documented in tm.texi and probably with some of the i386.c
handling moved to generic code, or we should abstract away the problem
in LRA somehow, e.g. by a new target hook.

Thanks,
Richard
diff mbox

Patch

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;
+}