From patchwork Tue Oct 23 20:35:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 193567 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]) by ozlabs.org (Postfix) with SMTP id 628FC2C008A for ; Wed, 24 Oct 2012 07:35:17 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1351629318; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Message-ID:Date:From:User-Agent:MIME-Version:To:Subject: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=XYuASHV W1R6TAJj74KuFCHIE3U0=; b=EOHkdVTvFvFSKPMImaByNRW/0VVhvIX2G7gdQGB Bqb7BxZU0iN/A/SYqFBwr6Tg//4gZf9GdXhFyWag/60167k0K3EcBIhQt+MnhOgp 3blu/6SZF3/t+pvWyDi4Qn0VSkr52d/SGAYi7VFgvYSHf7Jcr5h0FzYz94uoemhU I/L8= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:Subject:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=kJMBGpNskkzeT+D3dZYInokq6Bhpq2lKhxN+GrrR7GnUJeLRoC3O2XmGyyC6v9 koQIC7EH5cO4qc15f07Fj5alFd/VCbdFCEIzo5GorxN843ydwYxZp4JDlOmIu98q pCJWouvrjtuEtVpnW1PGTpX08v0woeAn4K1K3NW/t+hzY=; Received: (qmail 20492 invoked by alias); 23 Oct 2012 20:35:14 -0000 Received: (qmail 20359 invoked by uid 22791); 23 Oct 2012 20:35:14 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 23 Oct 2012 20:35:08 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9NKZ2aH030585 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 23 Oct 2012 16:35:07 -0400 Received: from stumpy.slc.redhat.com (ovpn-113-139.phx2.redhat.com [10.3.113.139]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q9NKZ2Xd025398 for ; Tue, 23 Oct 2012 16:35:02 -0400 Message-ID: <5086FF8C.40209@redhat.com> Date: Tue, 23 Oct 2012 14:35:24 -0600 From: Jeff Law User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:15.0) Gecko/20120911 Thunderbird/15.0.1 MIME-Version: 1.0 To: gcc-patches Subject: PR tree-optimization/54985 X-IsSubscribed: yes 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 When we try to thread across a back edge in the CFG we have a check to ensure that we don't use temporary equivalences which are invalidated by traversal of the back edge to simplify the final conditional. About a year ago I added code to pick up secondary threading opportunities after an initial jump threading was successful. However, I failed to account for equivalences which were invalidated by the back edge traversal in those new cases. This patch extracts the check into its own function, then calls it from the 3 locations where it's necessary. Bootstrapped and regression tested on x86_64-unknown-linux-gnu. Installed onto the trunk. Oh how I want to rewrite all this code.... Jeff ps. First time commiting using git svn, hopefully I did all the steps correctly. * tree-ssa-threadedge.c (cond_arg_set_in_bb): New function extracted from thread_across_edge. (thread_across_edge): Use it in all cases where we might thread across a back edge. * gcc.c-torture/execute/pr54985.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr54985.c b/gcc/testsuite/gcc.c-torture/execute/pr54985.c new file mode 100644 index 0000000..678c9f4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr54985.c @@ -0,0 +1,36 @@ + +typedef struct st { + int a; +} ST; + +int __attribute__((noinline,noclone)) +foo(ST *s, int c) +{ + int first = 1; + int count = c; + ST *item = s; + int a = s->a; + int x; + + while (count--) + { + x = item->a; + if (first) + first = 0; + else if (x >= a) + return 1; + a = x; + item++; + } + return 0; +} + +extern void abort (void); + +int main () +{ + ST _1[2] = {{2}, {1}}; + if (foo(_1, 2) != 0) + abort (); + return 0; +} diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 105e3ab..491aa9f 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -572,6 +572,44 @@ simplify_control_stmt_condition (edge e, return cached_lhs; } +/* Return TRUE if the statement at the end of e->dest depends on + the output of any statement in BB. Otherwise return FALSE. + + This is used when we are threading a backedge and need to ensure + that temporary equivalences from BB do not affect the condition + in e->dest. */ + +static bool +cond_arg_set_in_bb (edge e, basic_block bb, int n) +{ + ssa_op_iter iter; + use_operand_p use_p; + gimple last = gsi_stmt (gsi_last_bb (e->dest)); + + /* E->dest does not have to end with a control transferring + instruction. This can occurr when we try to extend a jump + threading opportunity deeper into the CFG. In that case + it is safe for this check to return false. */ + if (!last) + return false; + + if (gimple_code (last) != GIMPLE_COND + && gimple_code (last) != GIMPLE_GOTO + && gimple_code (last) != GIMPLE_SWITCH) + return false; + + FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE) + { + tree use = USE_FROM_PTR (use_p); + + if (TREE_CODE (use) == SSA_NAME + && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI + && gimple_bb (SSA_NAME_DEF_STMT (use)) == bb) + return true; + } + return false; +} + /* TAKEN_EDGE represents the an edge taken as a result of jump threading. See if we can thread around TAKEN_EDGE->dest as well. If so, return the edge out of TAKEN_EDGE->dest that we can statically compute will be @@ -705,19 +743,8 @@ thread_across_edge (gimple dummy_cond, safe to thread this edge. */ if (e->flags & EDGE_DFS_BACK) { - ssa_op_iter iter; - use_operand_p use_p; - gimple last = gsi_stmt (gsi_last_bb (e->dest)); - - FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE) - { - tree use = USE_FROM_PTR (use_p); - - if (TREE_CODE (use) == SSA_NAME - && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI - && gimple_bb (SSA_NAME_DEF_STMT (use)) == e->dest) - goto fail; - } + if (cond_arg_set_in_bb (e, e->dest, 1)) + goto fail; } stmt_count = 0; @@ -758,7 +785,9 @@ thread_across_edge (gimple dummy_cond, address. If DEST is not null, then see if we can thread through it as well, this helps capture secondary effects of threading without having to re-run DOM or VRP. */ - if (dest) + if (dest + && ((e->flags & EDGE_DFS_BACK) == 0 + || ! cond_arg_set_in_bb (taken_edge, e->dest, 2))) { /* We don't want to thread back to a block we have already visited. This may be overly conservative. */ @@ -816,11 +845,16 @@ thread_across_edge (gimple dummy_cond, e3 = taken_edge; do { - e2 = thread_around_empty_block (e3, - dummy_cond, - handle_dominating_asserts, - simplify, - visited); + if ((e->flags & EDGE_DFS_BACK) == 0 + || ! cond_arg_set_in_bb (e3, e->dest, 3)) + e2 = thread_around_empty_block (e3, + dummy_cond, + handle_dominating_asserts, + simplify, + visited); + else + e2 = NULL; + if (e2) { e3 = e2;