+2014-10-22 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/63542
+ * config/i386/i386.c (ix86_pic_register_p): Also return
+ true if x is a hard register with ORIGINAL_REGNO equal to
+ pic_offset_table_rtx pseudo REGNO.
+ (ix86_delegitimize_address): For ix86_use_pseudo_pic_reg ()
+ after reload, subtract GOT_SYMBOL_NAME symbol if possible.
+
2014-10-22 Alan Modra <amodra@gmail.com>
* gengtype.h (obstack_chunk_alloc, obstack_chunk_free): Remove cast.
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 (!REG_P (x))
+ return false;
else if (pic_offset_table_rtx)
- return REG_P (x) && REGNO (x) == REGNO (pic_offset_table_rtx);
+ {
+ if (REGNO (x) == REGNO (pic_offset_table_rtx))
+ return true;
+ if (HARD_REGISTER_P (x)
+ && !HARD_REGISTER_P (pic_offset_table_rtx)
+ && ORIGINAL_REGNO (x) == REGNO (pic_offset_table_rtx))
+ return true;
+ return false;
+ }
else
- return REG_P (x) && REGNO (x) == PIC_OFFSET_TABLE_REGNUM;
+ return REGNO (x) == PIC_OFFSET_TABLE_REGNUM;
}
/* Helper function for ix86_delegitimize_address.
leal (%ebx, %ecx, 4), %ecx
...
movl foo@GOTOFF(%ecx), %edx
- in which case we return (%ecx - %ebx) + foo.
-
- Note that when pseudo_pic_reg is used we can generate it only
- before reload_completed. */
+ in which case we return (%ecx - %ebx) + foo
+ or (%ecx - _GLOBAL_OFFSET_TABLE_) + foo if pseudo_pic_reg
+ and reload has 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);
+ else if (pic_offset_table_rtx && !TARGET_MACHO && !TARGET_VXWORKS_RTP)
+ {
+ rtx tmp = gen_rtx_SYMBOL_REF (Pmode, GOT_SYMBOL_NAME);
+ tmp = gen_rtx_MINUS (Pmode, copy_rtx (addend), tmp);
+ result = gen_rtx_PLUS (Pmode, tmp, result);
+ }
else
return orig_x;
}
--- /dev/null
+/* PR target/63542 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -dA" } */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+float
+foo (long long u)
+{
+ if (!(-(1LL << 53) < u && u < (1LL << 53)))
+ {
+ if ((unsigned long long) u & ((1ULL << 11) - 1))
+ {
+ u &= ~((1ULL << 11) - 1);
+ u |= (1ULL << 11);
+ }
+ }
+ double f = (int) (u >> (32));
+ f *= 0x1p32f;
+ f += (unsigned int) u;
+ return (float) f;
+}
--- /dev/null
+/* PR target/63542 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -dA" } */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+struct B { unsigned long c; unsigned char *d; };
+extern struct A { struct B *e[0x400]; } *f[128];
+extern void (*bar) (char *p, char *q);
+
+char *
+foo (char *p, char *q)
+{
+ struct B *g;
+ char *b, *l;
+ unsigned long s;
+
+ g = f[((unsigned long) p) >> 22]->e[(((unsigned long) p) >> 12) & 0x3ff];
+ s = g->c << 2;
+ int r = ((unsigned long) p) & 0xfff;
+ int m = g->d[r];
+ if (m > 0xfd)
+ {
+ m = (r >> 2) % (s >> 2);
+ if ((((unsigned long) p) & ~(unsigned long) 0xfff) != (((unsigned long) q) & ~(unsigned long) 0xfff))
+ goto fail;
+ }
+ b = (char *) ((unsigned long) p & ~(unsigned long) 3);
+ b -= m << 2;
+ l = b + s;
+
+ if ( q >= l || q < b)
+ goto fail;
+ return p;
+fail:
+ (*bar) (p, q);
+ return p;
+}