combine.c:make_extraction peels off truncating lowpart subregs from the structure operand. On !TRULY_NOOP_TRUNCATION targets, truncations are represented as TRUNCATE instead, so this patch handles them too.
As for why this patch is suddenly needed now: at the moment, we start out with INNER being the original (truncate:SI (foo:DI)) expression, but after having looked at the insv/ext(z)v pattern, we decide that we want INNER to be word_mode (DImode) instead. The truncation then gets stripped by the force_to_mode call. However, with optabs, an SImode INNER would cause us to use an SImode operation instead. That isn't what we want, because the explicit TRUNCATE is there precisely because the DImode value needs to be modified by active instructions before being acceptable in an SImode operation. Tested as described in the covering note. OK to install? Richard gcc/ * combine.c (make_extraction): Handle TRUNCATEd INNERs. Index: gcc/combine.c =================================================================== --- gcc/combine.c 2012-11-02 08:15:57.000000000 +0000 +++ gcc/combine.c 2012-11-02 08:22:07.702369220 +0000 @@ -7022,6 +7022,8 @@ make_extraction (enum machine_mode mode, if (new_rtx != 0) return gen_rtx_ASHIFT (mode, new_rtx, XEXP (inner, 1)); } + else if (GET_CODE (inner) == TRUNCATE) + inner = XEXP (inner, 0); inner_mode = GET_MODE (inner);