diff options
author | Jeff Law <law@redhat.com> | 2015-02-13 14:09:58 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2015-02-13 14:09:58 -0700 |
commit | 8f895cf1ac7babe0c89533e8e9e6b6ca6bb33950 (patch) | |
tree | b427100e1f8bad39e331f65b368651e87cfa1721 /gcc/tree-ssa-threadedge.c | |
parent | be1448389ab3038cccba3ed99e157bd6842ef88f (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.c | 39 |
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 |