This fixes PR48772, we can't update stmts with virtual defs during VN elimination as that may destroy SSA names we use in the VN lattice. So we have to defer it, similar to removing stmts.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-04-27 Richard Guenther <rguent...@suse.de> PR tree-optimization/48772 * tree-ssa-pre.c (eliminate): Update call stmts after elimination only. * g++.dg/pr48772.C: New testcase. Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 172965) --- gcc/tree-ssa-pre.c (working copy) *************** static unsigned int *** 4186,4191 **** --- 4186,4192 ---- eliminate (void) { VEC (gimple, heap) *to_remove = NULL; + VEC (gimple, heap) *to_update = NULL; basic_block b; unsigned int todo = 0; gimple_stmt_iterator gsi; *************** eliminate (void) *** 4411,4417 **** } gimple_call_set_fn (stmt, fn); ! update_stmt (stmt); /* When changing a call into a noreturn call, cfg cleanup is needed to fix up the noreturn call. */ --- 4412,4418 ---- } gimple_call_set_fn (stmt, fn); ! VEC_safe_push (gimple, heap, to_update, stmt); /* When changing a call into a noreturn call, cfg cleanup is needed to fix up the noreturn call. */ *************** eliminate (void) *** 4563,4568 **** --- 4564,4576 ---- } VEC_free (gimple, heap, to_remove); + /* We cannot update call statements with virtual operands during + SSA walk. This might remove them which in turn makes our + VN lattice invalid. */ + FOR_EACH_VEC_ELT (gimple, to_update, i, stmt) + update_stmt (stmt); + VEC_free (gimple, heap, to_update); + return todo; } Index: gcc/testsuite/g++.dg/pr48772.C =================================================================== *** gcc/testsuite/g++.dg/pr48772.C (revision 0) --- gcc/testsuite/g++.dg/pr48772.C (revision 0) *************** *** 0 **** --- 1,35 ---- + // { dg-do compile } + // { dg-options "-O -fnon-call-exceptions -fno-tree-ccp -fno-tree-dce" } + + extern "C" void abort (); + + struct A + { + void foo () + { + this->bar (); + } + virtual void bar () + { + abort (); + } + ~A () + { + } + }; + + struct B:A + { + virtual void bar () + { + } + }; + + int + main () + { + B b; + b.foo (); + return 0; + } +