re PR middle-end/59119 (Segfault in -fisolate-erroneous-paths pass)

* PR middle-end/59119
	* gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour): New
	function, extracted from gimple_ssa_isolate_erroneous_paths.
	(find_explicit_erroneous_behaviour): Similarly.
	(insert_trap_and_remove_trailing_statements): Remove statements
	in reverse order.

	* PR middle-end/59119
	* gcc.c-torture/compile/pr59119.c: New test.

From-SVN: r204760
This commit is contained in:
Jeff Law 2013-11-13 16:10:34 -07:00 committed by Jeff Law
parent 98eaa66fa5
commit 56d338c931
4 changed files with 118 additions and 35 deletions

View File

@ -1,3 +1,12 @@
2013-11-13 Jeff Law <law@redhat.com>
* PR middle-end/59119
* gimple-ssa-isolate-paths.c (find_implicit_erroneous_behaviour): New
function, extracted from gimple_ssa_isolate_erroneous_paths.
(find_explicit_erroneous_behaviour): Similarly.
(insert_trap_and_remove_trailing_statements): Remove statements
in reverse order.
2013-11-13 Steven Bosscher <steven@gcc.gnu.org>
* cfgrtl.c (can_fallthru): Reorder code to move tablejump check up.

View File

@ -100,14 +100,16 @@ insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op)
else
gsi_insert_before (si_p, seq, GSI_NEW_STMT);
/* The iterator points to the __builtin_trap. Advance the iterator
and delete everything else in the block. */
gsi_next (si_p);
for (; !gsi_end_p (*si_p);)
/* We must remove statements from the end of the block so that we
never reference a released SSA_NAME. */
basic_block bb = gimple_bb (gsi_stmt (*si_p));
for (gimple_stmt_iterator si = gsi_last_bb (bb);
gsi_stmt (si) != gsi_stmt (*si_p);
si = gsi_last_bb (bb))
{
stmt = gsi_stmt (*si_p);
stmt = gsi_stmt (si);
unlink_stmt_vdef (stmt);
gsi_remove (si_p, true);
gsi_remove (&si, true);
release_defs (stmt);
}
}
@ -192,40 +194,19 @@ isolate_path (basic_block bb, basic_block duplicate,
return duplicate;
}
/* Search the function for statements which, if executed, would cause
the program to fault such as a dereference of a NULL pointer.
/* Look for PHI nodes which feed statements in the same block where
the value of the PHI node implies the statement is erroneous.
Such a program can't be valid if such a statement was to execute
according to ISO standards.
For example, a NULL PHI arg value which then feeds a pointer
dereference.
We detect explicit NULL pointer dereferences as well as those implied
by a PHI argument having a NULL value which unconditionally flows into
a dereference in the same block as the PHI.
In the former case we replace the offending statement with an
unconditional trap and eliminate the outgoing edges from the statement's
basic block. This may expose secondary optimization opportunities.
In the latter case, we isolate the path(s) with the NULL PHI
feeding the dereference. We can then replace the offending statement
and eliminate the outgoing edges in the duplicate. Again, this may
expose secondary optimization opportunities.
A warning for both cases may be advisable as well.
Other statically detectable violations of the ISO standard could be
handled in a similar way, such as out-of-bounds array indexing. */
static unsigned int
gimple_ssa_isolate_erroneous_paths (void)
When found isolate and optimize the path associated with the PHI
argument feeding the erroneous statement. */
static void
find_implicit_erroneous_behaviour (void)
{
basic_block bb;
initialize_original_copy_tables ();
/* Search all the blocks for edges which, if traversed, will
result in undefined behaviour. */
cfg_altered = false;
FOR_EACH_BB (bb)
{
gimple_stmt_iterator si;
@ -288,6 +269,21 @@ gimple_ssa_isolate_erroneous_paths (void)
}
}
}
}
}
/* Look for statements which exhibit erroneous behaviour. For example
a NULL pointer dereference.
When found, optimize the block containing the erroneous behaviour. */
static void
find_explicit_erroneous_behaviour (void)
{
basic_block bb;
FOR_EACH_BB (bb)
{
gimple_stmt_iterator si;
/* Now look at the statements in the block and see if any of
them explicitly dereference a NULL pointer. This happens
@ -318,6 +314,56 @@ gimple_ssa_isolate_erroneous_paths (void)
}
}
}
}
/* Search the function for statements which, if executed, would cause
the program to fault such as a dereference of a NULL pointer.
Such a program can't be valid if such a statement was to execute
according to ISO standards.
We detect explicit NULL pointer dereferences as well as those implied
by a PHI argument having a NULL value which unconditionally flows into
a dereference in the same block as the PHI.
In the former case we replace the offending statement with an
unconditional trap and eliminate the outgoing edges from the statement's
basic block. This may expose secondary optimization opportunities.
In the latter case, we isolate the path(s) with the NULL PHI
feeding the dereference. We can then replace the offending statement
and eliminate the outgoing edges in the duplicate. Again, this may
expose secondary optimization opportunities.
A warning for both cases may be advisable as well.
Other statically detectable violations of the ISO standard could be
handled in a similar way, such as out-of-bounds array indexing. */
static unsigned int
gimple_ssa_isolate_erroneous_paths (void)
{
initialize_original_copy_tables ();
/* Search all the blocks for edges which, if traversed, will
result in undefined behaviour. */
cfg_altered = false;
/* First handle cases where traversal of a particular edge
triggers undefined behaviour. These cases require creating
duplicate blocks and thus new SSA_NAMEs.
We want that process complete prior to the phase where we start
removing edges from the CFG. Edge removal may ultimately result in
removal of PHI nodes and thus releasing SSA_NAMEs back to the
name manager.
If the two processes run in parallel we could release an SSA_NAME
back to the manager but we could still have dangling references
to the released SSA_NAME in unreachable blocks.
that any released names not have dangling references in the IL. */
find_implicit_erroneous_behaviour ();
find_explicit_erroneous_behaviour ();
free_original_copy_tables ();
/* We scramble the CFG and loop structures a bit, clean up

View File

@ -1,3 +1,8 @@
2013-11-12 Jeff Law <law@redhat.com>
* PR middle-end/59119
* gcc.c-torture/compile/pr59119.c: New test.
2013-11-13 Martin Jambor <mjambor@suse.cz>
* gcc.dg/ira-shrinkwrap-prep-1.c: Add lp64 to target requirements.

View File

@ -0,0 +1,23 @@
extern void *memmove (void *, const void *, __SIZE_TYPE__);
extern void *memset (void *, int, __SIZE_TYPE__);
typedef struct {
long n_prefix;
long n_spadding;
} NumberFieldWidths;
void
fill_number(char *buf, const NumberFieldWidths *spec)
{
if (spec->n_prefix) {
memmove(buf,
(char *) 0,
spec->n_prefix * sizeof(char));
buf += spec->n_prefix;
}
if (spec->n_spadding) {
memset(buf, 0, spec->n_spadding);
buf += spec->n_spadding;
}
}