simplify-rtx.c (simplify_unary_operation, [...]): Deal with vector modes

* simplify-rtx.c (simplify_unary_operation,
	simplify_binary_operation):  Deal with vector modes
	(simplify_ternary_operation):  Deal with no-op VEC_MERGE.

From-SVN: r62610
This commit is contained in:
Jan Hubicka 2003-02-09 23:55:35 +01:00 committed by Jan Hubicka
parent 2382b79f35
commit 852c8ba12e
2 changed files with 190 additions and 12 deletions

View 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

View 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;