From 89843f5dfbb0b867f42c7743a8691ebe5bb35682 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Thu, 3 Feb 2011 09:29:03 +0100
Subject: [PATCH] re PR target/47564 (internal compiler error in
 memory_address_addr_space, at explow.c:504)

	PR target/47564
	* toplev.c (target_reinit): Save and restore *crtl and regno_reg_rtx
	around backend_init_target and lang_dependent_init_target calls.
	* cgraphunit.c (cgraph_debug_gimple_stmt): New function.
	(verify_cgraph_node): Don't call set_cfun here.  Use
	cgraph_debug_gimple_stmt instead of debug_gimple_stmt.
	Set error_found for incorrectly represented calls to thunks.

	* gcc.target/i386/pr47564.c: New test.

From-SVN: r169784
---
 gcc/ChangeLog                           | 10 ++++++
 gcc/cgraphunit.c                        | 29 ++++++++++-------
 gcc/testsuite/ChangeLog                 |  5 +++
 gcc/testsuite/gcc.target/i386/pr47564.c | 42 +++++++++++++++++++++++++
 gcc/toplev.c                            | 26 +++++++++++++--
 5 files changed, 99 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr47564.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 90e257b51100..bf62fcadc066 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2011-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/47564
+	* toplev.c (target_reinit): Save and restore *crtl and regno_reg_rtx
+	around backend_init_target and lang_dependent_init_target calls.
+	* cgraphunit.c (cgraph_debug_gimple_stmt): New function.
+	(verify_cgraph_node): Don't call set_cfun here.  Use
+	cgraph_debug_gimple_stmt instead of debug_gimple_stmt.
+	Set error_found for incorrectly represented calls to thunks.
+
 2011-02-03  Alexandre Oliva  <aoliva@redhat.com>
 
 	PR debug/43092
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 848eba653040..f6fe2724b0b7 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -440,13 +440,22 @@ verify_edge_count_and_frequency (struct cgraph_edge *e)
   return error_found;
 }
 
+/* Switch to THIS_CFUN if needed and print STMT to stderr.  */
+static void
+cgraph_debug_gimple_stmt (struct function *this_cfun, gimple stmt)
+{
+  /* debug_gimple_stmt needs correct cfun */
+  if (cfun != this_cfun)
+    set_cfun (this_cfun);
+  debug_gimple_stmt (stmt);
+}
+
 /* Verify cgraph nodes of given cgraph node.  */
 DEBUG_FUNCTION void
 verify_cgraph_node (struct cgraph_node *node)
 {
   struct cgraph_edge *e;
   struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
-  struct function *saved_cfun = cfun;
   basic_block this_block;
   gimple_stmt_iterator gsi;
   bool error_found = false;
@@ -455,8 +464,6 @@ verify_cgraph_node (struct cgraph_node *node)
     return;
 
   timevar_push (TV_CGRAPH_VERIFY);
-  /* debug_generic_stmt needs correct cfun */
-  set_cfun (this_cfun);
   for (e = node->callees; e; e = e->next_callee)
     if (e->aux)
       {
@@ -499,7 +506,7 @@ verify_cgraph_node (struct cgraph_node *node)
 	  error ("An indirect edge from %s is not marked as indirect or has "
 		 "associated indirect_info, the corresponding statement is: ",
 		 identifier_to_locale (cgraph_node_name (e->caller)));
-	  debug_gimple_stmt (e->call_stmt);
+	  cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
 	  error_found = true;
 	}
     }
@@ -642,7 +649,7 @@ verify_cgraph_node (struct cgraph_node *node)
 			if (e->aux)
 			  {
 			    error ("shared call_stmt:");
-			    debug_gimple_stmt (stmt);
+			    cgraph_debug_gimple_stmt (this_cfun, stmt);
 			    error_found = true;
 			  }
 			if (!e->indirect_unknown_callee)
@@ -676,7 +683,8 @@ verify_cgraph_node (struct cgraph_node *node)
 			      {
 				error ("a call to thunk improperly represented "
 				       "in the call graph:");
-				debug_gimple_stmt (stmt);
+				cgraph_debug_gimple_stmt (this_cfun, stmt);
+				error_found = true;
 			      }
 			  }
 			else if (decl)
