In the following example, three loads to the vtable pointer value can be CSEed, so are two accesses to the same vtable entry (for foo), but final assembly dumping indicate otherwise. It is true that the object pointed to by ap may be modified by the calls, but this does not apply to the vptr field.
class A { public: virtual int foo(int i); virtual int bar(int i); private: int a; }; int test(A* ap, int i) { int r1 = ap->foo(i); int r2 = ap->bar(i); return r1+r2 + ap->foo(i); } ... .LCFI4: movq (%rdi), %rax movl %esi, %r12d call *(%rax) movl %eax, %r13d movq (%rbx), %rax <----- redundant movl %r12d, %esi movq %rbx, %rdi call *8(%rax) movl %eax, %ebp movq (%rbx), %rax <---- redundant movl %r12d, %esi movq %rbx, %rdi call *(%rax) <-- *(%rax) is redundant leal (%rbp,%r13), %edx movq 8(%rsp), %rbx movq 16(%rsp), %rbp movq 24(%rsp), %r12 movq 32(%rsp), %r13 addq $40, %rsp leal (%rdx,%rax), %eax ret -- Summary: Missing CSE/PRE for memory operations involved in virtual call. Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: xinliangli at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35560