From patchwork Thu Nov 8 11:00:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 994759 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-489331-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="SOOH3bGK"; 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 42rL1g6ZXKz9sBZ for ; Thu, 8 Nov 2018 22:01:11 +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 :content-transfer-encoding; q=dns; s=default; b=mh3Bh6WDwUBGgKBR UxtE1PQeHsbSAghLvodhcHeTWkw1uLgeednVQb98ARjVAhFAr+h9e8+wwizZKssN W4UAFVZfZOmWCLggyMWWmFStvZxmDo65MR3FJznfdOGaidDWazP7rRk6QWk3tRGv 6gSe0phFEiwj0JbzLy9yvo/eKww= 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=C13wozz4czvKWxm/tw5jeE Prgg4=; b=SOOH3bGK3dlI9JYB2XRfd3Cni/vxWQantPzO9PBixqk3DJe4XUcIM+ ub3TL6DAxFdfIp11IyyAJWd4jOkjUY12O4iFAJ/R03sb6mvOjnU3pyQZBdBARXfM oMeo2n18sPVSxNhVTAagP7w5W6f1BK1pzQnisAdi8o1XUKEpW1M1U= Received: (qmail 130730 invoked by alias); 8 Nov 2018 11:00:54 -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 130582 invoked by uid 89); 8 Nov 2018 11:00:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=*cmp X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 08 Nov 2018 11:00:44 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C92B4804E4 for ; Thu, 8 Nov 2018 11:00:42 +0000 (UTC) Received: from free.home (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6E84A5D762; Thu, 8 Nov 2018 11:00:36 +0000 (UTC) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTP id wA8B0GsD016874; Thu, 8 Nov 2018 09:00:16 -0200 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR86438] compare-elim: cope with set of in_b Date: Thu, 08 Nov 2018 09:00:16 -0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 When in_a resolves to a register set in the prev_clobber insn, we may use the SET_SRC for the compare instead. However, when in_b so resolves, we proceed to use the reg with its earlier value. When both resolve to the same register and prev_clobber is an insn that modifies the register, this arrangement may cause the compare to match (when it shouldn't) and the elimination of the compare to incorrectly succeed. (set (reg 1) (plus (reg 1) (const_int N))) (set (reg 2) (reg 1)) (set (reg flags) (compare (reg 1) (reg 2))) in_a: (reg 1) --> (plus (reg 1) (const_int N)) in_b: (reg 2) -> (reg 1) -/> oops (parallel [ (set (reg flags) (compare (plus (reg 1) (const_int N)) (reg 1))) ;; should be (plus...) (set (reg 1) (plus (reg 1) (const_int N)))]) (set (reg 2) (reg 1)) This patch arranges for in_b to also undergo SET_SRC substitution when appropriate, with a shortcut for when in_a and in_b are the same rtx. Bootstrapped, now regression-testing, on x86_64- and i686-linux-gnu. Ok to install if it passes? for gcc/ChangeLog PR rtl-optimization/86438 * compare-elim.c (try_eliminate_compare): Use SET_SRC instead of in_b for the compare if in_b is SET_DEST. for gcc/testsuite/ChangeLog PR rtl-optimization/86438 * gcc.dg/torture/pr86438.c: New. --- gcc/compare-elim.c | 25 +++++++++++++++++-------- gcc/testsuite/gcc.dg/torture/pr86438.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr86438.c diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c index 50bbaa84b6df..8afbe76c502b 100644 --- a/gcc/compare-elim.c +++ b/gcc/compare-elim.c @@ -734,7 +734,7 @@ try_merge_compare (struct comparison *cmp) static bool try_eliminate_compare (struct comparison *cmp) { - rtx flags, in_a, in_b, cmp_src; + rtx flags, in_a, in_b, cmp_a, cmp_b; if (try_merge_compare (cmp)) return true; @@ -786,7 +786,7 @@ try_eliminate_compare (struct comparison *cmp) rtx x = XVECEXP (PATTERN (insn), 0, 0); if (rtx_equal_p (SET_DEST (x), in_a)) - cmp_src = SET_SRC (x); + cmp_a = SET_SRC (x); /* Also check operations with implicit extensions, e.g.: [(set (reg:DI) @@ -800,7 +800,7 @@ try_eliminate_compare (struct comparison *cmp) && (GET_CODE (SET_SRC (x)) == ZERO_EXTEND || GET_CODE (SET_SRC (x)) == SIGN_EXTEND) && GET_MODE (XEXP (SET_SRC (x), 0)) == GET_MODE (in_a)) - cmp_src = XEXP (SET_SRC (x), 0); + cmp_a = XEXP (SET_SRC (x), 0); /* Also check fully redundant comparisons, e.g.: [(set (reg:SI) @@ -811,7 +811,7 @@ try_eliminate_compare (struct comparison *cmp) && GET_CODE (SET_SRC (x)) == MINUS && rtx_equal_p (XEXP (SET_SRC (x), 0), in_a) && rtx_equal_p (XEXP (SET_SRC (x), 1), in_b)) - cmp_src = in_a; + cmp_a = in_a; else return false; @@ -819,17 +819,26 @@ try_eliminate_compare (struct comparison *cmp) /* If the source uses addressing modes with side effects, we can't do the merge because we'd end up with a PARALLEL that has two instances of that side effect in it. */ - if (side_effects_p (cmp_src)) + if (side_effects_p (cmp_a)) + return false; + + if (in_a == in_b) + cmp_b = cmp_a; + else if (rtx_equal_p (SET_DEST (x), in_b)) + cmp_b = SET_SRC (x); + else + cmp_b = in_b; + if (side_effects_p (cmp_b)) return false; /* Determine if we ought to use a different CC_MODE here. */ - flags = maybe_select_cc_mode (cmp, cmp_src, in_b); + flags = maybe_select_cc_mode (cmp, cmp_a, cmp_b); if (flags == NULL) flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum); /* Generate a new comparison for installation in the setter. */ - rtx y = copy_rtx (cmp_src); - y = gen_rtx_COMPARE (GET_MODE (flags), y, in_b); + rtx y = copy_rtx (cmp_a); + y = gen_rtx_COMPARE (GET_MODE (flags), y, copy_rtx (cmp_b)); y = gen_rtx_SET (flags, y); /* Canonicalize instruction to: diff --git a/gcc/testsuite/gcc.dg/torture/pr86438.c b/gcc/testsuite/gcc.dg/torture/pr86438.c new file mode 100644 index 000000000000..d4a23f313a55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr86438.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ + +typedef unsigned int u32; +typedef unsigned long long u64; +#if __SIZEOF_INT128__ +typedef unsigned __int128 u128; +#else +typedef u64 u128; +#endif + +u128 g; + +static __attribute__ ((noinline, noclone)) +void check (u64 a, u64 b) +{ + if (a != 0 || b != 4) + __builtin_abort (); +} + +int +main (void) +{ + u64 d = (g ? 5 : 4); + u32 f = __builtin_sub_overflow_p (d, (u128) d, (u64) 0); + u128 x = g + f + d; + check ((x >> 32) >> 32, x); + return 0; +}