================
@@ -63,25 +63,89 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const 
CallExpr *e,
 static void emitAtomicFenceOp(CIRGenFunction &cgf, const CallExpr *expr,
                               cir::SyncScopeKind syncScope) {
   CIRGenBuilderTy &builder = cgf.getBuilder();
-  mlir::Value orderingVal = cgf.emitScalarExpr(expr->getArg(0));
-
-  auto constOrdering = orderingVal.getDefiningOp<cir::ConstantOp>();
-
-  if (!constOrdering) {
-    // TODO(cir): Emit code to switch on `orderingVal`,
-    //            and creating the fence op for valid values.
-    cgf.cgm.errorNYI("Variable atomic fence ordering");
+  mlir::Location loc = cgf.getLoc(expr->getSourceRange());
+
+  // Convert the memory order specified by user to effective one:
+  //   Relaxed                -> std::nullopt
+  //   Consume/Acquire        -> Acquire
+  //   Release                -> Release
+  //   AcquireRelease         -> AcquireRelease
+  //   SequentiallyConsistent -> SequentiallyConsistent
+  auto getEffectiveMemOrder =
+      [](cir::MemOrder oriOrder) -> std::optional<cir::MemOrder> {
+    if (oriOrder == cir::MemOrder::Relaxed)
+      return std::nullopt;
+    else if (oriOrder == cir::MemOrder::Consume ||
+             oriOrder == cir::MemOrder::Acquire)
+      return cir::MemOrder::Acquire;
+    else
+      return oriOrder;
+  };
+
+  // Handle constant memory ordering.
+  Expr::EvalResult eval;
+  if (expr->getArg(0)->EvaluateAsInt(eval, cgf.getContext())) {
+    uint64_t constOrder = eval.Val.getInt().getZExtValue();
+    // Not emit anything if it's an invalid constant.
+    if (!cir::isValidCIRAtomicOrderingCABI(constOrder))
+      return;
+    cir::MemOrder caseOrder = static_cast<cir::MemOrder>(constOrder);
+    if (std::optional<cir::MemOrder> order = getEffectiveMemOrder(caseOrder))
+      cir::AtomicFenceOp::create(
+          builder, loc, order.value(),
+          cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
     return;
   }
 
-  auto constOrderingAttr = constOrdering.getValueAttr<cir::IntAttr>();
-  assert(constOrderingAttr && "Expected integer constant for ordering");
-
-  auto ordering = static_cast<cir::MemOrder>(constOrderingAttr.getUInt());
-
-  cir::AtomicFenceOp::create(
-      builder, cgf.getLoc(expr->getSourceRange()), ordering,
-      cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
+  // Otherwise, handle variable memory ordering. Emit `SwitchOp` to convert
+  // dynamic value to static value.
+  mlir::Value varOrder = cgf.emitScalarExpr(expr->getArg(0));
+  cir::SwitchOp::create(
----------------
Lancern wrote:

`CIRGenAtomic.cpp` has very similar code snippet to deal with dynamic memory 
order, see the function `emitAtomicExprWithDynamicMemOrder`:

https://github.com/llvm/llvm-project/blob/ed5589b0dcec40e25675812a330e171ed0587644/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp#L726-L730

Can you try to merge these two pieces of code?

https://github.com/llvm/llvm-project/pull/172455
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to