From d02a5a4b9abb043ff6a243bb4f9a9aaac2fb8656 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Fri, 16 Oct 2009 12:43:18 +0200
Subject: [PATCH] re PR debug/41717 (internal compiler error: in
 expand_debug_expr)

	PR debug/41717
	* cfgexpand.c (expand_debug_expr): Handle CONJ_EXPR.
	* dwarf2out.c (mem_loc_descriptor): Don't handle
	POST_INT/POST_DEC/POST_MODIFY like SUBREG.  For SUBREG
	punt if it is not lowpart subreg or if inner mode isn't
	MODE_INT.

	* gcc.dg/debug/pr41717.c: New test.

From-SVN: r152897
---
 gcc/ChangeLog                        |  9 +++++++
 gcc/cfgexpand.c                      | 40 ++++++++++++++++++++++++++++
 gcc/dwarf2out.c                      | 30 +++++++++++++--------
 gcc/testsuite/ChangeLog              |  5 ++++
 gcc/testsuite/gcc.dg/debug/pr41717.c | 10 +++++++
 5 files changed, 83 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/pr41717.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dea101110588..2c8dff8cf498 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2009-10-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR debug/41717
+	* cfgexpand.c (expand_debug_expr): Handle CONJ_EXPR.
+	* dwarf2out.c (mem_loc_descriptor): Don't handle
+	POST_INT/POST_DEC/POST_MODIFY like SUBREG.  For SUBREG
+	punt if it is not lowpart subreg or if inner mode isn't
+	MODE_INT.
+
 2009-10-16  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
 
 	* config/s390/s390.c (s390_z10_optimize_cmp): Skip notes when
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 4f317d906bc0..acd70c13869f 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2869,6 +2869,46 @@ expand_debug_expr (tree exp)
 	op1 = gen_rtx_CONST (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case CONJ_EXPR:
+      if (GET_CODE (op0) == CONCAT)
+	return gen_rtx_CONCAT (mode, XEXP (op0, 0),
+			       gen_rtx_NEG (GET_MODE_INNER (mode),
+					    XEXP (op0, 1)));
+      else
+	{
+	  enum machine_mode imode = GET_MODE_INNER (mode);
+	  rtx re, im;
+
+	  if (MEM_P (op0))
+	    {
+	      re = adjust_address_nv (op0, imode, 0);
+	      im = adjust_address_nv (op0, imode, GET_MODE_SIZE (imode));
+	    }
+	  else
+	    {
+	      enum machine_mode ifmode = int_mode_for_mode (mode);
+	      enum machine_mode ihmode = int_mode_for_mode (imode);
+	      rtx halfsize;
+	      if (ifmode == BLKmode || ihmode == BLKmode)
+		return NULL;
+	      halfsize = GEN_INT (GET_MODE_BITSIZE (ihmode));
+	      re = op0;
+	      if (mode != ifmode)
+		re = gen_rtx_SUBREG (ifmode, re, 0);
+	      re = gen_rtx_ZERO_EXTRACT (ihmode, re, halfsize, const0_rtx);
+	      if (imode != ihmode)
+		re = gen_rtx_SUBREG (imode, re, 0);
+	      im = copy_rtx (op0);
+	      if (mode != ifmode)
+		im = gen_rtx_SUBREG (ifmode, im, 0);
+	      im = gen_rtx_ZERO_EXTRACT (ihmode, im, halfsize, halfsize);
+	      if (imode != ihmode)
+		im = gen_rtx_SUBREG (imode, im, 0);
+	    }
+	  im = gen_rtx_NEG (imode, im);
+	  return gen_rtx_CONCAT (mode, re, im);
+	}
+
     case ADDR_EXPR:
       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
       if (!op0 || !MEM_P (op0))
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 791ecd3c96a5..b67bab3f8e45 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -12894,10 +12894,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
     case POST_INC:
     case POST_DEC:
     case POST_MODIFY:
-      /* POST_INC and POST_DEC can be handled just like a SUBREG.  So we
-	 just fall into the SUBREG code.  */
-
-      /* ... fall through ...  */
+      return mem_loc_descriptor (XEXP (rtl, 0), mode, initialized);
 
     case SUBREG:
       /* The case of a subreg may arise when we have a local (register)
@@ -12905,9 +12902,13 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
 	 up an entire register.  For now, just assume that it is
 	 legitimate to make the Dwarf info refer to the whole register which
 	 contains the given subreg.  */
-      rtl = XEXP (rtl, 0);
+      if (!subreg_lowpart_p (rtl))
+	break;
+      rtl = SUBREG_REG (rtl);
       if (GET_MODE_SIZE (GET_MODE (rtl)) > DWARF2_ADDR_SIZE)
 	break;
+      if (GET_MODE_CLASS (GET_MODE (rtl)) != MODE_INT)
+	break;
       mem_loc_result = mem_loc_descriptor (rtl, mode, initialized);
       break;
 
@@ -13392,12 +13393,19 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
 	  if (BITS_BIG_ENDIAN)
 	    shift = GET_MODE_BITSIZE (GET_MODE (XEXP (rtl, 0)))
 		    - shift - size;
-	  add_loc_descr (&mem_loc_result,
-			 int_loc_descriptor (DWARF2_ADDR_SIZE - shift - size));
-	  add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_shl, 0, 0));
-	  add_loc_descr (&mem_loc_result,
-			 int_loc_descriptor (DWARF2_ADDR_SIZE - size));
-	  add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
+	  if (shift + size != DWARF2_ADDR_SIZE)
+	    {
+	      add_loc_descr (&mem_loc_result,
+			     int_loc_descriptor (DWARF2_ADDR_SIZE
+						 - shift - size));
+	      add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_shl, 0, 0));
+	    }
+	  if (size != DWARF2_ADDR_SIZE)
+	    {
+	      add_loc_descr (&mem_loc_result,
+			     int_loc_descriptor (DWARF2_ADDR_SIZE - size));
+	      add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
+	    }
 	}
       break;
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7e166317e4de..587f15369207 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-10-15  Jakub Jelinek  <jakub@redhat.com>
+
+	PR debug/41717
+	* gcc.dg/debug/pr41717.c: New test.
+
 2009-10-16  Paul Thomas  <pault@gcc.gnu.org>
 
 	PR fortran/41648
diff --git a/gcc/testsuite/gcc.dg/debug/pr41717.c b/gcc/testsuite/gcc.dg/debug/pr41717.c
new file mode 100644
index 000000000000..21250883a115
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/pr41717.c
@@ -0,0 +1,10 @@
+/* PR debug/41717 */
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+  _Complex float v[1], w;
+  v[1] = 0.0f + 0.8fi;
+  w = __builtin_conjf (v[1] * v[1]);
+}
-- 
GitLab