From patchwork Tue Jan 26 08:39:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 573122 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 9B8961402C9 for ; Tue, 26 Jan 2016 19:39:49 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=F5vbIGJ4; 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=B9NWCQeXsxLbZr+SDeC6Om9W7eT1d ScaqgtVD0oMPQajJ2UX3QyP7QG/LeKwJgyGMBlwXESSly2X8Iualg+P1o87YHAu1 sVv56PUBDLx05dPv6vyLx0HBBSCmclwq2tWgJb7LfLkJWVwGfd/nzcGUY2rUr6DS 7WNKWK57zw6B6k= 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=jlARB4hAInBi/Al3xxu8sD83Fgs=; b=F5v bIGJ4XN6AzvkDVXPZ1Nga5tgTzIrgRgmst1AFSahtoigrvdPi3K55F4lmQcjAM7S ctUDEv0BXI8M7h8MaY9t5trn/+s++iZSQphwJX2WdfHh48QHTqABJ1pGrbF3mlp0 SxrRh0oZ3ss+3m1b2sMuZ4l/quLc0yzG4klAlNzU= Received: (qmail 86759 invoked by alias); 26 Jan 2016 08:39:41 -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 85411 invoked by uid 89); 26 Jan 2016 08:39:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=validly, HTo:U*segher, kindly, 2016-01-26 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 (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 26 Jan 2016 08:39:39 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id CA7DF461D3; Tue, 26 Jan 2016 08:39:37 +0000 (UTC) Received: from tucnak.zalov.cz ([10.3.113.11]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0Q8dYp0005920 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 26 Jan 2016 03:39:36 -0500 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id u0Q8dVBY025442; Tue, 26 Jan 2016 09:39:32 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id u0Q8dTvD025441; Tue, 26 Jan 2016 09:39:29 +0100 Date: Tue, 26 Jan 2016 09:39:29 +0100 From: Jakub Jelinek To: Segher Boessenkool , Jeff Law Cc: gcc-patches@gcc.gnu.org, Kugan Vivekanandarajah Subject: [PATCH] Fix handling of ZERO_EXTRACT lhs with REG_EQUAL note in the combiner (PR target/69442) Message-ID: <20160126083929.GR3017@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-IsSubscribed: yes Hi! In the middle of last year, Kugan has defined REG_EQUAL notes even for the case when SET_DEST of the single set is ZERO_EXTRACT, before that I believe it has been defined only for REG/SUBREG and STRICT_LOW_PART thereof. But, like for STRICT_LOW_PART, the REG_EQUAL note describes the whole contained register rather than just the bits that are being set. Unfortunately, neither the documentation nor the combiner have been changed for this, so if say on (insn 7 4 8 2 (set (reg:SI 117) (const_int 65535 [0xffff])) pr69442.c:7 614 {*arm_movsi_vfp} (nil)) ... (insn 16 14 17 2 (set (reg:SI 123) (const_int 0 [0])) pr69442.c:9 614 {*arm_movsi_vfp} (nil)) (insn 17 16 18 2 (set (zero_extract:SI (reg:SI 123) (const_int 16 [0x10]) (const_int 16 [0x10])) (reg:SI 117)) pr69442.c:9 83 {insv_t2} (expr_list:REG_DEAD (reg:SI 117) (expr_list:REG_EQUAL (const_int -65536 [0xffffffffffff0000]) (nil)))) the combiner would replace the SET_SRC of the set with -65536, but that has different meaning, it says that the upper 16 bits of a register containing zero are supposed to be set to -65536 (and as we care just about 16 bits, that is in fact 0). So, either we could shift the constant around and say that the zero extract is set to -65536 >> 16 in this case, but then we don't say anything about the other bits and if e.g. there are multiple setters of the earlier 123 pseudo value, we'd give up, or as the patch does, it says the whole inner register is set to the given constant. This setting doesn't have to be recognized as valid, the whole point of the temporary assignment is just improve the try_combine and then revert it. Bootstrapped/regtested on x86_64-linux and i686-linux, Kugan has kindly tested it on arm too (my armhfp bootstrap/regtest of this is progressing too slowly). Ok for trunk? 2016-01-26 Jakub Jelinek PR target/69442 * combine.c (combine_instructions): For REG_EQUAL note with SET_DEST being ZERO_EXTRACT, also temporarily set SET_DEST to the underlying register. * doc/rtl.texi (REG_EQUAL): Document the behavior of REG_EQUAL/REG_EQUIV notes if SET_DEST is ZERO_EXTRACT. * gcc.dg/pr69442.c: New test. Jakub --- gcc/combine.c.jj 2016-01-14 16:10:24.000000000 +0100 +++ gcc/combine.c 2016-01-25 21:03:35.572594150 +0100 @@ -1454,15 +1454,21 @@ combine_instructions (rtx_insn *f, unsig && ! unmentioned_reg_p (note, SET_SRC (set)) && (GET_MODE (note) == VOIDmode ? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set))) - : GET_MODE (SET_DEST (set)) == GET_MODE (note))) + : (GET_MODE (SET_DEST (set)) == GET_MODE (note) + && (GET_CODE (SET_DEST (set)) != ZERO_EXTRACT + || (GET_MODE (XEXP (SET_DEST (set), 0)) + == GET_MODE (note)))))) { /* Temporarily replace the set's source with the contents of the REG_EQUAL note. The insn will be deleted or recognized by try_combine. */ - rtx orig = SET_SRC (set); + rtx orig_src = SET_SRC (set); + rtx orig_dest = SET_DEST (set); + if (GET_CODE (SET_DEST (set)) == ZERO_EXTRACT) + SET_DEST (set) = XEXP (SET_DEST (set), 0); SET_SRC (set) = note; i2mod = temp; - i2mod_old_rhs = copy_rtx (orig); + i2mod_old_rhs = copy_rtx (orig_src); i2mod_new_rhs = copy_rtx (note); next = try_combine (insn, i2mod, NULL, NULL, &new_direct_jump_p, @@ -1473,7 +1479,8 @@ combine_instructions (rtx_insn *f, unsig statistics_counter_event (cfun, "insn-with-note combine", 1); goto retry; } - SET_SRC (set) = orig; + SET_SRC (set) = orig_src; + SET_DEST (set) = orig_dest; } } --- gcc/doc/rtl.texi.jj 2016-01-04 14:55:58.000000000 +0100 +++ gcc/doc/rtl.texi 2016-01-25 18:51:23.813258380 +0100 @@ -3915,9 +3915,9 @@ indicates that that register will be equ scope of this equivalence differs between the two types of notes. The value which the insn explicitly copies into the register may look different from @var{op}, but they will be equal at run time. If the -output of the single @code{set} is a @code{strict_low_part} expression, -the note refers to the register that is contained in @code{SUBREG_REG} -of the @code{subreg} expression. +output of the single @code{set} is a @code{strict_low_part} or +@code{zero_extract} expression, the note refers to the register that +is contained in its first operand. For @code{REG_EQUIV}, the register is equivalent to @var{op} throughout the entire function, and could validly be replaced in all its --- gcc/testsuite/gcc.dg/pr69442.c.jj 2016-01-25 20:58:35.684703880 +0100 +++ gcc/testsuite/gcc.dg/pr69442.c 2016-01-25 20:58:14.000000000 +0100 @@ -0,0 +1,23 @@ +/* PR target/69442 */ +/* { dg-do run } */ +/* { dg-options "-Og" } */ + +unsigned long long __attribute__ ((noinline, noclone)) +foo (unsigned int x, unsigned long long y) +{ + x |= 0xffff; + y -= 0xffULL; + y %= 0xffff0000ffffffe7ULL; + return x + y; +} + +int +main () +{ + if (sizeof (unsigned long long) * __CHAR_BIT__ != 64) + return 0; + + if (foo (0, 0) != 0xffff0000ff19ULL) + __builtin_abort (); + return 0; +}