summaryrefslogtreecommitdiff
path: root/gcc/simplify-rtx.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-09 22:55:35 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-09 22:55:35 +0000
commita7e829221f280a3b0aba61e4498622b1ea493ef5 (patch)
tree64162b5387c0a25095855244c8e0a85d395c9bfa /gcc/simplify-rtx.c
parentb9acd9ea67b1a6646ed0bd2344cfd84e6dd94d43 (diff)
downloadgcc-a7e829221f280a3b0aba61e4498622b1ea493ef5.tar.gz
* simplify-rtx.c (simplify_unary_operation,
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
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r--gcc/simplify-rtx.c196
1 files changed, 184 insertions, 12 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 9685de0b693..e874c2a2883 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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;