From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27753 invoked by alias); 20 Jul 2007 11:39:11 -0000 Received: (qmail 27745 invoked by uid 22791); 20 Jul 2007 11:39:10 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 20 Jul 2007 11:39:06 +0000 Received: (qmail 16378 invoked from network); 20 Jul 2007 11:39:04 -0000 Received: from unknown (HELO gateway) (10.0.0.100) by mail.codesourcery.com with SMTP; 20 Jul 2007 11:39:04 -0000 Received: by gateway (Postfix, from userid 1010) id 642AB6C11E; Fri, 20 Jul 2007 04:39:04 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard@codesourcery.com Subject: Fix mode-switching problem for SH SJLJ exceptions Date: Fri, 20 Jul 2007 14:38:00 -0000 Message-ID: <87myxruwx4.fsf@firetop.home> User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-07/txt/msg01592.txt.bz2 Functions that return a value usually end with the sequence: A: (clobber (reg H)) ... B: (set (reg H) (reg P)) ... C: (use (reg H)) where H is the hard return register and P is the pseudo register to which return values are assigned. mode-switching.c uses a specially-split exit block to enforce MODE_EXIT (the mode required on exit from a function). The code that creates this block -- create_pre_exit -- tries to find insn B and starts the new block immediately before (or sometimes immediately after) it. However, B can be deleted if P is never initialised. In this case, create_pre_exit splits the block immediately before A instead. The code only searches for A and B in the fallthrough predecessor to the exit block; it assumes that P is never initialised if the block contains neither A nor B. In some cases B may be made up of several individual insns. create_pre_exit therefore records the range of modified registers and stops on the first SET that doesn't assign to part of H. It then asserts that it has found a SET or CLOBBER for the whole of H (except in some corner cases). This shows up a problem on SJLJ targets, where the call to the SJLJ unregister function is inserted between A and B. If B has been deleted, the first SET we find may be setting up the argument to that call. We then stop the search without having found either A or B, so the assertion triggers. At this point we have already searched past the call itself, and this seems bogus. We are supposed to enforce MODE_EXIT _after_ the last call. I therefore just treated searches that reach a call in the same way as searches that reach the beginning of a block. Bootstrapped & regression-tested on x86_64-linux-gnu. Also regression-tested on sh-elf (multilibs {,-m2,-m3,-m4,-m4/-ml}) and sh-wrs-vxworks. OK to install? Richard gcc/ * mode-switching.c (create_pre_exit): Don't search past calls. Index: gcc/mode-switching.c =================================================================== --- gcc/mode-switching.c (revision 126715) +++ gcc/mode-switching.c (working copy) @@ -246,6 +246,17 @@ create_pre_exit (int n_entities, int *en if (INSN_P (return_copy)) { + /* When using SJLJ exceptions, the call to the + unregister function is inserted between the + clobber of the return value and the copy. + We do not want to split the block before this + or any other call; if we have not found the + copy yet, the copy must have been deleted. */ + if (CALL_P (return_copy)) + { + short_block = 1; + break; + } return_copy_pat = PATTERN (return_copy); switch (GET_CODE (return_copy_pat)) {