The following patch fixes a bug in selecting a "better" mode to do a vector extract from. The existing code was evidently written without knowing what GET_MODE_WIDER_MODE does for vector modes in the face of multiple supported vector sizes. This results in odd code-generation choices for HImode extract from V16QI for example.
The patch adds a missing constraint - make the new vector element mode have the same size as the extraction mode as this is what vec_extract_optab requires. With the patch the testcase gcc.dg/vect/slp-45.c doesn't spill anymore with -msse4.1 or -mavx2 while it spills plenty without it. Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu. Note that the patch will now happily choose to extract DImode punning the source to V4DImode from V8SFmode (because the expander appearantly always chooses an integer mode for bit extraction). Hopefully we don't have targets that have separate register files for float vs. int vectors (or a heavy penalty in such punning). Note this is a pre-existing issue as well - we just less likely spill now (which possibly may made have such targets happy). Richard. 2016-07-26 Richard Biener <rguent...@suse.de> PR middle-end/72517 * expmed.c (extract_bit_field_1): Constrain the vector mode with element size matching the extraction mode size when choosing a better vector mode to do the extraction from. Index: gcc/expmed.c =================================================================== *** gcc/expmed.c (revision 238743) --- gcc/expmed.c (working copy) *************** extract_bit_field_1 (rtx str_rtx, unsign *** 1581,1586 **** --- 1581,1587 ---- for (; new_mode != VOIDmode ; new_mode = GET_MODE_WIDER_MODE (new_mode)) if (GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0)) + && GET_MODE_UNIT_SIZE (new_mode) == GET_MODE_SIZE (tmode) && targetm.vector_mode_supported_p (new_mode)) break; if (new_mode != VOIDmode)