Commit 215f8d9e by Jeff Law Committed by Jeff Law

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 real
	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: r220743
parent ed89033d
2015-02-16 Jeff Law <law@redhat.com>
PR tree-optimization/64823
* tree-vrp.c (identify_jump_threads): Handle blocks with no real
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.
2015-02-16 Jakub Jelinek <jakub@redhat.com> 2015-02-16 Jakub Jelinek <jakub@redhat.com>
James Greenhalgh <james.greenhalgh@arm.com> James Greenhalgh <james.greenhalgh@arm.com>
......
2015-02-16 Jeff Law <law@redhat.com>
PR tree-optimization/64823
* gcc.dg/uninit-20.c: New test.
2015-02-16 Jakub Jelinek <jakub@redhat.com> 2015-02-16 Jakub Jelinek <jakub@redhat.com>
James Greenhalgh <james.greenhalgh@arm.com> James Greenhalgh <james.greenhalgh@arm.com>
......
/* Spurious uninitialized variable warnings, from gdb */
/* { dg-do compile } */
/* { dg-options "-O2 -Wuninitialized" } */
struct os { struct o *o; };
struct o { struct o *next; struct os *se; };
void f(struct o *o){
struct os *s;
if(o) s = o->se;
while(o && s == o->se){
s++; // here `o' is non-zero and thus s is initialized
s == o->se // `?' is essential, `if' does not trigger the warning
? (o = o->next, o ? s = o->se : 0)
: 0;
}
}
...@@ -110,6 +110,15 @@ potentially_threadable_block (basic_block bb) ...@@ -110,6 +110,15 @@ potentially_threadable_block (basic_block bb)
{ {
gimple_stmt_iterator gsi; 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 /* If BB has a single successor or a single predecessor, then
there is no threading opportunity. */ there is no threading opportunity. */
if (single_succ_p (bb) || single_pred_p (bb)) if (single_succ_p (bb) || single_pred_p (bb))
...@@ -1281,16 +1290,32 @@ thread_through_normal_block (edge e, ...@@ -1281,16 +1290,32 @@ thread_through_normal_block (edge e,
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify, = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
*backedge_seen_p); *backedge_seen_p);
/* If we didn't look at all the statements, the most likely reason is /* There's two reasons STMT might be null, and distinguishing
there were too many and thus duplicating this block is not profitable. between them is important.
Also note if we do not look at all the statements, then we may not First the block may not have had any statements. For example, it
have invalidated equivalences that are no longer valid if we threaded might have some PHIs and unconditionally transfer control elsewhere.
around a loop. Thus we must signal to our caller that this block Such blocks are suitable for jump threading, particularly as a
is not suitable for use as a joiner in a threading path. */ 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) 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 /* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */ will be taken. */
if (gimple_code (stmt) == GIMPLE_COND if (gimple_code (stmt) == GIMPLE_COND
......
...@@ -10176,13 +10176,20 @@ identify_jump_threads (void) ...@@ -10176,13 +10176,20 @@ identify_jump_threads (void)
/* We only care about blocks ending in a COND_EXPR. While there /* We only care about blocks ending in a COND_EXPR. While there
may be some value in handling SWITCH_EXPR here, I doubt it's may be some value in handling SWITCH_EXPR here, I doubt it's
terribly important. */ terribly important. */
last = gsi_stmt (gsi_last_bb (bb)); last = gsi_stmt (gsi_last_nondebug_bb (bb));
/* We're basically looking for a switch or any kind of conditional with /* We're basically looking for a switch or any kind of conditional with
integral or pointer type arguments. Note the type of the second integral or pointer type arguments. Note the type of the second
argument will be the same as the first argument, so no need to argument will be the same as the first argument, so no need to
check it explicitly. */ check it explicitly.
if (gimple_code (last) == GIMPLE_SWITCH
We also handle the case where there are no statements in the
block. This come up with forwarder blocks that are not
optimized away because they lead to a loop header. But we do
want to thread through them as we can sometimes thread to the
loop exit which is obviously profitable. */
if (!last
|| gimple_code (last) == GIMPLE_SWITCH
|| (gimple_code (last) == GIMPLE_COND || (gimple_code (last) == GIMPLE_COND
&& TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME && TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last))) && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment