Consider these two approaches that can represent an "optional int
":
using std_optional_int = std::optional<int>;
using my_optional_int = std::pair<int, bool>;
Given these two functions...
auto get_std_optional_int() -> std_optional_int
{
return {42};
}
auto get_my_optional() -> my_optional_int
{
return {42, true};
}
...both g++ trunk and clang++ trunk (with -std=c++17 -Ofast -fno-exceptions -fno-rtti
) produce the following assembly:
get_std_optional_int():
mov rax, rdi
mov DWORD PTR [rdi], 42
mov BYTE PTR [rdi+4], 1
ret
get_my_optional():
movabs rax, 4294967338 // == 0x 0000 0001 0000 002a
ret
live example on godbolt.org
Why does get_std_optional_int()
require three mov
instructions, while get_my_optional()
only needs a single movabs
? Is this a QoI issue, or is there something in std::optional
's specification preventing this optimization?
Also please note that users of the functions might be completely optimized out regardless:
volatile int a = 0;
volatile int b = 0;
int main()
{
a = get_std_optional_int().value();
b = get_my_optional().first;
}
...results in:
main:
mov DWORD PTR a[rip], 42
xor eax, eax
mov DWORD PTR b[rip], 42
ret
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…