This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Clean up df in case of reload failure (PR middle-end/32370)


Hi!

df-core.c requires its passes (rest_of_handle_df_initialize
and rest_of_handle_df_finish) to be executed in pairs, if
it is initialized, it must be cleaned up and it can't be cleaned up
if not initialized.  But they are invoked in different passes.c
pass lists.
pass_df_initialize_{,no_}opt is invoked from pass_rest_of_compilation.sub
pass list, while pass_df_finish is invoked from pass_postreload.sub
(where pass_postreload is in pass_rest_of_compilation.sub pass list).
This means if gate_postreload returns false and none of
pass_postreload.sub passes are executed (this happens when there is some
global alloc or reload failure, as can be seen on the testcase below),
df will not be cleaned up.  When gcc tries to compile some next function,
it will be confused because df is non-NULL, but some of its data structures
(e.g. bitmaps) have been already freed.  Even if that went through, it
would crash on next rest_of_handle_df_initialize's assertion.

The following patch fixes this by adding another pass, which will
call rest_of_handle_df_finish in case of pass_postreload failure.

Ok for trunk?

2007-08-24  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/32370
	* df-core.c (gate_df_clean_state): New function.
	(pass_df_clean_state): New variable.
	* tree-pass.h (pass_df_clean_state): New decl.
	* passes.c (init_optimization_passes): Add pass_df_clean_state
	after pass_postreload.

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

--- gcc/df-core.c.jj	2007-08-13 15:11:18.000000000 +0200
+++ gcc/df-core.c	2007-08-24 22:08:50.000000000 +0200
@@ -842,6 +842,35 @@ struct tree_opt_pass pass_df_finish =
 };
 
 
+/* pass_df_finish is executed from within pass_postreload.sub pass list,
+   so if reload fails e.g. because of incorrect asm constraints, it
+   will be skipped.  The following pass will run only in that case
+   after pass_postreload to clean it up instead.  */
+
+
+static bool
+gate_df_clean_state (void)
+{
+  return !reload_completed;
+}
+
+
+struct tree_opt_pass pass_df_clean_state =
+{
+  "dfclean",				/* name */
+  gate_df_clean_state,			/* gate */
+  rest_of_handle_df_finish,		/* execute */
+  NULL,					/* sub */
+  NULL,					/* next */
+  0,					/* static_pass_number */
+  0,					/* tv_id */
+  0,					/* properties_required */
+  0,					/* properties_provided */
+  0,					/* properties_destroyed */
+  0,					/* todo_flags_start */
+  0,					/* todo_flags_finish */
+  'z'					/* letter */
+};
 
 
 
--- gcc/tree-pass.h.jj	2007-08-15 15:36:32.000000000 +0200
+++ gcc/tree-pass.h	2007-08-24 21:39:11.000000000 +0200
@@ -424,6 +424,7 @@ extern struct tree_opt_pass pass_sched2;
 extern struct tree_opt_pass pass_stack_regs;
 extern struct tree_opt_pass pass_stack_regs_run;
 extern struct tree_opt_pass pass_df_finish;
+extern struct tree_opt_pass pass_df_clean_state;
 extern struct tree_opt_pass pass_compute_alignments;
 extern struct tree_opt_pass pass_duplicate_computed_gotos;
 extern struct tree_opt_pass pass_variable_tracking;
--- gcc/passes.c.jj	2007-08-15 15:36:32.000000000 +0200
+++ gcc/passes.c	2007-08-24 21:39:11.000000000 +0200
@@ -769,6 +769,7 @@ init_optimization_passes (void)
 	  NEXT_PASS (pass_set_nothrow_function_flags);
 	  NEXT_PASS (pass_final);
 	}
+      NEXT_PASS (pass_df_clean_state);
     }
   NEXT_PASS (pass_clean_state);
   *p = NULL;
--- gcc/testsuite/gcc.dg/pr32370.c.jj	2007-08-24 21:59:04.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr32370.c	2007-08-24 21:58:32.000000000 +0200
@@ -0,0 +1,24 @@
+/* PR middle-end/32370 */
+/* { dg-do compile { target i?86-*-* x86_64-*-* ia64-*-* } } */
+/* { dg-options "" { target ia64-*-* } } */
+/* { dg-options "-ffixed-esi" { target i?86-*-* x86_64-*-* } } */
+
+#if defined __i386__ || defined __x86_64__
+# define C "=S"
+#elif defined __ia64__
+# define C "=a"
+#endif
+
+unsigned int
+foo (unsigned long port)
+{
+  unsigned int v;
+  __asm__ __volatile__ ("" : C (v) : "Nd" (port));	/* { dg-error "while reloading\|has impossible" } */
+  return v;
+}
+
+void
+bar (void)
+{
+  foo (0);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]