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