From patchwork Thu Jan 5 07:46:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 711257 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 3tvKWr5RtVz9sXx for ; Thu, 5 Jan 2017 18:47:01 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="dwYFRmT2"; 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:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=fcuZZFAfZiP13PPKuZGuJStKeAZURPbFFcfwc/sv2hkNOs9k1o PfkOSTVfqUX7RSxacaamfCVGZuYs87eDTBEjq2pzlrz/UTjYvBm0t6M8kAMHQfcC yUEeYiO4gb+VRoWQr9pG1jFJbGXs+MVePMgwsRCI6ypWiffd25ce1rG2U= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=GOzL8L+Y1aKHmj4iFWBNrsTme1o=; b=dwYFRmT2NnLEPzsJjTdt wpJZwmwA5YZ8Z7hP5xIeIkP+J15pwXtupH85uVj92ICjH74KHyxto5MAnCvD+wBY DVmQFv4wUWtLOoXcv0nYjqhRbFIK1bfLGkD4Uqi3A5nYMkBnNdm5RMpsn0BPmRIg UyIEUv2tnjo2bDJ4eLkJ84o= Received: (qmail 87047 invoked by alias); 5 Jan 2017 07:46:52 -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 87008 invoked by uid 89); 5 Jan 2017 07:46:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.1 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=6856, Hx-languages-length:6537 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, 05 Jan 2017 07:46:49 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F37AE341448 for ; Thu, 5 Jan 2017 07:46:48 +0000 (UTC) Received: from localhost.localdomain (ovpn-118-153.rdu2.redhat.com [10.10.118.153]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v057km8N032710 for ; Thu, 5 Jan 2017 02:46:48 -0500 To: gcc-patches From: Jeff Law Subject: [PATCH][PR rtl-optimization/78812] Fix pruning of expressions with embedded MEMs Message-ID: <57d8f7fd-fb0f-4b73-2747-dad157c9c887@redhat.com> Date: Thu, 5 Jan 2017 00:46:46 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 X-IsSubscribed: yes GCSE has some smarts to detect cases when a MEM appears in a block with predecessor edges marked as EDGE_ABNORMAL. Such MEMs are removed from the antic/transparent bitmaps. Unfortunately this code did not work if the MEM was not the topmost RTX. So something like (zero_extend (mem (...)) would not result in the MEM being removed. This in turn caused code hoisting to hoist the MEM into a predecessor block. The predecessor block ended with a function call so gcse was forced to insert the new insn before the call. But the value is changed by the call. This patch moves contains_mem_rtx_p into rtlanal.c and uses it to detect when there's MEMs that aren't the toplevel RTX expression. The patch also knows how to look through certain toplevel expressions (ZERO_EXTEND, SIGN_EXTEND) to find the buried MEM expression. This allows the code to prune more selectively if the MEM is a constant pool address or otherwise readonly. Bootstrapped and regression tested on x86_64-linux-gnu. ALso verified RTL hoisting no longer hoists the (zero_extend (mem)) expression with an s390x cross compiler. Installing on the trunk. It should be safe to backport to the release branches if anyone sees a need. Jeff commit 0998df91b6ad2035f5fd41ee024e3ab919a9cefe Author: Jeff Law Date: Thu Jan 5 00:37:57 2017 -0700 PR tree-optimizatin/78812 * rtl.h (contains_mem_rtx_p): Prototype. * ifcvt.c (containts_mem_rtx_p): Move from here to... * rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage. * gcse.c (prune_expressions): Use contains_mem_rtx_p to discover and prune MEMs that are not at the toplevel of a SET_SRC rtx. Look through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning MEMs. PR tree-optimization/78812 * g++.dg/torture/pr78812.C: New test. diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ce11bc4..78b4412 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-01-04 Jeff Law + + PR tree-optimizatin/78812 + * rtl.h (contains_mem_rtx_p): Prototype. + * ifcvt.c (containts_mem_rtx_p): Move from here to... + * rtlanal.c (contains_mem_rtx_p): Here and remvoe static linkage. + * gcse.c (prune_expressions): Use contains_mem_rtx_p to discover + and prune MEMs that are not at the toplevel of a SET_SRC rtx. Look + through ZERO_EXTEND and SIGN_EXTEND when trying to avoid pruning + MEMs. + 2017-01-04 Alexandre Oliva * input.c (assert_char_at_range): Default-initialize diff --git a/gcc/gcse.c b/gcc/gcse.c index fbc770a..d28288d 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -1709,7 +1709,7 @@ prune_expressions (bool pre_p) continue; } - if (!pre_p && MEM_P (expr->expr)) + if (!pre_p && contains_mem_rtx_p (expr->expr)) /* Note memory references that can be clobbered by a call. We do not split abnormal edges in hoisting, so would a memory reference get hoisted along an abnormal edge, @@ -1717,15 +1717,28 @@ prune_expressions (bool pre_p) constant memory references can be hoisted along abnormal edges. */ { - if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0))) - continue; - - if (MEM_READONLY_P (expr->expr) - && !MEM_VOLATILE_P (expr->expr) - && MEM_NOTRAP_P (expr->expr)) - /* Constant memory reference, e.g., a PIC address. */ - continue; + rtx x = expr->expr; + + /* Common cases where we might find the MEM which may allow us + to avoid pruning the expression. */ + while (GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) + x = XEXP (x, 0); + + /* If we found the MEM, go ahead and look at it to see if it has + properties that allow us to avoid pruning its expression out + of the tables. */ + if (MEM_P (x)) + { + if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))) + continue; + + if (MEM_READONLY_P (x) + && !MEM_VOLATILE_P (x) + && MEM_NOTRAP_P (x)) + /* Constant memory reference, e.g., a PIC address. */ + continue; + } /* ??? Optimally, we would use interprocedural alias analysis to determine if this mem is actually killed diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 56c785e..68c1a1d 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -3010,19 +3010,6 @@ noce_operand_ok (const_rtx op) return ! may_trap_p (op); } -/* Return true if X contains a MEM subrtx. */ - -static bool -contains_mem_rtx_p (rtx x) -{ - subrtx_iterator::array_type array; - FOR_EACH_SUBRTX (iter, array, x, ALL) - if (MEM_P (*iter)) - return true; - - return false; -} - /* Return true iff basic block TEST_BB is valid for noce if-conversion. The condition used in this if-conversion is in COND. In practice, check that TEST_BB ends with a single set diff --git a/gcc/rtl.h b/gcc/rtl.h index 302afc0..b9a7989 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3090,6 +3090,7 @@ extern bool rtx_referenced_p (const_rtx, const_rtx); extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **); extern int computed_jump_p (const rtx_insn *); extern bool tls_referenced_p (const_rtx); +extern bool contains_mem_rtx_p (rtx x); /* Overload for refers_to_regno_p for checking a single register. */ inline bool diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index ef93584..acb4230 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -685,6 +685,19 @@ rtx_addr_can_trap_p (const_rtx x) return rtx_addr_can_trap_p_1 (x, 0, 0, VOIDmode, false); } +/* Return true if X contains a MEM subrtx. */ + +bool +contains_mem_rtx_p (rtx x) +{ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, x, ALL) + if (MEM_P (*iter)) + return true; + + return false; +} + /* Return true if X is an address that is known to not be zero. */ bool diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 74e8d0d..16b27e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-01-04 Jeff Law + + PR tree-optimization/78812 + * g++.dg/torture/pr78812.C: New test. + 2017-01-04 Michael Meissner PR target/71977 diff --git a/gcc/testsuite/g++.dg/torture/pr78812.C b/gcc/testsuite/g++.dg/torture/pr78812.C new file mode 100644 index 0000000..efe0936 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr78812.C @@ -0,0 +1,24 @@ +// { dg-do run } +// { dg-options "-fpic" { target fpic } } + +struct T +{ + bool a; + T () : a (false) {} + ~T () { if (!a) __builtin_abort (); } +}; + +__attribute__((noinline)) +void +test (T &x) +{ + x.a = true; +} + +int +main () +{ + T T; + test (T); +} +