================
@@ -247,6 +247,73 @@ static RValue emitBinaryAtomicPost(CIRGenFunction &cgf,
return RValue::get(result);
}
+/// Emit a `cir.atomic.cmpxchg` for __sync_val_compare_and_swap_N.
+/// Returns the old value (type matches the pointee of ptr).
+static mlir::Value emitAtomicCmpXchgValue(CIRGenFunction &cgf,
+ const CallExpr *e,
+ cir::MemOrder succOrder,
+ cir::MemOrder failOrder) {
+ Address destAddr = checkAtomicAlignment(cgf, e);
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ mlir::Value destValue = destAddr.emitRawPointer();
+ mlir::Value expected = cgf.emitScalarExpr(e->getArg(1));
+ mlir::Value desired = cgf.emitScalarExpr(e->getArg(2));
+
+ auto cmpxchg = cir::AtomicCmpXchgOp::create(
+ builder, cgf.getLoc(e->getSourceRange()), destValue, expected, desired,
+ succOrder, failOrder, cir::SyncScopeKind::System,
+ /*alignment=*/nullptr, /*weak=*/false, /*is_volatile=*/false);
+ return cmpxchg.getOld();
+}
+
+/// Emit a `cir.atomic.cmpxchg` for __sync_bool_compare_and_swap_N.
+/// Returns a boolean: true if the exchange succeeded (old == expected).
+static RValue emitAtomicCmpXchgBool(CIRGenFunction &cgf, const CallExpr *e) {
+ mlir::Value old =
+ emitAtomicCmpXchgValue(cgf, e, cir::MemOrder::SequentiallyConsistent,
+ cir::MemOrder::SequentiallyConsistent);
+ CIRGenBuilderTy &builder = cgf.getBuilder();
+ // __sync_bool_compare_and_swap returns true on success.
+ // The classic llvm/cmpxchg produces {old, success}. We only have old here,
+ // so compare old == expected.
+ mlir::Value expected = cgf.emitScalarExpr(e->getArg(1));
+ mlir::Value cmp = builder.createCompare(cgf.getLoc(e->getSourceRange()),
+ cir::CmpOpKind::eq, old, expected);
----------------
dingcyrus wrote:
Thank you for the review.
1. bool_compare_and_swap 的 bug
Good catch, fixed. Now using `cmpxchg.getSuccess()` directly
instead of re-emitting `getArg(1)` and comparing.
2. alignment
`AtomicCmpXchgOp::alignment` (and `AtomicXchgOp`) defaults to
natural alignment when not set. This matches what the existing
`makeBinaryAtomicValue` does for `AtomicFetchOp`, which has no
alignment parameter at all. If you'd prefer an explicit alignment
set from `destAddr`, I can add that.
3. _16 variants
Moved `_16` variants back to `errorBuiltinNYI` — they need
`__atomic_*` libcall fallback which isn't wired up yet.
4. tests
Added `builtin-sync.cpp` — one test per family checking the
emitted CIR op and memory order, plus LLVM IR checks.
https://github.com/llvm/llvm-project/pull/214606
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits