summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadedge.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2015-02-13 14:09:58 -0700
committerJeff Law <law@gcc.gnu.org>2015-02-13 14:09:58 -0700
commit8f895cf1ac7babe0c89533e8e9e6b6ca6bb33950 (patch)
treeb427100e1f8bad39e331f65b368651e87cfa1721 /gcc/tree-ssa-threadedge.c
parentbe1448389ab3038cccba3ed99e157bd6842ef88f (diff)
re PR tree-optimization/64823 (false "may be used uninitialized", missed jump threading)
PR tree-optimization/64823 * tree-vrp.c (identify_jump_threads): Handle blocks with no statements. * tree-ssa-threadedge.c (potentially_threadable_block): Allow threading through blocks with PHIs, but no statements. (thread_through_normal_block): Distinguish between blocks where we did not process all the statements and blocks with no statements. PR tree-optimization/64823 gcc.dg/uninit-20.c: New test. From-SVN: r220696
Diffstat (limited to 'gcc/tree-ssa-threadedge.c')
-rw-r--r--gcc/tree-ssa-threadedge.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 4f839910a84..7187d065e91 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -110,6 +110,15 @@ potentially_threadable_block (basic_block bb)
{
gimple_stmt_iterator gsi;
+ /* Special case. We can get blocks that are forwarders, but are
+ not optimized away because they forward from outside a loop
+ to the loop header. We want to thread through them as we can
+ sometimes thread to the loop exit, which is obviously profitable.
+ the interesting case here is when the block has PHIs. */
+ if (gsi_end_p (gsi_start_nondebug_bb (bb))
+ && !gsi_end_p (gsi_start_phis (bb)))
+ return true;
+
/* If BB has a single successor or a single predecessor, then
there is no threading opportunity. */
if (single_succ_p (bb) || single_pred_p (bb))
@@ -1281,16 +1290,32 @@ thread_through_normal_block (edge e,
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
*backedge_seen_p);
- /* 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.
+ /* There's two reasons STMT might be null, and distinguishing
+ between them is important.
- 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. */
+ First the block may not have had any statements. For example, it
+ might have some PHIs and unconditionally transfer control elsewhere.
+ Such blocks are suitable for jump threading, particularly as a
+ joiner block.
+
+ The second reason would be if we did not process all the statements
+ in the block (because there were too many to make duplicating the
+ block profitable. If we did not look at all the statements, then
+ we may not have invalidated everything needing invalidation. 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 -1;
+ {
+ /* First case. The statement simply doesn't have any instructions, but
+ does have PHIs. */
+ if (gsi_end_p (gsi_start_nondebug_bb (e->dest))
+ && !gsi_end_p (gsi_start_phis (e->dest)))
+ return 0;
+ /* Second case. */
+ return -1;
+ }
+
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */
if (gimple_code (stmt) == GIMPLE_COND