Previously, GET_MODE_2XWIDER_MODE had no specific definition for
vector modes; yes you'd get _a_ type that contained twice as many
bits, but usually nothing interesting.

This allows me to remove a fixme from the i386 backend that has
been there for years.  I want to do this before introducing 3 more
copies of this fixme as I add vect_perm_const support to more backends.

Tested on x86_64-linux.


r~
commit 3ebc6d778bb4dcae8047227b036515e47cc3fb04
Author: Richard Henderson <r...@redhat.com>
Date:   Fri Dec 9 15:12:31 2011 -0800

    Let GET_MODE_2XWIDER_MODE find a double-width vector mode.
    
            * genmodes.c (struct mode_data): Remove wider_2x member.
            (blank_mode): Adjust initializer.
            (calc_wider_mode): Use XALLOCAVEC.
            (emit_move_wider): Select double-width same-element vectors for
            2xwider vectors.
            * machmode.h (GET_MODE_2XWIDER_MODE): Update documentation.
            * config/i386/i386.c (doublesize_vector_mode): Remove.
            (expand_vselect_vconcat): Use GET_MODE_2XWIDER_MODE instead.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 811ea31..3490874 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2011-12-10  Richard Henderson  <r...@redhat.com>
+
+       * genmodes.c (struct mode_data): Remove wider_2x member.
+       (blank_mode): Adjust initializer.
+       (calc_wider_mode): Use XALLOCAVEC.
+       (emit_move_wider): Select double-width same-element vectors for
+       2xwider vectors.
+       * machmode.h (GET_MODE_2XWIDER_MODE): Update documentation.
+       * config/i386/i386.c (doublesize_vector_mode): Remove.
+       (expand_vselect_vconcat): Use GET_MODE_2XWIDER_MODE instead.
+
 2011-12-10  Joern Rennecke  <joern.renne...@embecosm.com>
 
        * config/epiphany/epiphany.h (USE_LOAD_POST_INCREMENT): Define.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 15c6c37..216ab0b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -35306,40 +35306,6 @@ ix86_builtin_vectorization_cost (enum 
vect_cost_for_stmt type_of_cost,
     }
 }
 
-
-/* Return a vector mode with twice as many elements as VMODE.  */
-/* ??? Consider moving this to a table generated by genmodes.c.  */
-
-static enum machine_mode
-doublesize_vector_mode (enum machine_mode vmode)
-{
-  switch (vmode)
-    {
-    case V2SFmode:     return V4SFmode;
-    case V1DImode:     return V2DImode;
-    case V2SImode:     return V4SImode;
-    case V4HImode:     return V8HImode;
-    case V8QImode:     return V16QImode;
-
-    case V2DFmode:     return V4DFmode;
-    case V4SFmode:     return V8SFmode;
-    case V2DImode:     return V4DImode;
-    case V4SImode:     return V8SImode;
-    case V8HImode:     return V16HImode;
-    case V16QImode:    return V32QImode;
-
-    case V4DFmode:     return V8DFmode;
-    case V8SFmode:     return V16SFmode;
-    case V4DImode:     return V8DImode;
-    case V8SImode:     return V16SImode;
-    case V16HImode:    return V32HImode;
-    case V32QImode:    return V64QImode;
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
 /* Construct (set target (vec_select op0 (parallel perm))) and
    return true if that's a valid instruction in the active ISA.  */
 
@@ -35374,7 +35340,7 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   enum machine_mode v2mode;
   rtx x;
 
-  v2mode = doublesize_vector_mode (GET_MODE (op0));
+  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   return expand_vselect (target, x, perm, nelt);
 }
diff --git a/gcc/genmodes.c b/gcc/genmodes.c
index dae7e38..8b6f5bc 100644
--- a/gcc/genmodes.c
+++ b/gcc/genmodes.c
@@ -63,7 +63,6 @@ struct mode_data
 
   struct mode_data *component; /* mode of components */
   struct mode_data *wider;     /* next wider mode */
-  struct mode_data *wider_2x;  /* 2x wider mode */
 
   struct mode_data *contained;  /* Pointer to list of modes that have
                                   this mode as a component.  */
@@ -83,7 +82,7 @@ static struct mode_data *void_mode;
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
-  0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0,
   "<unknown>", 0, 0, 0, 0
 };
 
@@ -790,7 +789,7 @@ calc_wider_mode (void)
 
   /* Allocate max_n_modes + 1 entries to leave room for the extra null
      pointer assigned after the qsort call below.  */
-  sortbuf = (struct mode_data **) alloca ((max_n_modes + 1) * sizeof (struct 
mode_data *));
+  sortbuf = XALLOCAVEC (struct mode_data *, max_n_modes + 1);
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     {
@@ -804,7 +803,6 @@ calc_wider_mode (void)
          for (prev = 0, m = modes[c]; m; m = next)
            {
              m->wider = void_mode;
-             m->wider_2x = void_mode;
 
              /* this is nreverse */
              next = m->next;
@@ -827,7 +825,6 @@ calc_wider_mode (void)
          for (j = 0; j < i; j++)
            sortbuf[j]->next = sortbuf[j]->wider = sortbuf[j + 1];
 
-
          modes[c] = sortbuf[0];
        }
     }
@@ -1062,6 +1059,21 @@ emit_mode_wider (void)
                continue;
            }
 
+         /* For vectors we want twice the number of components,
+            with the same element type.  */
+         if (m->cl == MODE_VECTOR_INT
+             || m->cl == MODE_VECTOR_FLOAT
+             || m->cl == MODE_VECTOR_FRACT
+             || m->cl == MODE_VECTOR_UFRACT
+             || m->cl == MODE_VECTOR_ACCUM
+             || m->cl == MODE_VECTOR_UACCUM)
+           {
+             if (m2->ncomponents != 2 * m->ncomponents)
+               continue;
+             if (m->component != m2->component)
+               continue;
+           }
+
          break;
        }
       if (m2 == void_mode)
diff --git a/gcc/machmode.h b/gcc/machmode.h
index b965d0f..4a3f6f5 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -221,6 +221,8 @@ extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
 extern const unsigned char mode_wider[NUM_MACHINE_MODES];
 #define GET_MODE_WIDER_MODE(MODE) ((enum machine_mode) mode_wider[MODE])
 
+/* For scalars, this is a mode with twice the precision.  For vectors,
+   this is a mode with the same inner mode but with twice the elements.  */
 extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
 #define GET_MODE_2XWIDER_MODE(MODE) ((enum machine_mode) mode_2xwider[MODE])
 

Reply via email to