Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 18 additions & 24 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -4172,7 +4172,7 @@ def CIR_ThrowOp : CIR_Op<"throw"> {
// Atomic operations
//===----------------------------------------------------------------------===//

def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [
def CIR_AtomicXchgOp : CIR_Op<"atomic.xchg", [
AllTypesMatch<["result", "val"]>,
TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'",
"ptr", "val", "mlir::cast<cir::PointerType>($_self).getPointee()">
Expand All @@ -4190,9 +4190,7 @@ def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [
Example:

```mlir
%res = cir.atomic.xchg(%ptr : !cir.ptr<!u64i>,
%val : !u64i,
seq_cst) : !u64i
%res = cir.atomic.xchg seq_cst %ptr, %val : !cir.ptr<!u64i> -> !u64i
```
}];

Expand All @@ -4207,12 +4205,16 @@ def CIR_AtomicXchg : CIR_Op<"atomic.xchg", [
let assemblyFormat = [{
$mem_order (`volatile` $is_volatile^)?
$ptr `,` $val
`:` qualified(type($ptr)) `->` type($result) attr-dict
`:` functional-type(operands, results) attr-dict
}];
}

def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [
AllTypesMatch<["old", "expected", "desired"]>
def CIR_AtomicCmpXchgOp : CIR_Op<"atomic.cmpxchg", [
AllTypesMatch<["old", "expected", "desired"]>,
TypesMatchWith<"type of 'expected' must match the pointee type of 'ptr'",
"ptr", "expected", "mlir::cast<cir::PointerType>($_self).getPointee()">,
TypesMatchWith<"type of 'desired' must match the pointee type of 'ptr'",
"ptr", "desired", "mlir::cast<cir::PointerType>($_self).getPointee()">
]> {
let summary = "Atomic compare and exchange";
let description = [{
Expand Down Expand Up @@ -4245,12 +4247,11 @@ def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [
Example:

```mlir
%old, %success = cir.atomic.cmpxchg(%ptr : !cir.ptr<!u64i>,
%expected : !u64i,
%desired : !u64i,
success = seq_cst,
failure = seq_cst) weak
: (!u64i, !cir.bool)
%old, %success = cir.atomic.cmpxchg weak seq_cst %ptr, %expected, %desired
: (!cir.ptr<!u64i>, !u64i, !u64i) -> (!u64i, !cir.bool)
%old, %success = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire)
%ptr, %expected, %desired
: (!cir.ptr<!u64i>, !u64i, !u64i) -> (!u64i, !cir.bool)
```
}];
let results = (outs CIR_AnyType:$old, CIR_BoolType:$success);
Expand All @@ -4264,20 +4265,13 @@ def CIR_AtomicCmpXchg : CIR_Op<"atomic.cmpxchg", [
UnitAttr:$is_volatile);

let assemblyFormat = [{
`(`
$ptr `:` qualified(type($ptr)) `,`
$expected `:` type($expected) `,`
$desired `:` type($desired) `,`
`success` `=` $succ_order `,`
`failure` `=` $fail_order
`)`
(`align` `(` $alignment^ `)`)?
(`weak` $weak^)?
custom<AtomicCmpXchgMemOrder>($succ_order, $fail_order)
Copy link
Contributor

@xlauko xlauko Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need custom printer/parser?
why not just something like:

`success` `(` $succ_order `)` `failure` `(` $fail_order `)`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general we try to avoid custom printers/parser as they are harder to maintain and often error prone.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention here is to avoid showing the same memory order twice when $succ_order and $fail_order are the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to show it twice, more explicit, specially when the trade off is to do tablegen only.

$ptr `,` $expected `,` $desired
(`align` `(` $alignment^ `)`)?
(`volatile` $is_volatile^)?
`:` `(` type($old) `,` type($success) `)` attr-dict
`:` functional-type(operands, results) attr-dict
}];

let hasVerifier = 1;
}

#endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
4 changes: 2 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ static void emitAtomicCmpXchg(CIRGenFunction &cgf, AtomicExpr *e, bool isWeak,
mlir::Value expected = builder.createLoad(loc, val1);
mlir::Value desired = builder.createLoad(loc, val2);

auto cmpxchg = cir::AtomicCmpXchg::create(
auto cmpxchg = cir::AtomicCmpXchgOp::create(
builder, loc, expected.getType(), builder.getBoolTy(), ptr.getPointer(),
expected, desired,
cir::MemOrderAttr::get(&cgf.getMLIRContext(), successOrder),
Expand Down Expand Up @@ -404,7 +404,7 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
case AtomicExpr::AO__atomic_exchange:
opName = cir::AtomicXchg::getOperationName();
opName = cir::AtomicXchgOp::getOperationName();
break;

case AtomicExpr::AO__opencl_atomic_init:
Expand Down
62 changes: 48 additions & 14 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,54 @@ static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer,
/*printBlockTerminators=*/!omitRegionTerm(region));
}

static mlir::ParseResult
parseAtomicCmpXchgMemOrder(mlir::OpAsmParser &parser,
cir::MemOrderAttr &successOrder,
cir::MemOrderAttr &failureOrder) {
auto parseMemOrder = [&](cir::MemOrderAttr *output) -> mlir::ParseResult {
mlir::SMLoc loc = parser.getCurrentLocation();
llvm::StringRef memOrderStr;
if (parser.parseKeyword(&memOrderStr))
return failure();
std::optional<cir::MemOrder> memOrder = symbolizeMemOrder(memOrderStr);
if (!memOrder.has_value())
return parser.emitError(loc, "unknown memory order \"")
<< memOrderStr << "\"";
*output = cir::MemOrderAttr::get(parser.getContext(), *memOrder);
return success();
};

if (parser.parseOptionalKeyword("success")) {
// No "success" keyword found. successOrder and failureOrder will have the
// same value.
if (parseMemOrder(&successOrder))
return failure();
failureOrder = successOrder;
return success();
}

if (parser.parseLParen() || parseMemOrder(&successOrder) ||
parser.parseRParen())
return failure();

if (parser.parseKeyword("failure") || parser.parseLParen() ||
parseMemOrder(&failureOrder) || parser.parseRParen())
return failure();

return success();
}

static void printAtomicCmpXchgMemOrder(mlir::OpAsmPrinter &printer,
cir::AtomicCmpXchgOp &op,
cir::MemOrderAttr successOrder,
cir::MemOrderAttr failureOrder) {
if (successOrder.getValue() == failureOrder.getValue())
printer << stringifyMemOrder(successOrder.getValue());
else
printer << "success(" << stringifyMemOrder(successOrder.getValue()) << ") "
<< "failure(" << stringifyMemOrder(failureOrder.getValue()) << ")";
}

//===----------------------------------------------------------------------===//
// AllocaOp
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2846,20 +2894,6 @@ mlir::LogicalResult cir::ThrowOp::verify() {
return failure();
}

//===----------------------------------------------------------------------===//
// AtomicCmpXchg
//===----------------------------------------------------------------------===//

LogicalResult cir::AtomicCmpXchg::verify() {
mlir::Type pointeeType = getPtr().getType().getPointee();

if (pointeeType != getExpected().getType() ||
pointeeType != getDesired().getType())
return emitOpError("ptr, expected and desired types must match");

return success();
}

//===----------------------------------------------------------------------===//
// TypeInfoAttr
//===----------------------------------------------------------------------===//
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,8 @@ getLLVMMemOrder(std::optional<cir::MemOrder> memorder) {
llvm_unreachable("unknown memory order");
}

mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite(
cir::AtomicCmpXchg op, OpAdaptor adaptor,
mlir::LogicalResult CIRToLLVMAtomicCmpXchgOpLowering::matchAndRewrite(
cir::AtomicCmpXchgOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Value expected = adaptor.getExpected();
mlir::Value desired = adaptor.getDesired();
Expand All @@ -719,8 +719,8 @@ mlir::LogicalResult CIRToLLVMAtomicCmpXchgLowering::matchAndRewrite(
return mlir::success();
}

mlir::LogicalResult CIRToLLVMAtomicXchgLowering::matchAndRewrite(
cir::AtomicXchg op, OpAdaptor adaptor,
mlir::LogicalResult CIRToLLVMAtomicXchgOpLowering::matchAndRewrite(
cir::AtomicXchgOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
assert(!cir::MissingFeatures::atomicSyncScopeID());
mlir::LLVM::AtomicOrdering llvmOrder = getLLVMMemOrder(adaptor.getMemOrder());
Expand Down
48 changes: 24 additions & 24 deletions clang/test/CIR/CodeGen/atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void c11_atomic_cmpxchg_strong(_Atomic(int) *ptr, int *expected, int desired) {

__c11_atomic_compare_exchange_strong(ptr, expected, desired,
__ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -249,7 +249,7 @@ void c11_atomic_cmpxchg_weak(_Atomic(int) *ptr, int *expected, int desired) {

__c11_atomic_compare_exchange_weak(ptr, expected, desired,
__ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -286,7 +286,7 @@ void atomic_cmpxchg(int *ptr, int *expected, int *desired) {
// OGCG-LABEL: @atomic_cmpxchg

__atomic_compare_exchange(ptr, expected, desired, /*weak=*/0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -317,7 +317,7 @@ void atomic_cmpxchg(int *ptr, int *expected, int *desired) {
// OGCG-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1

__atomic_compare_exchange(ptr, expected, desired, /*weak=*/1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -354,7 +354,7 @@ void atomic_cmpxchg_n(int *ptr, int *expected, int desired) {
// OGCG-LABEL: @atomic_cmpxchg_n

__atomic_compare_exchange_n(ptr, expected, desired, /*weak=*/0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -385,7 +385,7 @@ void atomic_cmpxchg_n(int *ptr, int *expected, int desired) {
// OGCG-NEXT: store i8 %[[SUCCESS_2]], ptr %{{.+}}, align 1

__atomic_compare_exchange_n(ptr, expected, desired, /*weak=*/1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg(%{{.+}} : !cir.ptr<!s32i>, %{{.+}} : !s32i, %{{.+}} : !s32i, success = seq_cst, failure = acquire) align(4) weak : (!s32i, !cir.bool)
// CIR: %[[OLD:.+]], %[[SUCCESS:.+]] = cir.atomic.cmpxchg weak success(seq_cst) failure(acquire) %{{.+}}, %{{.+}}, %{{.+}} align(4) : (!cir.ptr<!s32i>, !s32i, !s32i) -> (!s32i, !cir.bool)
// CIR-NEXT: %[[FAILED:.+]] = cir.unary(not, %[[SUCCESS]]) : !cir.bool, !cir.bool
// CIR-NEXT: cir.if %[[FAILED]] {
// CIR-NEXT: cir.store align(4) %[[OLD]], %{{.+}} : !s32i, !cir.ptr<!s32i>
Expand Down Expand Up @@ -427,12 +427,12 @@ void c11_atomic_exchange(_Atomic(int) *ptr, int value) {
__c11_atomic_exchange(ptr, value, __ATOMIC_RELEASE);
__c11_atomic_exchange(ptr, value, __ATOMIC_ACQ_REL);
__c11_atomic_exchange(ptr, value, __ATOMIC_SEQ_CST);
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i

// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} monotonic, align 4
// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} acquire, align 4
Expand Down Expand Up @@ -460,12 +460,12 @@ void atomic_exchange(int *ptr, int *value, int *old) {
__atomic_exchange(ptr, value, old, __ATOMIC_RELEASE);
__atomic_exchange(ptr, value, old, __ATOMIC_ACQ_REL);
__atomic_exchange(ptr, value, old, __ATOMIC_SEQ_CST);
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i

// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} monotonic, align 4
// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} acquire, align 4
Expand Down Expand Up @@ -493,12 +493,12 @@ void atomic_exchange_n(int *ptr, int value) {
__atomic_exchange_n(ptr, value, __ATOMIC_RELEASE);
__atomic_exchange_n(ptr, value, __ATOMIC_ACQ_REL);
__atomic_exchange_n(ptr, value, __ATOMIC_SEQ_CST);
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : !cir.ptr<!s32i> -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg relaxed %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg consume %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acquire %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg release %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg acq_rel %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i
// CIR: %{{.+}} = cir.atomic.xchg seq_cst %{{.+}}, %{{.+}} : (!cir.ptr<!s32i>, !s32i) -> !s32i

// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} monotonic, align 4
// LLVM: %{{.+}} = atomicrmw xchg ptr %{{.+}}, i32 %{{.+}} acquire, align 4
Expand Down
Loading