https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91771
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |missed-optimization Status|UNCONFIRMED |NEW Last reconfirmed| |2019-09-16 CC| |hubicka at gcc dot gnu.org, | |marxin at gcc dot gnu.org Component|c++ |ipa Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- I think GCC at devirtualization time does not know that 'd' (in f) has the base 'Derived'. That is, GCC only speculates that 'd' might be 'Derived': t.C:3:33: note: speculatively devirtualizing call in int f(Derived&)/2 to virtual int Derived::do_foo(int)/1 Indirect call -> speculative call int f(Derived&)/2 => virtual int Derived::do_foo(int)/1 1 polymorphic calls, 0 devirtualized, 1 speculatively devirtualized, 0 cold 0 have multiple targets, 0 overwritable, 0 already speculated (0 agree, 0 disagree), 0 external, 0 not defined, 0 artificial, 0 infos dropped and IPA inlining performs the inlining: Considering virtual int Derived::do_foo(int)/1 with 4 size to be inlined into int f(Derived&)/2 in t.C:3 Estimated badness is -inf, frequency 0.80. Badness calculation for int f(Derived&)/2 -> virtual int Derived::do_foo(int)/1 size growth -4, time 0.000000 unspec 3.000000 IPA hints: declared_inline big_speedup -inf: Growth -4 <= 0 Adjusted by hints -inf Inlined virtual int Derived::do_foo(int) into int f(Derived&) which now has time 6.600000 and size 11, net change of -4. and then we get the code you quoted. So basically GCC fails to elide the runtime check guarding the inlined code. We're elsewhere looking at function signatures to derive stronger guarantees on pointed to types so devirt might be one place we could resort to this as well. Honza?