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);
 

Reply via email to