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

            Bug ID: 120945
           Summary: Missed optimization opportunity with std::bind_front
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Mark_B53 at yahoo dot com
  Target Milestone: ---

In the following code compiled using -O2, test2() is fully optimized to "mov
eax, 10" followed by "ret", whereas test1() invokes Foo::test in a loop.  The
difference between the functions is the use of an explicit lambda (test2) vs. a
call wrapper generated by std::bind_front (test1).


    #include <ranges>
    #include <functional>
    #include <algorithm>

    struct Foo {
        bool test(int idx) const { return data[idx] == 0; }
        int data[10];

        int count1() const {
            auto fn = std::bind_front(&Foo::test, this);
            return std::ranges::count_if(std::views::iota(0, 10), fn);
        }
        int count2() const {
            auto fn = [this](int idx) { return test(idx); };
            return std::ranges::count_if(std::views::iota(0, 10), fn);
        }
    };

    __attribute__((noinline)) int test1() {
        Foo foo{};
        return foo.count1();
    }

    __attribute__((noinline)) int test2() {
        Foo foo{};
        return foo.count2();
    }

---

clang 19.1 is able to optimize both implementations.  Although this fact is
likely not relevant, I'm including it here since I am not a language lawyer on
perfect forwarding call wrappers.

Reply via email to