@@ -685,14 +693,14 @@ verify_cgraph_node (struct cgraph_node *node)
 				   "corresponding to a call_stmt with "
 				   "a known declaration:");
 			    error_found = true;
-			    debug_gimple_stmt (e->call_stmt);
+			    cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
 			  }
 			e->aux = (void *)1;
 		      }
 		    else if (decl)
 		      {
 			error ("missing callgraph edge for call stmt:");
-			debug_gimple_stmt (stmt);
+			cgraph_debug_gimple_stmt (this_cfun, stmt);
 			error_found = true;
 		      }
 		  }
@@ -710,7 +718,7 @@ verify_cgraph_node (struct cgraph_node *node)
 	      error ("edge %s->%s has no corresponding call_stmt",
 		     identifier_to_locale (cgraph_node_name (e->caller)),
 		     identifier_to_locale (cgraph_node_name (e->callee)));
-	      debug_gimple_stmt (e->call_stmt);
+	      cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
 	      error_found = true;
 	    }
 	  e->aux = 0;
@@ -721,7 +729,7 @@ verify_cgraph_node (struct cgraph_node *node)
 	    {
 	      error ("an indirect edge from %s has no corresponding call_stmt",
 		     identifier_to_locale (cgraph_node_name (e->caller)));
-	      debug_gimple_stmt (e->call_stmt);
+	      cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
 	      error_found = true;
 	    }
 	  e->aux = 0;
@@ -732,7 +740,6 @@ verify_cgraph_node (struct cgraph_node *node)
       dump_cgraph_node (stderr, node);
       internal_error ("verify_cgraph_node failed");
     }
-  set_cfun (saved_cfun);
   timevar_pop (TV_CGRAPH_VERIFY);
 }
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 69da9d62bd8e..001d60425bb6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-02-03  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/47564
+	* gcc.target/i386/pr47564.c: New test.
+
 2011-02-03  Alexandre Oliva  <aoliva@redhat.com>
 
 	PR tree-optimization/45122
diff --git a/gcc/testsuite/gcc.target/i386/pr47564.c b/gcc/testsuite/gcc.target/i386/pr47564.c
new file mode 100644
index 000000000000..5d3f25d1089f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr47564.c
@@ -0,0 +1,42 @@
+/* PR target/47564 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+static inline unsigned long long
+foo (const unsigned char *p)
+{
+  return 1;
+}
+
+__attribute__ ((__target__ ("sse4"))) void
+bar (unsigned long long *x, const void *b, long long m)
+{
+  const unsigned char *p = (const unsigned char *) b;
+  const unsigned char *e = p + m;
+  unsigned int l = *x;
+  unsigned long long n = l;
+
+  if ((e - p) >= 8192)
+    {
+      while ((e - p) >= 128)
+	{
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	  n = __builtin_ia32_crc32di (n, foo (p));
+	}
+    }
+
+  while ((e - p) >= 16)
+    {
+      n = __builtin_ia32_crc32di (n, foo (p));
+      n = __builtin_ia32_crc32di (n, foo (p));
+    }
+  l = n;
+  *x = l;
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 082c842139db..64af11200e9f 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1,7 +1,7 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -1780,11 +1780,33 @@ lang_dependent_init (const char *name)
 void
 target_reinit (void)
 {
+  struct rtl_data saved_x_rtl;
+  rtx *saved_regno_reg_rtx;
+
+  /* Save *crtl and regno_reg_rtx around the reinitialization
+     to allow target_reinit being called even after prepare_function_start.  */
+  saved_regno_reg_rtx = regno_reg_rtx;
+  if (saved_regno_reg_rtx)
+    {  
+      saved_x_rtl = *crtl;
+      memset (crtl, '\0', sizeof (*crtl));
+      regno_reg_rtx = NULL;
+    }
+
   /* Reinitialize RTL backend.  */
   backend_init_target ();
 
   /* Reinitialize lang-dependent parts.  */
   lang_dependent_init_target ();
+
+  /* And restore it at the end, as free_after_compilation from
+     expand_dummy_function_end clears it.  */
+  if (saved_regno_reg_rtx)
+    {
+      *crtl = saved_x_rtl;
+      regno_reg_rtx = saved_regno_reg_rtx;
+      saved_regno_reg_rtx = NULL;
+    }
 }
 
 void
-- 
GitLab