RFA: more generic simd fixes
Joern Rennecke
joern.rennecke@superh.com
Wed Jun 26 16:58:00 GMT 2002
I found two more places that assumed that vectors consist of word_mode
elements. And once you are able to compile my testcasei, it caues a
division by zero error if the target architecture does this for the
component divides.
--
--------------------------
SuperH
2430 Aztec West / Almondsbury / BRISTOL / BS32 4AQ
T:+44 1454 462330
-------------- next part --------------
Thu Jun 27 00:01:17 2002 J"orn Rennecke <joern.rennecke@superh.com>
gcc:
* optabs.c (expand_vector_binop): Don't store using a SUBREG smaller
than UNITS_PER_WORD, unless this is little endian and the first unit
in this word.
(expand_vector_unop): Likewise.
* simplify-rtx.c (simplify_subreg): Don't assume that all vectors
consist of word_mode elements.
gcc/testsuite:
gcc.c-torture/execute/simd-2.c (i, j): Add initializer elements to
avoid division by zero.
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.138
diff -p -r1.138 optabs.c
*** optabs.c 25 Jun 2002 20:52:57 -0000 1.138
--- optabs.c 26 Jun 2002 23:00:54 -0000
*************** expand_vector_binop (mode, binoptab, op0
*** 1951,1958 ****
case DIV:
for (i = 0; i < elts; ++i)
{
! t = simplify_gen_subreg (submode, target, mode,
! i * subsize);
a = simplify_gen_subreg (submode, op0, mode,
i * subsize);
b = simplify_gen_subreg (submode, op1, mode,
--- 1951,1968 ----
case DIV:
for (i = 0; i < elts; ++i)
{
! /* If this is part of a register, and not the first item in the
! word, we can't store using a SUBREG - that would clobber
! previous results.
! And storing with a SUBREG is only possible for the least
! significant part, hence we can't do it for big endian
! (unless we want to permute the evaluation order. */
! if (GET_CODE (target) == REG
! && (BYTES_BIG_ENDIAN && subsize < UNITS_PER_WORD
! || ((i * subsize) % UNITS_PER_WORD) == 0))
! t = NULL_RTX;
! else
! t = simplify_gen_subreg (submode, target, mode, i * subsize);
a = simplify_gen_subreg (submode, op0, mode,
i * subsize);
b = simplify_gen_subreg (submode, op1, mode,
*************** expand_vector_binop (mode, binoptab, op0
*** 1974,1980 ****
if (res == 0)
break;
! emit_move_insn (t, res);
}
break;
--- 1984,1995 ----
if (res == 0)
break;
! if (t)
! emit_move_insn (t, res);
! else
! store_bit_field (target, subsize * BITS_PER_UNIT,
! i * subsize * BITS_PER_UNIT, submode, res,
! GET_MODE_SIZE (mode));
}
break;
*************** expand_vector_unop (mode, unoptab, op0,
*** 2018,2029 ****
for (i = 0; i < elts; ++i)
{
! t = simplify_gen_subreg (submode, target, mode, i * subsize);
a = simplify_gen_subreg (submode, op0, mode, i * subsize);
res = expand_unop (submode, unoptab, a, t, unsignedp);
! emit_move_insn (t, res);
}
seq = get_insns ();
--- 2033,2060 ----
for (i = 0; i < elts; ++i)
{
! /* If this is part of a register, and not the first item in the
! word, we can't store using a SUBREG - that would clobber
! previous results.
! And storing with a SUBREG is only possible for the least
! significant part, hence we can't do it for big endian
! (unless we want to permute the evaluation order. */
! if (GET_CODE (target) == REG
! && (BYTES_BIG_ENDIAN && subsize < UNITS_PER_WORD
! || ((i * subsize) % UNITS_PER_WORD) == 0))
! t = NULL_RTX;
! else
! t = simplify_gen_subreg (submode, target, mode, i * subsize);
a = simplify_gen_subreg (submode, op0, mode, i * subsize);
res = expand_unop (submode, unoptab, a, t, unsignedp);
! if (t)
! emit_move_insn (t, res);
! else
! store_bit_field (target, subsize * BITS_PER_UNIT,
! i * subsize * BITS_PER_UNIT, submode, res,
! GET_MODE_SIZE (mode));
}
seq = get_insns ();
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.107
diff -p -r1.107 simplify-rtx.c
*** simplify-rtx.c 18 Jun 2002 01:35:25 -0000 1.107
--- simplify-rtx.c 26 Jun 2002 23:00:54 -0000
*************** simplify_subreg (outermode, op, innermod
*** 2271,2289 ****
/* Simplify subregs of vector constants. */
if (GET_CODE (op) == CONST_VECTOR)
{
! int offset = byte / UNITS_PER_WORD;
rtx elt;
! /* This shouldn't happen, but let's not do anything stupid. */
! if (GET_MODE_INNER (innermode) != outermode)
! return NULL_RTX;
! elt = CONST_VECTOR_ELT (op, offset);
! /* ?? We probably don't need this copy_rtx because constants
! can be shared. ?? */
! return copy_rtx (elt);
}
/* Attempt to simplify constant to non-SUBREG expression. */
--- 2271,2315 ----
/* Simplify subregs of vector constants. */
if (GET_CODE (op) == CONST_VECTOR)
{
! int elt_size = GET_MODE_SIZE (GET_MODE_INNER (innermode));
! int offset = byte / elt_size;
rtx elt;
! if (GET_MODE_INNER (innermode) == outermode)
! {
! elt = CONST_VECTOR_ELT (op, offset);
!
! /* ?? We probably don't need this copy_rtx because constants
! can be shared. ?? */
! return copy_rtx (elt);
! }
! else if (GET_MODE_CLASS (outermode) == MODE_INT
! && (GET_MODE_SIZE (outermode) % elt_size == 0))
! {
! /* This happens when the target register size is smaller then
! the vector mode, and we synthesize operations with vectors
! of elements that are smaller than the register size. */
! HOST_WIDE_INT sum = 0;
! unsigned n_elts = (GET_MODE_SIZE (outermode) / elt_size);
! unsigned i = BYTES_BIG_ENDIAN ? offset : offset + n_elts - 1;
! unsigned step = BYTES_BIG_ENDIAN ? 1 : -1;
! if (GET_MODE_BITSIZE (outermode) > HOST_BITS_PER_WIDE_INT)
! return NULL_RTX;
! for (; n_elts--; i += step)
! {
! elt = CONST_VECTOR_ELT (op, i);
! if (GET_CODE (elt) != CONST_INT)
! return NULL_RTX;
! sum = (sum << BITS_PER_UNIT * elt_size) + INTVAL (elt);
! }
! return GEN_INT (trunc_int_for_mode (sum, outermode));
! }
! else
! /* This shouldn't happen, but let's not do anything stupid. */
! return NULL_RTX;
}
/* Attempt to simplify constant to non-SUBREG expression. */
Index: testsuite/gcc.c-torture/execute/simd-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/execute/simd-2.c,v
retrieving revision 1.1
diff -p -r1.1 simd-2.c
*** testsuite/gcc.c-torture/execute/simd-2.c 25 Jun 2002 20:53:12 -0000 1.1
--- testsuite/gcc.c-torture/execute/simd-2.c 26 Jun 2002 23:00:54 -0000
***************
*** 5,12 ****
typedef int __attribute__((mode(V8HI))) vecint;
! vecint i = { 150, 100, 150, 200 };
! vecint j = { 10, 13, 20, 30 };
vecint k;
union {
--- 5,12 ----
typedef int __attribute__((mode(V8HI))) vecint;
! vecint i = { 150, 100, 150, 200, 0, 0, 0, 0 };
! vecint j = { 10, 13, 20, 30, 1, 1, 1, 1 };
vecint k;
union {
More information about the Gcc-patches
mailing list