Skip to content

Invalid optimisation: atomicrmw xchg turned into atomic store #60418

@RalfJung

Description

@RalfJung

This is a sibling issue to #56450: LLVM will sometimes replace atomicrmw xchg by atomic store, specifically when the ordering is relaxed or release, and the result of the xchg is unused.

However, replacing an RMW by a non-RMW operation like is not sound under the C++ memory model (and LLVM does not seem to implement a fundamentally different model in that regard). Here's a counterexample using pseudocode notation:

Y:=1 rlx
fence(rel)
SWAP(X,0,rlx)
fence(acq)
a := Z rlx
||
Z:=1 rlx
fence(rel)
SWAP(X,0,rlx)
fence(acq)
b := Y rlx

One of the two SWAP has to read-from the other. This is because two RMWs cannot both read-from the same store (the implicit initial store of 0). Without loss of generality, let's assume the SWAP in the 2nd thread reads-from the first. Therefore we now have a synchronization edge from the fence(rel) in the first thread to the fence(acq) in the 2nd thread. Therefore b must be 1. (In the symmetric case, a must be 1.)

After the optimization, it is possible for both a and b to be 0. This means the optimization introduced new program behavior, and is therefore wrong.

(Thanks to Ori Lahav and Jeehoon Kang.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions