From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 53012 invoked by alias); 16 Feb 2017 19:41:56 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 52957 invoked by uid 89); 16 Feb 2017 19:41:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.1 required=5.0 tests=BAYES_00,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=sk:forward, replacements, Hx-languages-length:3032 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, 16 Feb 2017 19:41:53 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (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 995BC80F7C for ; Thu, 16 Feb 2017 19:41:53 +0000 (UTC) Received: from localhost.localdomain (ovpn-117-54.ams2.redhat.com [10.36.117.54]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1GJfqZN003148 for ; Thu, 16 Feb 2017 14:41:53 -0500 To: GCC Patches From: Bernd Schmidt Subject: fwprop fix for PR79405 Message-ID: <328a765e-5466-9740-d545-c1a620805ef9@redhat.com> Date: Thu, 16 Feb 2017 19:44:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.7.0 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------5EDB3FCFCC79240308E78DFC" X-IsSubscribed: yes X-SW-Source: 2017-02/txt/msg01064.txt.bz2 This is a multi-part message in MIME format. --------------5EDB3FCFCC79240308E78DFC Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 604 We have two registers being assigned to each other: (set (reg 213) (reg 209)) (set (reg 209) (reg 213)) These being the only definitions, we are happy to forward propagate reg 209 for reg 213 into a third insn, making a new use for reg 209. We are then happy to forward propagate reg 213 for it in the same insn... ending up in an infinite loop. I don't really see an elegant way to prevent this, so the following just tries to detect the situation (and more general ones) by brute force. Bootstrapped and tested on x86_64-linux, verified that the test passes with a ppc cross, ok? Bernd --------------5EDB3FCFCC79240308E78DFC Content-Type: text/x-patch; name="79405.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="79405.diff" Content-length: 2785 PR rtl-optimization/79405 * fwprop.c (forward_propagate_into): Detect potentially cyclic replacements and bail out for them. PR rtl-optimization/79405 * gcc.dg/torture/pr79405.c: New test. Index: gcc/fwprop.c =================================================================== --- gcc/fwprop.c (revision 244815) +++ gcc/fwprop.c (working copy) @@ -1374,13 +1374,42 @@ forward_propagate_into (df_ref use) /* Only consider uses that have a single definition. */ def = get_def_for_use (use); - if (!def) + if (!def || DF_REF_INSN_INFO (def) == NULL) return false; if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE) return false; if (DF_REF_IS_ARTIFICIAL (def)) return false; + df_ref tmp_def = def; + /* There is a problematic case where a chain of assignments + rA = rB; rB = rC; .... ; rM = rN; rN = rA. + can cause us to replace these registers in an infinite cycle. + Walk backwards until we can guarantee that this situation is + not present. */ + for (;;) + { + rtx_insn *insn = DF_REF_INSN (tmp_def); + rtx set = single_set (insn); + if (set == NULL_RTX) + break; + rtx src = SET_SRC (set); + rtx dst = SET_DEST (set); + if (GET_CODE (src) != REG || GET_CODE (dst) != REG) + break; + if (rtx_equal_p (src, DF_REF_REG (use))) + return false; + df_ref tmp_use = df_single_use (DF_REF_INSN_INFO (tmp_def)); + if (!tmp_use) + break; + tmp_def = get_def_for_use (tmp_use); + if (!tmp_def || DF_REF_INSN_INFO (tmp_def) == NULL) + break; + if (DF_REF_FLAGS (tmp_def) & DF_REF_READ_WRITE) + break; + if (DF_REF_IS_ARTIFICIAL (tmp_def)) + break; + } /* Do not propagate loop invariant definitions inside the loop. */ if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father) return false; Index: gcc/testsuite/gcc.dg/torture/pr79405.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr79405.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr79405.c (working copy) @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +char cz; +long long int xx, u2; + +void +qv (int js, int wl) +{ + if (js != 0) + { + short int sc; + int *at = (int *)≻ + long long int gx = 0; + + for (;;) + { + *at = 0; + js /= sc; + + for (wl = 0; wl < 2; ++wl) + { + xx = gx; + u2 %= xx > 0; + cz /= u2; + + fa: + if (cz != u2) + { + gx |= js; + cz = gx / js; + } + } + } + + yq: + wl /= 0x80000000; + u2 = wl; + u2 |= (wl != 0) | (wl != 0 && gx != 0); + js = u2; + goto fa; + } + goto yq; +} --------------5EDB3FCFCC79240308E78DFC--