* expmed.c (store_bit_field, extract_bit_field): Use new named patterns
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Jan 2004 14:13:44 +0000 (14:13 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 1 Jan 2004 14:13:44 +0000 (14:13 +0000)
* expr.c (store_constructor): Use vec_init pattern.
* genopinit.c (optabs): Initailize vec_set/vec_extract/vec_init.
* optabs.h (optab_index): ADD OTI_vec_set/OTI_vec_extract/OTI_vec_init
(vec_set_optab, vec_extract_optab, vec_init_optab): New.
* i386.md (vec_setv2df, vec_extractv2df, vec_setv4sf, vec_extractv4sf):
New patterns.
(sse2_unpc?pd): Fix pattern.
(sse2_movlpd): Kill.
(sse2_movsd): Deal with movlpd too.
* i386.c (ix86_expand_builtin): Use sse2_movsd instead of sse2_movlpd.
(ix86_expand_vector_init): New.
* emmintrin.h (__mm_set_pd, __mm_set_ps): Use vector extensions.
* md.texi (vec_set, vec_extract): Document

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@75304 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/emmintrin.h
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/xmmintrin.h
gcc/expmed.c
gcc/expr.c
gcc/genopinit.c
gcc/optabs.c
gcc/optabs.h

index 9db27a7..2271495 100644 (file)
@@ -1,3 +1,20 @@
+2004-01-01  Jan Hubicka  <jh@suse.cz>
+
+       * expmed.c (store_bit_field, extract_bit_field): Use new named patterns
+       * expr.c (store_constructor): Use vec_init pattern.
+       * genopinit.c (optabs): Initailize vec_set/vec_extract/vec_init.
+       * optabs.h (optab_index): ADD OTI_vec_set/OTI_vec_extract/OTI_vec_init
+       (vec_set_optab, vec_extract_optab, vec_init_optab): New.
+       * i386.md (vec_setv2df, vec_extractv2df, vec_setv4sf, vec_extractv4sf):
+       New patterns.
+       (sse2_unpc?pd): Fix pattern.
+       (sse2_movlpd): Kill.
+       (sse2_movsd): Deal with movlpd too.
+       * i386.c (ix86_expand_builtin): Use sse2_movsd instead of sse2_movlpd.
+       (ix86_expand_vector_init): New.
+       * emmintrin.h (__mm_set_pd, __mm_set_ps): Use vector extensions.
+       * md.texi (vec_set, vec_extract): Document
+
 2003-12-31  Jan Hubicka  <jh@suse.cz>
 
        PR opt/13473
index 3618c2b..a7dbc67 100644 (file)
@@ -115,15 +115,7 @@ _mm_set_pd1 (double __F)
 static __inline __m128d
 _mm_set_pd (double __Z, double __Y)
 {
-  union {
-    double __a[2];
-    __m128d __v;
-  } __u;
-
-  __u.__a[0] = __Y;
-  __u.__a[1] = __Z;
-
-  return __u.__v;
+  return (__v2df) {__Y, __Z};
 }
 
 /* Create the vector [Y Z].  */
index 66817c8..cc04a68 100644 (file)
@@ -217,6 +217,7 @@ extern int x86_field_alignment (tree, int);
 extern rtx ix86_tls_get_addr (void);
 extern bool ix86_must_pass_in_stack (enum machine_mode mode, tree);
 
+extern void ix86_expand_vector_init (rtx, rtx);
 /* In winnt.c  */
 extern int i386_pe_dllexport_name_p (const char *);
 extern int i386_pe_dllimport_name_p (const char *);
index 2762f63..0b904b1 100644 (file)
@@ -14075,7 +14075,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       icode = (fcode == IX86_BUILTIN_LOADHPS ? CODE_FOR_sse_movhps
               : fcode == IX86_BUILTIN_LOADLPS ? CODE_FOR_sse_movlps
               : fcode == IX86_BUILTIN_LOADHPD ? CODE_FOR_sse2_movhpd
-              : CODE_FOR_sse2_movlpd);
+              : CODE_FOR_sse2_movsd);
       arg0 = TREE_VALUE (arglist);
       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -14104,7 +14104,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       icode = (fcode == IX86_BUILTIN_STOREHPS ? CODE_FOR_sse_movhps
               : fcode == IX86_BUILTIN_STORELPS ? CODE_FOR_sse_movlps
               : fcode == IX86_BUILTIN_STOREHPD ? CODE_FOR_sse2_movhpd
-              : CODE_FOR_sse2_movlpd);
+              : CODE_FOR_sse2_movsd);
       arg0 = TREE_VALUE (arglist);
       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
@@ -15784,4 +15784,92 @@ ix86_must_pass_in_stack (enum machine_mode mode, tree type)
    return (!TARGET_64BIT && type && mode == TImode);
 }
 
+/* Initialize vector TARGET via VALS.  */
+void
+ix86_expand_vector_init (rtx target, rtx vals)
+{
+  enum machine_mode mode = GET_MODE (target);
+  int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+  int n_elts = (GET_MODE_SIZE (mode) / elt_size);
+  int i;
+  
+  for (i = n_elts - 1; i >= 0; i--)
+    if (GET_CODE (XVECEXP (vals, 0, i)) != CONST_INT
+       && GET_CODE (XVECEXP (vals, 0, i)) != CONST_DOUBLE)
+      break;
+
+  /* Few special cases first...  
+     ... constants are best loaded from constant pool.  */
+  if (i < 0)
+    {
+      emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
+      return;
+    }
+
+  /* ... values where only first field is non-constant are best loaded
+     from the pool and overwriten via move later.  */
+  if (!i)
+    {
+      rtx op = simplify_gen_subreg (mode, XVECEXP (vals, 0, 0),
+                                   GET_MODE_INNER (mode), 0);
+
+      op = force_reg (mode, op);
+      XVECEXP (vals, 0, 0) = CONST0_RTX (GET_MODE_INNER (mode));
+      emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
+      switch (GET_MODE (target))
+       {
+         case V2DFmode:
+           emit_insn (gen_sse2_movsd (target, target, op));
+           break;
+         case V4SFmode:
+           emit_insn (gen_sse_movss (target, target, op));
+           break;
+         default:
+           break;
+       }
+      return;
+    }
+
+  /* And the busy sequence doing rotations.  */
+  switch (GET_MODE (target))
+    {
+      case V2DFmode:
+       {
+         rtx vecop0 =
+           simplify_gen_subreg (V2DFmode, XVECEXP (vals, 0, 0), DFmode, 0);
+         rtx vecop1 =
+           simplify_gen_subreg (V2DFmode, XVECEXP (vals, 0, 1), DFmode, 0);
+
+         vecop0 = force_reg (V2DFmode, vecop0);
+         vecop1 = force_reg (V2DFmode, vecop1);
+         emit_insn (gen_sse2_unpcklpd (target, vecop0, vecop1));
+       }
+       break;
+      case V4SFmode:
+       {
+         rtx vecop0 =
+           simplify_gen_subreg (V4SFmode, XVECEXP (vals, 0, 0), SFmode, 0);
+         rtx vecop1 =
+           simplify_gen_subreg (V4SFmode, XVECEXP (vals, 0, 1), SFmode, 0);
+         rtx vecop2 =
+           simplify_gen_subreg (V4SFmode, XVECEXP (vals, 0, 2), SFmode, 0);
+         rtx vecop3 =
+           simplify_gen_subreg (V4SFmode, XVECEXP (vals, 0, 3), SFmode, 0);
+         rtx tmp1 = gen_reg_rtx (V4SFmode);
+         rtx tmp2 = gen_reg_rtx (V4SFmode);
+
+         vecop0 = force_reg (V4SFmode, vecop0);
+         vecop1 = force_reg (V4SFmode, vecop1);
+         vecop2 = force_reg (V4SFmode, vecop2);
+         vecop3 = force_reg (V4SFmode, vecop3);
+         emit_insn (gen_sse_unpcklps (tmp1, vecop1, vecop3));
+         emit_insn (gen_sse_unpcklps (tmp2, vecop0, vecop2));
+         emit_insn (gen_sse_unpcklps (target, tmp2, tmp1));
+       }
+       break;
+      default:
+       abort ();
+    }
+}
+
 #include "gt-i386.h"
index 06e3895..a004c32 100644 (file)
   "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_64BIT"
   "x86_emit_floatuns (operands); DONE;")
 \f
+;; SSE extract/set expanders
+
+(define_expand "vec_setv2df"
+  [(match_operand:V2DF 0 "register_operand" "")
+   (match_operand:DF 1 "register_operand" "")
+   (match_operand 2 "const_int_operand" "")]
+  "TARGET_SSE2"
+{
+  switch (INTVAL (operands[2]))
+    {
+    case 0:
+      emit_insn (gen_sse2_movsd (operands[0], operands[0],
+                                simplify_gen_subreg (V2DFmode, operands[1],
+                                                     DFmode, 0)));
+      break;
+    case 1:
+      {
+       rtx op1 = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0);
+
+       emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], op1));
+      }
+      break;
+    default:
+      abort ();
+    }
+  DONE;
+})
+
+(define_expand "vec_extractv2df"
+  [(match_operand:DF 0 "register_operand" "")
+   (match_operand:V2DF 1 "register_operand" "")
+   (match_operand 2 "const_int_operand" "")]
+  "TARGET_SSE2"
+{
+  switch (INTVAL (operands[2]))
+    {
+    case 0:
+      emit_move_insn (operands[0], gen_lowpart (DFmode, operands[1]));
+      break;
+    case 1:
+      {
+       rtx dest = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0);
+
+       emit_insn (gen_sse2_unpckhpd (dest, operands[1], operands[1]));
+      }
+      break;
+    default:
+      abort ();
+    }
+  DONE;
+})
+
+(define_expand "vec_initv2df"
+  [(match_operand:V2DF 0 "register_operand" "")
+   (match_operand 1 "" "")]
+  "TARGET_SSE2"
+{
+  ix86_expand_vector_init (operands[0], operands[1]);
+  DONE;
+})
+
+(define_expand "vec_setv4sf"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand:SF 1 "register_operand" "")
+   (match_operand 2 "const_int_operand" "")]
+  "TARGET_SSE"
+{
+  switch (INTVAL (operands[2]))
+    {
+    case 0:
+      emit_insn (gen_sse_movss (operands[0], operands[0],
+                               simplify_gen_subreg (V4SFmode, operands[1],
+                                                    SFmode, 0)));
+      break;
+    case 1:
+      {
+       rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+       rtx tmp = gen_reg_rtx (V4SFmode);
+        emit_move_insn (tmp, operands[0]);
+       emit_insn (gen_sse_unpcklps (operands[0], operands[0], operands[0]));
+       emit_insn (gen_sse_movss (operands[0], operands[0], op1));
+        emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
+                                   GEN_INT (1 + (0<<2) + (2<<4) + (3<<6))));
+      }
+    case 2:
+      {
+        rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+        rtx tmp = gen_reg_rtx (V4SFmode);
+
+        emit_move_insn (tmp, operands[0]);
+        emit_insn (gen_sse_movss (tmp, tmp, op1));
+        emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
+                                   GEN_INT (0 + (1<<2) + (0<<4) + (3<<6))));
+      }
+      break;
+    case 3:
+      {
+        rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+        rtx tmp = gen_reg_rtx (V4SFmode);
+
+        emit_move_insn (tmp, operands[0]);
+        emit_insn (gen_sse_movss (tmp, tmp, op1));
+        emit_insn (gen_sse_shufps (operands[0], operands[0], tmp,
+                                   GEN_INT (0 + (1<<2) + (2<<4) + (0<<6))));
+      }
+      break;
+    default:
+      abort ();
+    }
+  DONE;
+})
+
+(define_expand "vec_extractv4sf"
+  [(match_operand:SF 0 "register_operand" "")
+   (match_operand:V4SF 1 "register_operand" "")
+   (match_operand 2 "const_int_operand" "")]
+  "TARGET_SSE"
+{
+  switch (INTVAL (operands[2]))
+    {
+    case 0:
+      emit_move_insn (operands[0], gen_lowpart (SFmode, operands[1]));
+      break;
+    case 1:
+      {
+       rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+       rtx tmp = gen_reg_rtx (V4SFmode);
+        emit_move_insn (tmp, operands[1]);
+        emit_insn (gen_sse_shufps (op0, tmp, tmp,
+                                   GEN_INT (1)));
+      }
+    case 2:
+      {
+       rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+       rtx tmp = gen_reg_rtx (V4SFmode);
+        emit_move_insn (tmp, operands[1]);
+        emit_insn (gen_sse_unpckhps (op0, tmp, tmp));
+      }
+    case 3:
+      {
+       rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0);
+       rtx tmp = gen_reg_rtx (V4SFmode);
+        emit_move_insn (tmp, operands[1]);
+        emit_insn (gen_sse_shufps (op0, tmp, tmp,
+                                   GEN_INT (3)));
+      }
+    default:
+      abort ();
+    }
+  DONE;
+})
+
+(define_expand "vec_initv4sf"
+  [(match_operand:V4SF 0 "register_operand" "")
+   (match_operand 1 "" "")]
+  "TARGET_SSE"
+{
+  ix86_expand_vector_init (operands[0], operands[1]);
+  DONE;
+})
+\f
 ;; Add instructions
 
 ;; %%% splits for addsidi3
         (vec_select:DF (match_operand:V2DF 1 "register_operand" "0")
                        (parallel [(const_int 1)]))
         (vec_select:DF (match_operand:V2DF 2 "register_operand" "x")
-                       (parallel [(const_int 0)]))))]
+                       (parallel [(const_int 1)]))))]
   "TARGET_SSE2"
   "unpckhpd\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecvt")
