https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118033
Bug ID: 118033
Summary: [Missing optimization] Keep __builtin_unreachable for
asserts in the release build
Product: gcc
Version: 14.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: dmitriy.ovdienko at gmail dot com
Target Milestone: ---
Could you define `assert` macro as following in case if `NDEBUG` macro is
defined:
#if defined(NDEBUG)
# define assert(expr) if ((expr)) {} else { __builtin_unreachable(); }
#endif
Let's assume there is following function:
uint32_t assign32(char const* data, size_t size) noexcept
{
assert(size <= 4);
uint32_t result{0};
while(size)
{
size -= 1;
result <<= 8;
result |= static_cast<unsigned char>(data[size]);
}
return result;
}
When NDEBUG macro is not defined compiler unrolls the loop into the following
code:
assign32(char const*, unsigned long):
cmp rsi, 4
ja .L2
test rsi, rsi
je .L18
movzx eax, BYTE PTR [rdi-1+rsi]
cmp rsi, 1
je .L1
movzx edx, BYTE PTR [rdi-2+rsi]
sal eax, 8
or eax, edx
cmp rsi, 2
je .L1
movzx edx, BYTE PTR [rdi-3+rsi]
sal eax, 8
or eax, edx
cmp rsi, 3
je .L1
movzx edx, BYTE PTR [rdi]
sal eax, 8
or eax, edx
.L1:
ret
.L18:
xor eax, eax
ret
.L2:
push rax
mov ecx, OFFSET FLAT:.LC0
mov edx, 11
mov esi, OFFSET FLAT:.LC1
mov edi, OFFSET FLAT:.LC2
call __assert_fail
buffer_:
.zero 4
In case if NDEBUG macro is defined, then compiler does not unroll the function
and the output assembly is following:
assign32(char const*, unsigned long):
xor eax, eax
test rsi, rsi
je .L4
.L3:
sub rsi, 1
sal eax, 8
movzx edx, BYTE PTR [rdi+rsi]
or eax, edx
test rsi, rsi
jne .L3
ret
.L4:
ret
So from my point of view we are missing the optimization in the Release build