Open
Description
The code:
#include<stdint.h>
uint64_t foo(uint64_t a) {
uint32_t b = a;
if (b >= 100) __builtin_unreachable();
return b;
}
with -O3
compiles to:
foo:
mov rax, rdi
and eax, 127
ret
but it could be:
foo:
mov eax, edi
ret
compiler explorer on the instcombine pass that introduces the and
; namely, it transforms:
define dso_local range(i64 0, 4294967296) i64 @foo(i64 noundef %a) local_unnamed_addr {
entry:
%conv = trunc i64 %a to i32
%cmp = icmp uge i32 %conv, 100
%0 = xor i1 %cmp, true
call void @llvm.assume(i1 %0)
%conv2 = zext i32 %conv to i64
ret i64 %conv2
}
to:
define dso_local range(i64 0, 4294967296) i64 @foo(i64 noundef %a) local_unnamed_addr {
entry:
%conv = trunc i64 %a to i32
%cmp = icmp ult i32 %conv, 100
call void @llvm.assume(i1 %cmp)
%conv2 = and i64 %a, 127
ret i64 %conv2
}
reduced from this Rust code