-   (set_attr "mode" "TI")])
+   (set_attr "mode" "V2DF")])
 
 (define_insn "sse2_unpcklpd"
   [(set (match_operand:V2DF 0 "register_operand" "=x")
         (vec_select:DF (match_operand:V2DF 1 "register_operand" "0")
                        (parallel [(const_int 0)]))
         (vec_select:DF (match_operand:V2DF 2 "register_operand" "x")
-                       (parallel [(const_int 1)]))))]
+                       (parallel [(const_int 0)]))))]
   "TARGET_SSE2"
   "unpcklpd\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecvt")
-   (set_attr "mode" "TI")])
+   (set_attr "mode" "V2DF")])
 
 ;; MMX pack/unpack insns.
 
   [(set_attr "type" "ssecvt")
    (set_attr "mode" "V2DF")])
 
-(define_insn "sse2_movlpd"
-  [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
-       (vec_merge:V2DF
-        (match_operand:V2DF 1 "nonimmediate_operand" "0,0")
-        (match_operand:V2DF 2 "nonimmediate_operand" "m,x")
-        (const_int 1)))]
-  "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)"
-  "movlpd\t{%2, %0|%0, %2}"
-  [(set_attr "type" "ssecvt")
-   (set_attr "mode" "V2DF")])
-
 (define_expand "sse2_loadsd"
   [(match_operand:V2DF 0 "register_operand" "")
    (match_operand:DF 1 "memory_operand" "")]
    (set_attr "mode" "DF")])
 
 (define_insn "sse2_movsd"
-  [(set (match_operand:V2DF 0 "register_operand" "=x")
+  [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
        (vec_merge:V2DF
-        (match_operand:V2DF 1 "register_operand" "0")
-        (match_operand:V2DF 2 "register_operand" "x")
+        (match_operand:V2DF 1 "nonimmediate_operand" "0,0,0")
+        (match_operand:V2DF 2 "nonimmediate_operand" "x,m,x")
         (const_int 1)))]
-  "TARGET_SSE2"
-  "movsd\t{%2, %0|%0, %2}"
+  "TARGET_SSE2 && ix86_binary_operator_ok (UNKNOWN, V2DFmode, operands)"
+  "@movsd\t{%2, %0|%0, %2}
+    movlpd\t{%2, %0|%0, %2}
+    movlpd\t{%2, %0|%0, %2}"
   [(set_attr "type" "ssecvt")
-   (set_attr "mode" "DF")])
+   (set_attr "mode" "DF,V2DF,V2DF")])
 
 (define_insn "sse2_storesd"
   [(set (match_operand:DF 0 "memory_operand" "=m")
index f1275bd..dc54251 100644 (file)
@@ -42,7 +42,6 @@ typedef int __m128 __attribute__ ((__mode__(__V4SF__)));
 
 /* Internal data types for implementing the intrinsics.  */
 typedef int __v4sf __attribute__ ((__mode__(__V4SF__)));
-typedef int __v4si __attribute__ ((__mode__(__V4SI__)));
 
 /* Create a selector for use with the SHUFPS instruction.  */
 #define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
@@ -890,19 +889,9 @@ _mm_set_ps1 (float __F)
 
 /* Create the vector [Z Y X W].  */
 static __inline __m128
-_mm_set_ps (float __Z, float __Y, float __X, float __W)
+_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W)
 {
-  union {
-    float __a[4];
-    __m128 __v;
-  } __u;
-
-  __u.__a[0] = __W;
-  __u.__a[1] = __X;
-  __u.__a[2] = __Y;
-  __u.__a[3] = __Z;
-
-  return __u.__v;
+  return (__v4sf) {__W, __X, __Y, __Z};
 }
 
 /* Create the vector [W X Y Z].  */
index 98a26a1..8ebfb48 100644 (file)
@@ -313,6 +313,53 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   value = protect_from_queue (value, 0);
 
+  /* Use vec_extract patterns for extracting parts of vectors whenever
+     available.  */
+  if (VECTOR_MODE_P (GET_MODE (op0))
+      && GET_CODE (op0) != MEM
+      && (vec_set_optab->handlers[(int)GET_MODE (op0)].insn_code
+         != CODE_FOR_nothing)
+      && fieldmode == GET_MODE_INNER (GET_MODE (op0))
+      && bitsize == GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))
+      && !(bitnum % GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))))
+    {
+      enum machine_mode outermode = GET_MODE (op0);
+      enum machine_mode innermode = GET_MODE_INNER (outermode);
+      int icode = (int) vec_set_optab->handlers[(int) outermode].insn_code;
+      int pos = bitnum / GET_MODE_BITSIZE (innermode);
+      rtx rtxpos = GEN_INT (pos);
+      rtx src = value;
+      rtx dest = op0;
+      rtx pat, seq;
+      enum machine_mode mode0 = insn_data[icode].operand[0].mode;
+      enum machine_mode mode1 = insn_data[icode].operand[1].mode;
+      enum machine_mode mode2 = insn_data[icode].operand[2].mode;
+
+      start_sequence ();
+
+      if (! (*insn_data[icode].operand[1].predicate) (src, mode1))
+       src = copy_to_mode_reg (mode1, src);
+
+      if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
+       rtxpos = copy_to_mode_reg (mode1, rtxpos);
+
+      /* We could handle this, but we should always be called with a pseudo
+        for our targets and all insns should take them as outputs.  */
+      if (! (*insn_data[icode].operand[0].predicate) (dest, mode0)
+         || ! (*insn_data[icode].operand[1].predicate) (src, mode1)
+         || ! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
+       abort ();
+      pat = GEN_FCN (icode) (dest, src, rtxpos);
+      seq = get_insns ();
+      end_sequence ();
+      if (pat)
+       {
+         emit_insn (seq);
+         emit_insn (pat);
+         return dest;
+       }
+    }
+
   if (flag_force_mem)
     {
       int old_generating_concat_p = generating_concat_p;
@@ -1035,6 +1082,62 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       return op0;
     }
 
+  /* Use vec_extract patterns for extracting parts of vectors whenever
+     available.  */
+  if (VECTOR_MODE_P (GET_MODE (op0))
+      && GET_CODE (op0) != MEM
+      && (vec_extract_optab->handlers[(int)GET_MODE (op0)].insn_code
+         != CODE_FOR_nothing)
+      && ((bitsize + bitnum) / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))
+         == bitsize / GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (op0)))))
+    {
+      enum machine_mode outermode = GET_MODE (op0);
+      enum machine_mode innermode = GET_MODE_INNER (outermode);
+      int icode = (int) vec_extract_optab->handlers[(int) outermode].insn_code;
+      int pos = bitnum / GET_MODE_BITSIZE (innermode);
+      rtx rtxpos = GEN_INT (pos);
+      rtx src = op0;
+      rtx dest = NULL, pat, seq;
+      enum machine_mode mode0 = insn_data[icode].operand[0].mode;
+      enum machine_mode mode1 = insn_data[icode].operand[1].mode;
+      enum machine_mode mode2 = insn_data[icode].operand[2].mode;
+
+      if (innermode == tmode || innermode == mode)
+       dest = target;
+
+      if (!dest)
+       dest = gen_reg_rtx (innermode);
+
+      start_sequence ();
+
+      if (! (*insn_data[icode].operand[0].predicate) (dest, mode0))
+       dest = copy_to_mode_reg (mode0, dest);
+
+      if (! (*insn_data[icode].operand[1].predicate) (src, mode1))
+       src = copy_to_mode_reg (mode1, src);
+
+      if (! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
+       rtxpos = copy_to_mode_reg (mode1, rtxpos);
+
+      /* We could handle this, but we should always be called with a pseudo
+        for our targets and all insns should take them as outputs.  */
+      if (! (*insn_data[icode].operand[0].predicate) (dest, mode0)
+         || ! (*insn_data[icode].operand[1].predicate) (src, mode1)
+         || ! (*insn_data[icode].operand[2].predicate) (rtxpos, mode2))
+       abort ();
+      pat = GEN_FCN (icode) (dest, src, rtxpos);
+      seq = get_insns ();
+      end_sequence ();
+      if (pat)
+       {
+         emit_insn (seq);
+         emit_insn (pat);
+         return extract_bit_field (dest, bitsize,
+                                   bitnum - pos * GET_MODE_BITSIZE (innermode),
+                                   unsignedp, target, mode, tmode, total_size);
+       }
+    }
+
   /* Make sure we are playing with integral modes.  Pun with subregs
      if we aren't.  */
   {
index a38dee1..b0608fa 100644 (file)
@@ -4710,6 +4710,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
       int const_bounds_p;
       HOST_WIDE_INT minelt = 0;
       HOST_WIDE_INT maxelt = 0;
+      int icode = 0;
+      rtx *vector = NULL;
+      int elt_size = 0;
+      unsigned n_elts = 0;
 
       /* Vectors are like arrays, but the domain is stored via an array
         type indirectly.  */
@@ -4720,6 +4724,22 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
             it always will.  */
          domain = TYPE_DEBUG_REPRESENTATION_TYPE (type);
          domain = TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (domain)));
