Look at this simple code, it calculates the number array elements between e and b:
#include <cstddef>
struct Foo {
char z[3];
};
std::ptrdiff_t size(const Foo *b, const Foo *e) {
std::ptrdiff_t r = e - b;
//if (r < 0) __builtin_unreachable();
return r;
}
Clang generates fine code for this (using -O2):
size(Foo const*, Foo const*): # @size(Foo const*, Foo const*)
sub rsi, rdi
movabs rax, -6148914691236517205
imul rax, rsi
ret
However, if I uncomment the commented line, I'd expect that it doesn't change the asm code. But it does, and clang generates a larger and supposedly less efficient code:
size(Foo const*, Foo const*): # @size(Foo const*, Foo const*)
mov rax, rsi
sub rax, rdi
movabs rcx, -6148914691236517205
mul rcx
mov rax, rdx
shr rax
ret
Is this a bug?
Similar case, look at this code:
#include <cstddef>
struct Foo {
char z[3];
};
void bar(std::ptrdiff_t);
void foo(const Foo *b, const Foo *e) {
std::ptrdiff_t s = e - b;
for (std::ptrdiff_t i=0; i<s; i++) {
bar(i);
}
}
The generated code is this:
foo(Foo const*, Foo const*): # @foo(Foo const*, Foo const*)
push r14
push rbx
push rax
sub rsi, rdi
test rsi, rsi
jle .LBB0_3
movabs rcx, -6148914691236517205
mov rax, rsi
mul rcx
shr rdx
cmp rdx, 2
mov r14d, 1
cmovge r14, rdx
xor ebx, ebx
.LBB0_2: # =>This Inner Loop Header: Depth=1
mov rdi, rbx
call bar(long)
add rbx, 1
cmp r14, rbx
jne .LBB0_2
.LBB0_3:
add rsp, 8
pop rbx
pop r14
ret
Notice the same, less efficient number of elements calculation. I think this happens because clang first handles the case when e < b, so it knows that s is non-negative, so it applies the same "optimization" as the previous case.
And also, there is a comparison with 2, and a cmov. Aren't these unnecessary? Is this some trick, or a bug?
godbolt link: https://godbolt.org/z/zMeY1MKh7