Hi! In 64-bit PIC mode, we allow SYMBOL_REF/LABEL_REF or that + constant offset as disp, because we can use %rip addressing in that case, but as VSIB addressing doesn't allow %rip addressing, we have to disallow even those.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-07-02 Jakub Jelinek <ja...@redhat.com> PR target/57777 * config/i386/predicates.md (vsib_address_operand): Disallow SYMBOL_REF or LABEL_REF in parts.disp if TARGET_64BIT && flag_pic. * gcc.target/i386/pr57777.c: New test. --- gcc/config/i386/predicates.md.jj 2013-04-29 09:38:16.000000000 +0200 +++ gcc/config/i386/predicates.md 2013-07-02 20:39:00.933572451 +0200 @@ -880,19 +880,28 @@ (define_predicate "vsib_address_operand" return false; /* VSIB addressing doesn't support (%rip). */ - if (parts.disp && GET_CODE (parts.disp) == CONST) + if (parts.disp) { - disp = XEXP (parts.disp, 0); - if (GET_CODE (disp) == PLUS) - disp = XEXP (disp, 0); - if (GET_CODE (disp) == UNSPEC) - switch (XINT (disp, 1)) - { - case UNSPEC_GOTPCREL: - case UNSPEC_PCREL: - case UNSPEC_GOTNTPOFF: - return false; - } + disp = parts.disp; + if (GET_CODE (disp) == CONST) + { + disp = XEXP (disp, 0); + if (GET_CODE (disp) == PLUS) + disp = XEXP (disp, 0); + if (GET_CODE (disp) == UNSPEC) + switch (XINT (disp, 1)) + { + case UNSPEC_GOTPCREL: + case UNSPEC_PCREL: + case UNSPEC_GOTNTPOFF: + return false; + } + } + if (TARGET_64BIT + && flag_pic + && (GET_CODE (disp) == SYMBOL_REF + || GET_CODE (disp) == LABEL_REF)) + return false; } return true; --- gcc/testsuite/gcc.target/i386/pr57777.c.jj 2013-07-02 20:45:33.789156903 +0200 +++ gcc/testsuite/gcc.target/i386/pr57777.c 2013-07-02 20:45:18.000000000 +0200 @@ -0,0 +1,13 @@ +/* PR target/57777 */ +/* { dg-do assemble { target avx2 } } */ +/* { dg-options "-O3 -mavx2" } */ +/* { dg-additional-options "-fpic" { target fpic } } */ + +void +foo (unsigned long *x, int *y) +{ + static unsigned long b[2] = { 0x0UL, 0x9908b0dfUL }; + int c; + for (c = 0; c < 512; c++) + x[c] = b[x[c] & 1UL]; +} Jakub