+         if (REG_P (target) && VECTOR_MODE_P (GET_MODE (target)))
+           {
+             enum machine_mode mode = GET_MODE (target);
+
+             icode = (int) vec_init_optab->handlers[mode].insn_code;
+             if (icode != CODE_FOR_nothing)
+               {
+                 unsigned int i;
+
+                 elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+                 n_elts = (GET_MODE_SIZE (mode) / elt_size);
+                 vector = alloca (n_elts);
+                 for (i = 0; i < n_elts; i++)
+                   vector [i] = CONST0_RTX (GET_MODE_INNER (mode));
+               }
+           }
        }
 
       const_bounds_p = (TYPE_MIN_VALUE (domain)
@@ -4784,7 +4804,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
            need_to_clear = 1;
        }
 
-      if (need_to_clear && size > 0)
+      if (need_to_clear && size > 0 && !vector)
        {
          if (! cleared)
            {
@@ -4835,6 +4855,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
              HOST_WIDE_INT lo, hi, count;
              tree position;
 
+             if (vector)
+               abort ();
+
              /* If the range is constant and "small", unroll the loop.  */
              if (const_bounds_p
                  && host_integerp (lo_index, 0)
@@ -4926,6 +4949,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
            {
              tree position;
 
+             if (vector)
+               abort ();
+
              if (index == 0)
                index = ssize_int (1);
 
@@ -4943,6 +4969,16 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
              xtarget = adjust_address (xtarget, mode, 0);
              store_expr (value, xtarget, 0);
            }
+         else if (vector)
+           {
+             int pos;
+
+             if (index != 0)
+               pos = tree_low_cst (index, 0) - minelt;
+             else
+               pos = i;
+             vector[pos] = expand_expr (value, NULL_RTX, VOIDmode, 0);
+           }
          else
            {
              if (index != 0)
@@ -4958,12 +4994,17 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                  target = copy_rtx (target);
                  MEM_KEEP_ALIAS_SET_P (target) = 1;
                }
-
-             store_constructor_field (target, bitsize, bitpos, mode, value,
-                                      type, cleared, get_alias_set (elttype));
-
+             else
+               store_constructor_field (target, bitsize, bitpos, mode, value,
+                                        type, cleared, get_alias_set (elttype));
            }
        }
+      if (vector)
+       {
+         emit_insn (GEN_FCN (icode) (target,
+                                     gen_rtx_PARALLEL (GET_MODE (target),
+                                                       gen_rtvec_v (n_elts, vector))));
+       }
     }
 
   /* Set constructor assignments.  */
