From 40182dbff7fe0f85becc57d2fb0009289558bd46 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Mon, 6 Jun 2005 21:26:10 +0200
Subject: [PATCH] re PR middle-end/21897 (Segementation fault in fold_ternary)

	* fold-const.c (operand_equal_p): Don't return 1, if element
	chains for 2 VECTOR_CSTs are not the same length.

	PR regression/21897
	* fold-const.c (fold_ternary) <case BIT_FIELD_REF>: Don't crash if
	not all VECTOR_CST elements are given.

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

From-SVN: r100674
---
 gcc/ChangeLog                                 |  7 ++++
 gcc/fold-const.c                              |  9 +++--
 gcc/testsuite/ChangeLog                       |  5 +++
 .../gcc.c-torture/execute/20050604-1.c        | 39 +++++++++++++++++++
 4 files changed, 57 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/20050604-1.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 69bcc422168a..2007efc983dd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
 2005-06-06  Jakub Jelinek  <jakub@redhat.com>
 
+	* fold-const.c (operand_equal_p): Don't return 1, if element
+	chains for 2 VECTOR_CSTs are not the same length.
+
+	PR regression/21897
+	* fold-const.c (fold_ternary) <case BIT_FIELD_REF>: Don't crash if
+	not all VECTOR_CST elements are given.
+
 	* combine.c (try_combine): Use hard_regno_nregs array instead of
 	HARD_REGNO_NREGS macro.
 	* config/rs6000/rs6000.c (rs6000_split_multireg_move,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 21a5b1a66987..96fffe995d4d 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2460,7 +2460,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 	      v2 = TREE_CHAIN (v2);
 	    }
 
-	  return 1;
+	  return v1 == v2;
 	}
 
       case COMPLEX_CST:
@@ -10306,9 +10306,12 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
 		 < TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))
 	    {
 	      tree elements = TREE_VECTOR_CST_ELTS (arg0);
-	      while (idx-- > 0)
+	      while (idx-- > 0 && elements)
 		elements = TREE_CHAIN (elements);
-	      return TREE_VALUE (elements);
+	      if (elements)
+		return TREE_VALUE (elements);
+	      else
+		return fold_convert (type, integer_zero_node);
 	    }
 	}
       return NULL_TREE;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a89b7fef961f..65f2435a67ee 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-06-06  Jakub Jelinek  <jakub@redhat.com>
+
+	PR regression/21897
+	* gcc.c-torture/execute/20050604-1.c: New test.
+
 2005-06-06  Nathan Sidwell  <nathan@codesourcery.com>
 
 	PR 21903
diff --git a/gcc/testsuite/gcc.c-torture/execute/20050604-1.c b/gcc/testsuite/gcc.c-torture/execute/20050604-1.c
new file mode 100644
index 000000000000..70097aa14cb0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20050604-1.c
@@ -0,0 +1,39 @@
+/* PR regression/21897 */
+
+extern void abort (void);
+
+typedef short v4hi __attribute__ ((vector_size (8)));
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+union
+{
+  v4hi v;
+  short s[4];
+} u;
+
+union
+{
+  v4sf v;
+  float f[4];
+} v;
+
+void
+foo (void)
+{
+  unsigned int i;
+  for (i = 0; i < 2; i++)
+    u.v += (v4hi) { 12, 14 };
+  for (i = 0; i < 2; i++)
+    v.v += (v4sf) { 18.0, 20.0, 22 };
+}
+
+int
+main (void)
+{
+  foo ();
+  if (u.s[0] != 24 || u.s[1] != 28 || u.s[2] || u.s[3])
+    abort ();
+  if (v.f[0] != 36.0 || v.f[1] != 40.0 || v.f[2] != 44.0 || v.f[3] != 0.0)
+    abort ();
+  return 0;
+}
-- 
GitLab