From patchwork Fri May 31 17:59:34 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 247994 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 8D7352C0095 for ; Sat, 1 Jun 2013 04:00:35 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=w1JuswKT+lrQOxN4 f4/dSVEEQJKtCvfrglKgQu0BkCLbiZp0GhvWAcIfx43NYaBECNNABtEKb5Q5VQpe PDlYOAUHHZEleKg4Tw8aDhaWxlovwD5VoC64wC0T87g9PZlMS2etNbUCW9iEG1bG haVHg7QtHHy1153FH4RlShXISlI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=jVZ3GYYmf6pV8Q3WA4sUQb SunxQ=; b=cexb21xSt6wa4lo21hUxa6+sV0Qexaoiy0RjKMrqGBiZQEhKYjmsPW uOvOsUC0TN3EM//2ZtZZEB+JxrJiV21AH9LdowcrxGIkxS4zs2CRsOSBm2b9/L4q Wmm4Y/6pLJbyrafrspgtiYAlUKqrAOaAYgroynjoEF9KvCnSw7QaU= Received: (qmail 32332 invoked by alias); 31 May 2013 18:00:29 -0000 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 Received: (qmail 32318 invoked by uid 89); 31 May 2013 18:00:28 -0000 X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_00, TW_CF autolearn=ham version=3.3.1 Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 31 May 2013 18:00:27 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 93F932649044 for ; Fri, 31 May 2013 19:58:48 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6yVcV0Dn11v4 for ; Fri, 31 May 2013 19:58:47 +0200 (CEST) Received: from polaris.localnet (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id 9038B2649028 for ; Fri, 31 May 2013 19:58:47 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [ARM] Avoid spilling ip for nested APCS frames Date: Fri, 31 May 2013 19:59:34 +0200 Message-ID: <2875293.NhuTJeLEWM@polaris> User-Agent: KMail/4.7.2 (Linux/3.1.10-1.19-desktop; KDE/4.7.2; x86_64; ; ) MIME-Version: 1.0 X-Virus-Found: No The ARM/VxWorks port uses APCS frames and therefore ip to establish frames with a frame pointer. Now, for nested functions, ip is also the static chain register so it needs to be preserved when the frame is being established. There is code to that effect trying to save ip into r3 if the latter register is available but, unfortunately, it uses df_regs_ever_live_p (3) to detect the availability and this returns true for any non-toy function. Fixed by implementing an arm_r3_live_at_start_p modelled on the implementation of an equivalent predicate for %eax in the x86 back-end. Tested on ARM/VxWorks, OK for the mainline? 2013-05-31 Eric Botcazou * config/arm/arm.c (arm_r3_live_at_start_p): New predicate. (arm_compute_static_chain_stack_bytes): Use it. Tidy up. (arm_expand_prologue): Likewise. Index: config/arm/arm.c =================================================================== --- config/arm/arm.c (revision 199343) +++ config/arm/arm.c (working copy) @@ -16135,25 +16135,34 @@ arm_compute_save_reg0_reg12_mask (void) return save_reg_mask; } +/* Return true if r3 is live at the start of the function. */ + +static bool +arm_r3_live_at_start_p (void) +{ + /* Just look at cfg info, which is still close enough to correct at this + point. This gives false positives for broken functions that might use + uninitialized data that happens to be allocated in r3, but who cares? */ + return REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR), 3); +} /* Compute the number of bytes used to store the static chain register on the - stack, above the stack frame. We need to know this accurately to get the - alignment of the rest of the stack frame correct. */ + stack, above the stack frame. We need to know this accurately to get the + alignment of the rest of the stack frame correct. */ -static int arm_compute_static_chain_stack_bytes (void) +static int +arm_compute_static_chain_stack_bytes (void) { - unsigned long func_type = arm_current_func_type (); - int static_chain_stack_bytes = 0; + /* See the defining assertion in arm_expand_prologue. */ + if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM + && IS_NESTED (arm_current_func_type ()) + && arm_r3_live_at_start_p () + && crtl->args.pretend_args_size == 0) + return 4; - if (TARGET_APCS_FRAME && frame_pointer_needed && TARGET_ARM && - IS_NESTED (func_type) && - df_regs_ever_live_p (3) && crtl->args.pretend_args_size == 0) - static_chain_stack_bytes = 4; - - return static_chain_stack_bytes; + return 0; } - /* Compute a bit mask of which registers need to be saved on the stack for the current function. This is used by arm_get_frame_offsets, which may add extra registers. */ @@ -18081,16 +18090,16 @@ arm_expand_prologue (void) } else if (IS_NESTED (func_type)) { - /* The Static chain register is the same as the IP register + /* The static chain register is the same as the IP register used as a scratch register during stack frame creation. To get around this need to find somewhere to store IP whilst the frame is being created. We try the following places in order: - 1. The last argument register. + 1. The last argument register r3. 2. A slot on the stack above the frame. (This only works if the function is not a varargs function). - 3. Register r3, after pushing the argument registers + 3. Register r3 again, after pushing the argument registers onto the stack. Note - we only need to tell the dwarf2 backend about the SP @@ -18098,7 +18107,7 @@ arm_expand_prologue (void) doesn't need to be unwound, as it doesn't contain a value inherited from the caller. */ - if (df_regs_ever_live_p (3) == false) + if (!arm_r3_live_at_start_p ()) insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx); else if (args_to_push == 0) { @@ -18239,8 +18248,7 @@ arm_expand_prologue (void) if (IS_NESTED (func_type)) { /* Recover the static chain register. */ - if (!df_regs_ever_live_p (3) - || saved_pretend_args) + if (!arm_r3_live_at_start_p () || saved_pretend_args) insn = gen_rtx_REG (SImode, 3); else /* if (crtl->args.pretend_args_size == 0) */ {