index 2dc59f5..8f309f4 100644 (file)
@@ -152,7 +152,10 @@ static const char * const optabs[] =
   "movstr_optab[$A] = CODE_FOR_$(movstr$a$)",
   "clrstr_optab[$A] = CODE_FOR_$(clrstr$a$)",
   "cmpstr_optab[$A] = CODE_FOR_$(cmpstr$a$)",
-  "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)" };
+  "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)",
+  "vec_set_optab->handlers[$A].insn_code = CODE_FOR_$(vec_set$a$)",
+  "vec_extract_optab->handlers[$A].insn_code = CODE_FOR_$(vec_extract$a$)",
+  "vec_init_optab->handlers[$A].insn_code = CODE_FOR_$(vec_init$a$)" };
 
 static void gen_insn (rtx);
 
index 3a5705f..44d4b83 100644 (file)
@@ -5271,6 +5271,9 @@ init_optabs (void)
   cstore_optab = init_optab (UNKNOWN);
   push_optab = init_optab (UNKNOWN);
 
+  vec_extract_optab = init_optab (UNKNOWN);
+  vec_set_optab = init_optab (UNKNOWN);
+  vec_init_optab = init_optab (UNKNOWN);
   /* Conversions.  */
   sext_optab = init_convert_optab (SIGN_EXTEND);
   zext_optab = init_convert_optab (ZERO_EXTEND);
index 20d5df6..a85ce30 100644 (file)
@@ -197,6 +197,13 @@ enum optab_index
   /* Conditional add instruction.  */
   OTI_addcc,
 
+  /* Set specified field of vector operand.  */
+  OTI_vec_set,
+  /* Extract specified field of vector operand.  */
+  OTI_vec_extract,
+  /* Initialize vector operand.  */
+  OTI_vec_init,
+
   OTI_MAX
 };
 
@@ -281,6 +288,10 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define push_optab (optab_table[OTI_push])
 #define addcc_optab (optab_table[OTI_addcc])
 
+#define vec_set_optab (optab_table[OTI_vec_set])
+#define vec_extract_optab (optab_table[OTI_vec_extract])
+#define vec_init_optab (optab_table[OTI_vec_init])
+
 /* Conversion optabs have their own table and indexes.  */
 enum convert_optab_index
 {