Hi! Setting gimple_call_set_fndecl of a random method call to __bultin_unreachable can't work properly, the method call probably passes in arguments that __builtin_unreachable doesn't expect, and if the method call has LHS, we'll ICE, because __builtin_unreachable doesn't have a LHS. Fixed by not doing anything for fold_stmt_inplace and for fold_stmt just adding a new __buitin_unreachable () call before the method call, DCE will DTRT then and we don't have to bother with adding some dummy stmt to set up the lhs etc.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-12-30 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/59622 * gimple-fold.c (gimple_fold_call): Don't replace OBJ_TYPE_REF call fndecl with 0 possible targets with BUILT_IN_UNREACHABLE, instead only for !inplace add a __builtin_unreachable () call before the call. * g++.dg/opt/pr59622.C: New test. --- gcc/gimple-fold.c.jj 2013-12-18 17:32:59.000000000 +0100 +++ gcc/gimple-fold.c 2013-12-30 11:36:38.093211391 +0100 @@ -1184,13 +1184,19 @@ gimple_fold_call (gimple_stmt_iterator * = possible_polymorphic_call_targets (callee, &final); if (final && targets.length () <= 1) { - tree fndecl; if (targets.length () == 1) - fndecl = targets[0]->decl; - else - fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); - gimple_call_set_fndecl (stmt, fndecl); - changed = true; + { + gimple_call_set_fndecl (stmt, targets[0]->decl); + changed = true; + } + else if (!inplace) + { + tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + gimple new_stmt = gimple_build_call (fndecl, 0); + gimple_set_location (new_stmt, gimple_location (stmt)); + gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + return true; + } } } } --- gcc/testsuite/g++.dg/opt/pr59622.C.jj 2013-12-30 11:44:04.934893747 +0100 +++ gcc/testsuite/g++.dg/opt/pr59622.C 2013-12-30 11:43:38.000000000 +0100 @@ -0,0 +1,19 @@ +// PR tree-optimization/59622 +// { dg-do compile } +// { dg-options "-O2" } + +namespace +{ + struct A + { + virtual int foo (); + int bar () { return foo (); } + }; +} + +int +baz () +{ + A a; + return a.bar (); +} Jakub