From patchwork Mon Jan 20 13:03:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1225935 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-517767-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=F5i6ImJp; dkim-atps=neutral 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 481X1J6gblz9sR1 for ; Tue, 21 Jan 2020 00:04:04 +1100 (AEDT) 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; q=dns; s= default; b=Yn1Zd3NCmFmA3HrvXKizGIe8Uu0pcjqnQRCKU+8QUfiHqHjZve7zl MdMwgL8961najYe551hopKnlv7RnK17u4Jem+m7zFkZiHnCM0hu71++klt4WT2x8 mIdVzioj3CsZqbjgf9OH/+5K/x32NqOrXvIcnC13Skp1Cc17JYuT6c= 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; s= default; bh=j0ECzsiWVcLsRbhEk00FVj5LC2Q=; b=F5i6ImJpoQ6h8bhHtBzw c/NT9j/i+BNzuh1coCKUhgReLqeAmZ/+FsizgdcdrNejbvHiNiWk4ctWc5p2i5jW wBK9d+O2VJqKJc2i3jmiF+ODlfKDZuC37XgwENoUcL4R6eDQYHpM+tXFRiYT3Dmx X6inyLzUSk7csaFVdGlx9aI= Received: (qmail 13473 invoked by alias); 20 Jan 2020 13:03:57 -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 12921 invoked by uid 89); 20 Jan 2020 13:03:57 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-17.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=genuinely X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.110.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 Jan 2020 13:03:46 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8287630E for ; Mon, 20 Jan 2020 05:03:45 -0800 (PST) Received: from localhost (e121540-lin.manchester.arm.com [10.32.98.126]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2A9DB3F52E for ; Mon, 20 Jan 2020 05:03:45 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [PATCH] lra: Stop registers being incorrectly marked live [PR92989] Date: Mon, 20 Jan 2020 13:03:44 +0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes lra_assign has an assert to make sure that no pseudo is allocated to a conflicting hard register. It used to be restricted to !flag_ipa_ra, but in g:a1e6ee38e708ef2bdef4 I'd enabled it for flag_ipa_ra too. It then tripped while building libstdc++ for mips-mti-linux. The failure was due to code at the end of process_bb_lives. For an abnormal/EH edge, we need to make sure that all pseudos that are live on entry to the destination conflict with all hard registers that are clobbered by an abnormal call return. The usual way to do this would be to simulate a clobber of the hard registers, by making them live and them making them dead again. Making the registers live creates the conflict; making them dead again restores the correct live set for whatever follows. However, process_bb_lives skips the second step (making the registers dead again) at the start of a BB, presumably on the basis that there's no further code that needs a correct live set. The problem for the PR is that that wasn't quite true in practice. There was code further down process_bb_lives that updated the live-in set of the BB for some registers, and this live set was "contaminated" by registers that weren't live but that created conflicts. This information then got propagated to other blocks, so that registers that were made live purely to create a conflict at the start of the EH receiver then became needlessly live throughout preceding blocks. This in turn created a fake conflict with pseudos in those blocks, invalidating the choices made by IRA. The easiest fix seems to be to update the live-in set *before* adding the fake live registers. An alternative would be to simulate the full clobber, but that seems a bit wasteful. Tested on aarch64-linux-gnu and x86_64-linux-gnu, and that the preprocessed libstdc++ code now compiles for mipsisa64-elf. OK to install? Richard 2020-01-20 Richard Sandiford gcc/ PR rtl-optimization/92989 * lra-lives.c (process_bb_lives): Update the live-in set before processing additional clobbers. --- gcc/lra-lives.c | 96 ++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index 0adac6b5a42..f439e899395 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -1023,6 +1023,57 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) make_hard_regno_live (regno); } + bool live_change_p = false; + /* Check if bb border live info was changed. */ + unsigned int live_pseudos_num = 0; + EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), + FIRST_PSEUDO_REGISTER, j, bi) + { + live_pseudos_num++; + if (! sparseset_bit_p (pseudos_live, j)) + { + live_change_p = true; + if (lra_dump_file != NULL) + fprintf (lra_dump_file, + " r%d is removed as live at bb%d start\n", j, bb->index); + break; + } + } + if (! live_change_p + && sparseset_cardinality (pseudos_live) != live_pseudos_num) + { + live_change_p = true; + if (lra_dump_file != NULL) + EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j) + if (! bitmap_bit_p (df_get_live_in (bb), j)) + fprintf (lra_dump_file, + " r%d is added to live at bb%d start\n", j, bb->index); + } + + /* The order of this code and the code below is important. At this + point hard_regs_live does genuinely contain only live registers. + Below we pretend other hard registers are live in order to create + conflicts with pseudos, but this fake live set shouldn't leak out + into the df info. */ + for (i = 0; HARD_REGISTER_NUM_P (i); ++i) + { + if (!TEST_HARD_REG_BIT (hard_regs_live, i)) + continue; + + if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i)) + continue; + + if (bitmap_bit_p (df_get_live_in (bb), i)) + continue; + + live_change_p = true; + if (lra_dump_file) + fprintf (lra_dump_file, + " hard reg r%d is added to live at bb%d start\n", i, + bb->index); + bitmap_set_bit (df_get_live_in (bb), i); + } + /* Pseudos can't go in stack regs at the start of a basic block that is reached by an abnormal edge. Likewise for registers that are at least partly call clobbered, because caller-save, fixup_abnormal_edges @@ -1057,32 +1108,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) make_hard_regno_live (px); } - bool live_change_p = false; - /* Check if bb border live info was changed. */ - unsigned int live_pseudos_num = 0; - EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), - FIRST_PSEUDO_REGISTER, j, bi) - { - live_pseudos_num++; - if (! sparseset_bit_p (pseudos_live, j)) - { - live_change_p = true; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " r%d is removed as live at bb%d start\n", j, bb->index); - break; - } - } - if (! live_change_p - && sparseset_cardinality (pseudos_live) != live_pseudos_num) - { - live_change_p = true; - if (lra_dump_file != NULL) - EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j) - if (! bitmap_bit_p (df_get_live_in (bb), j)) - fprintf (lra_dump_file, - " r%d is added to live at bb%d start\n", j, bb->index); - } /* See if we'll need an increment at the end of this basic block. An increment is needed if the PSEUDOS_LIVE set is not empty, to make sure the finish points are set up correctly. */ @@ -1102,25 +1127,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) check_pseudos_live_through_calls (j, last_call_abi); } - for (i = 0; HARD_REGISTER_NUM_P (i); ++i) - { - if (!TEST_HARD_REG_BIT (hard_regs_live, i)) - continue; - - if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i)) - continue; - - if (bitmap_bit_p (df_get_live_in (bb), i)) - continue; - - live_change_p = true; - if (lra_dump_file) - fprintf (lra_dump_file, - " hard reg r%d is added to live at bb%d start\n", i, - bb->index); - bitmap_set_bit (df_get_live_in (bb), i); - } - if (need_curr_point_incr) next_program_point (curr_point, freq);