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

--- Comment #4 from LIU Hao <lh_mouse at 126 dot com> ---
Also this one, not sure whether it's related:
(https://gcc.godbolt.org/z/vvK9exavd)

```
typedef __UINT64_TYPE__ uint64_t;
typedef struct Value Value;

struct Value
  {
    uint64_t a :  1;
    uint64_t b :  4;
    uint64_t c :  4;
    uint64_t d : 55;
  };

inline
void
do_atomic_load_uint64_rlx(void* out, volatile const void* mem)
  {
    *(uint64_t*) out = __atomic_load_n((uint64_t*) mem, __ATOMIC_RELAXED);
  }

void
do_something(Value* p);

int
wants_no_b_or_d(Value* p) 
  {
    Value val;
    do_atomic_load_uint64_rlx(&val, p);
    if(val.b == 0 && val.d == 0) 
      do_something(p);
    return 42;
  }
```

GCC 16

```
"wants_no_b_or_d":
        mov     rax, QWORD PTR [rdi]
        test    al, 30
        jne     .L10
        cmp     rax, 511
        jbe     .L14
.L10:
        mov     eax, 42
        ret
.L14:
        sub     rsp, 8
        call    "do_something"
        mov     eax, 42
        add     rsp, 8
        ret
```

Clang 22

```
wants_no_b_or_d:
        mov     rax, qword ptr [rdi]
        test    rax, -482
        je      .LBB0_1
        mov     eax, 42
        ret
.LBB0_1:
        push    rax
        call    do_something@PLT
        add     rsp, 8
        mov     eax, 42
        ret
```

The workaround is to disable optimization on `val` after the atomic load:

```
    Value val;
    do_atomic_load_uint64_rlx(&val, p);
    __asm__ ("" : "+r"(val));
```

Reply via email to