This fixes PR47968, we are trying to expand a bitfield extraction
through vec_extract but strip subregs making the inputs invalid.
We try to compensate for this searching for a more proper vector mode
but then we have a strange requirement that NUNITS should stay the
same when the most important thing is to have matching element mode.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?

Thanks,
Richard.

2011-03-03  Richard Guenther  <rguent...@suse.de>

        PR middle-end/47968
        * expmed.c (extract_bit_field_1): Prefer vector modes that
        vec_extract patterns can handle.

        * gcc.dg/torture/pr47968.c: New testcase.

Index: gcc/expmed.c
===================================================================
*** gcc/expmed.c        (revision 170649)
--- gcc/expmed.c        (working copy)
*************** extract_bit_field_1 (rtx str_rtx, unsign
*** 1205,1211 ****
        && GET_MODE_INNER (GET_MODE (op0)) != tmode)
      {
        enum machine_mode new_mode;
-       int nunits = GET_MODE_NUNITS (GET_MODE (op0));
  
        if (GET_MODE_CLASS (tmode) == MODE_FLOAT)
        new_mode = MIN_MODE_VECTOR_FLOAT;
--- 1205,1210 ----
*************** extract_bit_field_1 (rtx str_rtx, unsign
*** 1221,1228 ****
        new_mode = MIN_MODE_VECTOR_INT;
  
        for (; new_mode != VOIDmode ; new_mode = GET_MODE_WIDER_MODE (new_mode))
!       if (GET_MODE_NUNITS (new_mode) == nunits
!           && GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0))
            && targetm.vector_mode_supported_p (new_mode))
          break;
        if (new_mode != VOIDmode)
--- 1220,1226 ----
        new_mode = MIN_MODE_VECTOR_INT;
  
        for (; new_mode != VOIDmode ; new_mode = GET_MODE_WIDER_MODE (new_mode))
!       if (GET_MODE_SIZE (new_mode) == GET_MODE_SIZE (GET_MODE (op0))
            && targetm.vector_mode_supported_p (new_mode))
          break;
        if (new_mode != VOIDmode)
Index: gcc/testsuite/gcc.dg/torture/pr47968.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr47968.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr47968.c      (revision 0)
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+ 
+ typedef __attribute__ ((vector_size (16))) float float4;
+ typedef __attribute__ ((vector_size (16))) double double2;
+ 
+ float foo (double2 d2)
+ {
+   float4 f4 = (float4) d2;
+   return *(float *) &f4;
+ }
+ 

Reply via email to