https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127913

            Bug ID: 127913
           Summary: Unnecessary 128-bit arithmetic in ranges::lower_bound
                    over a bounded iota_view
           Product: gcc
           Version: 16.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: adamant.pwn at gmail dot com
  Target Milestone: ---

Created attachment 65850
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65850&action=edit
Preprocessed reproducer and GCC build configuration

I ran into this when replacing an indexed binary search with
`std::ranges::lower_bound` over `std::views::iota`. The iota version keeps
128-bit distance arithmetic in the search loop, even when the compiler knows
that both bounds are between 0 and 100.

```cpp
#include <algorithm>
#include <cstdint>
#include <ranges>

using U = std::uint64_t;

U iota_search(const U* data, U first, U last, U value)
{
    if (first > last || last > 100)
        __builtin_unreachable();
    auto indices = std::views::iota(first, last);
    auto it = std::ranges::lower_bound(indices, value, {},
                                     [&](U i) { return data[i]; });
    return first + (it - indices.begin());
}

U pointer_search(const U* data, U first, U last, U value)
{
    if (first > last || last > 100)
        __builtin_unreachable();
    return std::ranges::lower_bound(data + first, data + last, value) - data;
}
```

Reproduced with GCC 16.2.1 20260810 (Arch Linux), target `x86_64-pc-linux-gnu`:

```sh
g++ -std=c++20 -O2 -S -masm=intel repro.cpp
```

`iota_search` emits `shrd`, `adc` and `sbb` for the loop's distance
calculations. `pointer_search` uses ordinary 64-bit arithmetic. The same
happens at `-O3`.

The wider difference type makes sense for a general 64-bit iota range, but here
the distance starts at no more than 100 and only decreases. Could that
arithmetic be narrowed after inlining?

The attached preprocessed source includes the full `g++ -v` output in a
comment. Compiling with `-Wall -Wextra -D_GLIBCXX_ASSERTIONS` produces no
diagnostics.

Assisted-by: OpenAI Codex

Reply via email to