i386.md (ahi?v*3): Set third operand type to TImode.
authorJan Hubicka <jh@suse.cz>
Sun, 9 Feb 2003 12:35:28 +0000 (13:35 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 9 Feb 2003 12:35:28 +0000 (12:35 +0000)
* i386.md (ahi?v*3): Set third operand type to TImode.
* i386.c (ix86_expand_binop_builtin): Extend operand when needed.

* simplify-rtx.c (simplify_subreg): Fix conversion from vector into
integer mode.

* rtl.def (VEC_MERGE, VEC_SELECT, VEC_CONCAT, VEC_DUPLICATE):
Change code so they are arithmetic expressions now.
* simplify-rtx.c (simplify_unary_operation, simplify_binary_operation,
simplify_ternary_operation): Deal with VEC_* expressions.

* i386.md (vmaskcmp, pinsrw, movd patterns):  Fix RTL representation.

From-SVN: r62600

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/rtl.def
gcc/simplify-rtx.c

index b078754b890a939302d278ae09651cb9dafa4fd3..85981b36788476e9f8317575842c9b34dee54d7a 100644 (file)
@@ -1,3 +1,18 @@
+Sun Feb  9 13:33:34 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (ahi?v*3): Set third operand type to TImode.
+       * i386.c (ix86_expand_binop_builtin): Extend operand when needed.
+
+       * simplify-rtx.c (simplify_subreg): Fix conversion from vector into
+       integer mode.
+
+       * rtl.def (VEC_MERGE, VEC_SELECT, VEC_CONCAT, VEC_DUPLICATE):
+       Change code so they are arithmetic expressions now.
+       * simplify-rtx.c (simplify_unary_operation, simplify_binary_operation,
+       simplify_ternary_operation): Deal with VEC_* expressions.
+
+       * i386.md (vmaskcmp, pinsrw, movd patterns):  Fix RTL representation.
+
 Sat Feb  8 00:21:22 CET 2003  Jan Hubicka  <jh@suse.cz>
 
        * cfgrtl.c (verify_flow_info):  Use control_flow_insn_p.
index def53d052d00345615b65867ac7935ba9607fe5d..b9b2c32d3dafc3e329bf0b46fd7862d4bf2f5995 100644 (file)
@@ -13434,6 +13434,13 @@ ix86_expand_binop_builtin (icode, arglist, target)
       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
     target = gen_reg_rtx (tmode);
 
+  if (GET_MODE (op1) == SImode && mode1 == TImode)
+    {
+      rtx x = gen_reg_rtx (V4SImode);
+      emit_insn (gen_sse2_loadd (x, op1));
+      op1 = gen_lowpart (TImode, x);
+    }
+
   /* In case the insn wants input operands in modes different from
      the result, abort.  */
   if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
index 2db17890011a0ce2798ff53d43be3af575052d02..97c6d9e6a75b857f68c7dfbc928944ac4b6af3ef 100644 (file)
         (match_operator:V4SI 3 "sse_comparison_operator"
                [(match_operand:V4SF 1 "register_operand" "0")
                 (match_operand:V4SF 2 "register_operand" "x")])
-        (match_dup 1)
+        (subreg:V4SI (match_dup 1) 0)
         (const_int 1)))]
   "TARGET_SSE"
   "cmp%D3ss\t{%2, %0|%0, %2}"
         (match_operator:V2DI 3 "sse_comparison_operator"
                              [(match_operand:V2DF 1 "register_operand" "0")
                               (match_operand:V2DF 2 "nonimmediate_operand" "x")])
