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 <vmaka...@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 <vmaka...@redhat.com> PR middle-end/66334 * gcc.target/i386/pr66334.c: New.
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); +}