Skip to content

Dead branch instructions in Aarch64 atomic compare exchange #142858

@ilovepi

Description

@ilovepi

Some of our kernel developers pointed out an odd instruction sequence emited by clang. We're not sure why this strange branch sequence appears, since its basically a NOP.

Godbolt: https://godbolt.org/z/T77qWvxW5

#include <atomic>
#include <stdlib.h>

bool cmpxchg(std::atomic<uint32_t>& a, uint32_t& expected, uint32_t desired) {
    return a.compare_exchange_strong(expected, desired, std::memory_order_acq_rel);
}
cmpxchg(std::atomic<unsigned int>&, unsigned int&, unsigned int):
        ldr     w9, [x1]
.LBB0_1:
        ldaxr   w8, [x0]
        cmp     w8, w9
        b.ne    .LBB0_4
        stlxr   w10, w2, [x0]
        cbnz    w10, .LBB0_1
        mov     w0, #1            // <-- move 1 into W)
        tbz     w0, #0, .LBB0_5   // <-- branch if the 0th bit is zero (always false)
        b       .LBB0_6           // Always taken
.LBB0_4:
        mov     w0, wzr
        clrex
        tbnz    wzr, #0, .LBB0_6
.LBB0_5:
        str     w8, [x1]
.LBB0_6:
        ret

Does anyone know why this is emitted this way? We could find no reason that we'd want such a lowering.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions