[PATCH] Fix ICE in expand_expr_real_1 on CONCAT (PR middle-end/41123)

Jakub Jelinek jakub@redhat.com
Wed Aug 19 22:33:00 GMT 2009


Hi!

GCC 4.4 ICEs on the following testcase on i686, due to VCE the tree
optimizers create normal_inner_ref: case in expand_expr_real_1 is called
with a CONCAT op0.  Before PR6177 this didn't handle CONCAT at all,
afterwards only bitpos == 0 && bitsize == sizeof op0 has been handled.
The following patch handles the easy cases (first or second part of the
CONCAT) specially and for the rest just forces spilling it into memory.

Bootstrapped/regtested on x86_64-linux and i686-linux on the 4.4 branch.
The testcase doesn't ICE on the trunk, supposedly because of SSA expansion,
but IMHO it shouldn't hurt there either.

Ok for trunk/4.4?

2009-08-19  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/41123
	* expr.c (expand_expr_real_1) <normal_inner_ref>: Handle all kinds
	of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT.

	* gcc.dg/pr41123.c: New test.

--- gcc/expr.c.jj	2009-06-19 12:35:39.000000000 +0200
+++ gcc/expr.c	2009-08-19 21:00:37.000000000 +0200
@@ -7806,6 +7806,33 @@ expand_expr_real_1 (tree exp, rtx target
 			  || mode1 == BLKmode
 			  || bitpos + bitsize > GET_MODE_BITSIZE (mode2));
 
+	/* Handle CONCAT first.  */
+	if (GET_CODE (op0) == CONCAT && !must_force_mem)
+	  {
+	    if (bitpos == 0
+		&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+	      return op0;
+	    if (bitpos == 0
+		&& bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
+		&& bitsize)
+	      {
+		op0 = XEXP (op0, 0);
+		mode2 = GET_MODE (op0);
+	      }
+	    else if (bitpos == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
+		     && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 1)))
+		     && bitpos
+		     && bitsize)
+	      {
+		op0 = XEXP (op0, 1);
+		bitpos = 0;
+		mode2 = GET_MODE (op0);
+	      }
+	    else
+	      /* Otherwise force into memory.  */
+	      must_force_mem = 1;
+	  }
+
 	/* If this is a constant, put it in a register if it is a legitimate
 	   constant and we don't need a memory reference.  */
 	if (CONSTANT_P (op0)
@@ -7879,16 +7906,6 @@ expand_expr_real_1 (tree exp, rtx target
 	    MEM_VOLATILE_P (op0) = 1;
 	  }
 
-	/* The following code doesn't handle CONCAT.
-	   Assume only bitpos == 0 can be used for CONCAT, due to
-	   one element arrays having the same mode as its element.  */
-	if (GET_CODE (op0) == CONCAT)
-	  {
-	    gcc_assert (bitpos == 0
-			&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)));
-	    return op0;
-	  }
-
 	/* In cases where an aligned union has an unaligned object
 	   as a field, we might be extracting a BLKmode value from
 	   an integer-mode (e.g., SImode) object.  Handle this case
--- gcc/testsuite/gcc.dg/pr41123.c.jj	2009-08-19 21:06:05.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr41123.c	2009-08-19 21:06:45.000000000 +0200
@@ -0,0 +1,46 @@
+/* PR middle-end/41123 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing" } */
+
+struct S { char a, b, c, d, e, f, g, h; };
+struct T { int a, b; };
+
+struct S
+f1 (float _Complex x)
+{
+  return *(struct S *) & x;
+}
+
+int
+f2 (float _Complex x)
+{
+  struct S f = f1 (x);
+  return f.b;
+}
+
+struct T
+f3 (float _Complex x)
+{
+  return *(struct T *) & x;
+}
+
+int
+f4 (float _Complex x)
+{
+  struct T f = f3 (x);
+  return f.a;
+}
+
+int
+f5 (float _Complex x)
+{
+  struct T f = f3 (x);
+  return f.b;
+}
+
+struct T
+f6 (float _Complex x)
+{
+  struct T f = f3 (x);
+  return f;
+}

	Jakub



More information about the Gcc-patches mailing list