================
@@ -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

Reply via email to