PATCH: sjlj exceptions

John David Anglin dave@hiauly1.hia.nrc.ca
Fri Oct 27 13:21:00 GMT 2000


This patch resolves to some extent the problems noted in these two postings:
< http://gcc.gnu.org/ml/gcc-bugs/2000-08/msg00687.html > and
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00083.html >.  My investigation
revealed that the problem is only present when sjlj exceptions are used.
The memory expansion occured in the gcse pass and was a result of the
large number of edges present in functions using sjlj exceptions.

There are two separate parts to the fix.  The first part is to define
a nonlocal goto label after the setjmp call when a library version of
setjmp.  This fixes the basic block reordering problem noted in this post:
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00526.html >.

The second part is to set current_function_calls_setjmp = 1.  This causes
the gcse pass to punt, preventing the memory buildup.  I think it is also
necessary to ensure that registers are properly saved.  It also causes
all the NOTE_INSN_EH_REGION_[BEG,END] notes to be deleted after the first
pass.

The patch has been tested with a complete bootstrap and check.
DONT_USE_BUILTIN_SETJMP was not defined for this test.  The tFile.exp
test now completes in a reasonable 196 seconds on a 735.  There are no gcc
regressions.  Here are the results of the g++ testsuite.

FAIL: g++.eh/crash4.C caused compiler crash
FAIL: g++.ext/attrib5.C (test for excess errors)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 18)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 20)
FAIL: g++.ext/instantiate2.C not instantiated (test for errors, line 16)
FAIL: g++.ext/instantiate3.C not instantiated (test for errors, line 13)
XPASS: g++.mike/eh33.C (test for excess errors)
XPASS: g++.mike/eh33.C  Execution test
XPASS: g++.mike/eh50.C (test for excess errors)
XPASS: g++.mike/eh50.C  Execution test
FAIL: g++.other/crash18.C (test for excess errors)
XPASS: g++.pt/static3.C (test for excess errors)
XPASS: g++.pt/static3.C  Execution test
XPASS: g++.pt/static6.C (test for excess errors)

Thus, all is ok with g++ testsuite.

Issues:

1)	The gcse pass no longer runs when sjlj exceptions are used.  It
	may be possible to run the gcse pass when using sjlj exceptions but
	I think make_edges needs improvement first.  Given this, should
	sjlj still be the default exception mode?  On the otherhand, I
	doubt -fno-sjlj-exceptions has ever been tested on the pa.

2)	The memory used by the gcse pass is very dependent on the number
	of edges created by make_edges.  I think make_edges has to try
	harder to determine the active handler for call insns and aynchronous
	exceptions (see code and notes following line 1157 in flow.c).
	Currently, calls without a REG_EH_REGION note generate edges to
	all nonlocal labels in the function.  The function t7 in tFile.cc
	has about 60 nonlocal goto labels on the pa and it is not a very
	big function.  The gcse pass needed about 40MB peak to handle this.

3)	There may be an issue regarding inlining.  According to
	function_cannot_inline_p, functions with current_function_calls_setjmp
	!= 0 are not safe to integrate into other functions.  Thus, using
	sjlj-exceptions may limit inlining.  On the otherhand, I don't
	think the above restriction is being adhered to.

4)	I suspect that expand_calls needs to be modified to add a nonlocal
	goto label after "real" setjmp calls to avoid the basic block
	reordering problem noted above.  This problem may only occur
	when the are multiple setjmp calls.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6605)

2000-10-26  J. David Anglin  <dave@hiauly1.hia.nrc.ca>

	* libgcc2.c: Don't provide an explicit prototype for longjmp since
	this may clash with a previously included one.
	* except.c (start_dynamic_handler): Add a nonlocal goto label after
	library setjmp calls so flow doesn't get confused and set
	current_function_calls_setjmp = 1 because gcse can't build an
	accurate cfg in functions which call setjmp.
	
--- libgcc2.c.orig	Sat Oct 21 14:00:41 2000
+++ libgcc2.c	Wed Oct 25 19:17:12 2000
@@ -3438,7 +3438,7 @@
    method.  */
 
 #ifdef DONT_USE_BUILTIN_SETJMP
-extern void longjmp (void *, int);
+extern void longjmp ();
 #endif
 
 /* Routine to get the head of the current thread's dynamic handler chain
--- except.c.orig	Fri Oct 13 15:58:55 2000
+++ except.c	Thu Oct 26 19:50:34 2000
@@ -1351,9 +1351,15 @@
   buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
 
 #ifdef DONT_USE_BUILTIN_SETJMP
+  /* Generate a nonlocal goto label so flow doesn't get confused. */
+  rtx lab1 = gen_label_rtx();
   x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
 			       TYPE_MODE (integer_type_node), 1,
 			       buf, Pmode);
+  emit_label (lab1);
+  current_function_has_nonlocal_label = 1;
+  nonlocal_goto_handler_labels
+    = gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
   /* If we come back here for a catch, transfer control to the handler.  */
   jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
 #else
@@ -1366,6 +1372,9 @@
   }
 #endif
 
+  /* Tell the world that this function calls setjmp. */ 
+  current_function_calls_setjmp = 1;
+
   /* We are committed to this, so update the handler chain.  */
 
   emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));


More information about the Gcc-bugs mailing list