aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2005-04-04 10:50:35 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2005-04-04 10:50:35 +0200
commit4b8d544bc69dca9cd1afe0905a2f7816aa0cdbe3 (patch)
tree1b181db21b4c2c7cc2de3a1c480cc3fa88cec9ef /gcc
parentedc3676fb0a275db10df71dd63f040e2f2a7f1b6 (diff)
downloadgcc-4b8d544bc69dca9cd1afe0905a2f7816aa0cdbe3.zip
gcc-4b8d544bc69dca9cd1afe0905a2f7816aa0cdbe3.tar.gz
gcc-4b8d544bc69dca9cd1afe0905a2f7816aa0cdbe3.tar.bz2
re PR rtl-optimization/16104 (ICE in reload_cse_simplify_operands, at postreload.c:378 with SSE2 code on -O2)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c14
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20050316-1.c69
4 files changed, 91 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4fc4bea..fe589da 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0b9a71f..efbf8ed 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a3691a6..4abe23e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..2a1c625
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20050316-1.c
@@ -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;
+}