OSDN Git Service

* simplify-rtx.c (simplify_unary_operation,
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Feb 2003 22:55:35 +0000 (22:55 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Feb 2003 22:55:35 +0000 (22:55 +0000)
simplify_binary_operation):  Deal with vector modes
(simplify_ternary_operation):  Deal with no-op VEC_MERGE.

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

gcc/ChangeLog
gcc/simplify-rtx.c

index 826f092..e7449de 100644 (file)
@@ -1,3 +1,9 @@
+Sun Feb  9 23:54:59 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+       * simplify-rtx.c (simplify_unary_operation,
+       simplify_binary_operation):  Deal with vector modes
+       (simplify_ternary_operation):  Deal with no-op VEC_MERGE.
+
 2002-02-09  Richard Sandiford  <rsandifo@redhat.com>
 
        * toplev.c (rest_of_compilation): Recompute register usage after
index 9685de0..e874c2a 100644 (file)
@@ -410,6 +410,31 @@ simplify_unary_operation (code, mode, op, op_mode)
        }
     }
 
+  if (VECTOR_MODE_P (mode) && GET_CODE (trueop) == CONST_VECTOR)
+    {
+      int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+      unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+      enum machine_mode opmode = GET_MODE (trueop);
+      int op_elt_size = GET_MODE_SIZE (GET_MODE_INNER (opmode));
+      unsigned op_n_elts = (GET_MODE_SIZE (opmode) / op_elt_size);
+      rtvec v = rtvec_alloc (n_elts);
+      unsigned int i;
+
+      if (op_n_elts != n_elts)
+       abort ();
+
+      for (i = 0; i < n_elts; i++)
+       {
+         rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode),
+                                           CONST_VECTOR_ELT (trueop, i),
+                                           GET_MODE_INNER (opmode));
+         if (!x)
+           return 0;
+         RTVEC_ELT (v, i) = x;
+       }
+      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.  */
@@ -875,6 +900,37 @@ simplify_binary_operation (code, mode, op0, op1)
       tem = trueop0, trueop0 = trueop1, trueop1 = tem;
     }
 
+  if (VECTOR_MODE_P (mode)
+      && GET_CODE (trueop0) == CONST_VECTOR
+      && GET_CODE (trueop1) == CONST_VECTOR)
+    {
+      int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
+      unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
+      enum machine_mode op0mode = GET_MODE (trueop0);
+      int op0_elt_size = GET_MODE_SIZE (GET_MODE_INNER (op0mode));
+      unsigned op0_n_elts = (GET_MODE_SIZE (op0mode) / op0_elt_size);
+      enum machine_mode op1mode = GET_MODE (trueop1);
+      int op1_elt_size = GET_MODE_SIZE (GET_MODE_INNER (op1mode));
+      unsigned op1_n_elts = (GET_MODE_SIZE (op1mode) / op1_elt_size);
+      rtvec v = rtvec_alloc (n_elts);
+      unsigned int i;
+
+      if (op0_n_elts != n_elts || op1_n_elts != n_elts)
+       abort ();
+
+      for (i = 0; i < n_elts; i++)
+       {
+         rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode),
+                                            CONST_VECTOR_ELT (trueop0, i),
+                                            CONST_VECTOR_ELT (trueop1, i));
+         if (!x)
+           return 0;
+         RTVEC_ELT (v, i) = x;
+       }
+
+      return gen_rtx_CONST_VECTOR (mode, v);
+    }
+
   if (GET_MODE_CLASS (mode) == MODE_FLOAT
       && GET_CODE (trueop0) == CONST_DOUBLE
       && GET_CODE (trueop1) == CONST_DOUBLE
@@ -1515,7 +1571,114 @@ simplify_binary_operation (code, mode, op0, op1)
          return 0;
 
        case VEC_SELECT:
+         if (!VECTOR_MODE_P (mode))
+           {
+             if (!VECTOR_MODE_P (GET_MODE (trueop0))
+                 || (mode
+                     != GET_MODE_INNER (GET_MODE (trueop0)))
+                 || GET_CODE (trueop1) != PARALLEL
+                 || XVECLEN (trueop1, 0) != 1
+                 || GET_CODE (XVECEXP (trueop1, 0, 0)) != CONST_INT)
+               abort ();
+
+             if (GET_CODE (trueop0) == CONST_VECTOR)
+               return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP (trueop1, 0, 0)));
+           }
+         else
+           {
+             if (!VECTOR_MODE_P (GET_MODE (trueop0))
+                 || (GET_MODE_INNER (mode)
+                     != GET_MODE_INNER (GET_MODE (trueop0)))
+                 || GET_CODE (trueop1) != PARALLEL)
+               abort ();
+
+             if (GET_CODE (trueop0) == 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 (XVECLEN (trueop1, 0) != (int)n_elts)
+                   abort ();
+                 for (i = 0; i < n_elts; i++)
+                   {
+                      rtx x = XVECEXP (trueop1, 0, i);
+
+                      if (GET_CODE (x) != CONST_INT)
+                        abort ();
+                      RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, INTVAL (x));
+                   }
+
+                 return gen_rtx_CONST_VECTOR (mode, v);
+               }
+           }
+         return 0;
        case VEC_CONCAT:
