-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Open
Labels
Description
struct PgAioHandle {
char x;
int y;
};
static inline bool
f(struct PgAioHandle *ioh, int y, char *x)
{
*x = ioh->x;
__atomic_thread_fence(__ATOMIC_ACQUIRE);
if (ioh->y != y)
return false;
return true;
}
bool
g(struct PgAioHandle *ioh, int y)
{
char x;
if (!f(ioh, y, &x))
return false;
if (!f(ioh, y, &x))
return false;
return x != 0;
}
If f() is inlined just once (ie commend out the second call), then we load ->x before ->y with a fence as expected:
lbu a2, 0(a0)
fence r, rw
lw a0, 4(a0)
If f() is inlined twice, then we get this:
fence r, rw
lw a2, 4(a0)
bne a2, a1, .LBB0_3
fence r, rw
lw a2, 4(a0)
bne a2, a1, .LBB0_3
lbu a0, 0(a0)
The lbu of ->x is on the wrong side of the fence, right? Happens with all Clang versions on godbolt with -O1 and above, but doesn't happen with GCC. (This is minimized from src/backend/storage/aio/aio.c in PostgreSQL.)