c++/8826: "a >> b" differs from "a.operator>>(b)" in that virtual function calls are not avoided
niemayer@isg.de
niemayer@isg.de
Thu Dec 5 10:56:00 GMT 2002
>Number: 8826
>Category: c++
>Synopsis: "a >> b" differs from "a.operator>>(b)" in that virtual function calls are not avoided
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: pessimizes-code
>Submitter-Id: net
>Arrival-Date: Thu Dec 05 10:56:02 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Peter Niemayer
>Release: gcc-3.x (x < 3)
>Organization:
>Environment:
linux / x86
>Description:
The compiler tries to avoid unneccessary virtual function
calls, which can sometimes cause dramatic performance
improvements, but alas, it fails to do so when one of two
possible (and IMHO equivalent) syntaxes is used when invoking
an operator member function.
This may seem very harmless as the code still works, but
the optimization is missing in a very often used scenario,
for calls that are done very frequently...
>How-To-Repeat:
Compile the following tiny piece of C++ source optimized
into assember, and have a look at the two code sequences
between the "testlabel?" pairs:
class A {
public:
virtual int operator>>(int x) { return x+1; }
};
int testfunc1(int y) {
A a;
asm volatile("testlabel1: ");
int r = a >> y;
asm volatile("testlabel2: ");
return r;
}
int testfunc2(int y) {
A a;
asm volatile("testlabel3: ");
int r = a.operator>>(y);
asm volatile("testlabel4: ");
return r;
}
(use "gcc -S test.cxx -O3" or similar)
You'll see that while the second function body is well
optimized, inlining just the necessary addition, the first
and most often used form is turned into badly optimized
code, doing an unneccessary virtual function call:
...
testlabel1:
#NO_APP
movl %edx, (%esp)
movl 8(%ebp), %eax
movl %eax, 4(%esp)
call *_ZTV1A+8
#APP
testlabel2:
- versus -
testlabel3:
#NO_APP
movl 8(%ebp), %eax
incl %eax
#APP
testlabel4:
>Fix:
The only work-around I've found is to use the awkward
"a.operator>>(b)" syntax, which is not only clumsy to
type but also fails to be valid when the operator function
is a two-argument global function rather than a member
function.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the Gcc-prs
mailing list