Hi! ipa_devirt apparently relies on -fdevirtualize, but -fno-devirtualize doesn't turn off -fdevirtualize-speculatively.
I've tried to make it a 3 state option, but then while -O2 implied flag_devirtualize == 2 (i.e. normal + speculative), -O2 -fdevirtualize would imply flag_devirtualize == 1, which is IMHO undesirable, so I went for ignoring -fdevirtualize-speculatively if -fdevirtualize is not on. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2013-12-03 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/59355 * ipa-devirt.c (gate_ipa_devirt): Return false if !flag_devirtualize. * opts.c (common_handle_option): Fix comment spelling. * g++.dg/ipa/pr59355.C: New test. --- gcc/ipa-devirt.c.jj 2013-12-03 15:02:12.000000000 +0100 +++ gcc/ipa-devirt.c 2013-12-03 15:03:01.176455678 +0100 @@ -1591,12 +1591,14 @@ ipa_devirt (void) return ndevirtualized ? TODO_remove_functions : 0; } -/* Gate for IPCP optimization. */ +/* Gate for speculative IPA devirtualization optimization. */ static bool gate_ipa_devirt (void) { - return flag_devirtualize_speculatively && optimize; + return (flag_devirtualize + && flag_devirtualize_speculatively + && optimize); } namespace { --- gcc/opts.c.jj 2013-12-03 15:02:12.000000000 +0100 +++ gcc/opts.c 2013-12-03 15:03:39.693285001 +0100 @@ -1709,7 +1709,7 @@ common_handle_option (struct gcc_options if (!opts_set->x_flag_tree_loop_distribute_patterns) opts->x_flag_tree_loop_distribute_patterns = value; /* Indirect call profiling should do all useful transformations - speculative devirutalization does. */ + speculative devirtualization does. */ if (!opts_set->x_flag_devirtualize_speculatively && opts->x_flag_value_profile_transformations) opts->x_flag_devirtualize_speculatively = false; --- gcc/testsuite/g++.dg/ipa/pr59355.C.jj 2013-12-03 15:28:38.430518411 +0100 +++ gcc/testsuite/g++.dg/ipa/pr59355.C 2013-12-03 15:22:32.000000000 +0100 @@ -0,0 +1,14 @@ +// PR tree-optimization/59355 +// { dg-do compile } +// { dg-options "-O2 -fno-devirtualize" } + +struct S +{ + virtual void bar (); +}; + +void +foo (S *s) +{ + s->bar (); +} Jakub