This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/43411] New: Missed inline optimization opportunity with indirect calls


C++ inlining of virtual calls does not occur in many instances when it should
be easy to determine that it is safe.

The problem occurs when there is an object that is referred to via a pointer or
reference. Normally a virtual call through a pointer cannot be inlined because
it is not known what its actual type is at compile time. However, sometimes the
pointer is assigned to an object of known type, and in this case the compiler
could determine the correct version of the method to call, and so inline it.

This is a somewhat unlikely state of affairs in normal code, but it becomes
important when some inlining has already taken place. Often the inlined method
will refer to a parameter via a reference, but this may refer to a type known
precisely at the call site. After inlining this information could be profitably
used to allow further inlining. Small getter/setter methods would benefit
enormously from this.

As far as I can make out, the microsoft C++ compiler seems to do this
optimization.

For example, consider the complete source file:


class P { public: virtual int val() { return 123; } };
class Psub : public P { };

extern int sink1, sink2;

void test() {
    Psub p;
    P &pRef = p;
    sink1 = p.val();
    sink2 = pRef.val();
}


inline int v(P &p) { return p.val(); }

void testInlineP() {
        P p;
        sink1 = v(p);
}

void testInlinePsub() {
        Psub p;
        sink1 = v(p);
}


With -O3 specified this generates the following code (with a very little
cleanup for clarity):

__Z4testv:
        pushl   %ebp
        movl    $123, %edx
        movl    %esp, %ebp
        leal    -24(%ebp), %eax
        subl    $40, %esp
        movl    %eax, (%esp)
        movl    $__ZTV4Psub+8, -24(%ebp)
        movl    %edx, _sink1
        call    *__ZTV4Psub+8
        movl    %eax, _sink2
        leave
        ret


__Z11testInlinePv:
        pushl   %ebp
        movl    %esp, %ebp
        leal    -24(%ebp), %eax
        subl    $40, %esp
        movl    %eax, (%esp)
        movl    $__ZTV1P+8, -24(%ebp)
        call    *__ZTV1P+8
        movl    %eax, _sink1
        leave
        ret


__Z14testInlinePsubv:
        pushl   %ebp
        movl    %esp, %ebp
        leal    -24(%ebp), %eax
        subl    $40, %esp
        movl    %eax, (%esp)
        movl    $__ZTV4Psub+8, -24(%ebp)
        call    *__ZTV4Psub+8
        movl    %eax, _sink1
        leave
        ret


Only the line "sink1 = p.val();" in test has been inlined to "movl $123, %edx /
movl %edx, _sink1". The other calls have not been inlined, even though they can
safely be replaced by the same instruction pair.

The above code was generated with version 3.4.5 mingw, but I have checked that
the same thing happens with version 4.3.3 under Ubuntu. I haven't checked that
it happens with targets other than i386, but it seems likely that it would.

This bug report seems likely to be a more general case of bug report 41012 and
probably replaces it.


-- 
           Summary: Missed inline optimization opportunity with indirect
                    calls
           Product: gcc
           Version: 4.3.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: jonty_lawson at yahoo dot co dot uk


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43411


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]