-        (match_dup 1)
+        (subreg:V2DI (match_dup 1) 0)
         (const_int 1)))]
   "TARGET_SSE2"
   "cmp%D3sd\t{%2, %0|%0, %2}"
   [(set (match_operand:V8HI 0 "register_operand" "=x")
         (vec_merge:V8HI (match_operand:V8HI 1 "register_operand" "0")
                        (vec_duplicate:V8HI
-                        (match_operand:SI 2 "nonimmediate_operand" "rm"))
+                        (truncate:HI
+                          (match_operand:SI 2 "nonimmediate_operand" "rm")))
                        (match_operand:SI 3 "immediate_operand" "i")))]
   "TARGET_SSE2"
   "pinsrw\t{%3, %2, %0|%0, %2, %3}"
 (define_insn "ashrv8hi3"
   [(set (match_operand:V8HI 0 "register_operand" "=x")
         (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
-                      (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                      (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psraw\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "ashrv4si3"
   [(set (match_operand:V4SI 0 "register_operand" "=x")
         (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
-                      (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                      (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psrad\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "lshrv8hi3"
   [(set (match_operand:V8HI 0 "register_operand" "=x")
         (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0")
-                      (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                      (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psrlw\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "lshrv4si3"
   [(set (match_operand:V4SI 0 "register_operand" "=x")
         (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0")
-                      (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                      (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psrld\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "lshrv2di3"
   [(set (match_operand:V2DI 0 "register_operand" "=x")
         (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0")
-                      (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                      (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psrlq\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "ashlv8hi3"
   [(set (match_operand:V8HI 0 "register_operand" "=x")
         (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0")
-                    (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                    (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psllw\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "ashlv4si3"
   [(set (match_operand:V4SI 0 "register_operand" "=x")
         (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0")
-                    (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                    (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "pslld\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "ashlv2di3"
   [(set (match_operand:V2DI 0 "register_operand" "=x")
         (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0")
-                    (match_operand:SI 2 "nonmemory_operand" "xi")))]
+                    (match_operand:TI 2 "nonmemory_operand" "xi")))]
   "TARGET_SSE2"
   "psllq\t{%2, %0|%0, %2}"
   [(set_attr "type" "sseishft")
 (define_insn "sse2_loadd"
   [(set (match_operand:V4SI 0 "register_operand" "=x")
        (vec_merge:V4SI
-        (vec_duplicate:V4HI (match_operand:SI 1 "nonimmediate_operand" "mr"))
+        (vec_duplicate:V4SI (match_operand:SI 1 "nonimmediate_operand" "mr"))
         (const_vector:V4SI [(const_int 0)
                             (const_int 0)
                             (const_int 0)
index ff19dd95d652d53882f22b03a5accae4d701d8df..b2087241e171d4daace95cf3121d826618e19d95 100644 (file)
@@ -1174,24 +1174,24 @@ DEF_RTL_EXPR(CALL_PLACEHOLDER, "call_placeholder", "uuuu", 'x')
    that specifies where the parts of the result are taken from.  Set bits
    indicate operand 0, clear bits indicate operand 1.  The parts are defined
    by the mode of the vectors.  */
-DEF_RTL_EXPR(VEC_MERGE, "vec_merge", "eee", 'x')
+DEF_RTL_EXPR(VEC_MERGE, "vec_merge", "eee", '3')
 
 /* Describes an operation that selects parts of a vector.
    Operands 0 is the source vector, operand 1 is a PARALLEL that contains
    a CONST_INT for each of the subparts of the result vector, giving the
    number of the source subpart that should be stored into it.  */
-DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", 'x')
+DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", '2')
 
 /* Describes a vector concat operation.  Operands 0 and 1 are the source
    vectors, the result is a vector that is as long as operands 0 and 1
    combined and is the concatenation of the two source vectors.  */
-DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", 'x')
+DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", '2')
 
 /* Describes an operation that converts a small vector into a larger one by
    duplicating the input values.  The output vector mode must have the same
    submodes as the input vector mode, and the number of output parts must be
    an integer multiple of the number of input parts.  */
-DEF_RTL_EXPR(VEC_DUPLICATE, "vec_duplicate", "e", 'x')
+DEF_RTL_EXPR(VEC_DUPLICATE, "vec_duplicate", "e", '1')
      
 /* Addition with signed saturation */
 DEF_RTL_EXPR(SS_PLUS, "ss_plus", "ee", 'c')
index 0298b79e8ce005b6918d5e0f6d2807c1de964ed7..9685de0b6930bea21f0b51a5871dbb1cea84983d 100644 (file)
@@ -372,6 +372,44 @@ simplify_unary_operation (code, mode, op, op_mode)
   unsigned int width = GET_MODE_BITSIZE (mode);
   rtx trueop = avoid_constant_pool_reference (op);
 
+  if (code == VEC_DUPLICATE)
+    {
+      if (!VECTOR_MODE_P (mode))
+       abort ();
+      if (GET_MODE (trueop) != VOIDmode
+         && !VECTOR_MODE_P (GET_MODE (trueop))
+         && GET_MODE_INNER (mode) != GET_MODE (trueop))
+       abort ();
+      if (GET_MODE (trueop) != VOIDmode
+         && VECTOR_MODE_P (GET_MODE (trueop))
+         && GET_MODE_INNER (mode) != GET_MODE_INNER (GET_MODE (trueop)))
+       abort ();
+      if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE
+         || GET_CODE (trueop) == CONST_VECTOR)
+       {
+          int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+          unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+         rtvec v = rtvec_alloc (n_elts);
+         unsigned int i;
+
+         if (GET_CODE (trueop) != CONST_VECTOR)
+           for (i = 0; i < n_elts; i++)
+             RTVEC_ELT (v, i) = trueop;
+         else
+           {
+             enum machine_mode inmode = GET_MODE (trueop);
+              int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode));
+              unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
+
+             if (in_n_elts >= n_elts || n_elts % in_n_elts)
+               abort ();
+             for (i = 0; i < n_elts; i++)
+               RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts);
+           }
+         return gen_rtx_CONST_VECTOR (mode, v);
+       }
+    }
+
   /* The order of these tests is critical so that, for example, we don't
      check the wrong mode (input vs. output) for a conversion operation,
      such as FIX.  At some point, this should be simplified.  */
@@ -1476,6 +1514,10 @@ simplify_binary_operation (code, mode, op0, op1)
          /* ??? There are simplifications that can be done.  */
          return 0;
 
+       case VEC_SELECT:
+       case VEC_CONCAT:
+         return 0;
+
        default:
          abort ();
        }
@@ -2332,6 +2374,30 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
            }
        }
       break;
+    case VEC_MERGE:
+      if (GET_MODE (op0) != mode
+         || GET_MODE (op1) != mode
+         || !VECTOR_MODE_P (mode))
+       abort ();
+      op0 = avoid_constant_pool_reference (op0);
+      op1 = avoid_constant_pool_reference (op1);
+      op2 = avoid_constant_pool_reference (op2);
+      if (GET_CODE (op0) == CONST_VECTOR
+         && GET_CODE (op1) == CONST_VECTOR
+         && GET_CODE (op2) == CONST_INT)
+       {
+          int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+         unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+         rtvec v = rtvec_alloc (n_elts);
+         unsigned int i;
+
+         for (i = 0; i < n_elts; i++)
+           RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i)
+                               ? CONST_VECTOR_ELT (op0, i)
+                               : CONST_VECTOR_ELT (op1, i));
+         return gen_rtx_CONST_VECTOR (mode, v);
+       }
+      break;
 
     default:
       abort ();
@@ -2413,13 +2479,16 @@ simplify_subreg (outermode, op, innermode, byte)
                }
              if (GET_CODE (elt) != CONST_INT)
                return NULL_RTX;
+             /* Avoid overflow.  */
+             if (high >> (HOST_BITS_PER_WIDE_INT - shift))
+               return NULL_RTX;
              high = high << shift | sum >> (HOST_BITS_PER_WIDE_INT - shift);
              sum = (sum << shift) + INTVAL (elt);
            }
          if (GET_MODE_BITSIZE (outermode) <= HOST_BITS_PER_WIDE_INT)
            return GEN_INT (trunc_int_for_mode (sum, outermode));
          else if (GET_MODE_BITSIZE (outermode) == 2* HOST_BITS_PER_WIDE_INT)
-           return immed_double_const (high, sum, outermode);
+           return immed_double_const (sum, high, outermode);
          else
            return NULL_RTX;
        }