From patchwork Tue Nov 1 06:32:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Filippov X-Patchwork-Id: 689773 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t7Lyz63Lgz9sD6 for ; Tue, 1 Nov 2016 17:33:31 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=quhAbmXB; dkim-atps=neutral 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:cc:subject:date:message-id; q=dns; s=default; b=l87Iql5tKF2P ri2SRaxippy3hfaOYQ8yOa0zQ67KAeyGykVb9iTFvycod+rgWdTiOL4WcES5ZTvj LR1rgyeH026xcjwVvZ1h/bFd78y9XGilFpDZzIXYe/J/2I2MoiPNhU1jDecnBpUD XFhJTA3CwM2SN0nns/z195dKf0IIRnA= 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:cc:subject:date:message-id; s=default; bh=vI/43SOX33W3cAFZe+ 3FcVUhJMI=; b=quhAbmXBXN5r8fQgwZGJ1t5Eoa46DVCovnr84qJhf0IhcZpEkC TxXTNLtXsXEh24TXMOEMqyhmBylZNp4sY+CeqHHj2sClifsY/svvHnyGTaGPN6OD sJ83oyG806VdNPaMBGo5601MGj/BR/PfgirIgXa3mIFueWI0+Mqjrn6U4= Received: (qmail 88698 invoked by alias); 1 Nov 2016 06:33:19 -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 69800 invoked by uid 89); 1 Nov 2016 06:33:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=BAYES_00, FREEMAIL_FROM, FROM_LOCAL_NOVOWEL, HK_RANDOM_ENVFROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=Largest, 9013, 1020, H*r:sk:c-73-20 X-HELO: mail-pf0-f196.google.com Received: from mail-pf0-f196.google.com (HELO mail-pf0-f196.google.com) (209.85.192.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 01 Nov 2016 06:32:55 +0000 Received: by mail-pf0-f196.google.com with SMTP id a136so7414739pfa.0 for ; Mon, 31 Oct 2016 23:32:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=C0bK6KgeFtfwOtWytrurBvOvxsDbvKgQVJLoc3C+VVA=; b=AnBriHFom10xGJ7JemyaP+mDM5TuYkTVUC00x9Cb4Y+LXuxsJ5aZjG3EkThYolWCmX Dw/eNEz52cXHVJ58LAs1w3uxfy6IxqiX5nmt67RfLDXNwra+tv3GAm5QnMvEjpAFq2bx vDKoaNITRllx2YpMt3TwaSbjAe+6S1Nl9kSPcG0RGqXvmU79zNaIEQm4/M+Zkq8TQaTm hrD2fdOUKBBmGUaJsg28x0HTcT7Ad/FRoHtTgy1xwJN9Yey2GMpwxPIBSRz/NobXqH7i I75yOoPPy4lJFMij1zqKE7cKwZrNC66twqyQB2rXX8Us0oybk+17egfYp3kQJd85fpyV kh8g== X-Gm-Message-State: ABUngvcJvfYQAJ8YCNy4fVjM6nAm2zyW+6R5LebaatElqS9Aywv9MZ6hbNb6hC9lte9x1w== X-Received: by 10.99.110.14 with SMTP id j14mr47179915pgc.135.1477981973285; Mon, 31 Oct 2016 23:32:53 -0700 (PDT) Received: from octofox.net (c-73-202-152-109.hsd1.ca.comcast.net. [73.202.152.109]) by smtp.gmail.com with ESMTPSA id n2sm39560900pfa.75.2016.10.31.23.32.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 31 Oct 2016 23:32:52 -0700 (PDT) From: Max Filippov To: gcc-patches@gcc.gnu.org Cc: linux-xtensa@linux-xtensa.org, Sterling Augustine , Max Filippov Subject: [PATCH] xtensa: Fix PR target/78118 Date: Mon, 31 Oct 2016 23:32:32 -0700 Message-Id: <1477981952-8738-1-git-send-email-jcmvbkbc@gmail.com> X-IsSubscribed: yes It started failing after the following commit: 32e90dc6a0cda45 ("PR rtl-optimization/61047"). The change that made xtensa backend go ICE looks completely unrelated, and indeed, the issue is caused by the side effect of compute_frame_size() function call hidden in the INITIAL_ELIMINATION_OFFSET macro. This call updates the value of the xtensa_current_frame_size static variable, used in "return" instruction predicate. Prior to the change the value of xtensa_current_frame_size was set to 0 after the end of epilogue generation, which enabled the "return" instruction for the CALL0 ABI, but after the change the additional INITIAL_ELIMINATION_OFFSET calls make xtensa_current_frame_size non-zero and "return" pattern unavailable. Get rid of the global xtensa_current_frame_size and xtensa_callee_save_size variables by moving them into the machine_function structure. Implement predicate for the "return" pattern as a function. Don't communicate completion of epilogue generation through zeroing of xtensa_current_frame_size, add explicit epilogue_done variable to the machine_function structure. Don't update stack frame layout after the completion of reload. 2016-10-26 Max Filippov gcc/ * config/xtensa/xtensa-protos.h (xtensa_use_return_instruction_p): New prototype. * config/xtensa/xtensa.c (xtensa_current_frame_size, xtensa_callee_save_size): Remove. (struct machine_function): Add new fields: current_frame_size, callee_save_size, frame_laid_out and epilogue_done. (compute_frame_size, xtensa_expand_prologue, xtensa_expand_epilogue): Replace xtensa_callee_save_size with cfun->machine->callee_save_size and xtensa_current_frame_size with cfun->machine->current_frame_size. (compute_frame_size): Update cfun->machine->frame_laid_out and don't update frame layout after reload completion. (xtensa_expand_epilogue): Set cfun->machine->epilogue_done instead of zeroing xtensa_current_frame_size. (xtensa_use_return_instruction_p): New function. * config/xtensa/xtensa.h (xtensa_current_frame_size): Remove declaration. (INITIAL_ELIMINATION_OFFSET): Use return value of compute_frame_size instead of xtensa_current_frame_size value. * config/xtensa/xtensa.md ("return" pattern): Use new predicate function xtensa_use_return_instruction_p instead of inline code. --- gcc/config/xtensa/xtensa-protos.h | 1 + gcc/config/xtensa/xtensa.c | 82 ++++++++++++++++++++++++--------------- gcc/config/xtensa/xtensa.h | 6 +-- gcc/config/xtensa/xtensa.md | 2 +- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index f2ca526..873557f 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx); extern void xtensa_setup_frame_addresses (void); extern int xtensa_dbx_register_number (int); extern long compute_frame_size (int); +extern bool xtensa_use_return_instruction_p (void); extern void xtensa_expand_prologue (void); extern void xtensa_expand_epilogue (void); extern void order_regs_for_local_alloc (void); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 60e5029..2115b57 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -79,11 +79,6 @@ enum internal_test can support a given mode. */ char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; -/* Current frame size calculated by compute_frame_size. */ -unsigned xtensa_current_frame_size; -/* Callee-save area size in the current frame calculated by compute_frame_size. */ -int xtensa_callee_save_size; - /* Largest block move to handle in-line. */ #define LARGEST_MOVE_RATIO 15 @@ -95,6 +90,13 @@ struct GTY(()) machine_function bool vararg_a7; rtx vararg_a7_copy; rtx_insn *set_frame_ptr_insn; + /* Current frame size calculated by compute_frame_size. */ + unsigned current_frame_size; + /* Callee-save area size in the current frame calculated by + compute_frame_size. */ + int callee_save_size; + bool frame_laid_out; + bool epilogue_done; }; /* Vector, indexed by hard register number, which contains 1 for a @@ -2632,24 +2634,29 @@ compute_frame_size (int size) { int regno; + if (reload_completed && cfun->machine->frame_laid_out) + return cfun->machine->current_frame_size; + /* Add space for the incoming static chain value. */ if (cfun->static_chain_decl != NULL) size += (1 * UNITS_PER_WORD); - xtensa_callee_save_size = 0; + cfun->machine->callee_save_size = 0; for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) { if (xtensa_call_save_reg(regno)) - xtensa_callee_save_size += UNITS_PER_WORD; + cfun->machine->callee_save_size += UNITS_PER_WORD; } - xtensa_current_frame_size = + cfun->machine->current_frame_size = XTENSA_STACK_ALIGN (size - + xtensa_callee_save_size + + cfun->machine->callee_save_size + crtl->outgoing_args_size + (WINDOW_SIZE * UNITS_PER_WORD)); - xtensa_callee_save_size = XTENSA_STACK_ALIGN (xtensa_callee_save_size); - return xtensa_current_frame_size; + cfun->machine->callee_save_size = + XTENSA_STACK_ALIGN (cfun->machine->callee_save_size); + cfun->machine->frame_laid_out = true; + return cfun->machine->current_frame_size; } @@ -2703,6 +2710,7 @@ xtensa_expand_prologue (void) { int regno; HOST_WIDE_INT offset = 0; + int callee_save_size = cfun->machine->callee_save_size; /* -128 is a limit of single addi instruction. */ if (total_size > 0 && total_size <= 128) @@ -2716,7 +2724,7 @@ xtensa_expand_prologue (void) add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); offset = total_size - UNITS_PER_WORD; } - else if (xtensa_callee_save_size) + else if (callee_save_size) { /* 1020 is maximal s32i offset, if the frame is bigger than that * we move sp to the end of callee-saved save area, save and then @@ -2724,13 +2732,13 @@ xtensa_expand_prologue (void) if (total_size > 1024) { insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-xtensa_callee_save_size))); + GEN_INT (-callee_save_size))); RTX_FRAME_RELATED_P (insn) = 1; note_rtx = gen_rtx_SET (stack_pointer_rtx, plus_constant (Pmode, stack_pointer_rtx, - -xtensa_callee_save_size)); + -callee_save_size)); add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); - offset = xtensa_callee_save_size - UNITS_PER_WORD; + offset = callee_save_size - UNITS_PER_WORD; } else { @@ -2766,13 +2774,13 @@ xtensa_expand_prologue (void) { rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); emit_move_insn (tmp_reg, GEN_INT (total_size - - xtensa_callee_save_size)); + callee_save_size)); insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); RTX_FRAME_RELATED_P (insn) = 1; note_rtx = gen_rtx_SET (stack_pointer_rtx, plus_constant (Pmode, stack_pointer_rtx, - xtensa_callee_save_size - + callee_save_size - total_size)); add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); } @@ -2840,21 +2848,21 @@ xtensa_expand_epilogue (void) int regno; HOST_WIDE_INT offset; - if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024)) + if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024)) { rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); - emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size - - xtensa_callee_save_size)); + emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size - + cfun->machine->callee_save_size)); emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx, tmp_reg)); - offset = xtensa_callee_save_size - UNITS_PER_WORD; + offset = cfun->machine->callee_save_size - UNITS_PER_WORD; } else { if (frame_pointer_needed) emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); - offset = xtensa_current_frame_size - UNITS_PER_WORD; + offset = cfun->machine->current_frame_size - UNITS_PER_WORD; } /* Prevent reordering of saved a0 update and loading it back from @@ -2874,16 +2882,16 @@ xtensa_expand_epilogue (void) } } - if (xtensa_current_frame_size > 0) + if (cfun->machine->current_frame_size > 0) { if (frame_pointer_needed || /* always reachable with addi */ - xtensa_current_frame_size > 1024 || - xtensa_current_frame_size <= 127) + cfun->machine->current_frame_size > 1024 || + cfun->machine->current_frame_size <= 127) { - if (xtensa_current_frame_size <= 127) - offset = xtensa_current_frame_size; + if (cfun->machine->current_frame_size <= 127) + offset = cfun->machine->current_frame_size; else - offset = xtensa_callee_save_size; + offset = cfun->machine->callee_save_size; emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, @@ -2892,7 +2900,8 @@ xtensa_expand_epilogue (void) else { rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG); - emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size)); + emit_move_insn (tmp_reg, + GEN_INT (cfun->machine->current_frame_size)); emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp_reg)); } @@ -2903,11 +2912,22 @@ xtensa_expand_epilogue (void) stack_pointer_rtx, EH_RETURN_STACKADJ_RTX)); } - xtensa_current_frame_size = 0; - xtensa_callee_save_size = 0; + cfun->machine->epilogue_done = true; emit_jump_insn (gen_return ()); } +bool +xtensa_use_return_instruction_p (void) +{ + if (!reload_completed) + return false; + if (TARGET_WINDOWED_ABI) + return true; + if (compute_frame_size (get_frame_size ()) == 0) + return true; + return cfun->machine->epilogue_done; +} + void xtensa_set_return_address (rtx address, rtx scratch) { diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index 82e9900..58eb1b2 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see /* External variables defined in xtensa.c. */ -extern unsigned xtensa_current_frame_size; - /* Macros used in the machine description to select various Xtensa configuration options. */ #ifndef XCHAL_HAVE_MUL32_HIGH @@ -477,14 +475,14 @@ enum reg_class /* Specify the initial difference between the specified pair of registers. */ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ do { \ - compute_frame_size (get_frame_size ()); \ + long frame_size = compute_frame_size (get_frame_size ()); \ switch (FROM) \ { \ case FRAME_POINTER_REGNUM: \ (OFFSET) = 0; \ break; \ case ARG_POINTER_REGNUM: \ - (OFFSET) = xtensa_current_frame_size; \ + (OFFSET) = frame_size; \ break; \ default: \ gcc_unreachable (); \ diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index db54a12..fcdb6c8 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -1663,7 +1663,7 @@ (define_insn "return" [(return) (use (reg:SI A0_REG))] - "(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed" + "xtensa_use_return_instruction_p ()" { return TARGET_WINDOWED_ABI ? (TARGET_DENSITY ? "retw.n" : "retw") :