I have this C++ which creates two derived objects and then invokes a virtual function call many times:
Parent* d;
Child1 d1[1];
Child2 d2[1];
if(__rdtsc() & 1 != 0){
d = d1;
}
else{
d = d2;
}
for(unsigned long long i =0; i<9000000000; ++i){
sum += d->process2();
}
and it produces this assembler:
for(unsigned long long i =0; i<9000000000; ++i){
000000013F4241A5 mov qword ptr [rsp+100h],0
000000013F4241B1 jmp main+2B6h (013F4241C6h)
000000013F4241B3 mov rax,qword ptr [rsp+100h]
000000013F4241BB inc rax
000000013F4241BE mov qword ptr [rsp+100h],rax
000000013F4241C6 mov rax,218711A00h
000000013F4241D0 cmp qword ptr [rsp+100h],rax
000000013F4241D8 jae main+306h (013F424216h)
sum += d->process2();
000000013F4241DA mov rax,qword ptr [rsp+0F8h]
000000013F4241E2 mov rax,qword ptr [rax]
000000013F4241E5 mov rcx,qword ptr [rsp+0F8h]
000000013F4241ED call qword ptr [rax+8]
000000013F4241F0 mov qword ptr [rsp+1D8h],rax
000000013F4241F8 mov rax,qword ptr [rsp+1D8h]
000000013F424200 mov rcx,qword ptr [sum (013F4385D8h)]
000000013F424207 add rcx,rax
000000013F42420A mov rax,rcx
000000013F42420D mov qword ptr [sum (013F4385D8h)],rax
}
Based on the assembler could somebody please confirm that the compiler cannot optimize the virtual call in the loop (even though every iteration calls the same derived object) because the compiler cannot possibly know whether d1
or d2
was selected, due to the call to __rdtsc()
only being resolvable at run-time?
(If anyone could give me some advice how to read the assembler for the d->process2()
call it would be most appreciated)
000000013F4241DA mov rax,qword ptr [rsp+0F8h] //load "this" into rax
000000013F4241E2 mov rax,qword ptr [rax] //load vtable pointer
000000013F4241E5 mov rcx,qword ptr [rsp+0F8h] //load "this" into rcx
000000013F4241ED call qword ptr [rax+8] //call second entry in vtable?
Clearly, call to virtual function is not optimized away. You are right, it is because of random factor.