aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc
diff options
context:
space:
mode:
authorCaroline Tice <cmtice@google.com>2016-03-16 20:56:07 (GMT)
committerCaroline Tice <cmtice@google.com>2016-03-16 20:56:07 (GMT)
commitac16f08b86701ecf70e32f4ead8db63d92603808 (patch)
tree08f5e73c8a8f3c980468347bcc0c283bc1e6d3eb /gcc-4.9/gcc
parent3a800d7d75ceba88429096186a2150a2d938334a (diff)
downloadtoolchain_gcc-ac16f08b86701ecf70e32f4ead8db63d92603808.zip
toolchain_gcc-ac16f08b86701ecf70e32f4ead8db63d92603808.tar.gz
toolchain_gcc-ac16f08b86701ecf70e32f4ead8db63d92603808.tar.bz2
GCC unification, part 2. Fix various errors from previous unificaiton.
The previous version of the unified GCC compiler (Android & ChromeOS) caused some ChromeOS tests to fail. It also caused an Android NDK test case to fail. This CL fixes those problems. In particular it does the following: - Fix some file formatting errors from previous unification patch. - Update ChangeLog files to reflect Android backport patches. - Find and incorporate a few missing pieces from the following backports backports from trunk r221007, r221675, r222011, r212011, r214942, r214957, r215012, r215016, r218115, r218733, r218746, r220491. This involved small changes in the following files: gcc/cfghoks.c gcc/cfgloop.c gcc/cfgloop.h gcc/except.c gcc/loop-init.c gcc/omp-low.c - Fix minor Android test case regression introduced in the previous unification patch. Change-Id: I482e3a34e3ed97c7ba609fe2954b4781f02ec617
Diffstat (limited to 'gcc-4.9/gcc')
-rw-r--r--gcc-4.9/gcc/ChangeLog136
-rw-r--r--gcc-4.9/gcc/cfghooks.c18
-rw-r--r--gcc-4.9/gcc/cfgloop.c13
-rw-r--r--gcc-4.9/gcc/cfgloop.h8
-rw-r--r--gcc-4.9/gcc/except.c5
-rw-r--r--gcc-4.9/gcc/loop-init.c27
-rw-r--r--gcc-4.9/gcc/omp-low.c4
-rw-r--r--gcc-4.9/gcc/testsuite/ChangeLog30
-rw-r--r--gcc-4.9/gcc/tree-ssa-threadedge.c55
-rw-r--r--gcc-4.9/gcc/tree-ssa-threadupdate.c182
10 files changed, 321 insertions, 157 deletions
diff --git a/gcc-4.9/gcc/ChangeLog b/gcc-4.9/gcc/ChangeLog
index dee0fa3..fe9d7ce 100644
--- a/gcc-4.9/gcc/ChangeLog
+++ b/gcc-4.9/gcc/ChangeLog
@@ -5,6 +5,33 @@
define_insn_and_split. Ensure operands[1] and operands[0] do not
get assigned the same register.
+2015-10-28 Yvan Roux <yvan.roux@linaro.org>
+ Sebastian Pop <s.pop@samsung.com>
+
+ Backport from trunk r221007, r221675, r222011.
+ 2015-04-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/65735
+ * tree-ssa-threadedge.c (fsm_find_control_statement_thread_paths):
+ Remove visited_phis argument, add visited_bbs, avoid recursing into the
+ same bb rather than just into the same phi node.
+ (thread_through_normal_block): Adjust caller.
+
+ 2015-03-25 Sebastian Pop <s.pop@samsung.com>
+
+ PR tree-optimization/65177
+ * tree-ssa-threadupdate.c (verify_seme): Renamed verify_jump_thread.
+ (bb_in_bbs): New.
+ (duplicate_seme_region): Renamed duplicate_thread_path. Redirect all
+ edges not adjacent on the path to the original code.
+
+ 2015-02-26 Sebastian Pop <s.pop@samsung.com>
+
+ PR tree-optimization/65048
+ * tree-ssa-threadupdate.c (valid_jump_thread_path): New.
+ (thread_through_all_blocks): Call valid_jump_thread_path.
+ Remove invalid FSM jump-thread paths.
+
2015-03-26 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Backport of r214242, r214254, and bug fix patches from mainline
@@ -56,6 +83,83 @@
(entry_register): Likewise.
(web_main): Likewise.
+2015-03-05 Yvan Roux <yvan.roux@linaro.org>
+
+ Backport from trunk r212011, r214942, r214957, r215012, r215016, r218115
+ r218733, r218746, r220491.
+ 2015-02-06 Sebastian Pop <s.pop@samsung.com>
+ Brian Rzycki <b.rzycki@samsung.com>
+
+ PR tree-optimization/64878
+ * tree-ssa-threadedge.c: Include tree-ssa-loop.h.
+ (fsm_find_control_statement_thread_paths): Add parameter seen_loop_phi.
+ Stop recursion at loop phi nodes after having visited a loop phi node.
+
+ 2014-12-15 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/64246
+ * cfgloop.c (mark_loop_for_removal): Make safe against multiple
+ invocations on the same loop.
+
+ 2014-12-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/64284
+ * tree-ssa-threadupdate.c (duplicate_seme_region): Mark
+ the loop for removal if we copied the loop header.
+
+ 2014-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/64083
+ * tree-ssa-threadupdate.c (thread_through_all_blocks): Do not
+ forcibly mark loop for removal the wrong way.
+
+ 2014-09-08 Richard Biener <rguenther@suse.de>
+
+ PR ipa/63196
+ * tree-inline.c (copy_loops): The source loop header should
+ always be non-NULL.
+ (tree_function_versioning): If loops need fixup after removing
+ unreachable blocks fix them.
+ * omp-low.c (simd_clone_adjust): Do not add incr block to
+ loop under construction.
+
+ 2014-09-08 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/63204
+ * cfgloop.c (mark_loop_for_removal): Track former header
+ unconditionally.
+ * cfgloop.h (struct loop): Add former_header member unconditionally.
+ * loop-init.c (fix_loop_structure): Enable bogus loop removal
+ diagnostic unconditionally.
+
+ 2014-09-05 Richard Biener <rguenther@suse.de>
+
+ * cfgloop.c (mark_loop_for_removal): Record former header
+ when ENABLE_CHECKING.
+ * cfgloop.h (strut loop): Add former_header member when
+ ENABLE_CHECKING.
+ * loop-init.c (fix_loop_structure): Sanity check loops
+ marked for removal if they re-appeared.
+
+ 2014-09-05 Richard Biener <rguenther@suse.de>
+
+ * cfgloop.c (mark_loop_for_removal): New function.
+ * cfgloop.h (mark_loop_for_removal): Declare.
+ * cfghooks.c (delete_basic_block): Use mark_loop_for_removal.
+ (merge_blocks): Likewise.
+ (duplicate_block): Likewise.
+ * except.c (sjlj_emit_dispatch_table): Likewise.
+ * tree-eh.c (cleanup_empty_eh_merge_phis): Likewise.
+ * tree-ssa-threadupdate.c (ssa_redirect_edges): Likewise.
+ (thread_through_loop_header): Likewise.
+
+ 2014-06-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/61607
+ * tree-ssa-threadupdate.c (ssa_redirect_edges): Cancel the
+ loop if we redirected its latch edge.
+ (thread_block_1): Do not cancel loops prematurely.
+
2015-01-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/64734
@@ -111,6 +215,38 @@
* expr.c (expand_expr_real_1) <normal_inner_ref>: Use the expression to
set the memory attributes in all cases but clear MEM_EXPR if need be.
+2015-01-14 Yvan Roux <yvan.roux@linaro.org>
+
+ Backport from trunk r218451.
+ 2014-12-06 James Greenhalgh <james.greenhalgh@arm.com>
+ Sebastian Pop <s.pop@samsung.com>
+ Brian Rzycki <b.rzycki@samsung.com>
+
+ PR tree-optimization/54742
+ * params.def (max-fsm-thread-path-insns, max-fsm-thread-length)
+ (max-fsm-thread-paths): New.
+
+ * doc/invoke.texi (max-fsm-thread-path-insns, max-fsm-thread-length)
+ (max-fsm-thread-paths): Documented.
+
+ * tree-cfg.c (split_edge_bb_loc): Export.
+ * tree-cfg.h (split_edge_bb_loc): Declared extern.
+
+ * tree-ssa-threadedge.c (simplify_control_stmt_condition): Restore the
+ original value of cond when simplification fails.
+ (fsm_find_thread_path): New.
+ (fsm_find_control_statement_thread_paths): New.
+ (thread_through_normal_block):Call find_control_statement_thread_paths.
+
+ * tree-ssa-threadupdate.c (dump_jump_thread_path): Pretty print
+ EDGE_FSM_THREAD.
+ (verify_seme): New.
+ (duplicate_seme_region): New.
+ (thread_through_all_blocks): Generate code for EDGE_FSM_THREAD edges
+ calling duplicate_seme_region.
+
+ * tree-ssa-threadupdate.h (jump_thread_edge_type): Add EDGE_FSM_THREAD.
+
2015-01-14 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
diff --git a/gcc-4.9/gcc/cfghooks.c b/gcc-4.9/gcc/cfghooks.c
index 87da0d0..76486b2 100644
--- a/gcc-4.9/gcc/cfghooks.c
+++ b/gcc-4.9/gcc/cfghooks.c
@@ -568,14 +568,10 @@ delete_basic_block (basic_block bb)
struct loop *loop = bb->loop_father;
/* If we remove the header or the latch of a loop, mark the loop for
- removal by setting its header and latch to NULL. */
+ removal. */
if (loop->latch == bb
|| loop->header == bb)
- {
- loop->header = NULL;
- loop->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
- }
+ mark_loop_for_removal (loop);
remove_bb_from_loops (bb);
}
@@ -759,11 +755,7 @@ merge_blocks (basic_block a, basic_block b)
/* ... we merge two loop headers, in which case we kill
the inner loop. */
if (b->loop_father->header == b)
- {
- b->loop_father->header = NULL;
- b->loop_father->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
- }
+ mark_loop_for_removal (b->loop_father);
}
/* If we merge a loop header into its predecessor, update the loop
structure. */
@@ -1098,9 +1090,7 @@ duplicate_block (basic_block bb, edge e, basic_block after)
&& cloop->header == bb)
{
add_bb_to_loop (new_bb, loop_outer (cloop));
- cloop->header = NULL;
- cloop->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
+ mark_loop_for_removal (cloop);
}
else
{
diff --git a/gcc-4.9/gcc/cfgloop.c b/gcc-4.9/gcc/cfgloop.c
index e4b60f5..a238405 100644
--- a/gcc-4.9/gcc/cfgloop.c
+++ b/gcc-4.9/gcc/cfgloop.c
@@ -1994,3 +1994,16 @@ bb_loop_depth (const_basic_block bb)
{
return bb->loop_father ? loop_depth (bb->loop_father) : 0;
}
+
+/* Marks LOOP for removal and sets LOOPS_NEED_FIXUP. */
+
+void
+mark_loop_for_removal (loop_p loop)
+{
+ if (loop->header == NULL)
+ return;
+ loop->former_header = loop->header;
+ loop->header = NULL;
+ loop->latch = NULL;
+ loops_state_set (LOOPS_NEED_FIXUP);
+}
diff --git a/gcc-4.9/gcc/cfgloop.h b/gcc-4.9/gcc/cfgloop.h
index 11bfc81..ce1a689 100644
--- a/gcc-4.9/gcc/cfgloop.h
+++ b/gcc-4.9/gcc/cfgloop.h
@@ -203,6 +203,12 @@ struct GTY ((chain_next ("%h.next"))) loop {
/* Number of iteration analysis data for RTL. */
struct niter_desc *simple_loop_desc;
+
+ /* For sanity checking during loop fixup we record here the former
+ loop header for loops marked for removal. Note that this prevents
+ the basic-block from being collected but its index can still be
+ reused. */
+ basic_block former_header;
};
/* Flags for state of loop structure. */
@@ -345,6 +351,8 @@ struct loop * loop_version (struct loop *, void *,
extern bool remove_path (edge);
extern void unloop (struct loop *, bool *, bitmap);
extern void scale_loop_frequencies (struct loop *, int, int);
+void mark_loop_for_removal (loop_p);
+
/* Induction variable analysis. */
diff --git a/gcc-4.9/gcc/except.c b/gcc-4.9/gcc/except.c
index d67b4e4..2818119 100644
--- a/gcc-4.9/gcc/except.c
+++ b/gcc-4.9/gcc/except.c
@@ -1394,10 +1394,7 @@ sjlj_emit_dispatch_table (rtx dispatch_label, int num_dispatch)
{
for (loop = bb->loop_father;
loop_outer (loop); loop = loop_outer (loop))
- {
- loop->header = NULL;
- loop->latch = NULL;
- }
+ mark_loop_for_removal (loop);
}
}
diff --git a/gcc-4.9/gcc/loop-init.c b/gcc-4.9/gcc/loop-init.c
index 4cc561c..a8abf37 100644
--- a/gcc-4.9/gcc/loop-init.c
+++ b/gcc-4.9/gcc/loop-init.c
@@ -272,6 +272,33 @@ fix_loop_structure (bitmap changed_bbs)
FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop)
if (loop && loop->header == NULL)
{
+ if (dump_file
+ && ((unsigned) loop->former_header->index
+ < basic_block_info_for_fn (cfun)->length ()))
+ {
+ basic_block former_header
+ = BASIC_BLOCK_FOR_FN (cfun, loop->former_header->index);
+ /* If the old header still exists we want to check if the
+ original loop is re-discovered or the old header is now
+ part of a newly discovered loop.
+ In both cases we should have avoided removing the loop. */
+ if (former_header == loop->former_header)
+ {
+ if (former_header->loop_father->header == former_header)
+ fprintf (dump_file, "fix_loop_structure: rediscovered "
+ "removed loop %d as loop %d with old header %d\n",
+ loop->num, former_header->loop_father->num,
+ former_header->index);
+ else if ((unsigned) former_header->loop_father->num
+ >= old_nloops)
+ fprintf (dump_file, "fix_loop_structure: header %d of "
+ "removed loop %d is part of the newly "
+ "discovered loop %d with header %d\n",
+ former_header->index, loop->num,
+ former_header->loop_father->num,
+ former_header->loop_father->header->index);
+ }
+ }
(*get_loops (cfun))[i] = NULL;
flow_loop_free (loop);
}
diff --git a/gcc-4.9/gcc/omp-low.c b/gcc-4.9/gcc/omp-low.c
index 6d9206c..6520c03 100644
--- a/gcc-4.9/gcc/omp-low.c
+++ b/gcc-4.9/gcc/omp-low.c
@@ -11705,6 +11705,7 @@ simd_clone_adjust (struct cgraph_node *node)
iteration increment and the condition/branch. */
basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
basic_block incr_bb = create_empty_bb (orig_exit);
+ add_bb_to_loop (incr_bb, body_bb->loop_father);
/* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
flag. Set it now to be a FALLTHRU_EDGE. */
gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
@@ -11729,7 +11730,6 @@ simd_clone_adjust (struct cgraph_node *node)
loop->safelen = node->simdclone->simdlen;
loop->force_vect = true;
loop->header = body_bb;
- add_bb_to_loop (incr_bb, loop);
/* Branch around the body if the mask applies. */
if (node->simdclone->inbranch)
@@ -11770,7 +11770,7 @@ simd_clone_adjust (struct cgraph_node *node)
gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
e = split_block (incr_bb, gsi_stmt (gsi));
basic_block latch_bb = e->dest;
- basic_block new_exit_bb = e->dest;
+ basic_block new_exit_bb;
new_exit_bb = split_block (latch_bb, NULL)->dest;
loop->latch = latch_bb;
diff --git a/gcc-4.9/gcc/testsuite/ChangeLog b/gcc-4.9/gcc/testsuite/ChangeLog
index 509b097..2f34469 100644
--- a/gcc-4.9/gcc/testsuite/ChangeLog
+++ b/gcc-4.9/gcc/testsuite/ChangeLog
@@ -3,6 +3,25 @@
PR target/69403
* gcc.c-torture/execute/pr69403.c: New test.
+2015-10-28 Yvan Roux <yvan.roux@linaro.org>
+ Sebastian Pop <s.pop@samsung.com>
+
+ Backport from trunk r221007, r221675, r222011.
+ 2015-04-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/65735
+ * gcc.c-torture/compile/pr65735.c: New test.
+
+ 2015-03-25 Sebastian Pop <s.pop@samsung.com>
+
+ PR tree-optimization/65177
+ * gcc.dg/tree-ssa/ssa-dom-thread-10.c: New.
+
+ 2015-02-26 Sebastian Pop <s.pop@samsung.com>
+
+ PR tree-optimization/65048
+ * gcc.dg/tree-ssa/ssa-dom-thread-9.c: New.
+
2015-03-26 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
Backport r214254 and related tests from mainline
@@ -56,6 +75,17 @@
* gnat.dg/opt47.adb: New test.
+2015-01-14 Yvan Roux <yvan.roux@linaro.org>
+
+ Backport from trunk r218451.
+ 2014-12-06 James Greenhalgh <james.greenhalgh@arm.com>
+ Sebastian Pop <s.pop@samsung.com>
+ Brian Rzycki <b.rzycki@samsung.com>
+
+ PR tree-optimization/54742
+ * gcc.dg/tree-ssa/ssa-dom-thread-6.c: New test.
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: New test.
+
2015-01-14 Jakub Jelinek <jakub@redhat.com>
Backported from mainline
diff --git a/gcc-4.9/gcc/tree-ssa-threadedge.c b/gcc-4.9/gcc/tree-ssa-threadedge.c
index 604123e..2549789 100644
--- a/gcc-4.9/gcc/tree-ssa-threadedge.c
+++ b/gcc-4.9/gcc/tree-ssa-threadedge.c
@@ -912,8 +912,8 @@ thread_around_empty_blocks (edge taken_edge,
static bool
fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
- vec<basic_block, va_gc> *&path,
- pointer_set_t *visited_bbs, loop_p loop)
+ vec<basic_block, va_gc> *&path,
+ pointer_set_t *visited_bbs, loop_p loop)
{
if (loop != start_bb->loop_father)
return false;
@@ -947,7 +947,7 @@ static int max_threaded_paths;
static void
fsm_find_control_statement_thread_paths (tree expr,
- pointer_set_t *visited_bbs,
+ pointer_set_t *visited_bbs,
vec<basic_block, va_gc> *&path,
bool seen_loop_phi)
{
@@ -976,7 +976,7 @@ fsm_find_control_statement_thread_paths (tree expr,
{
/* Do not walk through more than one loop PHI node. */
if (seen_loop_phi)
- return;
+ return;
seen_loop_phi = true;
}
@@ -997,23 +997,23 @@ fsm_find_control_statement_thread_paths (tree expr,
if (fsm_find_thread_path (var_bb, e->src, next_path, visited_bbs,
e->src->loop_father))
- ++e_count;
+ ++e_count;
- pointer_set_destroy (visited_bbs);
+ pointer_set_destroy (visited_bbs);
- /* If there is more than one path, stop. */
- if (e_count > 1)
+ /* If there is more than one path, stop. */
+ if (e_count > 1)
{
- vec_free (next_path);
- return;
+ vec_free (next_path);
+ return;
}
- }
+ }
/* Stop if we have not found a path: this could occur when the recursion
is stopped by one of the bounds. */
if (e_count == 0)
{
- vec_free (next_path);
+ vec_free (next_path);
return;
}
@@ -1034,18 +1034,17 @@ fsm_find_control_statement_thread_paths (tree expr,
/* Skip edges pointing outside the current loop. */
if (!arg || var_bb->loop_father != bbi->loop_father)
- continue;
+ continue;
if (TREE_CODE (arg) == SSA_NAME)
- {
+ {
vec_safe_push (path, bbi);
- /* Recursively follow SSA_NAMEs looking for a constant definition. */
+ /* Recursively follow SSA_NAMEs looking for a constant definition. */
fsm_find_control_statement_thread_paths (arg, visited_bbs, path,
seen_loop_phi);
-
path->pop ();
continue;
- }
+ }
if (TREE_CODE (arg) != INTEGER_CST)
continue;
@@ -1066,12 +1065,12 @@ fsm_find_control_statement_thread_paths (tree expr,
if (max_threaded_paths <= 0)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "FSM jump-thread path not considered: "
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "FSM jump-thread path not considered: "
"the number of previously recorded FSM paths to thread "
"exceeds PARAM_MAX_FSM_THREAD_PATHS.\n");
continue;
- }
+ }
/* Add BBI to the path. */
vec_safe_push (path, bbi);
@@ -1085,8 +1084,8 @@ fsm_find_control_statement_thread_paths (tree expr,
/* Count the number of instructions on the path: as these instructions
will have to be duplicated, we will not record the path if there are
- too many instructions on the path. Also check that all the blocks in
- the path belong to a single loop. */
+ too many instructions on the path. Also check that all the blocks in
+ the path belong to a single loop. */
for (j = 1; j < path_length - 1; j++)
{
basic_block bb = (*path)[j];
@@ -1109,23 +1108,23 @@ fsm_find_control_statement_thread_paths (tree expr,
}
if (path_crosses_loops)
- {
+ {
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "FSM jump-thread path not considered: "
"the path crosses loops.\n");
path->pop ();
- continue;
+ continue;
}
if (n_insns >= PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATH_INSNS))
- {
+ {
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "FSM jump-thread path not considered: "
"the number of instructions on the path "
"exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
path->pop ();
- continue;
- }
+ continue;
+ }
vec<jump_thread_edge *> *jump_thread_path
= new vec<jump_thread_edge *> ();
@@ -1137,7 +1136,7 @@ fsm_find_control_statement_thread_paths (tree expr,
(*path)[path_length - j - 2]);
gcc_assert (e);
jump_thread_edge *x = new jump_thread_edge (e, EDGE_FSM_THREAD);
- jump_thread_path->safe_push (x);
+ jump_thread_path->safe_push (x);
}
/* Add the edge taken when the control variable has value ARG. */
diff --git a/gcc-4.9/gcc/tree-ssa-threadupdate.c b/gcc-4.9/gcc/tree-ssa-threadupdate.c
index c2f02a6..e2c2dbe 100644
--- a/gcc-4.9/gcc/tree-ssa-threadupdate.c
+++ b/gcc-4.9/gcc/tree-ssa-threadupdate.c
@@ -156,9 +156,9 @@ dump_jump_thread_path (FILE *dump_file, vec<jump_thread_edge *> path,
bool registering)
{
fprintf (dump_file,
- " %s%s jump thread: (%d, %d) incoming edge; ",
+ " %s jump thread: (%d, %d) incoming edge; ",
(registering ? "Registering" : "Cancelling"),
- (path[0]->type == EDGE_FSM_THREAD ? " FSM": ""),
+ (path[0]->type == EDGE_FSM_THREAD ? " FSM": ""),
path[0]->e->src->index, path[0]->e->dest->index);
for (unsigned int i = 1; i < path.length (); i++)
@@ -700,6 +700,10 @@ ssa_redirect_edges (struct redirection_data **slot,
if ((*path)[1]->type != EDGE_COPY_SRC_JOINER_BLOCK)
EDGE_SUCC (rd->dup_blocks[0], 0)->count += e->count;
+ /* If we redirect a loop latch edge cancel its loop. */
+ if (e->src == e->src->loop_father->latch)
+ mark_loop_for_removal (e->src->loop_father);
+
/* Redirect the incoming edge (possibly to the joiner block) to the
appropriate duplicate block. */
e2 = redirect_edge_and_branch (e, rd->dup_blocks[0]);
@@ -780,7 +784,6 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
edge e, e2;
edge_iterator ei;
ssa_local_info_t local_info;
- struct loop *loop = bb->loop_father;
/* To avoid scanning a linear array for the element we need we instead
use a hash table. For normal code there should be no noticeable
@@ -788,32 +791,6 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
incoming and outgoing edges such linear searches can get expensive. */
redirection_data.create (EDGE_COUNT (bb->succs));
- /* If we thread the latch of the loop to its exit, the loop ceases to
- exist. Make sure we do not restrict ourselves in order to preserve
- this loop. */
- if (loop->header == bb)
- {
- e = loop_latch_edge (loop);
- vec<jump_thread_edge *> *path = THREAD_PATH (e);
-
- if (path
- && (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && joiners)
- || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && !joiners)))
- {
- for (unsigned int i = 1; i < path->length (); i++)
- {
- edge e2 = (*path)[i]->e;
-
- if (loop_exit_edge_p (loop, e2))
- {
- loop->header = NULL;
- loop->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
- }
- }
- }
- }
-
/* Record each unique threaded destination into a hash table for
efficient lookups. */
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -1257,9 +1234,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
{
/* If the loop ceased to exist, mark it as such, and thread through its
original header. */
- loop->header = NULL;
- loop->latch = NULL;
- loops_state_set (LOOPS_NEED_FIXUP);
+ mark_loop_for_removal (loop);
return thread_block (header, false);
}
@@ -1626,7 +1601,7 @@ bb_ends_with_multiway_branch (basic_block bb ATTRIBUTE_UNUSED)
/* Verify that the REGION is a valid jump thread. A jump thread is a special
case of SEME Single Entry Multiple Exits region in which all nodes in the
REGION have exactly one incoming edge. The only exception is the first block
- that may not have been connected to the rest of the cfg yet. */
+ that may not have been connected to the rest of the cfg yet. */
DEBUG_FUNCTION void
verify_jump_thread (basic_block *region, unsigned n_region)
@@ -1643,7 +1618,6 @@ bb_in_bbs (basic_block bb, basic_block *bbs, int n)
for (int i = 0; i < n; i++)
if (bb == bbs[i])
return true;
-
return false;
}
@@ -1661,11 +1635,11 @@ bb_in_bbs (basic_block bb, basic_block *bbs, int n)
static bool
duplicate_thread_path (edge entry, edge exit,
- basic_block *region, unsigned n_region,
- basic_block *region_copy)
+ basic_block *region, unsigned n_region,
+ basic_block *region_copy)
{
unsigned i;
- bool free_region_copy = false, copying_header = false;
+ bool free_region_copy = false;
struct loop *loop = entry->dest->loop_father;
edge exit_copy;
edge redirected;
@@ -1682,17 +1656,14 @@ duplicate_thread_path (edge entry, edge exit,
for (i = 0; i < n_region; i++)
{
/* We do not handle subloops, i.e. all the blocks must belong to the
- same loop. */
+ same loop. */
if (region[i]->loop_father != loop)
- return false;
+ return false;
}
initialize_original_copy_tables ();
- if (copying_header)
- set_loop_copy (loop, loop_outer (loop));
- else
- set_loop_copy (loop, loop);
+ set_loop_copy (loop, loop);
if (!region_copy)
{
@@ -1705,25 +1676,24 @@ duplicate_thread_path (edge entry, edge exit,
total_count = entry->dest->count;
entry_count = entry->count;
/* Fix up corner cases, to avoid division by zero or creation of negative
- frequencies. */
+ frequencies. */
if (entry_count > total_count)
- entry_count = total_count;
+ entry_count = total_count;
}
else
{
total_freq = entry->dest->frequency;
entry_freq = EDGE_FREQUENCY (entry);
/* Fix up corner cases, to avoid division by zero or creation of negative
- frequencies. */
+ frequencies. */
if (total_freq == 0)
- total_freq = 1;
+ total_freq = 1;
else if (entry_freq > total_freq)
- entry_freq = total_freq;
+ entry_freq = total_freq;
}
copy_bbs (region, n_region, region_copy, &exit, 1, &exit_copy, loop,
- split_edge_bb_loc (entry), false);
-
+ split_edge_bb_loc (entry), false);
/* Fix up: copy_bbs redirects all edges pointing to copied blocks. The
following code ensures that all the edges exiting the jump-thread path are
redirected back to the original code: these edges are exceptions
@@ -1737,50 +1707,50 @@ duplicate_thread_path (edge entry, edge exit,
basic_block bb = region_copy[i];
if (single_succ_p (bb))
- {
- /* Make sure the successor is the next node in the path. */
- gcc_assert (i + 1 == n_region
- || region_copy[i + 1] == single_succ_edge (bb)->dest);
- continue;
- }
+ {
+ /* Make sure the successor is the next node in the path. */
+ gcc_assert (i + 1 == n_region
+ || region_copy[i + 1] == single_succ_edge (bb)->dest);
+ continue;
+ }
/* Special case the last block on the path: make sure that it does not
- jump back on the copied path. */
+ jump back on the copied path. */
if (i + 1 == n_region)
- {
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (bb_in_bbs (e->dest, region_copy, n_region - 1))
- {
- basic_block orig = get_bb_original (e->dest);
- if (orig)
- redirect_edge_and_branch_force (e, orig);
- }
- continue;
- }
+ {
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (bb_in_bbs (e->dest, region_copy, n_region - 1))
+ {
+ basic_block orig = get_bb_original (e->dest);
+ if (orig)
+ redirect_edge_and_branch_force (e, orig);
+ }
+ continue;
+ }
/* Redirect all other edges jumping to non-adjacent blocks back to the
- original code. */
+ original code. */
FOR_EACH_EDGE (e, ei, bb->succs)
- if (region_copy[i + 1] != e->dest)
- {
- basic_block orig = get_bb_original (e->dest);
- if (orig)
- redirect_edge_and_branch_force (e, orig);
- }
+ if (region_copy[i + 1] != e->dest)
+ {
+ basic_block orig = get_bb_original (e->dest);
+ if (orig)
+ redirect_edge_and_branch_force (e, orig);
+ }
}
if (total_count)
{
scale_bbs_frequencies_gcov_type (region, n_region,
- total_count - entry_count,
- total_count);
+ total_count - entry_count,
+ total_count);
scale_bbs_frequencies_gcov_type (region_copy, n_region, entry_count,
- total_count);
+ total_count);
}
else
{
scale_bbs_frequencies_int (region, n_region, total_freq - entry_freq,
- total_freq);
+ total_freq);
scale_bbs_frequencies_int (region_copy, n_region, entry_freq, total_freq);
}
@@ -1799,6 +1769,8 @@ duplicate_thread_path (edge entry, edge exit,
}
/* Redirect the entry and add the phi node arguments. */
+ if (entry->dest == loop->header)
+ mark_loop_for_removal (loop);
redirected = redirect_edge_and_branch (entry, get_bb_copy (entry->dest));
gcc_assert (redirected != NULL);
flush_pending_stmts (entry);
@@ -1872,31 +1844,31 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* Do not jump-thread twice from the same block. */
if (bitmap_bit_p (threaded_blocks, entry->src->index)
- /* Verify that the jump thread path is still valid: a
- previous jump-thread may have changed the CFG, and
- invalidated the current path. */
- || !valid_jump_thread_path (path))
- {
- /* Remove invalid FSM jump-thread paths. */
- delete_jump_thread_path (path);
- paths.unordered_remove (i);
- continue;
- }
+ /* Verify that the jump thread path is still valid: a
+ previous jump-thread may have changed the CFG, and
+ invalidated the current path. */
+ || !valid_jump_thread_path (path))
+ {
+ /* Remove invalid FSM jump-thread paths. */
+ delete_jump_thread_path (path);
+ paths.unordered_remove (i);
+ continue;
+ }
unsigned len = path->length ();
edge exit = (*path)[len - 1]->e;
basic_block *region = XNEWVEC (basic_block, len - 1);
for (unsigned int j = 0; j < len - 1; j++)
- region[j] = (*path)[j]->e->dest;
+ region[j] = (*path)[j]->e->dest;
if (duplicate_thread_path (entry, exit, region, len - 1, NULL))
- {
- /* We do not update dominance info. */
- free_dominance_info (CDI_DOMINATORS);
- bitmap_set_bit (threaded_blocks, entry->src->index);
- retval = true;
- }
+ {
+ /* We do not update dominance info. */
+ free_dominance_info (CDI_DOMINATORS);
+ bitmap_set_bit (threaded_blocks, entry->src->index);
+ retval = true;
+ }
delete_jump_thread_path (path);
paths.unordered_remove (i);
@@ -1911,12 +1883,12 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* Do not jump-thread twice from the same block. */
if (bitmap_bit_p (threaded_blocks, entry->src->index))
- {
- delete_jump_thread_path (path);
- paths.unordered_remove (i);
- }
+ {
+ delete_jump_thread_path (path);
+ paths.unordered_remove (i);
+ }
else
- i++;
+ i++;
}
bitmap_clear (threaded_blocks);
@@ -2006,16 +1978,8 @@ thread_through_all_blocks (bool may_peel_loop_headers)
/* Our path is still valid, thread it. */
if (e->aux)
{
- struct loop *loop = (*path)[0]->e->dest->loop_father;
-
if (thread_block ((*path)[0]->e->dest, false))
- {
- /* This jump thread likely totally scrambled this loop.
- So arrange for it to be fixed up. */
- loop->header = NULL;
- loop->latch = NULL;
- e->aux = NULL;
- }
+ e->aux = NULL;
else
{
delete_jump_thread_path (path);