Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missed optimization: Imperfect optimization of straightforward std::find #112063

Open
Alcaro opened this issue Oct 12, 2024 · 4 comments
Open

Missed optimization: Imperfect optimization of straightforward std::find #112063

Alcaro opened this issue Oct 12, 2024 · 4 comments

Comments

@Alcaro
Copy link
Contributor

Alcaro commented Oct 12, 2024

static bool any_of_impl(int* first, int* last, int num)
{
    for (; first != last; ++first) {
        if (*first == num)
            return true;
    }
    return false;
}
bool square(int num) {
    int x[] = {1,2,3};
    return any_of_impl(x, x+3, num);
}

bool cube(int num) {
    return num==1 || num==2 || num==3;
}

-O2 or -O3

Expected: Same asm for both

Actual:

square(int):
        cmp     edi, 1
        sete    cl
        add     edi, -2
        test    edi, -2
        sete    al
        or      al, cl
        ret

cube(int):
        dec     edi
        cmp     edi, 3
        setb    al
        ret

The expected result shows up on pretty much any simplification of the input, including moving the +3 to the callee, or changing both functions' return type to int. Feels like some optimizer passes are running in wrong order and confusing each other.

https://godbolt.org/z/88938fP3d

Originally found via a std::ranges::any_of call, hence the function name. It turned into std::find when I reduced it. https://godbolt.org/z/GjsE3vEK4

@dtcxzyw
Copy link
Member

dtcxzyw commented Oct 12, 2024

Should be fixed in trunk: https://godbolt.org/z/o5Mzzadcj

@dtcxzyw dtcxzyw closed this as completed Oct 12, 2024
@dtcxzyw
Copy link
Member

dtcxzyw commented Oct 12, 2024

Originally found via a std::ranges::any_of call, hence the function name. It turned into std::find when I reduced it.

Oops, codegen for this case is still suboptimal: https://godbolt.org/z/5nh1fWvva

@dtcxzyw dtcxzyw reopened this Oct 12, 2024
@dtcxzyw dtcxzyw self-assigned this Oct 12, 2024
@dtcxzyw
Copy link
Member

dtcxzyw commented Oct 12, 2024

This seems to be a phase-ordering problem. We need another InstCombine run to cleanup after late SimplifyCFG pass converts the icmp chain into a range check + select. Or just handle this case in SimplifyCFG.

@Alcaro
Copy link
Contributor Author

Alcaro commented Oct 12, 2024

Yep, as I said, it's fragile. Re-reducing it reveals that it reproduces in trunk only if the outer function returns int, not bool.

static bool any_of_impl(int* first, int* last, int num)
{
    for (; first != last; ++first) {
        if (*first == num)
            return true;
    }
    return false;
}
int square(int num) {
    int x[] = {1,2,3};
    return any_of_impl(x, x+3, num);
}

int cube(int num) {
    return num==1 || num==2 || num==3;
}

https://godbolt.org/z/hnzvhcb8r

Which is a pretty goofy code pattern. Feel free to wontfix it if you feel it's too rare to care about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants