diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c5448784624..ecc7aed56d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-11-13 Jeff Law + + * 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 * cfgrtl.c (can_fallthru): Reorder code to move tablejump check up. diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index 2d8f176c4b9..0051da2126f 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31b952b5f9e..36f48fd17f9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-11-12 Jeff Law + + * PR middle-end/59119 + * gcc.c-torture/compile/pr59119.c: New test. + 2013-11-13 Martin Jambor * gcc.dg/ira-shrinkwrap-prep-1.c: Add lp64 to target requirements. diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59119.c b/gcc/testsuite/gcc.c-torture/compile/pr59119.c new file mode 100644 index 00000000000..b026ba5d4ac --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr59119.c @@ -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; + } +} +