Hi, testcase in PR35545 shows case where profile feedback infrastructure does everything to make the testcase optimized (fully devirutalized) but it does not happen because tracer is run too late in the queue.
Tail duplication in general is a pass enabling more optimizations to be done by forward propagating passes, such as constant propagation, fre or vrp. It makes no sense to run it afterwards. This patch moves it shortly after loop optimization (as like loop optimization it increases basic blocks). It may make sense to move it even further, but that would probalby need more benchamrking. I have profiledbootstrapped the patch with LTO at x86_64-linux and also tested with firefox. Comitted. Honza PR middle-end/35545 * passes.def (pass_tracer): Move before last dominator pass. * g++.dg/tree-prof/pr35545.C: New testcase. Index: passes.def =================================================================== --- passes.def (revision 215645) +++ passes.def (working copy) @@ -252,6 +252,7 @@ along with GCC; see the file COPYING3. NEXT_PASS (pass_cse_reciprocals); NEXT_PASS (pass_reassoc); NEXT_PASS (pass_strength_reduction); + NEXT_PASS (pass_tracer); NEXT_PASS (pass_dominator); NEXT_PASS (pass_strlen); NEXT_PASS (pass_vrp); @@ -262,7 +263,6 @@ along with GCC; see the file COPYING3. opportunities. */ NEXT_PASS (pass_phi_only_cprop); NEXT_PASS (pass_cd_dce); - NEXT_PASS (pass_tracer); NEXT_PASS (pass_dse); NEXT_PASS (pass_forwprop); NEXT_PASS (pass_phiopt); Index: testsuite/g++.dg/tree-prof/pr35545.C =================================================================== --- testsuite/g++.dg/tree-prof/pr35545.C (revision 0) +++ testsuite/g++.dg/tree-prof/pr35545.C (revision 0) @@ -0,0 +1,52 @@ +// devirt.cc +/* { dg-options "-O2 -fdump-ipa-profile_estimate -fdump-tree-optimized" } */ + +class A { +public: + virtual int foo() { + return 1; + } + +int i; +}; + +class B : public A +{ +public: + virtual int foo() { + return 2; + } + + int b; +} ; + + +int main() +{ + int i; + + A* ap = 0; + + for (i = 0; i < 10000; i++) + { + + if (i%7==0) + { + ap = new A(); + } + else + ap = new B(); + + ap->foo(); + + delete ap; + + } + + return 0; + +} +/* { dg-final-use { scan-ipa-dump "Indirect call -> direct call" "profile_estimate" } } */ +/* { dg-final-use { cleanup-ipa-dump "profile" } } */ +/* { dg-final-use { scan-ipa-dump-not "OBJ_TYPE_REF" "optimized" } } */ +/* { dg-final-use { cleanup-tree-dump "optimized" } } */