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

[clang] unnecessary conditions marked with [[likely]] or [[unlikely]] are not removed by the optimizer #69841

Closed
jonathanpoelen opened this issue Oct 21, 2023 · 2 comments · Fixed by #68882
Assignees

Comments

@jonathanpoelen
Copy link

https://godbolt.org/z/jEM7nrKhs

With the following code

struct A {
    int type;
};

struct B : A {
    int value;
};

struct C : A {
    int value;
    int value2;
};

int foo(A *p) {
    if (p->type == 0) [[likely]] return static_cast<B*>(p)->value;
    return static_cast<C*>(p)->value;
}

int bar(A *p) {
    if (p->type == 0) [[unlikely]] return static_cast<B*>(p)->value;
    return static_cast<C*>(p)->value;
}

int zeta(A *p) {
    if (p->type == 0) return static_cast<B*>(p)->value;
    return static_cast<C*>(p)->value;
}

The offset of B::value and C::value are identical, so the 2 branches should give the same code. This is the case with gcc and the zeta function:

mov     eax, DWORD PTR [rdi+4]
ret

On the other hand, the 2 branches using [[(un)likely]] retain the cmp instruction with clang:

cmp     dword ptr [rdi], 0
mov     eax, dword ptr [rdi + 4]
ret

Testes with clang-15, clang-16 and clang-trunk.

@github-actions github-actions bot added the clang Clang issues not falling into any other category label Oct 21, 2023
@nikic
Copy link
Contributor

nikic commented Oct 21, 2023

I believe #68882 will fix this.

@EugeneZelenko EugeneZelenko added llvm:instcombine and removed clang Clang issues not falling into any other category labels Oct 21, 2023
@nikic nikic self-assigned this Dec 20, 2023
@nikic
Copy link
Contributor

nikic commented Dec 20, 2023

Just checked, and it does fix it.

nikic added a commit that referenced this issue Jan 24, 2024
…68882)

This patch canonicalizes getelementptr instructions with constant
indices to use the `i8` source element type. This makes it easier for
optimizations to recognize that two GEPs are identical, because they
don't need to see past many different ways to express the same offset.

This is a first step towards
https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699.
This is limited to constant GEPs only for now, as they have a clear
canonical form, while we're not yet sure how exactly to deal with
variable indices.

The test llvm/test/Transforms/PhaseOrdering/switch_with_geps.ll gives
two representative examples of the kind of optimization improvement we
expect from this change. In the first test SimplifyCFG can now realize
that all switch branches are actually the same. In the second test it
can convert it into simple arithmetic. These are representative of
common optimization failures we see in Rust.

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

Successfully merging a pull request may close this issue.

3 participants