[Bug c++/99093] New: [missed optimization] Missed devirtualization involving internal-linkage class type (but only sometimes)

arthur.j.odwyer at gmail dot com gcc-bugzilla@gcc.gnu.org
Sun Feb 14 01:08:17 GMT 2021


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99093

            Bug ID: 99093
           Summary: [missed optimization] Missed devirtualization
                    involving internal-linkage class type (but only
                    sometimes)
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

// https://godbolt.org/z/hx7h7v
struct Base {
    virtual int f() { return 1; }
};

namespace {
    struct Derived1 : public Base {
        int f() override { return 2; }
    };
    struct Derived2 : public Base {};
}

int leaf_class1(Base *p) { return ((Derived1*)p)->f(); }
    // devirtualized by GCC, because PrivateDerived is provably a leaf

int leaf_class2(Base *p) { return ((Derived2*)p)->f(); }
    // not devirtualized by GCC -- this smells like a missed-optimization bug

====

GCC 4.9 started to be able to devirtualize things in the compiler, based on
translation-unit-wide (but still compiler-time) information. GCC 4.9.0 is able
to devirtualize the call in `leaf_class1`. This is awesome!

However, both GCC 4.9 and GCC trunk fail to apply the exact same optimization
to `leaf_class2`. The only difference between `Derived1` and `Derived2` is that
`Derived1::f` is declared directly in `Derived1` whereas `Derived2::f` is
technically a member of `Base`. That shouldn't matter at all to the
devirtualization logic. But apparently it does.

====

Barely possibly related missed-devirtualization bugs: #47316, #60674, #89924,
#94243.


More information about the Gcc-bugs mailing list