The following patch fixes https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64110
The patch was successfully tested and bootstrapped on x86/x86-64. Committed as rev. 218688. 2014-12-12 Vladimir Makarov <vmaka...@redhat.com> PR target/64110 * lra-constraints.c (process_alt_operands): Refuse alternative when reload pseudo of given class can not hold value of given mode. 2014-12-12 Vladimir Makarov <vmaka...@redhat.com> PR target/64110 * gcc.target/i386/pr64110.c: New.
Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 218685) +++ lra-constraints.c (working copy) @@ -2267,6 +2267,29 @@ process_alt_operands (int only_alternati goto fail; } + /* Alternative loses if it required class pseudo can not + hold value of required mode. Such insns can be + described by insn definitions with mode iterators. + Don't use ira_prohibited_class_mode_regs here as it + is common practice for constraints to use a class + which does not have actually enough regs to hold the + value (e.g. x86 AREG for mode requiring more one + general reg). */ + if (GET_MODE (*curr_id->operand_loc[nop]) != VOIDmode + && ! hard_reg_set_empty_p (this_alternative_set) + && ! HARD_REGNO_MODE_OK (ira_class_hard_regs + [this_alternative][0], + GET_MODE (*curr_id->operand_loc[nop]))) + { + if (lra_dump_file != NULL) + fprintf + (lra_dump_file, + " alt=%d: reload pseudo for op %d " + " can not hold the mode value -- refuse\n", + nalt, nop); + goto fail; + } + /* Check strong discouragement of reload of non-constant into class THIS_ALTERNATIVE. */ if (! CONSTANT_P (op) && ! no_regs_p Index: testsuite/gcc.target/i386/pr64110.c =================================================================== --- testsuite/gcc.target/i386/pr64110.c (revision 0) +++ testsuite/gcc.target/i386/pr64110.c (working copy) @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=core-avx2" } */ + +int foo (void); +int a; +short *b; + +void +bar (short x) +{ + while (a--) + { + int i, j = foo (); + for (i = 0; i < j; ++i) + *b++ = x; + } +}