This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR middle-end/17055: Casting integer zero to a vector


The following is my proposed solution to PR middle-end/17055 which is
an ICE-on-valid known to affect 3.3, 3.4 and mainline.

The problem is that the middle end contains an optimization such that
anything subtracted from itself, i.e. x - x, is equivalent to "zero"
(for floating point test this is guarded by -ffast-math).  This holds
for integers, enumerated types, pointers, floats, doubles, complex
types, references, offset types, etc... except vectors!  It turns out
the middle-end is unable to cast integer zero to either a integer
vector type or a floating point vector type, hence the ICE.

There are two possible solutions.  The first is to disable the "x - x"
constant folding transformation in "fold", by explicitly listing all of
the types that this is valid for.  Or alternatively, as done below,
teach the middle-end internally how to cast integer zero to a suitable
VECTOR_CST.  The latter is both conceptually simpler, and provides for
better optimization.  Note that the conversion of integer zero to a
vector type is performed in "fold_convert", and is therefore independent
of (and doesn't affect/change) the front-end's semantics of vector casts,
which are handled in "convert".

Jim (and/or other vector folks) are you happy with this solution?  The
new function build_zero_vector may also be useful elsewhere in the
compiler.  I check all calls to build_vector to confirm that this
functionality doesn't already exist.


The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.

It isn't clear whether this is a regression, so the decision of whether
to backport to 3.4 and/or 3.3 (or WONTFIX the PR) is up to the release
managers.

Ok for mainline?


2004-09-08  Roger Sayle  <roger@eyesopen.com>

	PR middle-end/17055
	* fold-const.c (build_zero_vector): New function to construct a
	vector (either floating point or integer) of zeros.
	(fold_convert): Internally, enable conversions of integer zero
	to arbitrary vector types, using the new build_zero_vector.

	* gcc.dg/pr17055-1.c: New test case.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.447
diff -c -3 -p -r1.447 fold-const.c
*** fold-const.c	1 Sep 2004 16:32:39 -0000	1.447
--- fold-const.c	8 Sep 2004 12:54:56 -0000
*************** static tree negate_expr (tree);
*** 89,94 ****
--- 89,95 ----
  static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
  static tree associate_trees (tree, tree, enum tree_code, tree);
  static tree const_binop (enum tree_code, tree, tree, int);
+ static tree build_zero_vector (tree);
  static tree fold_convert_const (enum tree_code, tree, tree);
  static enum tree_code invert_tree_comparison (enum tree_code, bool);
  static enum comparison_code comparison_to_compcode (enum tree_code);
*************** size_diffop (tree arg0, tree arg1)
*** 1681,1686 ****
--- 1682,1704 ----
  							arg1, arg0)));
  }

+ /* Construct a vector of zero elements of vector type TYPE.  */
+
+ static tree
+ build_zero_vector (tree type)
+ {
+   tree elem, list;
+   int i, units;
+
+   elem = fold_convert_const (NOP_EXPR, TREE_TYPE (type), integer_zero_node);
+   units = TYPE_VECTOR_SUBPARTS (type);
+
+   list = NULL_TREE;
+   for (i = 0; i < units; i++)
+     list = tree_cons (NULL_TREE, elem, list);
+   return build_vector (type, list);
+ }
+

  /* Attempt to fold type conversion operation CODE of expression ARG1 to
     type TYPE.  If no simplification can be done return NULL_TREE.  */
*************** fold_convert (tree type, tree arg)
*** 1930,1935 ****
--- 1948,1955 ----
      }
    else if (TREE_CODE (type) == VECTOR_TYPE)
      {
+       if (integer_zerop (arg))
+ 	return build_zero_vector (type);
        if ((INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig))
  	  && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)))
  	return fold (build1 (NOP_EXPR, type, arg));


/* PR middle-end/17055.  */
/* { dg-do compile } */
/* { dg-options "-O2 -ffast-math" } */

/* This test used to abort, beacuse we do an "integer" fold to zero, i.e.
   x - x = (T)0 where T is the type of x.  Unfortunately, fold_convert
   was unable to convert integer_zero_node to the appropriate vector type.  */

typedef float v4sf __attribute__((vector_size(16)));
typedef int v4si __attribute__((vector_size(16)));

v4sf ivf, ovf;
v4si ivi, ovi;

void testf (void)
{
  ovf = ivf - ivf;
}

void testi (void)
{
  ovi = ivi - ivi;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]