re PR rtl-optimization/16104 (ICE in reload_cse_simplify_operands, at postreload...
authorJakub Jelinek <jakub@gcc.gnu.org>
Mon, 4 Apr 2005 08:50:35 +0000 (10:50 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 4 Apr 2005 08:50:35 +0000 (10:50 +0200)
PR rtl-optimization/16104
* fold-const.c (fold_unary): Fix folding of vector conversions.

* gcc.c-torture/execute/20050316-1.c: New test.

From-SVN: r97529

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20050316-1.c [new file with mode: 0644]

index 4fc4bea315c01568b971306bb927680f4d8054e6..fe589da8458dc2bd57dccd4e344a7476cd9a210a 100644 (file)
@@ -1,3 +1,9 @@
+2005-04-04  Richard Henderson  <rth@redhat.com>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/16104
+       * fold-const.c (fold_unary): Fix folding of vector conversions.
+
 2005-04-04  Richard Sandiford  <rsandifo@redhat.com>
 
        * config.gcc (xstormy16-*-elf): Set extra_options.
index 0b9a71f09f7b3152db890566b66cd179f59e40e5..efbf8ed5c78bb6b4b031ce9ae13a484855879f9b 100644 (file)
@@ -6772,16 +6772,19 @@ fold_unary (enum tree_code code, tree type, tree op0)
          int inside_int = INTEGRAL_TYPE_P (inside_type);
          int inside_ptr = POINTER_TYPE_P (inside_type);
          int inside_float = FLOAT_TYPE_P (inside_type);
+         int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
          unsigned int inside_prec = TYPE_PRECISION (inside_type);
          int inside_unsignedp = TYPE_UNSIGNED (inside_type);
          int inter_int = INTEGRAL_TYPE_P (inter_type);
          int inter_ptr = POINTER_TYPE_P (inter_type);
          int inter_float = FLOAT_TYPE_P (inter_type);
+         int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
          unsigned int inter_prec = TYPE_PRECISION (inter_type);
          int inter_unsignedp = TYPE_UNSIGNED (inter_type);
          int final_int = INTEGRAL_TYPE_P (type);
          int final_ptr = POINTER_TYPE_P (type);
          int final_float = FLOAT_TYPE_P (type);
+         int final_vec = TREE_CODE (type) == VECTOR_TYPE;
          unsigned int final_prec = TYPE_PRECISION (type);
          int final_unsignedp = TYPE_UNSIGNED (type);
 
@@ -6801,12 +6804,15 @@ fold_unary (enum tree_code code, tree type, tree op0)
             since then we sometimes need the inner conversion.  Likewise if
             the outer has a precision not equal to the size of its mode.  */
          if ((((inter_int || inter_ptr) && (inside_int || inside_ptr))
-              || (inter_float && inside_float))
+              || (inter_float && inside_float)
+              || (inter_vec && inside_vec))
              && inter_prec >= inside_prec
-             && (inter_float || inter_unsignedp == inside_unsignedp)
+             && (inter_float || inter_vec
+                 || inter_unsignedp == inside_unsignedp)
              && ! (final_prec != GET_MODE_BITSIZE (TYPE_MODE (type))
                    && TYPE_MODE (type) == TYPE_MODE (inter_type))
-             && ! final_ptr)
+             && ! final_ptr
+             && (! final_vec || inter_prec == inside_prec))
            return fold_build1 (code, type, TREE_OPERAND (op0, 0));
 
          /* If we have a sign-extension of a zero-extended value, we can
@@ -6818,6 +6824,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
 
          /* Two conversions in a row are not needed unless:
             - some conversion is floating-point (overstrict for now), or
+            - some conversion is a vector (overstrict for now), or
             - the intermediate type is narrower than both initial and
               final, or
             - the intermediate type and innermost type differ in signedness,
@@ -6827,6 +6834,7 @@ fold_unary (enum tree_code code, tree type, tree op0)
             - the final type is a pointer type and the precisions of the
               initial and intermediate types differ.  */
          if (! inside_float && ! inter_float && ! final_float
+             && ! inside_vec && ! inter_vec && ! final_vec
              && (inter_prec > inside_prec || inter_prec > final_prec)
              && ! (inside_int && inter_int
                    && inter_unsignedp != inside_unsignedp
index a3691a6c4955a84e6225a9768487adc499203382..4abe23ea4de2e13cd2a33c155417920b88e65025 100644 (file)
@@ -1,3 +1,8 @@
+2005-04-04  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/16104
+       * gcc.c-torture/execute/20050316-1.c: New test.
+
 2005-04-04  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/template/spec23.C: Fix dg-error text.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050316-1.c b/gcc/testsuite/gcc.c-torture/execute/20050316-1.c
new file mode 100644 (file)
index 0000000..2a1c625
--- /dev/null
@@ -0,0 +1,69 @@
+/* PR rtl-optimization/16104 */
+
+extern void abort (void);
+
+typedef int V2SI __attribute__ ((vector_size (8)));
+typedef unsigned int V2USI __attribute__ ((vector_size (8)));
+typedef short V2HI __attribute__ ((vector_size (4)));
+typedef unsigned int V2UHI __attribute__ ((vector_size (4)));
+
+int
+test1 (void)
+{
+  return (long long) (V2SI) 0LL;
+}
+
+int
+test2 (V2SI x)
+{
+  return (long long) x;
+}
+
+V2SI
+test3 (void)
+{
+  return (V2SI) (long long) (int) (V2HI) 0;
+}
+
+V2SI
+test4 (V2HI x)
+{
+  return (V2SI) (long long) (int) x;
+}
+
+V2SI
+test5 (V2USI x)
+{
+  return (V2SI) x;
+}
+
+int
+main (void)
+{
+  if (sizeof (short) != 2 || sizeof (int) != 4 || sizeof (long long) != 8)
+    return 0;
+
+  if (test1 () != 0)
+    abort ();
+
+  V2SI x = { 2, 2 };
+  if (test2 (x) != 2)
+    abort ();
+
+  union { V2SI x; int y[2]; V2USI z; long long l; } u;
+  u.x = test3 ();
+  if (u.y[0] != 0 || u.y[1] != 0)
+    abort ();
+
+  V2HI y = { 4, 4 };
+  union { V2SI x; long long y; } v;
+  v.x = test4 (y);
+  if (v.y != 0x40004)
+    abort ();
+
+  V2USI z = { 6, 6 };
+  u.x = test5 (z);
+  if (u.y[0] != 6 || u.y[1] != 6)
+    abort ();
+  return 0;
+}