+         {
+           enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode
+                                         ? GET_MODE (trueop0)
+                                         : GET_MODE_INNER (mode));
+           enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode
+                                         ? GET_MODE (trueop1)
+                                         : GET_MODE_INNER (mode));
+
+           if (!VECTOR_MODE_P (mode)
+               || (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode)
+                   != GET_MODE_SIZE (mode)))
+             abort ();
+
+           if ((VECTOR_MODE_P (op0_mode)
+                && (GET_MODE_INNER (mode)
+                    != GET_MODE_INNER (op0_mode)))
+               || (!VECTOR_MODE_P (op0_mode)
+                   && GET_MODE_INNER (mode) != op0_mode))
+             abort ();
+
+           if ((VECTOR_MODE_P (op1_mode)
+                && (GET_MODE_INNER (mode)
+                    != GET_MODE_INNER (op1_mode)))
+               || (!VECTOR_MODE_P (op1_mode)
+                   && GET_MODE_INNER (mode) != op1_mode))
+             abort ();
+
+           if ((GET_CODE (trueop0) == CONST_VECTOR
+                || GET_CODE (trueop0) == CONST_INT
+                || GET_CODE (trueop0) == CONST_DOUBLE)
+               && (GET_CODE (trueop1) == CONST_VECTOR
+                   || GET_CODE (trueop1) == CONST_INT
+                   || GET_CODE (trueop1) == CONST_DOUBLE))
+             {
+               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;
+               unsigned in_n_elts = 1;
+
+               if (VECTOR_MODE_P (op0_mode))
+                 in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size);
+               for (i = 0; i < n_elts; i++)
+                 {
+                   if (i < in_n_elts)
+                     {
+                       if (!VECTOR_MODE_P (op0_mode))
+                         RTVEC_ELT (v, i) = trueop0;
+                       else
+                         RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i);
+                     }
+                   else
+                     {
+                       if (!VECTOR_MODE_P (op1_mode))
+                         RTVEC_ELT (v, i) = trueop1;
+                       else
+                         RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1,
+                                                              i - in_n_elts);
+                     }
+                 }
+
+               return gen_rtx_CONST_VECTOR (mode, v);
+             }
+           }
          return 0;
 
        default:
@@ -2379,23 +2542,32 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
          || 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)
+      if (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;
+         int mask = (1<<n_elts) - 1;
 
-         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);
+         if (!(INTVAL (op2) & mask))
+           return op1;
+         if ((INTVAL (op2) & mask) == mask)
+           return op0;
+
+         op0 = avoid_constant_pool_reference (op0);
+         op1 = avoid_constant_pool_reference (op1);
+         if (GET_CODE (op0) == CONST_VECTOR
+             && GET_CODE (op1) == CONST_VECTOR)
+           {
+             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;