Live data from Hacker News

The Performance Impact of C++'s `final` Keyword

16bpp.net

151–160 of 385 posts

Re: The Performance Impact of C++'s `final` Keyword

#155
post #26

I don't do much C++, but I have definitely found that engineers will just assert that something is "faster" without any evidence to back that up. Quick example, I got in an argument with someone a few years ago that claimed in C# that a `switch` was better than an `if(x==1) elseif(x==2)...` because switch was "faster" and rejected my PR. I mentioned that that doesn't appear to be true, we went back and forth until I…

.NET is a little smarter about switch code generation these days: https://github.com/dotnet/roslyn/pull/66081

Re: The Performance Impact of C++'s `final` Keyword

#157
post #16

Earlier quoted context omitted.

If you already have LTO, can't the compiler determine this information for devirtualization purposes on its own?

At the level that LLVM's LTO operates, no information about classes or objects is left, so LLVM itself can't really devirtualize C++ methods in most cases

You appear to be correct. Clang does not devirtualize in LTO, but GCC does. Personally I consider this very strange.

     $ cat animal.h cat.cpp main.cpp
    // animal.h
    
    #pragma once
    
    class animal {
     public:
      virtual ~animal() {}
      virtual void speak() = 0;
    };
    
    animal& get_mystery_animal();
    // cat.cpp
    
    #include "animal.h"
    #include 
    
    class cat final : public animal {
    public:
      ~cat() override{}
      void speak() override{
        puts("meow");
      }
    };
    
    static cat garfield{};
    
    animal& get_mystery_animal() {
      return garfield;
    }
    // main.cpp
    
    #include "animal.h"
    
    int main() {
      animal& a = get_mystery_animal();
      a.speak();
    }
     $ make clean && CXX=clang++ make -j && objdump --disassemble=main -C lto_test
    rm -f *.o lto_test
    clang++ -c -flto -O3 -g cat.cpp -o cat.o
    clang++ -c -flto -O3 -g main.cpp -o main.o
    clang++ -flto -O3 -g cat.o main.o -o lto_test
    
    lto_test:     file format elf64-x86-64
    
    
    Disassembly of section .init:
    
    Disassembly of section .plt:
    
    Disassembly of section .plt.got:
    
    Disassembly of section .text:
    
    00000000000011b0 :
        11b0: 50                    push   %rax
        11b1: 48 8b 05 58 2e 00 00  mov    0x2e58(%rip),%rax        # 4010 
        11b8: 48 8d 3d 51 2e 00 00  lea    0x2e51(%rip),%rdi        # 4010 
        11bf: ff 50 10              call   *0x10(%rax)
        11c2: 31 c0                 xor    %eax,%eax
        11c4: 59                    pop    %rcx
        11c5: c3                    ret
    
    Disassembly of section .fini:
     $ make clean && CXX=g++ make -j && objdump --disassemble=main -C lto_test|sed -e 's,^,    ,'
    rm -f *.o lto_test
    g++ -c -flto -O3 -g cat.cpp -o cat.o
    g++ -c -flto -O3 -g main.cpp -o main.o
    g++ -flto -O3 -g cat.o main.o -o lto_test
    
    lto_test:     file format elf64-x86-64
    
    
    Disassembly of section .init:
    
    Disassembly of section .plt:
    
    Disassembly of section .plt.got:
    
    Disassembly of section .text:
    
    0000000000001090 :
        1090: 48 83 ec 08           sub    $0x8,%rsp
        1094: 48 8d 3d 75 2f 00 00  lea    0x2f75(%rip),%rdi        # 4010 
        109b: e8 50 01 00 00        call   11f0 
        10a0: 31 c0                 xor    %eax,%eax
        10a2: 48 83 c4 08           add    $0x8,%rsp
        10a6: c3                    ret
    
    Disassembly of section .fini:
Post reply on HN