aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/tree-ssa-threadedge.c
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2014-05-17 17:03:43 -0700
committerBen Cheng <bccheng@google.com>2014-05-17 17:12:35 -0700
commit8c493ead6366b552adee796de296936b78f34c5a (patch)
tree4936e52fb9b84edbcd9293bd321027413d1835bf /gcc-4.9/gcc/tree-ssa-threadedge.c
parent9750bde7e561731ce8a07cdbd0165a688e74a696 (diff)
downloadtoolchain_gcc-8c493ead6366b552adee796de296936b78f34c5a.tar.gz
toolchain_gcc-8c493ead6366b552adee796de296936b78f34c5a.tar.bz2
toolchain_gcc-8c493ead6366b552adee796de296936b78f34c5a.zip
[4.9] Refresh GCC 4.9 to the 20140514 snapshot.
For critical bug fixes including devirtualization and codegen. Change-Id: I8138d3dc408fc12db5eecb01d2753d39219712f2
Diffstat (limited to 'gcc-4.9/gcc/tree-ssa-threadedge.c')
-rw-r--r--gcc-4.9/gcc/tree-ssa-threadedge.c88
1 files changed, 74 insertions, 14 deletions
diff --git a/gcc-4.9/gcc/tree-ssa-threadedge.c b/gcc-4.9/gcc/tree-ssa-threadedge.c
index c447b72c3..8e628d553 100644
--- a/gcc-4.9/gcc/tree-ssa-threadedge.c
+++ b/gcc-4.9/gcc/tree-ssa-threadedge.c
@@ -387,7 +387,34 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
&& (gimple_code (stmt) != GIMPLE_CALL
|| gimple_call_lhs (stmt) == NULL_TREE
|| TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME))
- continue;
+ {
+ /* STMT might still have DEFS and we need to invalidate any known
+ equivalences for them.
+
+ Consider if STMT is a GIMPLE_ASM with one or more outputs that
+ feeds a conditional inside a loop. We might derive an equivalence
+ due to the conditional. */
+ tree op;
+ ssa_op_iter iter;
+
+ if (backedge_seen)
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
+ {
+ /* This call only invalidates equivalences created by
+ PHI nodes. This is by design to keep the cost of
+ of invalidation reasonable. */
+ invalidate_equivalences (op, stack, src_map, dst_map);
+
+ /* However, conditionals can imply values for real
+ operands as well. And those won't be recorded in the
+ maps. In fact, those equivalences may be recorded totally
+ outside the threading code. We can just create a new
+ temporary NULL equivalence here. */
+ record_temporary_equivalence (op, NULL_TREE, stack);
+ }
+
+ continue;
+ }
/* The result of __builtin_object_size depends on all the arguments
of a phi node. Temporarily using only one edge produces invalid
@@ -939,9 +966,14 @@ thread_around_empty_blocks (edge taken_edge,
SIMPLIFY is a pass-specific function used to simplify statements.
Our caller is responsible for restoring the state of the expression
- and const_and_copies stacks. */
+ and const_and_copies stacks.
-static bool
+ Positive return value is success. Zero return value is failure, but
+ the block can still be duplicated as a joiner in a jump thread path,
+ negative indicates the block should not be duplicated and thus is not
+ suitable for a joiner in a jump threading path. */
+
+static int
thread_through_normal_block (edge e,
gimple dummy_cond,
bool handle_dominating_asserts,
@@ -963,7 +995,7 @@ thread_through_normal_block (edge e,
/* PHIs create temporary equivalences. */
if (!record_temporary_equivalences_from_phis (e, stack, *backedge_seen_p,
src_map, dst_map))
- return false;
+ return 0;
/* Now walk each statement recording any context sensitive
temporary equivalences we can detect. */
@@ -971,8 +1003,16 @@ thread_through_normal_block (edge e,
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
*backedge_seen_p,
src_map, dst_map);
+
+ /* If we didn't look at all the statements, the most likely reason is
+ there were too many and thus duplicating this block is not profitable.
+
+ Also note if we do not look at all the statements, then we may not
+ have invalidated equivalences that are no longer valid if we threaded
+ around a loop. Thus we must signal to our caller that this block
+ is not suitable for use as a joiner in a threading path. */
if (!stmt)
- return false;
+ return -1;
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */
@@ -996,7 +1036,7 @@ thread_through_normal_block (edge e,
if (dest == NULL
|| dest == e->dest
|| bitmap_bit_p (visited, dest->index))
- return false;
+ return 0;
/* Only push the EDGE_START_JUMP_THREAD marker if this is
first edge on the path. */
@@ -1030,10 +1070,10 @@ thread_through_normal_block (edge e,
visited,
path,
backedge_seen_p);
- return true;
+ return 1;
}
}
- return false;
+ return 0;
}
/* We are exiting E->src, see if E->dest ends with a conditional
@@ -1085,9 +1125,12 @@ thread_across_edge (gimple dummy_cond,
if (backedge_seen)
simplify = dummy_simplify;
- if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts,
- stack, simplify, path, visited,
- &backedge_seen, src_map, dst_map))
+ int threaded = thread_through_normal_block (e, dummy_cond,
+ handle_dominating_asserts,
+ stack, simplify, path,
+ visited, &backedge_seen,
+ src_map, dst_map);
+ if (threaded > 0)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
e->dest);
@@ -1100,10 +1143,27 @@ thread_across_edge (gimple dummy_cond,
}
else
{
- /* There should be no edges on the path, so no need to walk through
- the vector entries. */
+ /* Negative and zero return values indicate no threading was possible,
+ thus there should be no edges on the thread path and no need to walk
+ through the vector entries. */
gcc_assert (path->length () == 0);
path->release ();
+
+ /* A negative status indicates the target block was deemed too big to
+ duplicate. Just quit now rather than trying to use the block as
+ a joiner in a jump threading path.
+
+ This prevents unnecessary code growth, but more importantly if we
+ do not look at all the statements in the block, then we may have
+ missed some invalidations if we had traversed a backedge! */
+ if (threaded < 0)
+ {
+ BITMAP_FREE (visited);
+ BITMAP_FREE (src_map);
+ BITMAP_FREE (dst_map);
+ remove_temporary_equivalences (stack);
+ return;
+ }
}
/* We were unable to determine what out edge from E->dest is taken. However,
@@ -1185,7 +1245,7 @@ thread_across_edge (gimple dummy_cond,
handle_dominating_asserts,
stack, simplify, path, visited,
&backedge_seen,
- src_map, dst_map);
+ src_map, dst_map) > 0;
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */