From patchwork Sun Nov 27 10:31:09 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 127881 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 14989B6F9D for ; Sun, 27 Nov 2011 21:31:34 +1100 (EST) Received: (qmail 5818 invoked by alias); 27 Nov 2011 10:31:30 -0000 Received: (qmail 5810 invoked by uid 22791); 27 Nov 2011 10:31:29 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 27 Nov 2011 10:31:13 +0000 Received: by wwo28 with SMTP id 28so7489877wwo.8 for ; Sun, 27 Nov 2011 02:31:12 -0800 (PST) Received: by 10.227.205.130 with SMTP id fq2mr31029768wbb.17.1322389872264; Sun, 27 Nov 2011 02:31:12 -0800 (PST) Received: from localhost (rsandifo.gotadsl.co.uk. [82.133.89.107]) by mx.google.com with ESMTPS id et20sm34865034wbb.15.2011.11.27.02.31.10 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 27 Nov 2011 02:31:11 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: Shrink-wrapping vs. EXIT_IGNORE_STACK Date: Sun, 27 Nov 2011 10:31:09 +0000 Message-ID: <87fwh96emq.fsf@firetop.home> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org resource.c (as used by dbr_schedule) considers the stack pointer to be unused on entry to the epilogue if: EXIT_IGNORE_STACK && frame_pointer_needed && !current_function_sp_is_unchanging Then the stack deallocation in the epilogue usually causes the stack pointer to become live on function exit (which it must always be): while ((epilogue_insn = next_nonnote_insn (epilogue_insn))) { mark_set_resources (epilogue_insn, &end_of_function_needs, 0, MARK_SRC_DEST_CALL); if (return_insn_p (epilogue_insn)) break; } But in gcc.c-torture/execute/920428-2.c -Os on mips64-linux-gnu, we have a case where the shrink-wrapped part of the function requires a frame but has no normal exits. There is therefore no epilogue. This means that the stack pointer is never added to end_of_function_needs, and dbr_schedule thinks that normal exits (which are all outside the shrink-wrapped part) do not care about the stack pointer. We then end up speculatively executing the prologue stack allocation. One fix would be to add: SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM); after the loop above, but it felt odd for start_of_epilogue_needs to be different from end_of_function_needs when there is no epilogue. The patch below seemed better. Tested on mips64-linux-gnu. OK to install? Richard gcc/ * resource.c (init_resource_info): Only consider EXIT_IGNORE_STACK if there is in epilogue. Index: gcc/resource.c =================================================================== --- gcc/resource.c 2011-11-26 14:38:30.000000000 +0000 +++ gcc/resource.c 2011-11-26 14:40:04.000000000 +0000 @@ -1145,11 +1145,11 @@ init_resource_info (rtx epilogue_insn) basic_block bb; /* Indicate what resources are required to be valid at the end of the current - function. The condition code never is and memory always is. If the - frame pointer is needed, it is and so is the stack pointer unless - EXIT_IGNORE_STACK is nonzero. If the frame pointer is not needed, the - stack pointer is. Registers used to return the function value are - needed. Registers holding global variables are needed. */ + function. The condition code never is and memory always is. + The stack pointer is needed unless EXIT_IGNORE_STACK is true + and there is an epilogue that restores the original stack pointer + from the frame pointer. Registers used to return the function value + are needed. Registers holding global variables are needed. */ end_of_function_needs.cc = 0; end_of_function_needs.memory = 1; @@ -1162,11 +1162,11 @@ init_resource_info (rtx epilogue_insn) #if !HARD_FRAME_POINTER_IS_FRAME_POINTER SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM); #endif - if (! EXIT_IGNORE_STACK - || current_function_sp_is_unchanging) - SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM); } - else + if (!(EXIT_IGNORE_STACK + && epilogue_insn + && frame_pointer_needed + && !current_function_sp_is_unchanging)) SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM); if (crtl->return_rtx != 0)