
2013 Keynote: Chandler Carruth: Optimizing the Emergent Structures of C++
About this video
Chandler Carruth's CppNow 2013 keynote on how C++ builds complex software from simple emergent structures, and how compilers optimize them through inlining and value semantics.
Why it appears in the archive
HN lists it among C++ optimization talks and cites it for how much optimizer performance comes from inlining, from an experienced compiler engineer.
AI-generated summary and labels from the source dataset; verify important details against the video. Source & credits.
From the Hacker News discussion
Here's a few: - "Tuning C++: Benchmarks, and CPUs, and Compilers! Oh My!" [LINK] - "Understanding Compiler Optimization" [LINK] - "Optimizing the Emergent Structures of C++" [VIDEO] - "Efficiency with Algorithms" [LINK] The first one is really good if you've never benchmarked anything in a Linux environment. Or if you otherwise want to learn how to investigate how C++ gets turned into machine code.
Read original comment ↗> That said, avoiding libraries (especially avoiding templates and just using void*-like stuff) does keep binaries/libs smaller, but I'll gladly make the computer work slightly harder considering that the result is the same speed (C++ is often faster than C, in practice). This should not be an issue with modern C++ compilers. If two template instantiations generate the same or similar code, they will be merged and useless code is removed by dead code elimination. > The downside I care about is compilation speed. Simple C projects compile/link faster than modern C++ ones, even though the code for the same functionality is far more brittle, unsafe, and opaque At the same time, a lot of potential for optimization is lost by barricading everything between translation units and/or behind opaque pointers. While yes, LTO is supposed to help there, all those memory accesses make it infinitely harder for the compiler to prove trivial properties about the data flow. See also this recent presentation by someone who has a lot more experience than me with writing compiler backends: [VIDEO]
Read original comment ↗I don't claim to have any answers, but I found all of this interesting and surprising. I wondered about a couple of things. What happens if the do_stuff_to_foo is actually defined (and what happens in that actual function)? And is there a difference between value semantics and pointer/reference semantics? These questions were my take-away from one of Chandler Carruth's C++ compiler optimization talks, I think it was this talk. [VIDEO] My take aways were that the optimizer gets a huge chunk of its performance by inlining. And with value semantics, the optimizer can "cheat like crazy". So I defined two different variants for do_stuff_to_foo Original Pointer/Reference Semantics: void do_stuff_to_foo(foo* a) { a->x++; } Value Semantics: foo do_stuff_to_foo(foo a) { a.x++; return a; } In both cases, the compiler emits effectively the same output for C and C++ (I only tested clang.) (The main difference was name mangling. I omit stuff for brevity.) Pointer/Reference Semantics: Lcfi2: .cfi_def_cfa_register %rbp incl (%rdi) popq %rbp retq .cfi_endproc ## -- End function .globl _blah ## -- Begin function blah .p2align 4, 0x90 _blah: ## @blah .cfi_startproc ## BB#0: pushq %rbp Lcfi3: .cfi_def_cfa_offset 16 Lcfi4: .cfi_offset %rbp, -16 movq %rsp, %rbp Lcfi5: .cfi_def_cfa_register %rbp movq %rdi, %rax popq %rbp retq .cfi_endproc Value Semantics: Lcfi3: .cfi_offset %rbx, -24 movq %rdi, %rbx incl 16(%rbp) leaq 16(%rbp), %rsi movl $1036, %edx ## imm = 0x40C callq _memcpy movq %rbx, %rax add
Read original comment ↗