From patchwork Sun Oct 26 21:34:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sebastian Pop X-Patchwork-Id: 403332 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 60ED2140082 for ; Mon, 27 Oct 2014 08:34:53 +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:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=x2clYdsnHCqFOeYMz rrXq2z+tLuuvUYPACDbBzaadjI9qUBClqAD3DRU329ZirFUQFkjr4gx0rllVLGya vBo1svy5Yi/avZrrwOS0HHPrU4ZE7eGwpSp5N57MnOMZXFyzK1uT7goJyz+HBpTs GTPeFsDK62zeW22tyDP898w58g= 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:references:mime-version :content-type:in-reply-to; s=default; bh=q24CFOF/AjOAlF+PM6viiR6 lSk8=; b=Frya8NeSYFS7SoMgdhSd51SnEPa/XlOGCjaNTPKcFRYJEPqGhbPaMeK RJU+nzwid0oM3vlCRp/l08dH2c5/pzdHoEj3noqL8lsROtL6tuMzYg03uWG12hw8 owOumlxyJNAEA39rmm5FmmmFjAR5YzrAtMx4Dpw3+6L2o+c+9P3E= Received: (qmail 19014 invoked by alias); 26 Oct 2014 21:34:42 -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 19001 invoked by uid 89); 26 Oct 2014 21:34:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-ig0-f177.google.com Received: from mail-ig0-f177.google.com (HELO mail-ig0-f177.google.com) (209.85.213.177) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sun, 26 Oct 2014 21:34:39 +0000 Received: by mail-ig0-f177.google.com with SMTP id h18so1889726igc.16 for ; Sun, 26 Oct 2014 14:34:36 -0700 (PDT) X-Received: by 10.50.67.9 with SMTP id j9mr17784987igt.12.1414359276712; Sun, 26 Oct 2014 14:34:36 -0700 (PDT) Received: from f1.c.bardezibar.internal (81.37.148.146.bc.googleusercontent.com. [146.148.37.81]) by mx.google.com with ESMTPSA id zy11sm1231332igc.4.2014.10.26.14.34.35 for (version=SSLv3 cipher=RC4-SHA bits=128/128); Sun, 26 Oct 2014 14:34:35 -0700 (PDT) Date: Sun, 26 Oct 2014 21:34:33 +0000 From: Sebastian Pop To: Jeff Law Cc: Richard Biener , James Greenhalgh , Steve Ellcey , GCC Patches Subject: [Patch] Improving jump-thread pass for PR 54742 Message-ID: <20141026213433.GA22140@f1.c.bardezibar.internal> References: <1408480796.31355.7.camel@ubuntu-sellcey> <20140821094109.GA20536@arm.com> <53FB73C0.7090507@redhat.com> <20140926201451.GA16704@f1.c.bardezibar.internal> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20140926201451.GA16704@f1.c.bardezibar.internal> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Sebastian Pop wrote: > Jeff Law wrote: > > On 08/21/14 04:30, Richard Biener wrote: > > >>It turns Jeff's jump-threading code in to a strange franken-pass of bits and > > >>pieces of detection and optimisation, and would need some substantial > > >>reworking to fit in with Jeff's changes last Autumn, but if it is more > > >>likely to be acceptable for trunk then perhaps we could look to revive it. > > >>It would be nice to reuse the path copy code Jeff added last year, but I > > >>don't have much intuition as to how feasible that is. > > >> > > >>Was this the sort of thing that you were imagining? > > > > > >Yeah, didn't look too closely though. > > It'd be pretty ugly I suspect. But it's probably worth pondering > > since that approach would eliminate the concerns about the cost of > > detection (which is problematical for the jump threader) by using > > Steve's code for that. > > > > On the update side, I suspect most, if not all of the framework is > > in place to handle this kind of update if the right threading paths > > were passed to the updater. I can probably cobble together that > > by-hand and see what the tree-ssa-threadupdate does with it. But > > it'll be a week or so before I could look at it. > > I adapted the patch James has sent last year to use the new update paths Attached an updated version of the patch. > mechanism. I verified that the attached patch does register all the paths that > need to be threaded. Thread updater seems to have some problems handling the > attached testcase (a simplified version of the testcase attached to the bug.) > > Jeff, could you please have a look at why the jump-thread updater is crashing? I have tried to understand why the code generation part ICEs on coremark: the first problem that I have seen is that tree-ssa-threadupdate.c does not handle more than a joiner block per path to be threaded, so we would not be able to jump thread accross the joiners of the if condition and the joiner of the switch condition: i.e., these paths patch: Registering jump thread: (7, 10) incoming edge; (10, 25) joiner; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 14) nocopy; patch: Registering jump thread: (28, 10) incoming edge; (10, 25) joiner; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 11) nocopy; patch: Registering jump thread: (8, 10) incoming edge; (10, 25) joiner; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; patch: Registering jump thread: (9, 10) incoming edge; (10, 25) joiner; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Another problem is that we attach the path to be threaded to the ->aux field of the first edge in the path, such that we would have to cancel some of the paths because we cannot keep track of all the paths to be threaded. For coremark, we would discover some jump-thread paths from one of the switch cases over the loop exit condition, either to bb_27 outside the loop, or to bb_4 staying inside the loop. Then with the "patch:" we would discover jump threads that would thread switch cases to switch cases, and because these paths start with the same edges for which we have already assigned a path to e->aux, we would have to cancel the interesting threads added by the patch: Registering jump thread: (12, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (13, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (29, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (31, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (16, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (15, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (32, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (19, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (18, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (22, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (21, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (34, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (33, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; Registering jump thread: (35, 25) incoming edge; (25, 26) joiner; (26, 27) nocopy; Registering jump thread: (24, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; patch: Registering jump thread: (12, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; patch: Registering jump thread: (16, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 14) nocopy; patch: Registering jump thread: (19, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; patch: Registering jump thread: (22, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (34, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (35, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (29, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 14) nocopy; patch: Registering jump thread: (13, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (15, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; patch: Registering jump thread: (31, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (18, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 20) nocopy; patch: Registering jump thread: (32, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; patch: Registering jump thread: (21, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 23) nocopy; patch: Registering jump thread: (33, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 24) nocopy; patch: Registering jump thread: (24, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 24) nocopy; Registering jump thread: (6, 36) incoming edge; (36, 7) normal; Cancelling jump thread: (12, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; Cancelling jump thread: (16, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 14) nocopy; Cancelling jump thread: (19, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; Cancelling jump thread: (22, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (34, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (35, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (29, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 14) nocopy; Cancelling jump thread: (13, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (15, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 17) nocopy; Cancelling jump thread: (31, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (18, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 20) nocopy; Cancelling jump thread: (32, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 25) nocopy; Cancelling jump thread: (21, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 23) nocopy; Cancelling jump thread: (33, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 24) nocopy; Cancelling jump thread: (24, 25) incoming edge; (25, 26) joiner; (26, 4) nocopy; (4, 37) nocopy; (37, 36) nocopy; (36, 24) nocopy; Here is the structure of the CFG with the loops: (gdb) p debug_loops (2) loop_0 (header = 0, latch = 1, niter = ) { bb_2 (preds = {bb_0 }, succs = {bb_3 bb_27 }) bb_3 (preds = {bb_2 }, succs = {bb_5 bb_6 }) bb_5 (preds = {bb_4 bb_3 }, succs = {bb_27 }) bb_6 (preds = {bb_3 }, succs = {bb_36 }) bb_27 (preds = {bb_5 bb_25 bb_26 bb_2 }, succs = {bb_1 }) loop_1 (header = 36, latch = 37, niter = ) { bb_4 (preds = {bb_26 }, succs = {bb_5 bb_37 }) bb_37 (preds = {bb_4 }, succs = {bb_36 }) bb_36 (preds = {bb_6 bb_37 }, succs = {bb_25 bb_7 bb_11 bb_20 bb_14 bb_17 bb_23 bb_24 }) bb_7 (preds = {bb_36 }, succs = {bb_10 bb_28 }) bb_8 (preds = {bb_28 }, succs = {bb_10 bb_9 }) bb_9 (preds = {bb_8 }, succs = {bb_10 }) bb_10 (preds = {bb_7 bb_28 bb_8 bb_9 }, succs = {bb_25 }) bb_11 (preds = {bb_36 }, succs = {bb_29 bb_30 }) bb_12 (preds = {bb_30 }, succs = {bb_25 }) bb_13 (preds = {bb_30 }, succs = {bb_25 }) bb_14 (preds = {bb_36 }, succs = {bb_15 bb_16 }) bb_15 (preds = {bb_14 }, succs = {bb_25 }) bb_16 (preds = {bb_14 }, succs = {bb_25 bb_31 }) bb_17 (preds = {bb_36 }, succs = {bb_18 bb_19 }) bb_18 (preds = {bb_17 }, succs = {bb_25 }) bb_19 (preds = {bb_17 }, succs = {bb_25 bb_32 }) bb_20 (preds = {bb_36 }, succs = {bb_21 bb_22 }) bb_21 (preds = {bb_20 }, succs = {bb_25 }) bb_22 (preds = {bb_20 }, succs = {bb_25 }) bb_23 (preds = {bb_36 }, succs = {bb_33 bb_34 }) bb_24 (preds = {bb_36 }, succs = {bb_25 bb_35 }) bb_25 (preds = {bb_10 bb_12 bb_16 bb_19 bb_22 bb_34 bb_35 bb_36 bb_29 bb_13 bb_15 bb_31 bb_18 bb_32 bb_21 bb_33 bb_24 }, succs = {bb_26 bb_27 }) bb_26 (preds = {bb_25 }, succs = {bb_4 bb_27 }) bb_28 (preds = {bb_7 }, succs = {bb_10 bb_8 }) bb_29 (preds = {bb_11 }, succs = {bb_25 }) bb_30 (preds = {bb_11 }, succs = {bb_12 bb_13 }) bb_31 (preds = {bb_16 }, succs = {bb_25 }) bb_32 (preds = {bb_19 }, succs = {bb_25 }) bb_33 (preds = {bb_23 }, succs = {bb_25 }) bb_34 (preds = {bb_23 }, succs = {bb_25 }) bb_35 (preds = {bb_24 }, succs = {bb_25 }) } } What about removing the use of e->aux in threadupdate.c, to be able to jump thread across all the recorded paths? Thanks, Sebastian From bac0f2a390048652910f77503b21b3e208daeae1 Mon Sep 17 00:00:00 2001 From: Sebastian Pop Date: Fri, 26 Sep 2014 14:54:20 -0500 Subject: [PATCH] jump thread for PR 54742 Adapted from a patch from James Greenhalgh. * tree-ssa-threadedge.c (simplify_control_stmt_condition): Restore the original value of cond when simplification fails. (find_thread_path): New. (find_control_statement_thread_paths): New. (thread_through_normal_block): Call find_control_statement_thread_paths. * testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c: New. --- gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c | 32 ++++ gcc/tree-ssa-threadedge.c | 180 ++++++++++++++++++++++- gcc/tree-ssa-threadupdate.c | 4 + 3 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c new file mode 100644 index 0000000..f3ef725 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-6.c @@ -0,0 +1,32 @@ +int sum0, sum1, sum2, sum3; +int foo(char * s, char** ret) +{ + int state=0; + char c; + + for (; *s && state != 4; s++) + { + c = *s; + if (c == '*') + { + s++; + break; + } + switch (state) { + case 0: + if (c == '+') state = 1; + else if (c != '-') sum0+=c; + break; + case 1: + if (c == '+') state = 2; + else if (c == '-') state = 0; + else sum1+=c; + break; + default: + break; + } + + } + *ret = s; + return state; +} diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 3dee5ba..7b9e5b6 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -628,6 +628,7 @@ simplify_control_stmt_condition (edge e, rather than use a relational operator. These are simpler to handle. */ if (TREE_CODE (cond) == SSA_NAME) { + tree original_lhs = cond; cached_lhs = cond; /* Get the variable's current value from the equivalence chains. @@ -656,6 +657,12 @@ simplify_control_stmt_condition (edge e, pass specific callback to try and simplify it further. */ if (cached_lhs && ! is_gimple_min_invariant (cached_lhs)) cached_lhs = (*simplify) (stmt, stmt); + + /* We couldn't find an invariant. But, callers of this + function may be able to do something useful with the + unmodified destination. */ + if (!cached_lhs) + cached_lhs = original_lhs; } else cached_lhs = NULL; @@ -915,6 +922,155 @@ thread_around_empty_blocks (edge taken_edge, return false; } +/* Return true if there is at least one path from START_BB to END_BB. + VISITED_BBS is used to make sure we don't fall into an infinite loop. */ + +static bool +find_thread_path (basic_block start_bb, basic_block end_bb, + vec *&path, + hash_set *visited_bbs) +{ + if (start_bb == end_bb) + { + vec_safe_push (path, start_bb); + return true; + } + + if (!visited_bbs->add(start_bb)) + { + edge e; + edge_iterator ei; + FOR_EACH_EDGE (e, ei, start_bb->succs) + if (find_thread_path (e->dest, end_bb, path, visited_bbs)) + { + vec_safe_push (path, start_bb); + return true; + } + } + + return false; +} + +/* We trace the value of the variable EXPR back through any phi nodes looking + for places where it gets a constant value and save the path. */ + +static void +find_control_statement_thread_paths (tree expr, + hash_set *visited_phis, + vec *&path) +{ + tree var = SSA_NAME_VAR (expr); + gimple def_stmt = SSA_NAME_DEF_STMT (expr); + basic_block var_bb = gimple_bb (def_stmt); + + if (var == NULL || var_bb == NULL) + return; + + vec *next_path; + vec_alloc (next_path, n_basic_blocks_for_fn (cfun)); + + basic_block last_bb_in_path = path->last (); + + /* Put the path from var_bb to last_bb_in_path into next_path. */ + if (var_bb != last_bb_in_path) + { + edge e; + int e_count = 0; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, last_bb_in_path->preds) + { + hash_set *visited_bbs = new hash_set; + + if (find_thread_path (var_bb, e->src, next_path, visited_bbs)) + e_count = e_count + 1; + + delete visited_bbs; + + /* If there is more than one path, stop. */ + if (e_count > 1) + { + vec_free (next_path); + return; + } + } + } + + /* Visit PHI nodes once. */ + if (gimple_code (def_stmt) != GIMPLE_PHI + || visited_phis->add(def_stmt)) { + vec_free (next_path); + return; + } + + /* Append all the nodes from next_path to path. */ + vec_safe_splice (path, next_path); + gcc_assert (path->last () == var_bb); + + /* Iterate over the arguments of PHI. */ + unsigned int i; + for (i = 0; i < gimple_phi_num_args (def_stmt); i++) + { + tree arg = gimple_phi_arg_def (def_stmt, i); + basic_block bbi = gimple_phi_arg_edge (def_stmt, i)->src; + + /* Skip edges pointing outside the current loop. */ + if (!arg || var_bb->loop_father != bbi->loop_father) + continue; + + /* Add BBI to the path. */ + vec_safe_push (path, bbi); + + if (TREE_CODE (arg) == INTEGER_CST) + { + int j, n = path->length (); + vec *jump_thread_path + = new vec (); + int joiners = 0; + + for (j = 0; j < n - 1; j++) + { + edge e = find_edge ((*path)[n - j - 1], + (*path)[n - j - 2]); + gcc_assert (e); + enum jump_thread_edge_type kind; + + if (j == 0) + kind = EDGE_START_JUMP_THREAD; + else if (single_pred_p (e->src)) + kind = EDGE_NO_COPY_SRC_BLOCK; + else { + kind = EDGE_COPY_SRC_JOINER_BLOCK; + ++joiners; + } + + jump_thread_edge *x = new jump_thread_edge (e, kind); + jump_thread_path->safe_push (x); + } + + /* Add the edge taken when the control variable has value ARG. */ + edge taken_edge = find_taken_edge ((*path)[0], arg); + jump_thread_edge *x + = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK); + jump_thread_path->safe_push (x); + + /* Thread-update does not handle more than two joiners. A path with + less than 3 nodes should not be jump-threaded. */ + if (joiners < 2 && n > 2) + register_jump_thread (jump_thread_path); + } + else if (TREE_CODE (arg) == SSA_NAME) + find_control_statement_thread_paths (arg, visited_phis, path); + + /* Remove BBI from the path. */ + path->pop (); + } + + /* Remove all the nodes that we added from next_path. */ + vec_safe_truncate (path, (path->length () - next_path->length ())); + vec_free (next_path); +} + /* We are exiting E->src, see if E->dest ends with a conditional jump which has a known value when reached via E. @@ -1000,7 +1156,10 @@ thread_through_normal_block (edge e, cond = simplify_control_stmt_condition (e, stmt, dummy_cond, simplify, handle_dominating_asserts); - if (cond && is_gimple_min_invariant (cond)) + if (!cond) + return 0; + + if (is_gimple_min_invariant (cond)) { edge taken_edge = find_taken_edge (e->dest, cond); basic_block dest = (taken_edge ? taken_edge->dest : NULL); @@ -1046,7 +1205,25 @@ thread_through_normal_block (edge e, backedge_seen_p); return 1; } + + if (TREE_CODE (cond) != SSA_NAME + || e->dest->loop_father != e->src->loop_father) + return 0; + + /* When COND cannot be simplified, try to find paths from a control + statement back through the PHI nodes which would affect that control + statement. */ + vec *bb_path; + vec_alloc (bb_path, n_basic_blocks_for_fn (cfun)); + vec_safe_push (bb_path, e->dest); + hash_set *visited_phis = new hash_set; + + find_control_statement_thread_paths (cond, visited_phis, bb_path); + + delete visited_phis; + vec_free (bb_path); + + return -1; } return 0; } -- 2.1.0.243.g30d45f7