The following patch fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66424
The patch was tested and bootstrapped on x86/x86-64. Committed as rev. 226053. 2015-07-21 Vladimir Makarov <vmaka...@redhat.com> PR ipa/66424. * lra-remat.c (operand_to_remat): Prevent using insns with input subregs processed separately by IRA. 2015-07-21 Vladimir Makarov <vmaka...@redhat.com> PR ipa/66424. * gcc.target/i386/pr66424.c: New.
Index: lra-remat.c =================================================================== --- lra-remat.c (revision 225979) +++ lra-remat.c (working copy) @@ -417,6 +417,16 @@ operand_to_remat (rtx_insn *insn) return -1; found_reg = reg; } + /* IRA calculates conflicts separately for subregs of two words + pseudo. Even if the pseudo lives, e.g. one its subreg can be + used lately, another subreg hard register can be already used + for something else. In such case, it is not safe to + rematerialize the insn. */ + else if (reg->type == OP_IN && reg->subreg_p + && reg->regno >= FIRST_PSEUDO_REGISTER + && (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)) + == 2 * UNITS_PER_WORD)) + return -1; if (found_reg == NULL) return -1; if (found_reg->regno < FIRST_PSEUDO_REGISTER) Index: testsuite/gcc.target/i386/pr66424.c =================================================================== --- testsuite/gcc.target/i386/pr66424.c (revision 0) +++ testsuite/gcc.target/i386/pr66424.c (working copy) @@ -0,0 +1,51 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target ia32 } */ +int a, b, c, d, e[2], f, l, m, n, o; +long long g = 1, j; +static unsigned int h; +static int i, k; + +void +fn1 (long long p) +{ + int q = p; + f = 1 ^ e[f ^ (q & 1)]; +} + +static void +fn2 (long long p) +{ + f = 1 ^ e[(f ^ 1) & 1]; + fn1 (p >> 1 & 1); + fn1 (p >> 32 & 1); +} + +void +fn3 (int p) +{ + g |= j = p; +} + +int +main () +{ + e[0] = 1; + char p = l; + h = --g; + i = o = c; + m = d ? 1 / d : 0; + fn3 (l || 0); + b = a; + n = j++; + k--; + fn2 (g); + fn2 (h); + fn2 (i); + + if (k + f) + __builtin_abort (); + + return 0; +} +