Closed
Description
I tried this code:
#include <cstdint>
#include <vector>
int get_idx_half(
const std::size_t idx,
const std::vector<int>& __restrict__ nums
) {
if (idx >= nums.size() / 2){
return 0;
}
// Bounds check here is not optimized.
return nums.at(idx);
}
int get_idx_full(
const std::size_t idx,
const std::vector<int>& __restrict__ nums
) {
if (idx >= nums.size()){
return 0;
}
// Bounds check here is eliminated.
return nums.at(idx);
}
This code generates this machine code:
get_idx_half(unsigned long, std::vector<int, std::allocator<int> > const&): # @get_idx_half(unsigned long, std::vector<int, std::allocator<int> > const&)
push rax
mov rcx, rdi
mov rdi, qword ptr [rsi]
mov rdx, qword ptr [rsi + 8]
sub rdx, rdi
sar rdx, 2
mov rsi, rdx
shr rsi
xor eax, eax
cmp rsi, rcx
jbe .LBB0_3
cmp rdx, rcx
jbe .LBB0_4
mov eax, dword ptr [rdi + 4*rcx]
.LBB0_3:
pop rcx
ret
.LBB0_4:
lea rdi, [rip + .L.str]
mov rsi, rcx
xor eax, eax
call std::__throw_out_of_range_fmt(char const*, ...)@PLT
get_idx_full(unsigned long, std::vector<int, std::allocator<int> > const&): # @get_idx_full(unsigned long, std::vector<int, std::allocator<int> > const&)
mov rcx, qword ptr [rsi]
mov rdx, qword ptr [rsi + 8]
sub rdx, rcx
sar rdx, 2
xor eax, eax
cmp rdx, rdi
jbe .LBB1_2
mov eax, dword ptr [rcx + 4*rdi]
.LBB1_2:
ret
.L.str:
.asciz "vector::_M_range_check: __n (which is %zu) >= this->size() (which is %zu)"
In the second function, bounds check at nums.at(idx)
is eliminated. However, it is not eliminated in first function despite the fact that idx
is limited to half of length which is guaranteed to be in valid range for indices of vector.