The mainline fix for PR58139 which is a wrong code gen bug was submitted here:
http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00910.html and approved for mainline and 4.8 (after a few weeks) here: http://gcc.gnu.org/ml/gcc-patches/2013-09/msg00134.html However, my fix exposed a latent x86 bug, so this patch was never committed to 4.8. The latent x86 bug was fixed by Honza and I'd like to now ask to be able to backport my fix for PR58139 along with Honza's fix to 4.8. This passed bootstrap and regtesting on powerpc64-linux and I bootstrapped this on x86_64 and verified that the ICE seen when compiling the test case with only my patch in: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58269#c2 is fixed when we add Honza's patch. Ok for 4.8? Peter Backport from mainline 2013-09-06 Jan Hubicka <j...@suse.cz> * config/i386/i386.c (ix86_hard_regno_mode_ok): AVX modes are valid only when AVX is enabled. 2013-09-05 Peter Bergner <berg...@vnet.ibm.com> PR target/58139 * reginfo.c (choose_hard_reg_mode): Scan through all mode classes looking for widest mode. Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c (revision 206582) +++ gcc/config/i386/i386.c (working copy) @@ -33944,7 +33944,7 @@ ix86_hard_regno_mode_ok (int regno, enum are available. OImode move is available only when AVX is enabled. */ return ((TARGET_AVX && mode == OImode) - || VALID_AVX256_REG_MODE (mode) + || (TARGET_AVX && VALID_AVX256_REG_MODE (mode)) || VALID_SSE_REG_MODE (mode) || VALID_SSE2_REG_MODE (mode) || VALID_MMX_REG_MODE (mode) Index: gcc/reginfo.c =================================================================== --- gcc/reginfo.c (revision 206582) +++ gcc/reginfo.c (working copy) @@ -620,40 +620,35 @@ choose_hard_reg_mode (unsigned int regno mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; - if (found_mode != VOIDmode) - return found_mode; - for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) if ((unsigned) hard_regno_nregs[regno][mode] == nregs && HARD_REGNO_MODE_OK (regno, mode) - && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))) + && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode)) found_mode = mode; if (found_mode != VOIDmode)