This patch fixes a regression caused by my ext and extzv changes. The original idea was that the extract side could pass the number of significant bits in the structure to get_best_reg_extraction_insn, ignoring any bits higher than the field we're extracting:
/* Return true if an instruction exists to access a field of mode FIELDMODE in a register structure that has STRUCT_BITS significant bits. Describe the "best" such instruction in *INSN if so. PATTERN describes the type of insertion or extraction we want to perform. For an insertion, the number of significant structure bits includes all bits of the target. For an extraction, it need only include the most significant bit of the field. Larger widths are acceptable in both cases. */ That still seems correct in itself, but I'd fluffed the call site: if (!MEM_P (op0) && get_best_reg_extraction_insn (&extv, pattern, bitnum + bitsize, tmode)) in two ways: the calculation was wrong for big-endian, and extract_bit_field wouldn't cope with cases where TRULY_NOOP_TRUNCATION was false for the implied truncation. The latter problem triggered an UNPREDICTABLE warning from the GDB simulator on vshuf-v8qi.c for -mips64r2 on mips-sde-elf. It also shows why the truncation optimisation isn't useful for MIPS: anything smaller than a word uses the SImode optabs anyway, and TRULY_NOOP_TRUNCATION makes it wrong to use the SImode optabs on DImode structures. So for 4.8 I think the best thing is simply to pass the full width of the structure. We could revisit it in later releases if another target would find it useful. Tested on x86_64-linux-gnu and mips-sde-elf. OK to install? Richard gcc/ * expmed.c (extract_bit_field_1): Pass the full width of the structure to get_best_reg_extraction_insn. Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2013-02-02 08:46:38.031991259 +0000 +++ gcc/expmed.c 2013-02-02 08:57:04.726958347 +0000 @@ -1569,7 +1569,11 @@ extract_bit_field_1 (rtx str_rtx, unsign enum extraction_pattern pattern = unsignedp ? EP_extzv : EP_extv; extraction_insn extv; if (!MEM_P (op0) - && get_best_reg_extraction_insn (&extv, pattern, bitnum + bitsize, + /* ??? We could limit the structure size to the part of OP0 that + contains the field, with appropriate checks for endianness + and TRULY_NOOP_TRUNCATION. */ + && get_best_reg_extraction_insn (&extv, pattern, + GET_MODE_BITSIZE (GET_MODE (op0)), tmode)) { rtx result = extract_bit_field_using_extv (&extv, op0, bitsize, bitnum,