diff mbox

Patch to fix PR66334

Message ID 559D3E26.8070609@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov July 8, 2015, 3:13 p.m. UTC
The following patch fixes

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

   The patch was bootstrapped and tested on x86/x86-64.

   Committed as rev. 225561.

2015-07-08  Vladimir Makarov  <vmakarov@redhat.com>

         PR middle-end/66334
         * ira-lives.c (process_bb_node_lives): Make conflicts with PIC
         hard regno live at the start of BB with incoming abnormal edges.
         * lra-lives.c (process_bb_lives): Ditto.

2015-07-08  Vladimir Makarov  <vmakarov@redhat.com>

         PR middle-end/66334
         * gcc.target/i386/pr66334.c: New.
diff mbox

Patch

Index: ira-lives.c
===================================================================
--- ira-lives.c	(revision 225559)
+++ ira-lives.c	(working copy)
@@ -1344,7 +1344,21 @@  process_bb_node_lives (ira_loop_tree_nod
 	     allocate such regs in this case.  */
 	  if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
 	    for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
-	      if (call_used_regs[px])
+	      if (call_used_regs[px]
+#ifdef REAL_PIC_OFFSET_TABLE_REGNUM
+		  /* We should create a conflict of PIC pseudo with
+		     PIC hard reg as PIC hard reg can have a wrong
+		     value after jump described by the abnormal edge.
+		     In this case we can not allocate PIC hard reg to
+		     PIC pseudo as PIC pseudo will also have a wrong
+		     value.  This code is not critical as LRA can fix
+		     it but it is better to have the right allocation
+		     earlier.  */
+		  || (px == REAL_PIC_OFFSET_TABLE_REGNUM
+		      && pic_offset_table_rtx != NULL_RTX
+		      && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+#endif
+		  )
 		make_hard_regno_born (px);
 	}
 
Index: lra-lives.c
===================================================================
--- lra-lives.c	(revision 225559)
+++ lra-lives.c	(working copy)
@@ -953,7 +953,18 @@  process_bb_lives (basic_block bb, int &c
 	 allocate such regs in this case.  */
       if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
 	for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
-	  if (call_used_regs[px])
+	  if (call_used_regs[px]
+#ifdef REAL_PIC_OFFSET_TABLE_REGNUM
+	      /* We should create a conflict of PIC pseudo with PIC
+		 hard reg as PIC hard reg can have a wrong value after
+		 jump described by the abnormal edge.  In this case we
+		 can not allocate PIC hard reg to PIC pseudo as PIC
+		 pseudo will also have a wrong value.  */
+	      || (px == REAL_PIC_OFFSET_TABLE_REGNUM
+		  && pic_offset_table_rtx != NULL_RTX
+		  && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+#endif
+	      )
 	    make_hard_regno_born (px, false);
     }
 
Index: testsuite/gcc.target/i386/pr66334.c
===================================================================
--- testsuite/gcc.target/i386/pr66334.c	(revision 0)
+++ testsuite/gcc.target/i386/pr66334.c	(working copy)
@@ -0,0 +1,41 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2 -fpic -fexceptions -fasynchronous-unwind-tables" } */
+/* { dg-final { scan-assembler "movl\[ \\t\].+, %ebx" } } */
+extern int foo (int);
+extern void exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));
+struct __pthread_cleanup_frame
+{
+  void (*__cancel_routine) (void *);
+  void *__cancel_arg;
+  int __do_it;
+  int __cancel_type;
+};
+extern __inline void
+__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
+{
+  if (__frame->__do_it)
+    __frame->__cancel_routine (__frame->__cancel_arg);
+}
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+void *
+tf_usleep (void *arg)
+{
+
+  do { struct __pthread_cleanup_frame __clframe __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) = { .__cancel_routine = (cl), .__cancel_arg = (
+																			 ((void *)0)), .__do_it = 1 };;
+
+    foo (arg == ((void *)0) ? (0x7fffffffL * 2UL + 1UL) : 0);
+
+    __clframe.__do_it = (0); } while (0);
+
+  exit (1);
+}