Well, you can somewhat simplify it:
int add_two_numbers_smart_way(int a, int b) {
auto x = std::make_shared<Data>(a, b);
return add_numbers(x);
}
But you still get what you ask the compiler to deliver. If you don't specifically ask it to count references, it won't:
static int add_numbers(Data *p) {
return p->a + p->b;
}
int add_two_numbers_smart_way(int a, int b) {
Data x(a, b);
return add_numbers(&x);
}
Here's the result:
add_two_numbers_smart_way(int, int):
lea eax, [rdi + rsi]
ret
To answer the original question, it won't optimize the smart pointers away because the smart pointers are not implemented by the compiler. They are a generic construct telling the compiler to allocate memory, increase reference counter, decrease reference counter and free memory. How does it now this is not a unit test for memory allocation API or atomic operations?
A better question would be why C++ went for implementing certain things on the library level instead of the compiler level, and the answer here is probably "historical reasons" and someone's judgement call on flexibility vs performance under specific circumstances.