Why does the SIMD path use < instead of <= in std.mem.findScalarPos?

I’m trying to understand the reasoning behind the < checks in this SIMD code.

The relevant part is:

if (i + 2 * block_len < slice.len) {
    const mask: Block = @splat(value);
    while (true) {
        inline for (0..2) |_| {
            const block: Block = slice[i..][0..block_len].*;
            const matches = block == mask;
            if (@reduce(.Or, matches)) {
                return i + std.simd.firstTrue(matches).?;
            }
            i += block_len;
        }
        if (i + 2 * block_len >= slice.len) break;
    }
}

Then the tail handling has:

const block_x_len = block_len / (1 << j);

if (i + block_x_len < slice.len) {
    const block: BlockX = slice[i..][0..block_x_len].*;
    ...
}

I’m wondering why these use < instead of <=.

If a block ends exactly at slice.len, wouldn’t it still be valid? For example, if slice.len == 16 and block_len == 8, the block [8..16) fits completely.

With <, that final block is left for the scalar loop instead.

I’m mainly trying to understand if there is a performance, bounds-check, or other implementation reason for using < here that I’m missing.

Looks to me like the usual difference between Offset (i) and Size (slice.len). There is a nice visualization at TigerBeetles Blog post Index, Count, Offset, Size

I think the use of < is appropriate here.

I see the index/count distinction, but in this case I think i + block_len is an end position rather than an index. If i = 8 , block_len = 8 , and slice.len = 16 , the accessed range is [8..16) , so the block fits exactly. That’s why I’m wondering why the condition uses < rather than <= .