From patchwork Fri Nov 28 01:44:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Segher Boessenkool X-Patchwork-Id: 415767 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 D2007140182 for ; Fri, 28 Nov 2014 12:46:21 +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:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; q=dns; s=default; b=HfjdT+jjkLO6c9PRiFs c2nzha1VTxCWzy5vm4GCQO8occ/ozrgjfRkYNZhA4lLUvLmMsL1YDgvV8YKWiPSy Xo0FPgvvICVuwA68NuIu4HgiEpTN03B/BojPAaCaaJCqqPAk8adpNJsaUkGm15HP lZXwyC4VjKmGbmYhd4U1iEms= 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:in-reply-to:references :in-reply-to:references; s=default; bh=Lo/+HmZUZZldUacHpZgF99j0t 7U=; b=sECYvXVJ8E17GYiEcAM3EgtIjjjX7i0uoSvuZ00KuYYazhdy2Xe2EyYJb knqgR8rhLvPJ04PPQjqluZXWQEMgCU3lCdXJ/QfrDPMfb6vJZOClF3VVBY3AQC/T 8vP0CGD9WzxcwXYsHrkpbqawlDDAlF2Qa5kXdmAslC/bavWP3Q= Received: (qmail 30091 invoked by alias); 28 Nov 2014 01:46:14 -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 30078 invoked by uid 89); 28 Nov 2014 01:46:11 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: gcc1-power7.osuosl.org Received: from gcc1-power7.osuosl.org (HELO gcc1-power7.osuosl.org) (140.211.15.137) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 28 Nov 2014 01:46:10 +0000 Received: from gcc1-power7.osuosl.org (localhost [127.0.0.1]) by gcc1-power7.osuosl.org (8.14.6/8.14.6) with ESMTP id sAS1k7VX010085; Thu, 27 Nov 2014 17:46:07 -0800 Received: (from segher@localhost) by gcc1-power7.osuosl.org (8.14.6/8.14.6/Submit) id sAS1k76b010083; Thu, 27 Nov 2014 17:46:07 -0800 From: Segher Boessenkool To: gcc-patches@gcc.gnu.org Cc: Segher Boessenkool Subject: [PATCH 3/6] combine: handle I2 a parallel of two SETs Date: Thu, 27 Nov 2014 17:44:33 -0800 Message-Id: <9c173bc0a5f174717ca93b7263231f63631c65a7.1417135737.git.segher@kernel.crashing.org> In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes If I2 is a PARALLEL of two SETs, split it into two instructions, I1 and I2. If there already was an I1, rename it to I0. If there already was an I0, don't do anything. This surprisingly simple patch is enough to let combine handle such PARALLELs properly. v2: Add some functions to make the checking for a suitable PARALLEL more readable (and more general). 2014-11-27 Segher Boessenkool gcc/ * combine.c (is_parallel_of_n_reg_sets): New function. (can_split_parallel_of_n_reg_sets): New function. (try_combine): If I2 is a PARALLEL of two SETs, split it into two insns if possible. --- gcc/combine.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/gcc/combine.c b/gcc/combine.c index 7e3f4e6..6c94e53 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2461,6 +2461,59 @@ update_cfg_for_uncondjump (rtx_insn *insn) } } +/* Return whether INSN is a PARALLEL of exactly N register SETs followed + by an arbitrary number of CLOBBERs. */ +static bool +is_parallel_of_n_reg_sets (rtx_insn *insn, int n) +{ + rtx pat = PATTERN (insn); + + if (GET_CODE (pat) != PARALLEL) + return false; + + int len = XVECLEN (pat, 0); + if (len < n) + return false; + + int i; + for (i = 0; i < n; i++) + if (GET_CODE (XVECEXP (pat, 0, i)) != SET + || !REG_P (SET_DEST (XVECEXP (pat, 0, i)))) + return false; + for ( ; i < len; i++) + if (GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER) + return false; + + return true; +} + +/* Return whether INSN, a PARALLEL of N register SETs (and maybe some + CLOBBERs), can be split into individual SETs in that order, without + changing semantics. */ +static bool +can_split_parallel_of_n_reg_sets (rtx_insn *insn, int n) +{ + if (!insn_nothrow_p (insn)) + return false; + + rtx pat = PATTERN (insn); + + int i, j; + for (i = 0; i < n; i++) + { + if (side_effects_p (SET_SRC (XVECEXP (pat, 0, i)))) + return false; + + rtx reg = SET_DEST (XVECEXP (pat, 0, i)); + + for (j = i + 1; j < n; j++) + if (reg_referenced_p (reg, XVECEXP (pat, 0, j))) + return false; + } + + return true; +} + /* Try to combine the insns I0, I1 and I2 into I3. Here I0, I1 and I2 appear earlier than I3. I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into @@ -2817,6 +2870,31 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, alloc_insn_link (i1, regno, LOG_LINKS (i2))); } } + + /* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs), + make those two SETs separate I1 and I2 insns, and make an I0 that is + the original I1. */ + if (i0 == 0 + && is_parallel_of_n_reg_sets (i2, 2) + && can_split_parallel_of_n_reg_sets (i2, 2) + && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0)), i2, i3) + && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1)), i2, i3)) + { + /* If there is no I1, there is no I0 either. */ + i0 = i1; + + /* We make I1 with the same INSN_UID as I2. This gives it + the same DF_INSN_LUID for value tracking. Our fake I1 will + never appear in the insn stream so giving it the same INSN_UID + as I2 will not cause a problem. */ + + i1 = gen_rtx_INSN (VOIDmode, NULL, i2, BLOCK_FOR_INSN (i2), + XVECEXP (PATTERN (i2), 0, 0), INSN_LOCATION (i2), + -1, NULL_RTX); + INSN_UID (i1) = INSN_UID (i2); + + SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 1)); + } #endif /* Verify that I2 and I1 are valid for combining. */