Take the following code and compile it with -O3
under any compiler out there: msvc, clang, gcc.
#include <map>
#include <unordered_map>
#include <vector>
int main() {
std::map< int, int > m;
std::map< int, int > p;
std::map< int, int > q;
std::unordered_map< int, int > r;
std::vector<int> n;
}
It generates assembly that contains one call for each of the std::map but no assembly whatsoever for std::unordered_map or std::vector. You can comment out those lines and there will be no difference in the resulting assembly. If you comment any of the lines with std::map though there will be a reduction.
leaq 104(%rsp), %rdi
xorl %esi, %esi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
movq 24(%rsp), %rsi
leaq 8(%rsp), %rdi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
movq 72(%rsp), %rsi
leaq 56(%rsp), %rdi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
xorl %eax, %eax
addq $152, %rsp
retq
movq %rax, %rdi
callq __clang_call_terminate
movq %rax, %rdi
callq __clang_call_terminate
movq %rax, %rdi
callq __clang_call_terminate
leaq 104(%rsp), %rdi
xorl %esi, %esi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
movq 24(%rsp), %rsi
leaq 8(%rsp), %rdi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
movq 72(%rsp), %rsi
leaq 56(%rsp), %rdi
callq std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_erase(std::_Rb_tree_node<std::pair<int const, int> >*)
xorl %eax, %eax
addq $152, %rsp
retq
movq %rax, %rdi
callq __clang_call_terminate
movq %rax, %rdi
callq __clang_call_terminate
movq %rax, %rdi
callq __clang_call_terminate
What is the reason for this? Why isn't any of the compilers able to optimize away any of the std::map objects, although none of them has any side effect?
Godbolt: https://godbolt.org/z/cjfE3hjfo