diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-02-23 18:05:56 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-02-23 18:05:56 +0100 |
commit | 5ead99faadd6b813fb277a87b96a324766b0b3b8 (patch) | |
tree | 2c90d4090e679c7a192bfc56041047f0a565d9d7 /gcc | |
parent | 2a8e30fbf34c8364dc0710b374f34038634c90a6 (diff) | |
download | gcc-5ead99faadd6b813fb277a87b96a324766b0b3b8.zip gcc-5ead99faadd6b813fb277a87b96a324766b0b3b8.tar.gz gcc-5ead99faadd6b813fb277a87b96a324766b0b3b8.tar.bz2 |
re PR target/43139 (ICE in output_operand)
PR target/43139
* config/i386/i386.c (ix86_delegitimize_address): Delegitimize all
GOTOFF relocs, even when the base reg isn't pic pointer.
* gcc.dg/pr43139.c: New test.
From-SVN: r157011
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr43139.c | 59 |
4 files changed, 93 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce7caff..7bd2c7b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-02-23 Jakub Jelinek <jakub@redhat.com> + + PR target/43139 + * config/i386/i386.c (ix86_delegitimize_address): Delegitimize all + GOTOFF relocs, even when the base reg isn't pic pointer. + 2010-02-23 Michael Matz <matz@suse.de> PR debug/43077 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 27593d7..84f5f53 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10883,6 +10883,9 @@ static rtx ix86_delegitimize_address (rtx x) { rtx orig_x = delegitimize_mem_from_attrs (x); + /* addend is NULL or some rtx if x is something+GOTOFF where + something doesn't include the PIC register. */ + rtx addend = NULL_RTX; /* reg_addend is NULL or a multiple of some register. */ rtx reg_addend = NULL_RTX; /* const_addend is NULL or a const_int. */ @@ -10921,14 +10924,13 @@ ix86_delegitimize_address (rtx x) else if (ix86_pic_register_p (XEXP (reg_addend, 1))) reg_addend = XEXP (reg_addend, 0); else - return orig_x; - if (!REG_P (reg_addend) - && GET_CODE (reg_addend) != MULT - && GET_CODE (reg_addend) != ASHIFT) - return orig_x; + { + reg_addend = NULL_RTX; + addend = XEXP (x, 0); + } } else - return orig_x; + addend = XEXP (x, 0); x = XEXP (XEXP (x, 1), 0); if (GET_CODE (x) == PLUS @@ -10939,7 +10941,7 @@ ix86_delegitimize_address (rtx x) } if (GET_CODE (x) == UNSPEC - && ((XINT (x, 1) == UNSPEC_GOT && MEM_P (orig_x)) + && ((XINT (x, 1) == UNSPEC_GOT && MEM_P (orig_x) && !addend) || (XINT (x, 1) == UNSPEC_GOTOFF && !MEM_P (orig_x)))) result = XVECEXP (x, 0, 0); @@ -10954,6 +10956,22 @@ ix86_delegitimize_address (rtx x) result = gen_rtx_CONST (Pmode, gen_rtx_PLUS (Pmode, result, const_addend)); if (reg_addend) result = gen_rtx_PLUS (Pmode, reg_addend, result); + if (addend) + { + /* If the rest of original X doesn't involve the PIC register, add + addend and subtract pic_offset_table_rtx. This can happen e.g. + for code like: + leal (%ebx, %ecx, 4), %ecx + ... + movl foo@GOTOFF(%ecx), %edx + in which case we return (%ecx - %ebx) + foo. */ + if (pic_offset_table_rtx) + result = gen_rtx_PLUS (Pmode, gen_rtx_MINUS (Pmode, copy_rtx (addend), + pic_offset_table_rtx), + result); + else + return orig_x; + } return result; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6fe4b8d..ee078d1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2010-02-23 Jakub Jelinek <jakub@redhat.com> + PR target/43139 + * gcc.dg/pr43139.c: New test. + PR debug/43077 * gcc.dg/guality/pr43077-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr43139.c b/gcc/testsuite/gcc.dg/pr43139.c new file mode 100644 index 0000000..4dc725b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr43139.c @@ -0,0 +1,59 @@ +/* PR target/43139 */ +/* { dg-do compile { target fpic } } */ +/* { dg-options "-g -O2 -fpic" } */ + +typedef double T1[10]; +typedef double T2[10][10]; +typedef int T3[10]; + +void __attribute__((noinline)) +fn1 (void) +{ + asm volatile ("" : : : "memory"); +} + +void __attribute__((noinline)) +fn2 (int x, ...) +{ + asm volatile ("" : : "r" (x) : "memory"); +} + +static void +bar (double v, double w, double x, double y, double z) +{ + double a; + if (v / w < 200.0) + { + a = x + (y - x) * __builtin_exp (-v / w); + fn2 (0); + fn2 (1, a * 20.2 / z, z); + fn1 (); + } +} + +static void +baz (T2 u, T2 v, T2 t, T2 x, T1 y, T3 z, double q, int j, int k) +{ + int i = z[k]; + if (u[i][j] > 0.0) + bar (q, x[i][j], v[i][j], t[i][j], y[i]); +} + +static T2 a, b, c, d; +static T1 e; +static T3 f; + +void __attribute__((noinline)) +test (int j, int k, double q) +{ + baz (a, b, c, d, e, f, q, j, k); +} + +int +main (void) +{ + d[0][6] = 1.0; + a[0][6] = 2.0; + test (6, 7, 400.0); + return 0; +} |