On a change of tack, this tackles some redundant code in combine. It has code to convert a variable bit position to the mode required by the bit position operand to insv, extv or extzv:
[A] else if (pos_rtx != 0 && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) pos_rtx = gen_lowpart (pos_mode, pos_rtx); However, this is protected by an earlier: [B] if (pos_rtx && GET_MODE (pos_rtx) != VOIDmode && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) pos_mode = GET_MODE (pos_rtx); so [B] makes [A] redundant. That leaves this block: /* Adjust mode of POS_RTX, if needed. If we want a wider mode, we have to zero extend. Otherwise, we can just use a SUBREG. */ if (pos_rtx != 0 && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx))) { as the only use of pos_mode, so [B] can go too. Similarly, the memory case has: [C] /* If we have to change the mode of memory and cannot, the desired mode is EXTRACTION_MODE. */ if (inner_mode != wanted_inner_mode && (mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner)) || MEM_VOLATILE_P (inner) || pos_rtx)) wanted_inner_mode = extraction_mode; but those same conditions are repeated in the code that actually applies wanted_inner_mode: /* If INNER has a wider mode, and this is a constant extraction, try to make it smaller and adjust the byte to point to the byte containing the value. */ if (wanted_inner_mode != VOIDmode && inner_mode != wanted_inner_mode && ! pos_rtx && GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode) && MEM_P (inner) && ! mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner)) && ! MEM_VOLATILE_P (inner)) { so [C] too is unnecessary. Tested as described in the covering note. OK to install? Richard gcc/ * combine.c (make_extraction): Remove dead wanted_inner_mode- and pos_rtx-related code. Index: gcc/combine.c =================================================================== --- gcc/combine.c 2012-10-27 22:22:45.000000000 +0100 +++ gcc/combine.c 2012-10-27 22:32:26.811370582 +0100 @@ -7211,10 +7211,6 @@ make_extraction (enum machine_mode mode, && GET_MODE_SIZE (extraction_mode) < GET_MODE_SIZE (mode)) extraction_mode = mode; - if (pos_rtx && GET_MODE (pos_rtx) != VOIDmode - && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) - pos_mode = GET_MODE (pos_rtx); - /* If this is not from memory, the desired mode is the preferred mode for an extraction pattern's first input operand, or word_mode if there is none. */ @@ -7231,14 +7227,6 @@ make_extraction (enum machine_mode mode, wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode); gcc_assert (wanted_inner_mode != VOIDmode); } - - /* If we have to change the mode of memory and cannot, the desired mode - is EXTRACTION_MODE. */ - if (inner_mode != wanted_inner_mode - && (mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner)) - || MEM_VOLATILE_P (inner) - || pos_rtx)) - wanted_inner_mode = extraction_mode; } orig_pos = pos; @@ -7359,9 +7347,6 @@ make_extraction (enum machine_mode mode, } pos_rtx = temp; } - else if (pos_rtx != 0 - && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx))) - pos_rtx = gen_lowpart (pos_mode, pos_rtx); /* Make POS_RTX unless we already have it and it is correct. If we don't have a POS_RTX but we do have an ORIG_POS_RTX, the latter must