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

            Bug ID: 115413
           Summary: Missing optimization: devirtualize the call in
                    "if(typeid(*a)==typeid(A)) a->f();" structure
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: user202729 at protonmail dot com
  Target Milestone: ---

Created attachment 58397
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58397&action=edit
Code to reproduce the example where gcc devirtualizes the call.

As mentioned in the title.

I think code of the form

    if(typeid(*a)==typeid(A)) a->f();

where `f` is a virtual function in `A` can be optimized to eliminate the
virtualization.

(Of course in practice it won't gain much performance because `type_info`
comparison involves a string comparison which is slow, but if the `else` branch
is `__builtin_unreachable()` it could potentially result in a performance
gain.)

As pointed out in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115410 ,
however, the address of `a->f` may not be the same as `A::f` if `a` comes from
a shared library, however gcc already does that optimization in some cases e.g.

    A a = create_object();
    a.f();

where `create_object` is loaded with `dlopen()`, then the address of `a.f` will
actually be different from `A::f`, nevertheless gcc optimizes it to call `A::f`
anyway. Because of ODR, the behavior must be identical.

Example: in the linked file, compile with

    g++ -fPIC -shared -o libshared.so shared_lib.cpp -Wno-pmf-conversions
    g++ test4.cpp -ldl -Wno-pmf-conversions
    ./a.out


then the 4 addresses will not be identical. (Note that the program technically
invokes undefined behavior by referencing the address of
`(void*)(&MyClass::hello)` which I believe violate ODR; nevertheless, it just
serves to show which copy of `hello()` actually gets called.)

Reply via email to