This fixes missed placements of VUSEs during gimplify_and_update_call_from_tree. The gimplifier doesn't fill out virtual operands (it doesn't call update_stmt) - for a reason, we'd mark it for renaming else. So we have to stick a VUSE on every stmt that can possibly have one. update_stmt will remove it again when it is not necessary.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2011-10-10 Richard Guenther <rguent...@suse.de> PR middle-end/50389 * gimple-fold.c (gimplify_and_update_call_from_tree): Do not mark symbols for renaming. Append the VUSE to all statements that possibly can have one. * gcc.dg/torture/pr50389.c: New testcase. Index: gcc/gimple-fold.c =================================================================== *** gcc/gimple-fold.c (revision 179738) --- gcc/gimple-fold.c (working copy) *************** gimplify_and_update_call_from_tree (gimp *** 588,600 **** } new_stmt = gsi_stmt (i); if (gimple_in_ssa_p (cfun)) ! { ! find_new_referenced_vars (new_stmt); ! mark_symbols_for_renaming (new_stmt); ! } ! /* If the new statement has a VUSE, update it with exact SSA name we ! know will reach this one. */ ! if (gimple_vuse (new_stmt)) { /* If we've also seen a previous store create a new VDEF for the latter one, and make that the new reaching VUSE. */ --- 588,597 ---- } new_stmt = gsi_stmt (i); if (gimple_in_ssa_p (cfun)) ! find_new_referenced_vars (new_stmt); ! /* If the new statement possibly has a VUSE, update it with exact SSA ! name we know will reach this one. */ ! if (gimple_has_mem_ops (new_stmt)) { /* If we've also seen a previous store create a new VDEF for the latter one, and make that the new reaching VUSE. */ Index: gcc/testsuite/gcc.dg/torture/pr50389.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr50389.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr50389.c (revision 0) *************** *** 0 **** --- 1,15 ---- + /* { dg-do compile } */ + /* { dg-options "-freorder-blocks -ftracer" } */ + + extern int data[]; + extern int i; + + void + foo (void) + { + char buf[8]; + __builtin___memcpy_chk (buf, data, i ? 8 : 4, + __builtin_object_size (buf, 0)); + __builtin___memcpy_chk (buf, data, i ? 8 : 4, + __builtin_object_size (buf, 0)); + }